- improvements in object rendering support.
authorAndrew Sutherland <asutherland@asutherland.org>
Sun, 18 Oct 2009 20:45:04 -0700
changeset 8 a5ae6f37661293559fa364939bffadb83fd20d4d
parent 7 11aee5e369988d1385c7f8e2410198eb5dec6759
child 9 d107201f319d13332112095efbc68a4005f44c18
push id2
push userbugmail@asutherland.org
push dateMon, 26 Oct 2009 10:02:58 +0000
- improvements in object rendering support. - tried to create a reset button, but I've obviously missed an invariant somewhere.
chrome/content/formatters.js
chrome/content/logaggr.js
chrome/content/logman.js
chrome/content/logui.js
chrome/content/logviewer.css
chrome/content/logviewer.xhtml
chrome/content/logvis.js
--- a/chrome/content/formatters.js
+++ b/chrome/content/formatters.js
@@ -1,15 +1,16 @@
 let FormatHelp = {
   /**
    * Create/wrap into a clicky node that shows an object explorer for the given
    *  object when clicked.
    */
   makeDetailLink: function FormatHelp_makeDetailLink(textOrNodes, detailObj) {
-    let node = document.createElement("a");
+    let node = document.createElement("span");
+    $(node).addClass("clicky");
     if (typeof(textOrNodes) == "string") {
       node.textContent = textOrNodes;
     }
     else {
       for each (let [, childNode] in Iterator(textOrNodes)) {
         node.appendChild(childNode);
       }
     }
@@ -122,18 +123,21 @@ function nodifyThing(obj, genericObjHand
     return nodifyTypedObj(obj);
   }
   else if ("length" in obj) {
     return nodifyList(obj, genericObjHandler, true);
   }
   else if (genericObjHandler) {
     return genericObjHandler(obj);
   }
+  else if ("_stringRep" in obj) {
+    return FormatHelp.makeDetailLink(obj._stringRep, obj);
+  }
   else {
-    return document.createTextNode(obj.toString());
+    return FormatHelp.makeDetailLink("OBJECT", obj);
   }
 };
 
 function nodifyList(things, genericObjHandler, delimit) {
   let span = document.createElement("span");
   for each (let [iThing, thing] in Iterator(things)) {
     if (iThing) {
       if (delimit)
--- a/chrome/content/logaggr.js
+++ b/chrome/content/logaggr.js
@@ -1,12 +1,16 @@
 /**
  * Aggregation logic and such.
  */
 let LogAggr = {
+  _init: function LogAggr__init() {
+    LogManager.registerListener("onReset", this.reset, this);
+  },
+
   curBucket: null,
   curBucketAggr: null,
   curBucketCount: 0,
 
   _chewBucket: function(bucket, bucketAggr) {
     let counts = bucketAggr.loggerCounts;
 
     for each (let [, msg] in Iterator(bucket)) {
@@ -15,16 +19,20 @@ let LogAggr = {
       else
         counts[msg.loggerName] = 1;
     }
   },
 
   bucketAggrs: [],
   reset: function() {
     this.bucketAggrs = [];
+
+    this.curBucket = null;
+    this.curBucketAggr = null;
+    this.curBucketCount = 0;
   },
 
   chew: function() {
     let didSomething = false;
 
     if (this.curBucket && this.curBucket.length != this.curBucketCount) {
       didSomething = true;
       this._chewBucket(this.curBucket, this.curBucketAggr);
@@ -47,8 +55,9 @@ let LogAggr = {
         this.curBucketAggr = bucketAggr;
         this.curBucketCount = bucket.length;
       }
     }
 
     return didSomething;
   }
 };
+LogAggr._init();
--- a/chrome/content/logman.js
+++ b/chrome/content/logman.js
@@ -51,23 +51,28 @@ let LogManager = {
       return this._dateBuckets[bucketName];
     return null;
   },
 
   /**
    * Reset all state
    */
   reset: function LogManager_reset() {
+    dump("LogManager resetting...\n");
+
     this._knownLoggers = {};
 
     this._dateBuckets = {};
+    this._firstBucketName = null;
     this._curBucket = null;
     this._curBucketName = null;
 
     this._newBuckets = [];
+
+    this._notifyListeners("onReset", []);
   },
 
   /**
    * Handle the existence of a previously unknown named logged.
    */
   _noteNewLogger: function LogManager__noteNewLogger(loggerName) {
     this._knownLoggers[loggerName] = {};
     this._notifyListeners("onNewLogger", [this._knownLoggers, loggerName]);
@@ -103,17 +108,24 @@ let LogManager = {
   _listenersByListeningFor: {},
 
   _notifyListeners: function LogManager__notifyListeners(listeningFor, args) {
     if (!(listeningFor in this._listenersByListeningFor))
       return;
 
     for each (let [, [listener, listenerThis]] in
               Iterator(this._listenersByListeningFor[listeningFor])) {
-      listener.apply(listenerThis, args);
+      try {
+        listener.apply(listenerThis, args);
+      }
+      catch (ex) {
+        dump("!!! exception calling listener " + listener + "\n");
+        dump(ex + "\n");
+        dump(ex.stack + "\n\n");
+      }
     }
   },
 
   registerListener: function LogManager_registerListener(listenFor, listener,
                                                          listenerThis) {
     if (!(listenFor in this._listenersByListeningFor))
       this._listenersByListeningFor[listenFor] = [];
 
--- a/chrome/content/logui.js
+++ b/chrome/content/logui.js
@@ -12,20 +12,22 @@ let LogUI = {
 
   /**
    * Select a bucket and make it current.
    *
    * @param bucketAggr A bucket aggregation as provided by LogAggr.
    */
   selectBucket: function LogUI_showBucket(bucketAggr) {
     this._notifyListeners("onBucketSelected", arguments);
+    $("#data-tabs").tabs("select", "bucket-contents");
   },
 
   showDetail: function LogUI_showDetail(obj, clickOrigin) {
     this._notifyListeners("onShowDetail", arguments);
+    $("#data-tabs").tabs("select", "detail-view");
   },
 
   /**
    * Maps a listeningFor identifier to a list of listeners.
    */
   _listenersByListeningFor: {},
 
   _notifyListeners: function LogManager__notifyListeners(listeningFor, args) {
--- a/chrome/content/logviewer.css
+++ b/chrome/content/logviewer.css
@@ -1,12 +1,17 @@
 body {
+  font-size: 80%;
 }
 
-a {
-  color: #444488;
+.clicky {
+  text-decoration: underline;
   cursor: pointer;
   font-weight: 500;
 }
 
 #bucket-contents {
   overflow: auto;
 }
+
+dt {
+  font-weight: bold;
+}
--- a/chrome/content/logviewer.xhtml
+++ b/chrome/content/logviewer.xhtml
@@ -36,14 +36,22 @@
     <div id="visualizations" style="display: inline-block">
       <div id="logger-hierarchy-vis" style="float: left;"/>
       <div id="date-bucket-vis" style="float: left;"/>
     </div>
     <div id="data-tabs">
       <ul>
         <li><a href="#bucket-contents">Log Contents</a></li>
         <li><a href="#detail-view">Detail View</a></li>
+        <li><a href="#controls">Controls</a></li>
       </ul>
       <div id="bucket-contents"/>
       <div id="detail-view"/>
+      <div id="controls">
+        <ul>
+          <li class="clicky" onclick="LogManager.reset();">
+            Reset: Clear Everything
+          </li>
+        </ul>
+      </div>
     </div>
   </body>
 </html>
--- a/chrome/content/logvis.js
+++ b/chrome/content/logvis.js
@@ -13,16 +13,22 @@ function makeTimeVis(aWidth, aHeight) {
 
 }
 
 let LoggerHierarchyVisier = {
   WIDTH: 360,
   HEIGHT: 360,
   _init: function LoggerHierarchyVisier_init() {
     LogManager.registerListener("onNewLogger", this.onNewLogger, this);
+    LogManager.registerListener("onReset", this._onReset, this);
+  },
+
+  _onReset: function LoggerHierarchyVisier__onReset() {
+    this.loggerTree = [];
+    this._updateVis();
   },
 
   /**
    * Map loggers to their colors.  We do this as a side-effect of building and
    *  updating the treemap.
    */
   loggersToColors: {},
 
@@ -34,17 +40,17 @@ let LoggerHierarchyVisier = {
       .width(this.WIDTH)
       .height(this.HEIGHT);
 
     //let colorize = pv.Colors.category20().by(function(n) n.keys);
     let colorize = function(s, n) {
       let loggerName = n.keys.join(".");
       let hue = 360 * s.index / s.scene.length;
       let mapColor = new pv.Color.Hsl(hue, 1, 0.8, 1);
-      let textColor = new pv.Color.Hsl(hue, 1, 0.5, 1);
+      let textColor = new pv.Color.Hsl(hue, 1, 0.3, 1);
       LoggerHierarchyVisier.loggersToColors[loggerName] = textColor.color;
       return mapColor;
     };
 
     this._treemap = pv.Layout.treemap(this.loggerTree)
       //.inset(17, 1, 1, 1)
       .round(true);
 
@@ -83,16 +89,26 @@ let LoggerHierarchyVisier = {
     this._updateVis();
   },
 };
 LoggerHierarchyVisier._init();
 
 
 
 let DateBucketVis = {
+  _init: function DateBucketVis__init() {
+    this._updateRequired = true;
+    LogManager.registerListener("onReset", this._onReset, this);
+  },
+
+  _onReset: function DateBucketVis__onReset() {
+    this._updateRequired = true;
+    this.updateVis();
+  },
+
   WIDTH: 610,
   HEIGHT: 366,
   CELL_WIDTH: 61,
   CELL_HEIGHT: 61,
   _vis: null,
   _makeVis: function DateBucketVis__makeVis() {
     let vis = this._vis = new pv.Panel()
       .canvas("date-bucket-vis")
@@ -131,24 +147,24 @@ let DateBucketVis = {
       .event("click", function(d) LogUI.selectBucket(d));
     this._mapvis = cell.add(pv.Bar)
       .extend(this._treemap)
       .fillStyle(function(n) colorize(this, n));
 
   },
   updateVis: function DateBucketVis__updateVis() {
     // don't do anything if nothing changed.
-    if(!LogAggr.chew())
+    if(!LogAggr.chew() && !this._updateRequired)
       return;
+
     this.buckets = LogAggr.bucketAggrs;
 
-    if (this.buckets.length == 0)
+    if ((this.buckets.length == 0) && !this._updateRequired)
       return;
-
-    dump(this.buckets.length + " buckets\n");
+    this._updateRequired = false;
 
     if (this._vis == null)
       this._makeVis();
     else {
       this._treemap = pv.Layout.treemap(LoggerHierarchyVisier.loggerTree)
         .round(true);
       this._mapvis.extend(this._treemap);
     }