diff options
Diffstat (limited to 'js/dojo/dojox/drawing/util')
| -rw-r--r-- | js/dojo/dojox/drawing/util/common.js | 284 | ||||
| -rw-r--r-- | js/dojo/dojox/drawing/util/oo.js | 126 | ||||
| -rw-r--r-- | js/dojo/dojox/drawing/util/positioning.js | 69 | ||||
| -rw-r--r-- | js/dojo/dojox/drawing/util/typeset.js | 72 |
4 files changed, 551 insertions, 0 deletions
diff --git a/js/dojo/dojox/drawing/util/common.js b/js/dojo/dojox/drawing/util/common.js new file mode 100644 index 0000000..af740a0 --- /dev/null +++ b/js/dojo/dojox/drawing/util/common.js @@ -0,0 +1,284 @@ +//>>built +// wrapped by build app +define("dojox/drawing/util/common", ["dijit","dojo","dojox","dojo/require!dojox/math/round"], function(dijit,dojo,dojox){ +dojo.provide("dojox.drawing.util.common"); +dojo.require("dojox.math.round"); + +(function(){ + + var uidMap = {}; + var start = 0; + dojox.drawing.util.common = { + // summary: + // A collection of common methods used for DojoX Drawing. + // This singleton is accessible in most Drawing classes + // as this.util + // + // NOTE: + // A lot of functions use a EventObject + // as an argument. An attempt was made to accept + // either that object or a list of numbers. That wasn't + // finished (it didn't work well in all cases) but is + // likely to happen in the future. + // In cases where you are not sending a Mouse object, + // form your argument like so: + // var obj = { + // start:{ + // x:Number, // start x + // y:Number // start y + // }, + // x: Number, // end x + // y:Number // end y + // } + // + // + radToDeg: function(/*Numer*/n){ + // summary: + // Convert the passed number to degrees. + return (n*180)/Math.PI; // Number + }, + + degToRad: function(/*Numer*/n){ + // summary: + // Convert the passed number to radians. + return (n*Math.PI)/180; // Number + }, + + angle: function(/*EventObject*/obj, /* ? Float */snap){ + // summary: + // Return angle based on mouse object + // arguments: + // obj: EventObject + // Manager.Mouse event. + // snap: Float + // Returns nearest angle within snap limits + // + //obj = this.argsToObj.apply(this, arguments); + if(snap){ + snap = snap/180; + var radians = this.radians(obj), + seg = Math.PI * snap, + rnd = dojox.math.round(radians/seg), + new_radian = rnd*seg; + return dojox.math.round(this.radToDeg(new_radian)); // Whole Number + + }else{ + return this.radToDeg(this.radians(obj)); // Float + } + }, + + oppAngle: function(/*Angle*/ang){ + (ang+=180) > 360 ? ang = ang - 360 : ang; + return ang; + }, + + radians: function(/*EventObject*/o){ + // summary: + // Return the radians derived from the coordinates + // in the Mouse object. + // + //var o = this.argsToObj.apply(this, arguments); + return Math.atan2(o.start.y-o.y,o.x-o.start.x); + }, + + length: function(/*EventObject*/o){ + // summary: + // Return the length derived from the coordinates + // in the Mouse object. + // + return Math.sqrt(Math.pow(o.start.x-o.x, 2)+Math.pow(o.start.y-o.y, 2)); + }, + + lineSub: function(/*Number*/x1, /*Number*/y1, /*Number*/x2, /*Number*/y2, /*Number*/amt){ + // summary: + // Subtract an amount from a line + // description: + // x1,y1,x2,y2 represents the Line. 'amt' represents the amount + // to subtract from it. + // + var len = this.distance(this.argsToObj.apply(this, arguments)); + len = len < amt ? amt : len; + var pc = (len-amt)/len; + var x = x1 - (x1-x2) * pc; + var y = y1 - (y1-y2) * pc; + return {x:x, y:y}; // Object + }, + + argsToObj: function(){ + // summary: + // Attempts to determine in a Mouse Object + // was passed or indiviual numbers. Returns + // an object. + // + var a = arguments; + if(a.length < 4){ return a[0]; } + return { + start:{ + x:a[0], + y:a[1] + }, + x:a[2], + y:a[3]//, + //snap:a[4] + }; // Object + }, + + distance: function(/*EventObject or x1,y1,x2,y2*/){ + // summary: + // Return the length derived from the coordinates + // in the Mouse object. Different from util.length + // in that this always returns an absolute value. + // + var o = this.argsToObj.apply(this, arguments); + return Math.abs(Math.sqrt(Math.pow(o.start.x-o.x, 2)+Math.pow(o.start.y-o.y, 2))); // Number + }, + + slope:function(/*Object*/p1, /*Object*/p2){ + // summary: + // Given two poits of a line, returns the slope. + if(!(p1.x-p2.x)){ return 0; } + return ((p1.y-p2.y)/(p1.x-p2.x)); // Number + }, + + pointOnCircle: function(/*Number*/cx, /*Number*/cy, /*Number*/radius, /*Number*/angle){ + // summary: + // A *very* helpful method. If you know the center + // (or starting) point, length and angle, find the + // x,y point at the end of that line. + // + var radians = angle * Math.PI / 180.0; + var x = radius * Math.cos(radians); + var y = radius * Math.sin(radians); + return { + x:cx+x, + y:cy-y + }; // Object + }, + + constrainAngle: function(/*EventObject*/obj, /*Number*/min, /*Number*/max){ + // summary: + // Ensures the angle in the Mouse Object is within the + // min and max limits. If not one of those limits is used. + // Returns an x,y point for the angle used. + // + var angle = this.angle(obj); + if(angle >= min && angle <= max){ + return obj; // Object + } + var radius = this.length(obj); + var new_angle = angle > max ? max : min - angle < 100 ? min : max; + return this.pointOnCircle(obj.start.x,obj.start.y,radius, new_angle); // Object + }, + + snapAngle: function(/*EventObject*/obj, /*Float*/ca){ + // summary: + // Snaps a line to the nearest angle + // obj: Mouse object (see dojox.drawing.Mouse) + // ca: Fractional amount to snap to + // A decimal number fraction of a half circle + // .5 would snap to 90 degrees + // .25 would snap to 45 degrees + // .125 would snap to 22.5 degrees, etc. + // + var radians = this.radians(obj), + radius = this.length(obj), + seg = Math.PI * ca, + rnd = Math.round(radians/seg), + new_radian = rnd*seg, + new_angle = this.radToDeg(new_radian), + pt = this.pointOnCircle(obj.start.x,obj.start.y,radius,new_angle); + return pt; // Object + }, + + // helpers + idSetStart: function(num){ + start=num; + }, + + uid: function(/* ? String */str){ + // summary: + // Creates a unique ID. + // arguments: + // str: String + // If provided, kept in a map, incremented + // and used in the id. Otherwise 'shape' is used. + // + str = str || "shape"; + uidMap[str] = uidMap[str]===undefined ? start : uidMap[str] + 1; + return str + uidMap[str]; // String + }, + + abbr: function(type){ + // summary: + // Converts a namespace (typically a tool or a stencil) into + // an abbreviation + return type.substring(type.lastIndexOf(".")+1).charAt(0).toLowerCase() + + type.substring(type.lastIndexOf(".")+2); + }, + mixin: function(o1, o2){ + // TODO: make faster + //return dojo.mixin(dojo.clone(o1), dojo.clone(o2)); + }, + + objects:{}, //private? + register: function(/*Object*/obj){ + // summary: + // Since util is the only Singleton in Drawing (besides + // keys) it is used to help connect the Drawing object + // the Toolbar. Since multiple drawings can be on one + // page, this function serves a little more use than + // on first apearance. + this.objects[obj.id] = obj; + }, + byId: function(/*String*/id){ + // summary: + // Get an object that was registered with util.register + // + return this.objects[id]; + }, + attr: function(/* Object */ elem, /* property */ prop, /* ? value */ value, squelchErrors){ + // summary: + // Helper function to attach attributes to SVG and VML raw nodes. + // + + if(!elem){ return false; } + try{ + + // util is a crappy check, but we need to tell the diff + // between a Drawing shape and a GFX shape + if(elem.shape && elem.util){ + elem = elem.shape; + } + + if(!value && prop=="id" && elem.target){ + + var n = elem.target; + while(!dojo.attr(n, "id")){ + n = n.parentNode; + } + return dojo.attr(n, "id"); + } + + if(elem.rawNode || elem.target){ + var args = Array.prototype.slice.call(arguments); + args[0] = elem.rawNode || elem.target; + return dojo.attr.apply(dojo, args); + } + return dojo.attr(elem, "id"); + + + + }catch(e){ + if(!squelchErrors){ + // For debugging only. These errors actually cause errors in IE's console + //console.error("BAD ATTR: prop:", prop, "el:", elem) + //console.error(e) + //console.trace(); + } + return false; + } + } + }; + +})(); +}); diff --git a/js/dojo/dojox/drawing/util/oo.js b/js/dojo/dojox/drawing/util/oo.js new file mode 100644 index 0000000..33048f9 --- /dev/null +++ b/js/dojo/dojox/drawing/util/oo.js @@ -0,0 +1,126 @@ +//>>built +// wrapped by build app +define("dojox/drawing/util/oo", ["dijit","dojo","dojox"], function(dijit,dojo,dojox){ +dojo.provide("dojox.drawing.util.oo"); + +// TODO: +// allow a declare without a mixin + +dojox.drawing.util.oo = { + // summary: + // Inheritance utilities used in DojoX Drawing + // description: + // Inheritance utilities used in DojoX Drawing. + // There were designed in a effort to make Drawing as + // fast as possible - especially in a case where thousands + // of objects are being loaded. Drawing declare performs + // about 3 times faster than Dojo declare and 2 times + // faster than Dojox declare. This is not to say Drawing + // declare is wthout limitations. It doesn't have the same + // syntatic sugar and extensibility of the other two. You + // can't inhert methods. It won't work with Dijit. But it + // is simple and effective. + // + declare: function(){ + // summary: + // Creates a constructor Function from a + // Function, and collection of methods, and + // more Functions that are extended. + // description: + // Similar in look and feel to Dojo declare as + // far as order and number of arguments, although + // constructed a little closer to prototypical + // inheritance. All arguments passed into the + // constructor are passed into all sub constructors. + // arguments: + // Function, [Object|Function....] + // The first argument is always the base + // constructor. The last argument is always + // an object of methods (or empty object) to + // be mixed in (in the future would like to + // make that object optional). Remaining + // arguments are other constructors mixed in + // using extend() (See below). + // example: + // | MyFunction = dojox.drawing.util.oo.declare( + // | MyOtherFunction, + // | YetAnotherFunction, + // | function(options){ + // | // This is my constructor. It will fire last. + // | // The other constructors will fire before this. + // | }, + // | { + // | customType:"equation", // mixed in property + // | doThing: function(){ // mixed in method + // | + // | } + // | } + // | ); + // | + // | var f = new MyFunction(); + // + var f, o, ext=0, a = arguments; + + if(a.length<2){ console.error("drawing.util.oo.declare; not enough arguments")} + if(a.length==2){ + f = a[0]; o = a[1]; + }else{ + a = Array.prototype.slice.call(arguments); + o = a.pop(); + f = a.pop(); + ext = 1; + } + for(var n in o){ + f.prototype[n] = o[n]; + } + if(ext){ + a.unshift(f); + f = this.extend.apply(this, a); + } + return f; // Function + }, + extend: function(){ + // summary: + // Extends constructors to inherit from other + // constructors . + // description: + // Typically not used by itself - it's used as + // part of declare(). Could be used by itself + // however, to mix together two or more + // constructors. + // arguments: + // Function, [ Function...] + // Any number of arguments, all must be + // function constructors. The first is + // considered the base object and its + // constructor will fire first. + // example: + // | var A = function(){}; + // | var B = function(){}; + // | var C = function(){}; + // | var D = dojox.drawing.util.oo.extend(A, B, C); + // | var e = new D(); + // + var a = arguments, sub = a[0]; + if(a.length<2){ console.error("drawing.util.oo.extend; not enough arguments")} + var f = function (){ + for(var i=1;i<a.length;i++){ + a[i].prototype.constructor.apply(this, arguments); + } + // sub should fire last + sub.prototype.constructor.apply(this, arguments); + + } + for(var i=1;i<a.length;i++){ + for(var n in a[i].prototype){ + f.prototype[n] = a[i].prototype[n]; + } + } + + for(n in sub.prototype){ + f.prototype[n] = sub.prototype[n]; + } + return f; // Function + } +}; +}); diff --git a/js/dojo/dojox/drawing/util/positioning.js b/js/dojo/dojox/drawing/util/positioning.js new file mode 100644 index 0000000..13afcad --- /dev/null +++ b/js/dojo/dojox/drawing/util/positioning.js @@ -0,0 +1,69 @@ +//>>built +// wrapped by build app +define("dojox/drawing/util/positioning", ["dijit","dojo","dojox"], function(dijit,dojo,dojox){ +dojo.provide("dojox.drawing.util.positioning"); + +(function(){ + + var textOffset = 4; // distance from line to text box + var textYOffset = 20; // height of text box + + + dojox.drawing.util.positioning.label = function(/*Object*/start, /*Object*/end){ + // summary: + // Returns the optimal text positions for annotations.Label. + + // label at middle of vector + var x = 0.5*(start.x+end.x); + var y = 0.5*(start.y+end.y); + + // move label a set distance from the line + var slope = dojox.drawing.util.common.slope(start, end); + var deltay = textOffset/Math.sqrt(1.0+slope*slope); + + if(end.y>start.y && end.x>start.x || end.y<start.y && end.x<start.x){ + // Position depending on quadrant. Y offset + // positions box aligned vertically from top + deltay = -deltay; + y -= textYOffset; + } + x += -deltay*slope; + y += deltay; + + // want text to be away from start of vector + // This will make force diagrams less crowded + var align = end.x<start.x ? "end" : "start"; + + return { x:x, y:y, foo:"bar", align:align}; // Object + }; + + dojox.drawing.util.positioning.angle = function(/*Object*/start, /*Object*/end){ + // summary: + // Returns the optimal position for annotations.Angle. + // + // angle at first third of vector + var x = 0.7*start.x+0.3*end.x; + var y = 0.7*start.y+0.3*end.y; + // move label a set distance from the line + var slope = dojox.drawing.util.common.slope(start, end); + var deltay = textOffset/Math.sqrt(1.0+slope*slope); + + if(end.x<start.x){deltay = -deltay;} + x += -deltay * slope; + y += deltay; + + // want text to be clockwise from vector + // to match angle measurement from x-axis + var align = end.y>start.y ? "end" : "start"; + // box vertical aligned from middle + y += end.x > start.x ? 0.5*textYOffset : -0.5*textYOffset; + + return { x:x, y:y, align:align}; // Object + } + +})(); + + + + +}); diff --git a/js/dojo/dojox/drawing/util/typeset.js b/js/dojo/dojox/drawing/util/typeset.js new file mode 100644 index 0000000..c9c81c1 --- /dev/null +++ b/js/dojo/dojox/drawing/util/typeset.js @@ -0,0 +1,72 @@ +//>>built +// wrapped by build app +define("dojox/drawing/util/typeset", ["dijit","dojo","dojox","dojo/require!dojox/drawing/library/greek"], function(dijit,dojo,dojox){ +dojo.provide("dojox.drawing.util.typeset"); +dojo.require("dojox.drawing.library.greek"); +// Summary: +// Singleton used for converting characters and typsetting. Required by _base. +// +// Description: +// Eventually, this is supposed to turn input strings of mathematical +// expressions into typeset expressions that can be displayed on the +// canvas. For now, we just generate Greek letters based on LaTeX style +// entity codes. + +(function(){ + + var greeks = dojox.drawing.library.greek; + + dojox.drawing.util.typeset = { + + convertHTML: function(inText){ + if(inText){ + return inText.replace(/&([^;]+);/g,function(match,code){ + if(code.charAt(0)=='#'){ + //coerce remainder of string to int + var number=+code.substr(1); + if(!isNaN(number)){ + return String.fromCharCode(number); + } + }else if(greeks[code]){ + return String.fromCharCode(greeks[code]); + } + // This is generally for server code, so there + // is no point bothering the user in the case of an error. + console.warn("no HTML conversion for ",match); + return match; + }); + } + return inText; + }, + + convertLaTeX: function(inText){ + // console.log("***** convertLaTeX for ",inText); + if(inText){ + return inText.replace(/\\([a-zA-Z]+)/g,function(match,word){ + if(greeks[word]){ + return String.fromCharCode(greeks[word]); + }else if(word.substr(0,2)=="mu"){ + // special handling for \mu since it is + // a unit prefix for micro. + return String.fromCharCode(greeks["mu"])+word.substr(2); + }else if(word.substr(0,5)=="theta"){ + // special handling for \theta since it is + // a standard prefix for angle associated with a vector. + return String.fromCharCode(greeks["theta"])+word.substr(5); + }else if(word.substr(0,3)=="phi"){ + // special handling for \phi since it is + // a standard prefix for angle associated with a z-axis vector. + return String.fromCharCode(greeks["phi"])+word.substr(3); + } + console.log("no match for ",match," in ",inText); + console.log("Need user-friendly error handling here!"); + }).replace(/\\\\/g,'\\'); + } + return inText; + } + + }; + +})(); + +}); |
