HTRACE-204. htrace-web: add draggable bar which allows more or less visual space for process name in search view (Colin Patrick McCabe via iwasakims)
diff --git a/htrace-webapp/src/main/web/app/partition_widget.js b/htrace-webapp/src/main/web/app/partition_widget.js
new file mode 100644
index 0000000..a68c8ce
--- /dev/null
+++ b/htrace-webapp/src/main/web/app/partition_widget.js
@@ -0,0 +1,72 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+var htrace = htrace || {};
+
+// Widget containing draggable horizontal partition
+htrace.PartitionWidget = function(params) {
+  this.draw = function() {
+    this.ctx.save();
+    this.ctx.fillStyle = this.selected ? "#6600ff" : "#aaaaaa";
+    this.ctx.fillRect(this.x0, this.y0, this.xF - this.x0, this.yF - this.y0);
+    this.ctx.restore();
+  };
+
+  this.handle = function(e) {
+    switch (e.type) {
+      case "mouseDown":
+        if (!htrace.inBoundingBox(e.x, e.y,
+              this.x0, this.xF, this.y0, this.yF)) {
+          return true;
+        }
+        this.manager.registerHighPriority("mouseUp", this);
+        this.manager.registerHighPriority("mouseMove", this);
+        this.selected = true;
+        $(this.el).css('cursor', 'ew-resize');
+        return false;
+      case "mouseMove":
+        // Move the partition to the mouse pointer area
+        var x = Math.min(Math.max(e.x, this.xMin), this.xMax);
+        var width = this.xF - this.x0;
+        this.x0 = Math.floor(x - (width / 2));
+        this.xF = this.x0 + width;
+        return false;
+      case "mouseUp":
+        this.manager.unregister("mouseUp", this);
+        this.manager.unregister("mouseMove", this);
+        $(this.el).css('cursor', 'pointer');
+        this.selected = false;
+        this.releaseHandler(this.x0);
+        return false;
+      case "draw":
+        this.draw();
+        return true;
+      default:
+        return true;
+    }
+  };
+
+  for (var k in params) {
+    this[k]=params[k];
+  }
+  this.selected = false;
+  this.manager.register("mouseDown", this);
+  this.manager.register("draw", this);
+  return this;
+};
diff --git a/htrace-webapp/src/main/web/app/search_results_view.js b/htrace-webapp/src/main/web/app/search_results_view.js
index f88b096..7a154dd 100644
--- a/htrace-webapp/src/main/web/app/search_results_view.js
+++ b/htrace-webapp/src/main/web/app/search_results_view.js
@@ -27,14 +27,12 @@
 
   end: this.MINIMUM_TIME_SPAN,
 
+  processNameFraction: 0.2,
+
   initialize: function(options) {
     this.searchResults = options.searchResults;
     this.el = options.el;
     var view = this;
-    this.listenTo(this.searchResults, 'add remove change reset',
-      _.debounce(function()  {
-      view.render();
-    }, 10));
 
     // Re-render the canvas when the window size changes.
     // Add a debouncer delay to avoid spamming render requests.
@@ -168,7 +166,7 @@
   setupCoordinates: function() {
     this.viewX = this.canvas.parent().innerWidth();
     this.viewY = $(window).innerHeight() - $("#header").innerHeight() - 50;
-    this.xB = Math.min(300, Math.floor(this.viewX / 5));
+    this.xB = Math.floor(this.viewX * this.processNameFraction);
     this.xD = this.xB + Math.min(75, Math.floor(this.viewX / 20));
     var scrollBarWidth = Math.min(50, Math.floor(this.viewX / 10));
     this.xS = this.viewX - scrollBarWidth;
@@ -176,8 +174,11 @@
   },
 
   setupWidgets: function() {
+    var searchResultsView = this;
     this.widgetManager = new htrace.WidgetManager({searchResultsView: this});
 
+    var partitionWidgetWidth = Math.max(5, Math.floor(this.viewX / 300));
+
     // Create a SpanWidget for each span we know about
     var spanWidgetHeight = Math.min(25, Math.floor(this.viewY / 32));
     var numResults = this.searchResults.size();
@@ -188,7 +189,7 @@
         ctx: this.ctx,
         span: this.searchResults.at(i),
         x0: 0,
-        xB: this.xB,
+        xB: this.xB + partitionWidgetWidth,
         xD: this.xD,
         xF: this.xS,
         y0: groupY,
@@ -202,6 +203,26 @@
       this.canvasY = groupY;
     }
 
+    // Create the draggable horizontal parition between process names and span
+    // names.
+    new htrace.PartitionWidget({
+      el: '#resultsCanvas',
+      manager: this.widgetManager,
+      ctx: this.ctx,
+      x0: this.xB,
+      xF: this.xB + partitionWidgetWidth,
+      xMin: Math.floor(this.viewX * 0.10),
+      xMax: Math.floor(this.viewX * 0.90),
+      y0: 0, 
+      yF: groupY,
+      releaseHandler: function(x) {
+        searchResultsView.processNameFraction = (x / searchResultsView.viewX);
+        console.log("htrace#PartitionWidget setting processNameFraction to " +
+              searchResultsView.processNameFraction);
+        searchResultsView.render();
+      }
+    });
+
     // Create the time cursor widget.
     var selectedTime = this.begin;
     if (this.timeCursor != null) {
@@ -371,13 +392,13 @@
         toDelete.push(model);
       }
     }
-    this.render();
     ids = [];
     for (var i = 0; i < toDelete.length; i++) {
       ids.push(toDelete[i].get("spanId"));
     }
     console.log("clearHandler: removing " + JSON.stringify(ids));
     this.searchResults.remove(toDelete);
+    this.render();
   },
 
   getSelectedSpansOrAllSpans: function() {
diff --git a/htrace-webapp/src/main/web/app/search_view.js b/htrace-webapp/src/main/web/app/search_view.js
index a530d70..270f11d 100644
--- a/htrace-webapp/src/main/web/app/search_view.js
+++ b/htrace-webapp/src/main/web/app/search_view.js
@@ -122,6 +122,7 @@
               "No additional results were found for your query.<p/>");
           }
         }
+        searchView.resultsView.render();
       },
       error: function(model, response, options){
         searchView.searchResults.reset();
diff --git a/htrace-webapp/src/main/web/app/widget_manager.js b/htrace-webapp/src/main/web/app/widget_manager.js
index ae14b2b..e519485 100644
--- a/htrace-webapp/src/main/web/app/widget_manager.js
+++ b/htrace-webapp/src/main/web/app/widget_manager.js
@@ -40,6 +40,10 @@
     this.listeners[type].push(widget);
   }
 
+  this.registerHighPriority = function(type, widget) {
+    this.listeners[type].unshift(widget);
+  }
+
   this.unregister = function(type, widget) {
     this.listeners[type] = _.without(this.listeners[type], widget);
   }
diff --git a/htrace-webapp/src/main/web/index.html b/htrace-webapp/src/main/web/index.html
index 77cbe09..63956e4 100644
--- a/htrace-webapp/src/main/web/index.html
+++ b/htrace-webapp/src/main/web/index.html
@@ -228,6 +228,7 @@
 
     <script src="app/widget_manager.js" type="text/javascript"></script>
     <script src="app/triangle_button.js" type="text/javascript"></script>
+    <script src="app/partition_widget.js" type="text/javascript"></script>
 
     <script src="app/span.js" type="text/javascript"></script>