diff --git a/flare/src/flare/util/Shapes.as b/flare/src/flare/util/Shapes.as index 06873d6..1ec4853 100644 --- a/flare/src/flare/util/Shapes.as +++ b/flare/src/flare/util/Shapes.as @@ -29,6 +29,8 @@ package flare.util /** Constant indicating a B-spline. */ public static const BSPLINE:String = "bspline"; + /** Constant indicating a new rectangular block shape. */ + public static const TREEMAPBLOCK:String = "treemapblock"; /** Constant indicating a rectangular block shape. */ public static const BLOCK:String = "block"; /** Constant indicating a polygon shape. */ diff --git a/flare/src/flare/vis/data/render/ShapeRenderer.as b/flare/src/flare/vis/data/render/ShapeRenderer.as index 9a926a2..63d1b09 100644 --- a/flare/src/flare/vis/data/render/ShapeRenderer.as +++ b/flare/src/flare/vis/data/render/ShapeRenderer.as @@ -4,6 +4,7 @@ package flare.vis.data.render import flare.vis.data.DataSprite; import flash.display.Graphics; + import flash.display.JointStyle; /** * Renderer that draws shapes. The ShapeRender uses a ShapePalette instance @@ -34,6 +35,8 @@ package flare.vis.data.render { var lineAlpha:Number = d.lineAlpha; var fillAlpha:Number = d.fillAlpha; + var lineColor:Number = d.lineColor; + var fillColor:Number = d.fillColor; var size:Number = d.size * defaultSize; var g:Graphics = d.graphics; @@ -45,8 +48,33 @@ package flare.vis.data.render switch (d.shape) { case null: break; + + case Shapes.TREEMAPBLOCK: + // This draws a rectangle inside of a rectangle. + // This serves as a replacement for Shapes.BLOCK + // This behaves in an identical fashion to the original flash line border + // in that the borders are drawn on the outside of the shape. + // Shapes are scaled down by the amount of the linewidth area in the + // treemap layout to achieve smooth treemap nirvana. + g.lineStyle(0.0, 0, 0); + if (lineColor == 0xffffff && lineAlpha == 1.0) { + g.beginFill(lineColor, 0.99); + } else { + g.beginFill(lineColor, lineAlpha); + } + g.drawRect(d.u-d.x-d.lineWidth/2, d.v-d.y-d.lineWidth/2, d.w+d.lineWidth, d.h+d.lineWidth); + // Rectangles with a white (0xffffffff) fill are rendered as transparent in flash graphics. + // We slightly decrease the alpha in these cases to avoid errors. + if (fillColor == 0xffffff && fillAlpha == 1.0) { + g.beginFill(fillColor, 0.99); + } else { + g.beginFill(fillColor, fillAlpha); + } + g.drawRect(d.u-d.x, d.v-d.y, d.w, d.h); + break; + case Shapes.BLOCK: - g.drawRect(d.u-d.x, d.v-d.y, d.w, d.h); + g.drawRect(d.u-d.x, d.v-d.y, d.w, d.h); break; case Shapes.POLYGON: if (d.points!=null) diff --git a/flare/src/flare/vis/operator/layout/TreeMapLayout.as b/flare/src/flare/vis/operator/layout/TreeMapLayout.as index 23f90d1..1dec392 100644 --- a/flare/src/flare/vis/operator/layout/TreeMapLayout.as +++ b/flare/src/flare/vis/operator/layout/TreeMapLayout.as @@ -1,6 +1,5 @@ package flare.vis.operator.layout { - import flare.animate.Transitioner; import flare.util.Property; import flare.vis.data.NodeSprite; @@ -38,6 +37,8 @@ package flare.vis.operator.layout private var _row:Array = new Array(); private var _r:Rectangle = new Rectangle(); + private var treemapScale:Number; + private var _size:Property = Property.$("size"); /** The property from which to access size values for leaf nodes. */ @@ -68,8 +69,8 @@ package flare.vis.operator.layout // layout root node var o:Object = _t.$(root); - o.x = 0;//_r.x + _r.width/2; - o.y = 0;//_r.y + _r.height/2; + o.x = 0; + o.y = 0; o.u = _r.x; o.v = _r.y; o.w = _r.width; @@ -110,6 +111,7 @@ package flare.vis.operator.layout const rootArea:Number = root.props[AREA]; if (!isNaN(rootArea) && rootArea !== 0) { const scale:Number = area / rootArea; + treemapScale = scale; root.visitTreeDepthFirst(function(n:NodeSprite):void { n.props[AREA] *= scale; }); @@ -123,7 +125,9 @@ package flare.vis.operator.layout { // create sorted list of children's properties for (var i:uint = 0; i < p.childDegree; ++i) { - _kids.push(p.getChildNode(i).props); + var c:NodeSprite = p.getChildNode(i); + c.props[AREA] *= (r.height*r.width/(treemapScale * _size.getValue(_t.$(p)))); + _kids.push(c.props); } _kids.sortOn(AREA, Array.NUMERIC); // update array to point to sprites, not props @@ -138,21 +142,26 @@ package flare.vis.operator.layout // recurse for (i=0; i 0) { - updateArea(c, r); + doLayout(c, r); } } } + /** + * Compute areas and adjust for the width of the frames. + */ private function updateArea(n:NodeSprite, r:Rectangle):void { var o:Object = _t.$(n); - r.x = o.u; - r.y = o.v; - r.width = o.w; - r.height = o.h; + r.x = o.u = o.w > n.lineWidth ? o.u + n.lineWidth/2: o.u; + r.y = o.v = o.v > n.lineWidth ? o.v + n.lineWidth/2: o.v; + r.width = o.w = o.w > n.lineWidth ? o.w - n.lineWidth : 0; + r.height = o.h = o.h > n.lineWidth ? o.h - n.lineWidth : 0; + return; /* @@ -198,9 +207,14 @@ package flare.vis.operator.layout var item:NodeSprite = c[len-1]; var a:Number = item.props[AREA]; if (a <= 0.0) { + var o:Object = _t.$(item); + item.visible=false; c.pop(); continue; } + else { + item.visible=true; + } row.push(item); nworst = getWorst(row, w);