Author: clopes
Date: 2011-07-29 13:10:21 -0700 (Fri, 29 Jul 2011)
New Revision: 26337
Modified:
cytoscapeweb/trunk/cytoscapeweb/html-template/fixtures/test1.graphml
cytoscapeweb/trunk/cytoscapeweb/html-template/js/tests.js
cytoscapeweb/trunk/cytoscapeweb/src/org/cytoscapeweb/model/converters/SVGExporter.as
cytoscapeweb/trunk/cytoscapeweb/src/org/cytoscapeweb/util/ErrorCodes.as
cytoscapeweb/trunk/cytoscapeweb/src/org/cytoscapeweb/view/render/Labeler.as
Log:
Fixed #2498: PDF and SVG: Line breaks in labels (SVG only!)
Improved label alignment--automatic text justification for each horizontal
anchor.
Updated JS tests.
Modified: cytoscapeweb/trunk/cytoscapeweb/html-template/fixtures/test1.graphml
===================================================================
--- cytoscapeweb/trunk/cytoscapeweb/html-template/fixtures/test1.graphml
2011-07-29 20:04:37 UTC (rev 26336)
+++ cytoscapeweb/trunk/cytoscapeweb/html-template/fixtures/test1.graphml
2011-07-29 20:10:21 UTC (rev 26337)
@@ -1,9 +1,10 @@
<graphml>
+ <key id="label" for="all" attr.name="label" attr.type="string"/>
+
<key id="weight" for="node" attr.name="weight" attr.type="double"/>
<key id="ranking" for="node" attr.name="ranking" attr.type="int"/>
<key id="type" for="node" attr.name="type" attr.type="string"/>
<key id="shape" for="node" attr.name="shape" attr.type="string"/>
- <key id="label" for="node" attr.name="label" attr.type="string"/>
<key id="special" for="node" attr.name="special" attr.type="boolean"/>
<key id="type" for="edge" attr.name="type" attr.type="string"/>
@@ -18,7 +19,7 @@
<node id="1">
<data key="weight">0.45</data>
<data key="ranking">1</data>
- <data key="label">n1</data>
+ <data key="label">n1
TEST LINE BREAK</data>
<data key="type">1</data>
<data key="shape">ELLIPSE</data>
<data key="special">false</data>
Modified: cytoscapeweb/trunk/cytoscapeweb/html-template/js/tests.js
===================================================================
--- cytoscapeweb/trunk/cytoscapeweb/html-template/js/tests.js 2011-07-29
20:04:37 UTC (rev 26336)
+++ cytoscapeweb/trunk/cytoscapeweb/html-template/js/tests.js 2011-07-29
20:10:21 UTC (rev 26337)
@@ -151,6 +151,12 @@
function runGraphTests(moduleName, vis, options) {
module(moduleName);
+ var _errId;
+ var _onError = function(evt) {
+ _errId = evt.value.id;
+ }
+ vis.addListener("error", _onError);
+
test("Initialization Parameters", function() {
same(vis.panZoomControlVisible(), options.panZoomControlVisible,
"Pan-zoom control visible?");
same(vis.nodeLabelsVisible(), options.nodeLabelsVisible, "Node
Labels visible?");
@@ -1037,13 +1043,12 @@
var ids = [];
// 1: Update all nodes and edges (same data):
- var data = { weight: 1/*, new_attr: "ignore it!"*/ };
+ var data = { weight: 1 };
vis.updateData(data);
all = vis.nodes().concat(vis.edges());
$.each(all, function(i, el) {
same(el.data.weight, 1, "weight updated ("+el.data.id+")");
-// same(el.data.new_attr, undefined, "New attribute ignored
("+el.data.id+")");
});
// 2: Update more than one node and edge at once (by ID - ALL groups -
same data):
@@ -1133,23 +1138,16 @@
ok(vis.node(id).data.weight === null, "Node weight should be null");
// Test Errors:
- var errId;
- var onError = function(evt) {
- errId = evt.value.id;
- }
- vis.addListener("error", onError);
- // 7: Update a field with type 'int' to null (should set 0 as default):
+ // 7: Update a field with type 'int' to null => ERROR:
vis.updateData("nodes", [id], { ranking: null });
- same(errId, "dat001", "node.data.ranking (error: int type with null
value)");
- errId = null;
+ same(_errId, "dat001", "node.data.ranking (error: int type with null
value)");
+ _errId = null;
- // 8: Update a field with type 'boolean' to null (should set false as
default):
+ // 8: Update a field with type 'boolean' to null => ERROR:
vis.updateData("nodes", [id], { special: null });
- same(errId, "dat001", "node.data.special (error: boolean type with
null value)");
- errId = null;
-
- vis.removeListener("error", onError);
+ same(_errId, "dat001", "node.data.special (error: boolean type with
null value)");
+ _errId = null;
});
test("Get Data Schema", function() {
@@ -1367,7 +1365,7 @@
var base64 = vis.pdf();
var beginning =
"JVBERi0xLjUKMSAwIG9iago8PC9UeXBlIC9QYWdlcwovS2lkcyBbMyAwIFJdCi9Db3VudCAxPj4K";
- ok(base64.length > 13000, "PDF string has compatible length
("+base64.length+")");
+ ok(base64.length > 9000, "PDF string has compatible length
("+base64.length+")");
same(base64.indexOf(beginning), 0, "PDF begins with correct chars");
});
Modified:
cytoscapeweb/trunk/cytoscapeweb/src/org/cytoscapeweb/model/converters/SVGExporter.as
===================================================================
---
cytoscapeweb/trunk/cytoscapeweb/src/org/cytoscapeweb/model/converters/SVGExporter.as
2011-07-29 20:04:37 UTC (rev 26336)
+++
cytoscapeweb/trunk/cytoscapeweb/src/org/cytoscapeweb/model/converters/SVGExporter.as
2011-07-29 20:10:21 UTC (rev 26337)
@@ -43,6 +43,7 @@
import flash.geom.Point;
import flash.geom.Rectangle;
import flash.text.TextField;
+ import flash.text.TextFormatAlign;
import flash.utils.ByteArray;
import mx.graphics.codec.PNGEncoder;
@@ -368,14 +369,17 @@
var lblSize:int = Math.round(lbl.size*_scale);
if (text == null || text === "" || lblSize < 1) continue;
+
var field:TextField = lbl.textField;
+ var lines:Array = text.split("\r");
// ATTENTION!!!
// It seems that Flash does not convert points to pixels
correctly.
// See: - http://alarmingdevelopment.org/?p=66
// -
http://www.actionscript.org/forums/showthread.php3?p=821842
// I found out that the text height is usually 28% smaller
than the label size.
- var textHeight:Number = lbl.size * 0.72;
+ var textHeight:Number = lbl.size * 0.72 * _scale;
+ textHeight *= 1.5; // vertical spacing between lines
var textWidth:Number = field.textWidth;
// Get the Global label point (relative to the stage):
@@ -390,23 +394,27 @@
var hpad:Number = 2;
switch (hAnchor) {
- case Anchors.LEFT: p.x += hpad * _scale; break;
- case Anchors.CENTER: p.x -= (textWidth/2)*_scale;
break;
- case Anchors.RIGHT: p.x -= (textWidth + hpad)*_scale;
break;
+ case Anchors.LEFT: p.x += (hpad * _scale); break;
+ case Anchors.RIGHT: p.x -= (hpad * _scale); break;
}
// Vertical anchor:
// The label height is different from the real text
height, because
// there is a margin between the text and the text field
border:
var vpad:Number = 2;
+
switch (vAnchor) {
- case Anchors.TOP: p.y += (field.height -
textHeight)/2 * _scale; break;
- case Anchors.MIDDLE: p.y -= textHeight/2 * _scale;
break;
- case Anchors.BOTTOM: p.y -= (vpad + textHeight) *
_scale; break;
+ case Anchors.TOP:
+ p.y -= textHeight/2;
+ p.y += ( textHeight/4 + vpad );
+ break;
+ case Anchors.MIDDLE:
+ p.y -= ( (textHeight/2) * lines.length );
+ p.y -= textHeight/6;
+ break;
+ case Anchors.BOTTOM:
+ p.y -= ( (textHeight * lines.length) + vpad );
+ break;
}
-
- // Flare's label cordinates is relative to the label's
upper-left corner (x,y)=(0,0),
- // but AlivePDF uses the bottom-left corner instead
(x,y)=(0,fonSize):
- p.y += textHeight*_scale;
var style:String = lbl.italic ? 'italic': 'normal';
var weight:String = lbl.bold ? 'bold' : 'normal';
@@ -418,10 +426,22 @@
else if (family == Fonts.TYPEWRITER) family = 'courier';
var c:String = Utils.rgbColorAsString(lbl.color);
- var a:Number = lbl.alpha;
+ var a:Number = d.alpha;
+ var ta:String = getTextAnchor(lbl);
+
+ svg += '<text font-family="'+family+'"
font-style="'+style+'" font-weight="'+weight+'" stroke="none" fill="'+c+'"' +
+ ' fill-opacity="'+a+'" font-size="'+lblSize+'"
x="'+p.x+'" y="'+p.y+'" style="text-anchor:'+ta+';">';
- svg += '<text font-family="'+family+'"
font-style="'+style+'" font-weight="'+weight+'" stroke="none" fill="'+c+'"' +
- ' fill-opacity="'+a+'" font-size="'+lblSize+'"
x="'+p.x+'" y="'+p.y+'">' + text+ '</text>';
+ if (lines.length > 0) {
+ for (var i:int = 0; i < lines.length; i++) {
+ var ln:String = lines[i];
+ svg += '<tspan style="text-anchor:'+ta+';"
x="'+p.x+'" dy="'+textHeight+'">'+ln+'</tspan>';
+ }
+ } else {
+ svg += text;
+ }
+
+ svg += '</text>';
}
}
@@ -610,5 +630,14 @@
return pageEdge / graphEdge;
}
+
+ private function getTextAnchor(lbl:TextSprite):String {
+ var ta:String = 'middle';
+
+ if (lbl.textFormat.align === TextFormatAlign.LEFT) ta = 'start';
+ else if (lbl.textFormat.align === TextFormatAlign.RIGHT) ta =
'end';
+
+ return ta;
+ }
}
}
\ No newline at end of file
Modified:
cytoscapeweb/trunk/cytoscapeweb/src/org/cytoscapeweb/util/ErrorCodes.as
===================================================================
--- cytoscapeweb/trunk/cytoscapeweb/src/org/cytoscapeweb/util/ErrorCodes.as
2011-07-29 20:04:37 UTC (rev 26336)
+++ cytoscapeweb/trunk/cytoscapeweb/src/org/cytoscapeweb/util/ErrorCodes.as
2011-07-29 20:10:21 UTC (rev 26337)
@@ -37,6 +37,7 @@
// ========[ CONSTANTS
]====================================================================
public static const INVALID_DATA_CONVERSION:String = "dat001";
+ public static const MISSING_DATA_FIELD:String = "dat002";
public static const BROKEN_IMAGE:String = "img001";
// ========[ CONSTRUCTOR
]==================================================================
Modified:
cytoscapeweb/trunk/cytoscapeweb/src/org/cytoscapeweb/view/render/Labeler.as
===================================================================
--- cytoscapeweb/trunk/cytoscapeweb/src/org/cytoscapeweb/view/render/Labeler.as
2011-07-29 20:04:37 UTC (rev 26336)
+++ cytoscapeweb/trunk/cytoscapeweb/src/org/cytoscapeweb/view/render/Labeler.as
2011-07-29 20:10:21 UTC (rev 26337)
@@ -43,6 +43,7 @@
import flash.events.Event;
import flash.geom.Point;
import flash.text.TextFormat;
+ import flash.text.TextFormatAlign;
import org.cytoscapeweb.util.Utils;
import org.cytoscapeweb.util.methods.$each;
@@ -138,8 +139,7 @@
label.text = getLabelText(d);
label.visible = visible;
- updateTextFormat(d);
- label.applyFormat(textFormat);
+ updateLabel(d, label);
_access.setValue(d, label);
if (_policy == LAYER) {
@@ -158,18 +158,9 @@
}
} else if (label && !cacheText) {
label.text = getLabelText(d);
-
- updateTextFormat(d);
- label.applyFormat(textFormat);
+ updateLabel(d, label);
}
- label.textMode = textMode;
- label.horizontalAnchor = horizontalAnchor;
- label.verticalAnchor = verticalAnchor;
-
- if (hAnchor != null) label.horizontalAnchor = hAnchor(d);
- if (vAnchor != null) label.verticalAnchor = vAnchor(d);
-
return label;
}
@@ -226,12 +217,28 @@
label.render();
}
- protected function updateTextFormat(d:DataSprite):void {
+ protected function updateLabel(d:DataSprite, label:TextSprite):void {
+ label.textMode = textMode;
+ label.horizontalAnchor = horizontalAnchor;
+ label.verticalAnchor = verticalAnchor;
+
+ if (hAnchor != null) label.horizontalAnchor = hAnchor(d);
+ if (vAnchor != null) label.verticalAnchor = vAnchor(d);
+
if (fontName != null) textFormat.font = fontName(d);
if (fontColor != null) textFormat.color = fontColor(d);
if (fontSize != null) textFormat.size = fontSize(d);
if (fontWeight != null) textFormat.bold = (fontWeight(d) ===
"bold");
if (fontStyle != null) textFormat.italic = (fontStyle(d) ===
"italic");
+
+ if (label.horizontalAnchor === TextSprite.CENTER)
+ textFormat.align = TextFormatAlign.CENTER;
+ if (label.horizontalAnchor === TextSprite.RIGHT)
+ textFormat.align = TextFormatAlign.RIGHT;
+ if (label.horizontalAnchor === TextSprite.LEFT)
+ textFormat.align = TextFormatAlign.LEFT;
+
+ label.applyFormat(textFormat);
}
// ========[ PRIVATE METHODS
]==============================================================
--
You received this message because you are subscribed to the Google Groups
"cytoscape-cvs" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to
[email protected].
For more options, visit this group at
http://groups.google.com/group/cytoscape-cvs?hl=en.