diff options
Diffstat (limited to 'includes/js/dojox/sketch')
20 files changed, 1977 insertions, 0 deletions
diff --git a/includes/js/dojox/sketch/Anchor.js b/includes/js/dojox/sketch/Anchor.js new file mode 100644 index 0000000..de72ac0 --- /dev/null +++ b/includes/js/dojox/sketch/Anchor.js @@ -0,0 +1,61 @@ +if(!dojo._hasResource["dojox.sketch.Anchor"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code. +dojo._hasResource["dojox.sketch.Anchor"] = true; +dojo.provide("dojox.sketch.Anchor"); +dojo.require("dojox.gfx"); + +(function(){ + var ta=dojox.sketch; + ta.Anchor=function(an, id, isControl){ + var self=this; + var size=4; // .5 * size of anchor. + var rect=null; + + this.type=function(){ return "Anchor"; }; + this.annotation=an; + + this.id=id; + this._key="anchor-" + ta.Anchor.count++; + this.shape=null; + this.isControl=(isControl!=null)?isControl:true; + + this.beginEdit=function(){ + this.annotation.beginEdit(ta.CommandTypes.Modify); + }; + this.endEdit=function(){ + this.annotation.endEdit(); + }; + this.doChange=function(pt){ + if(this.isControl) this.shape.applyTransform(pt); + else{ + an.transform.dx+=pt.dx; + an.transform.dy+=pt.dy; + } + }; + this.setBinding=function(pt){ + an[id]={ x: an[id].x+pt.dx, y:an[id].y+pt.dy }; + an.draw(); + an.drawBBox(); + }; + this.setUndo=function(){ an.setUndo(); }; + + this.enable=function(){ + if(!an.shape) return; + an.figure._add(this); + rect={ x:an[id].x-size, y:an[id].y-size, width:size*2, height:size*2 }; + this.shape=an.shape.createRect(rect) + .setStroke({ color:"black", width:1 }) + .setFill([255,255,255,0.35]); + this.shape.getEventSource().setAttribute("id", self._key); + this.shape.getEventSource().setAttribute("shape-rendering", "crispEdges"); + }; + this.disable=function(){ + an.figure._remove(this); + if(an.shape) an.shape.remove(this.shape); + this.shape=null; + rect=null; + }; + }; + ta.Anchor.count=0; +})(); + +} diff --git a/includes/js/dojox/sketch/Annotation.js b/includes/js/dojox/sketch/Annotation.js new file mode 100644 index 0000000..ea260ca --- /dev/null +++ b/includes/js/dojox/sketch/Annotation.js @@ -0,0 +1,223 @@ +if(!dojo._hasResource["dojox.sketch.Annotation"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code. +dojo._hasResource["dojox.sketch.Annotation"] = true; +dojo.provide("dojox.sketch.Annotation"); +dojo.require("dojox.sketch.Anchor"); +dojo.require("dojox.sketch._Plugin"); + +(function(){ + var ta=dojox.sketch; + dojo.declare("dojox.sketch.AnnotationTool", ta._Plugin, { +// constructor: function(){ +//// console.log('this.shape',this.shape); +//// this.annotation=ta.tools[this.shape]; +// }, + onMouseMove: function(e,rect){ + if(this._cshape){ + this._cshape.setShape(rect); + } else { + this._cshape=this.figure.surface.createRect(rect) + .setStroke({color:"#999", width:1, style:"ShortDot"}) + .setFill([255,255,255,0.7]); + this._cshape.getEventSource().setAttribute("shape-rendering","crispEdges"); + } + }, + onMouseUp: function(e){ + var f=this.figure; + if(!(f._startPoint.x==e.pageX&&f._startPoint.y==e.pageY)){ + if(this._cshape){ + // The minimum number of pixels one has to travel before a shape + // gets drawn. + var limit=40; + if(Math.max( + limit, + Math.abs(f._absEnd.x-f._start.x), + Math.abs(f._absEnd.y-f._start.y) + )>limit){ + this._create(f._start, f._end); + } + } + } + if(this._cshape) f.surface.remove(this._cshape); + }, + _create: function(start,end){ + // create a new shape, needs to be accessible from the + // dragging functions. + var f=this.figure; + var _=f.nextKey(); + var a=new (this.annotation)(f, "annotation-"+_); + a.transform={dx:start.x/f.zoomFactor, dy:start.y/f.zoomFactor}; + a.end={ x:end.x/f.zoomFactor, y:end.y/f.zoomFactor }; + if(a.control){ + a.control={ x:Math.round((end.x/2)/f.zoomFactor),y:Math.round((end.y/2)/f.zoomFactor) }; + } + f.onBeforeCreateShape(a); + a.initialize(); + f.select(a); + f.onCreateShape(a); + f.history.add(ta.CommandTypes.Create,a); + } + }); + ta.Annotation=function(figure, id){ + // for editing stuff. + this.id=this._key=id; + this.figure=figure; + this.mode=ta.Annotation.Modes.View; + this.shape=null; // dojox.gfx.Group + this.boundingBox=null; // rect for boundaries + this.hasAnchors=true; + this.anchors={}; // ta.Anchor + this._properties={ + 'stroke':{ color:"blue", width:2 }, + 'fill': "blue", + 'label': "" + }; + + if(this.figure) this.figure.add(this); + }; + var p=ta.Annotation.prototype; + p.constructor=ta.Annotation; + p.type=function(){ return ''; }; + p.getType=function(){ return ta.Annotation; }; + + p.remove=function(){ + this.figure.history.add(ta.CommandTypes.Delete, this, this.serialize()); + }; + p.property=function(name,/*?*/value){ + var r; + name=name.toLowerCase(); + if(this._properties[name]!==undefined){ + r=this._properties[name]; + } + if(arguments.length>1){ + this._properties[name]=value; + } + if(r!=value){ + this.onPropertyChange(name,r); + } + return r; + }; + p.onPropertyChange=function(name,oldvalue){}; + p.onCreate=function(){ + this.figure.history.add(ta.CommandTypes.Create,this); + } + p.onDblClick=function(event){ + var l=prompt('Set new text:',this.property('label')); + if(l!==false){ + this.beginEdit(ta.CommandTypes.Modify); + this.property('label',l); + this.draw(); + this.endEdit(); + } + } + p.initialize=function(){ }; + p.destroy=function(){ }; + p.draw=function(){ }; + p.apply=function(obj){ }; + p.serialize=function(){ }; + p.getBBox=function(){ }; + p.beginEdit=function(type){ + this._type=type||ta.CommandTypes.Move; + this._prevState=this.serialize(); + }; + p.endEdit=function(){ + var newstep=true; + if(this._type==ta.CommandTypes.Move){ + var f=this.figure; + if(f._absEnd.x==f._start.x&&f._absEnd.y==f._start.y){ + newstep=false; + } + } + if(newstep){ + this.figure.history.add(this._type,this,this._prevState); + } + this._type=this._prevState=''; + }; + p.calculate={ + slope:function(p1, p2){ + if(!(p1.x-p2.x)) return 0; + return ((p1.y-p2.y)/(p1.x-p2.x)); + }, + dx:function(p1, p2, dy){ + var s=this.slope(p1,p2); + if(s==0) return s; + return dy/s; + }, + dy:function(p1, p2, dx){ return this.slope(p1,p2)*dx; } + }; + p.drawBBox=function(){ + var r=this.getBBox(); + if(!this.boundingBox){ + this.boundingBox=this.shape.createRect(r) + .moveToBack() + .setStroke({color:"#999", width:1, style:"Dash"}) + .setFill([238,238,238,0.3]); + this.boundingBox.getEventSource().setAttribute("id",this.id+"-boundingBox"); + this.boundingBox.getEventSource().setAttribute("shape-rendering","crispEdges"); + this.figure._add(this); + } else this.boundingBox.setShape(r); + }; + p.setBinding=function(pt){ + this.transform.dx+=pt.dx; + this.transform.dy+=pt.dy; + this.draw(); + }; + p.doChange=function(pt){ }; + p.getTextBox=function(){ + return dojox.gfx._base._getTextBox(this.property('label'),ta.Annotation.labelFont); + }; + p.setMode=function(m){ + if(this.mode==m) return; + this.mode=m; + var method="disable"; + if(m==ta.Annotation.Modes.Edit) method="enable"; + if(method=="enable"){ + // draw the bounding box + this.drawBBox(); + this.figure._add(this); + } else { + if(this.boundingBox){ + if(this.shape) this.shape.remove(this.boundingBox); + this.boundingBox=null; + } + } + for(var p in this.anchors){ this.anchors[p][method](); } + }; +// p.writeProperties=function(){ +// var ps=this._properties; +// return "<!CDATA[properties:"+dojo.toJson(ps)+"]]>"; +// }; + p.writeCommonAttrs=function(){ + return 'id="' + this.id + '" dojoxsketch:type="' + this.type() + '"' + + ' transform="translate('+ this.transform.dx + "," + this.transform.dy + ')"' + + (this.data?(' ><![CDATA[data:'+dojo.toJson(this.data)+']]'):''); + }; + p.readCommonAttrs=function(obj){ + var i=0,cs=obj.childNodes,c; + while((c=cs[i++])){ + if(c.nodeType==4){ //CDATA + if(c.nodeValue.substr(0,11)=='properties:'){ + this._properties=dojo.fromJson(c.nodeValue.substr(11)); + }else if(c.nodeValue.substr(0,5)=='data:'){ + this.data=dojo.fromJson(c.nodeValue.substr(5)); + }else{ + console.error('unknown CDATA node in node ',obj); + } + } + } + + if(obj.getAttribute('transform')){ + var t=obj.getAttribute('transform').replace("translate(",""); + var pt=t.split(","); + this.transform.dx=parseFloat(pt[0],10); + this.transform.dy=parseFloat(pt[1],10); + } + }; + ta.Annotation.Modes={ View:0, Edit:1 }; + ta.Annotation.labelFont={family:"Arial", size:"16px", weight:"bold"}; + ta.Annotation.register=function(name){ + var cls=ta[name+'Annotation']; + ta.registerTool(name, function(p){dojo.mixin(p,{shape: name,annotation:cls});return new ta.AnnotationTool(p)}); + }; +})(); + +} diff --git a/includes/js/dojox/sketch/DoubleArrowAnnotation.js b/includes/js/dojox/sketch/DoubleArrowAnnotation.js new file mode 100644 index 0000000..0817f0a --- /dev/null +++ b/includes/js/dojox/sketch/DoubleArrowAnnotation.js @@ -0,0 +1,200 @@ +if(!dojo._hasResource["dojox.sketch.DoubleArrowAnnotation"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code. +dojo._hasResource["dojox.sketch.DoubleArrowAnnotation"] = true; +dojo.provide("dojox.sketch.DoubleArrowAnnotation"); + +dojo.require("dojox.sketch.Annotation"); +dojo.require("dojox.sketch.Anchor"); + +(function(){ + var ta=dojox.sketch; + ta.DoubleArrowAnnotation=function(figure, id){ + ta.Annotation.call(this, figure, id); + this.transform={ dx:0, dy:0 }; + this.start={x:0, y:0}; + this.control={x:100, y:-50}; + this.end={x:200, y:0}; + this.textPosition={ x:0, y:0 }; + this.textOffset=6; + this.textYOffset=10; + this.textAlign="middle"; + this.startRotation=0; + this.endRotation=0; + +// this.property('label',this.id); + this.labelShape=null; + this.pathShape=null; + this.startArrow=null; + this.startArrowGroup=null; + this.endArrow=null; + this.endArrowGroup=null; + + this.anchors.start=new ta.Anchor(this, "start"); + this.anchors.control=new ta.Anchor(this, "control"); + this.anchors.end=new ta.Anchor(this, "end"); + }; + ta.DoubleArrowAnnotation.prototype=new ta.Annotation; + var p=ta.DoubleArrowAnnotation.prototype; + p.constructor=ta.DoubleArrowAnnotation; + + p.type=function(){ return 'DoubleArrow'; }; + p.getType=function(){ return ta.DoubleArrowAnnotation; }; + + p._rot=function(){ + // arrowhead rotation + var opp=this.start.y-this.control.y; + var adj=this.start.x-this.control.x; + if(!adj) adj=1; + this.startRotation=Math.atan(opp/adj); + opp=this.control.y-this.end.y; + adj=this.control.x-this.end.x; + if(!adj) adj=1; + this.endRotation=Math.atan(opp/adj); + }; + p._pos=function(){ + // text position + var offset=this.textOffset; + + // figure out the pull of the curve and place accordingly + if(this.control.y<this.end.y) offset*=-1; + else offset+=this.textYOffset; + var ab={x:((this.control.x-this.start.x)*.5)+this.start.x, y:((this.control.y-this.start.y)*.5)+this.start.y}; + var bc={x:((this.end.x-this.control.x)*.5)+this.control.x, y:((this.end.y-this.control.y)*.5)+this.control.y}; + this.textPosition={x:((bc.x-ab.x)*.5)+ab.x, y:(((bc.y-ab.y)*.5)+ab.y)+offset}; + }; + + p.apply=function(obj){ + if(!obj) return; + if(obj.documentElement) obj=obj.documentElement; + this.readCommonAttrs(obj); + + for(var i=0; i<obj.childNodes.length; i++){ + var c=obj.childNodes[i]; + if(c.localName=="text") this.property('label',c.childNodes.length?c.childNodes[0].nodeValue:''); + else if(c.localName=="path"){ + // the line + var d=c.getAttribute('d').split(" "); + var s=d[0].split(","); + this.start.x=parseFloat(s[0].substr(1),10); + this.start.y=parseFloat(s[1],10); + s=d[1].split(","); + this.control.x=parseFloat(s[0].substr(1),10); + this.control.y=parseFloat(s[1],10); + s=d[2].split(","); + this.end.x=parseFloat(s[0],10); + this.end.y=parseFloat(s[1],10); + } + } + }; + p.initialize=function(obj){ + // create, based on passed DOM node if available. + var font=(ta.Annotation.labelFont)?ta.Annotation.labelFont:{family:"Times", size:"16px"}; + this.apply(obj); + + // calculate the other positions + this._rot(); + this._pos(); + + // rotation matrix + var rot=this.startRotation; + if(this.control.x<this.start.x) rot+=Math.PI; + var startRot=dojox.gfx.matrix.rotate(rot); + + rot=this.endRotation; + if(this.control.x>=this.end.x) rot+=Math.PI; + var endRot=dojox.gfx.matrix.rotateAt(rot, this.end.x, this.end.y); + + // draw the shapes + this.shape=this.figure.group.createGroup(); + this.shape.getEventSource().setAttribute("id", this.id); + if(this.transform.dx||this.transform.dy) this.shape.setTransform(this.transform); + this.pathShape=this.shape.createPath( + "M"+this.start.x+" "+this.start.y+"Q"+this.control.x+" "+this.control.y+" "+this.end.x+" "+this.end.y + " l0,0" + ).setStroke(this.property('stroke')); + + this.startArrowGroup=this.shape.createGroup().setTransform({ dx:this.start.x, dy:this.start.y }); + this.startArrowGroup.applyTransform(startRot); +// console.log('startArrow',this.property('fill')); + this.startArrow=this.startArrowGroup.createPath("M0,0 l20,-5 -3,5 3,5 Z").setFill(this.property('fill')); + + this.endArrowGroup=this.shape.createGroup().setTransform(endRot); + this.endArrow=this.endArrowGroup.createPath( + "M" + this.end.x + "," + this.end.y + " l-20,-5 3,5 -3,5 Z" + ).setFill(this.property('fill')); + this.labelShape=this.shape.createText({ + x:this.textPosition.x, y:this.textPosition.y, text:this.property('label'), align:this.textAlign + }).setFont(font).setFill(this.property('fill')); + }; + p.destroy=function(){ + if(!this.shape) return; + this.startArrowGroup.remove(this.startArrow); + this.endArrowGroup.remove(this.endArrow); + this.shape.remove(this.startArrowGroup); + this.shape.remove(this.endArrowGroup); + this.shape.remove(this.pathShape); + this.shape.remove(this.labelShape); + this.figure.group.remove(this.shape); + this.shape=this.pathShape=this.labelShape=this.startArrowGroup=this.startArrow=this.endArrowGroup=this.endArrow=null; + }; + p.draw=function(obj){ + this.apply(obj); + this._rot(); + this._pos(); + // rotation matrix + var rot=this.startRotation; + if(this.control.x<this.start.x) rot+=Math.PI; + var startRot=dojox.gfx.matrix.rotate(rot); + rot=this.endRotation; + if(this.control.x>=this.end.x) rot+=Math.PI; + var endRot=dojox.gfx.matrix.rotateAt(rot, this.end.x, this.end.y); + + this.shape.setTransform(this.transform); + this.pathShape.setShape( + "M"+this.start.x+" "+this.start.y+" Q"+this.control.x+" "+this.control.y+" "+this.end.x+" "+this.end.y + " l0,0" + ).setStroke(this.property('stroke')); + this.startArrowGroup.setTransform({ dx:this.start.x, dy:this.start.y }); + this.startArrowGroup.applyTransform(startRot); + this.startArrow.setFill(this.property('fill')); + + this.endArrowGroup.setTransform(endRot); + this.endArrow.setShape( + "M" + this.end.x + "," + this.end.y + " l-20,-5 3,5 -3,5 Z" + ).setFill(this.property('fill')); + this.labelShape.setShape({x:this.textPosition.x, y:this.textPosition.y, text:this.property('label')}).setFill(this.property('fill')); + }; + p.getBBox=function(){ + var x=Math.min(this.start.x, this.control.x, this.end.x); + var y=Math.min(this.start.y, this.control.y, this.end.y); + var w=Math.max(this.start.x, this.control.x, this.end.x)-x; + var h=Math.max(this.start.y, this.control.y, this.end.y)-y; + return { x:x, y:y, width:w, height:h }; + }; + p.serialize=function(){ + var s=this.property('stroke'); + return '<g '+this.writeCommonAttrs()+'>' + + '<path style="stroke:'+s.color+';stroke-width:'+s.width+';fill:none;" d="' + + "M"+this.start.x+","+this.start.y+" " + + "Q"+this.control.x+","+this.control.y+" " + + this.end.x+","+this.end.y + + '" />' + + '<g transform="translate(' + this.start.x + "," + this.start.y + ") " + + 'rotate(' + (Math.round((this.startRotation*(180/Math.PI))*Math.pow(10,4))/Math.pow(10,4)) + ')">' + + '<path style="fill:'+s.color+';" d="M0,0 l20,-5, -3,5, 3,5 Z" />' + + '</g>' + + '<g transform="rotate(' + + (Math.round((this.endRotation*(180/Math.PI))*Math.pow(10,4))/Math.pow(10,4)) + + ", "+this.end.x+", "+this.end.y + + ')">' + + '<path style="fill:'+s.color+';" d="M'+this.end.x+","+this.end.y+' l-20,-5, 3,5, -3,5 Z" />' + + '</g>' + + '<text style="fill:'+s.color+';text-anchor:'+this.textAlign+'" font-weight="bold" ' + + 'x="' + this.textPosition.x + '" ' + + 'y="' + this.textPosition.y + '">' + + this.property('label') + + '</text>' + + '</g>'; + }; + + ta.Annotation.register("DoubleArrow"); +})(); + +} diff --git a/includes/js/dojox/sketch/Figure.js b/includes/js/dojox/sketch/Figure.js new file mode 100644 index 0000000..ae573bb --- /dev/null +++ b/includes/js/dojox/sketch/Figure.js @@ -0,0 +1,493 @@ +if(!dojo._hasResource["dojox.sketch.Figure"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code. +dojo._hasResource["dojox.sketch.Figure"] = true; +dojo.provide("dojox.sketch.Figure"); +dojo.experimental("dojox.sketch"); + +dojo.require("dojox.gfx"); +dojo.require("dojox.sketch.UndoStack"); + +(function(){ + var ta=dojox.sketch; + ta.tools={}; + ta.registerTool=function(type, fn){ ta.tools[type]=fn; }; + ta.Figure = function(){ + var self=this; + var annCounter=1; + + this.shapes=[]; + this.image=null; + this.imageSrc=null; + this.size={ w:0, h:0 }; + this.surface=null; + this.group=null; + this.node=null; + + this.zoomFactor=1; // multiplier for zooming. + + this.tools=null; // toolbar reference. + this.nextKey=function(){ return annCounter++; }; + + this.obj={}; // lookup table for shapes. Not keen on this solution. + + this.initUndoStack(); + + // what is selected. + this.selected=[]; + this.hasSelections=function(){ return this.selected.length>0 }; + this.isSelected=function(obj){ + for(var i=0; i<self.selected.length; i++){ + if(self.selected[i]==obj) return true; + } + return false; + }; + this.select=function(obj){ + // TODO: deal with multiple vs. single selections. + if(!self.isSelected(obj)){ + // force single select + self.clearSelections(); + self.selected=[ obj ]; + } + // force a bbox update, regardless + obj.setMode(ta.Annotation.Modes.View); + obj.setMode(ta.Annotation.Modes.Edit); + }; + this.deselect=function(obj){ + var idx=-1; + for(var i=0; i<self.selected.length; i++){ + if(self.selected[i]==obj){ + idx=i; + break; + } + } + if(idx>-1){ + obj.setMode(ta.Annotation.Modes.View); + self.selected.splice(idx,1); + } + return obj; + }; + this.clearSelections=function(){ + for(var i=0; i<self.selected.length; i++) + self.selected[i].setMode(ta.Annotation.Modes.View); + self.selected=[]; + }; + this.replaceSelection=function(n, o){ + if(!self.isSelected(o)){ + self.select(n); + return; + } + var idx=-1; + for(var i=0; i<self.selected.length; i++){ + if(self.selected[i]==o){ + idx=i; break; + } + } + if(idx>-1){ + self.selected.splice(idx,1,n); + } + }; + + // for the drag and drop handlers. + this._c=null; // current shape + this._ctr=null; // container measurements + this._lp=null; // last position + this._action=null; + this._prevState=null; + this._startPoint=null; // test to record a move. + + // if an object isn't selected and we're dragging anyways. + this._ctool=null; // hard code it. + this._start=null; + this._end=null; + this._absEnd=null; + this._cshape=null; + + this._click=function(e){ + if(self._c){ + dojo.stopEvent(e); + return; + } + var o=self._fromEvt(e); + if(!o){ + self.clearSelections(); + dojo.stopEvent(e); + } else if(!o.setMode){ + // skip me. + } else self.select(o); + }; + this._dblclick=function(e){ + var o=self._fromEvt(e); + if(o){ + self.onDblClickShape(o,e); + } + }; + + this._keydown=function(e){ + var prevent=false; + if(e.ctrlKey){ + if(e.keyCode==90){ //ctrl+z + self.undo(); + prevent = true; + }else if(e.keyCode==89){ //ctrl+y + self.redo(); + prevent = true; + } + } + + if(e.keyCode==46 || e.keyCode==8){ //delete or backspace + self._delete(self.selected); + prevent = true; + } + + if(prevent){ + dojo.stopEvent(e); + } + }; + + // drag handlers. + this._md=function(e){ + var o=self._fromEvt(e); + self._startPoint={ x:e.pageX, y:e.pageY }; + var win = dijit.getDocumentWindow(self.node.ownerDocument); + // figure out the coordinates within the iframe + self._ctr=dojo._abs(self.node); + var scroll=dojo.withGlobal(win,dojo._docScroll); + self._ctr={x:self._ctr.x-scroll.x, y:self._ctr.y-scroll.y}; + var X=e.clientX-self._ctr.x, Y=e.clientY-self._ctr.y; + self._lp={ x:X, y:Y }; + + // capture it separately + self._start={ x:X, y:Y }; + self._end={ x:X, y:Y }; + self._absEnd={ x:X, y:Y }; + if(!o){ + self.clearSelections(); + self._ctool.onMouseDown(e); + }else{ + if(o.type && o.type()!="Anchor"){ + self.select(o); + } + o.beginEdit(); + self._c=o; + } + }; + this._mm=function(e){ + if(!self._ctr) return; + var x=e.clientX-self._ctr.x; + var y=e.clientY-self._ctr.y; + var dx=x-self._lp.x; + var dy=y-self._lp.y; + self._absEnd={x:x, y:y}; + if(self._c){ + self._c.doChange({dx:Math.round(dx/self.zoomFactor), dy:Math.round(dy/self.zoomFactor)}); + self._c.setBinding({dx:Math.round(dx/self.zoomFactor), dy:Math.round(dy/self.zoomFactor)}); + self._lp={x:x, y:y}; + } + else { + self._end={x:dx, y:dy}; + var rect={ + x:Math.min(self._start.x,self._absEnd.x), + y:Math.min(self._start.y,self._absEnd.y), + width:Math.abs(self._start.x-self._absEnd.x), + height:Math.abs(self._start.y-self._absEnd.y) + } + self._ctool.onMouseMove(e,rect); + } + }; + this._mu=function(e){ + if(self._c){ + // record the event. + self._c.endEdit(); + }else{ + self._ctool.onMouseUp(e); + } + + // clear the stuff out. + self._c=self._ctr=self._lp=self._action=self._prevState=self._startPoint=null; + self._cshape=self._start=self._end=self._absEnd=null; + }; + + this._delete=function(arr,noundo){ + for(var i=0; i<arr.length; i++){ + //var before=arr[i].serialize(); + if(!noundo){ + arr[i].remove(); + } + arr[i].setMode(ta.Annotation.Modes.View); + arr[i].destroy(); + self.remove(arr[i]); + self._remove(arr[i]); + } + arr.splice(0,arr.length); + }; + }; + + var p=ta.Figure.prototype; + p.initUndoStack=function(){ + this.history=new ta.UndoStack(this); + }; + p.setTool=function(/*dojox.sketch._Plugin*/t){ + this._ctool=t; + }; + p.onDblClickShape=function(shape,e){ + if(shape['onDblClick']){ + shape.onDblClick(e); + } + }; + + p.onCreateShape=function(shape){}; + p.onBeforeCreateShape=function(shape){}; + p.initialize=function(node){ + this.node=node; + this.surface=dojox.gfx.createSurface(node, this.size.w, this.size.h); + this.surface.createRect({ x:0, y:0, width:this.size.w, height:this.size.h }) + .setFill("white"); + this.group=this.surface.createGroup(); + + // kill any dragging events. + this._cons=[]; + this._cons.push(dojo.connect(this.node, "ondragstart", dojo, "stopEvent")); + this._cons.push(dojo.connect(this.node, "onselectstart", dojo, "stopEvent")); + + // hook up the drag system. + this._cons.push(dojo.connect(this.surface.getEventSource(), 'onmousedown', this._md)); + this._cons.push(dojo.connect(this.surface.getEventSource(), 'onmousemove', this._mm)); + this._cons.push(dojo.connect(this.surface.getEventSource(), 'onmouseup', this._mu)); + + this._cons.push(dojo.connect(this.surface.getEventSource(), 'ondblclick', this._dblclick)); + this._cons.push(dojo.connect(this.surface.getEventSource().ownerDocument, 'onkeydown', this._keydown)); + + // rect hack. Fcuking VML> + this.group.createRect({ x:0, y:0, width:this.size.w, height:this.size.h }); + this.image=this.group.createImage({ width:this.size.w, height:this.size.h, src:this.imageSrc }); + }; + p.destroy=function(isLoading){ + if(!this.node){ + return; + } + if(!isLoading){ + if(this.history) this.history.destroy(); + if(this._subscribed){ + dojo.unsubscribe(this._subscribed); + delete this._subscribed; + } + } + dojo.forEach(this._cons,dojo.disconnect); + this._cons=[]; + + this.node.removeChild(this.surface.getEventSource()); + this.group=this.surface=null; + this.obj={}; + this.shapes=[]; + }; + p.draw=function(){ }; + p.zoom=function(pct){ + // first get the new dimensions + this.zoomFactor=pct/100; + var w=this.size.w*this.zoomFactor; + var h=this.size.h*this.zoomFactor; + this.surface.setDimensions(w, h); + // then scale it. + this.group.setTransform(dojox.gfx.matrix.scale(this.zoomFactor, this.zoomFactor)); + if(dojo.isIE){ + this.image.rawNode.style.width=Math.max(w,this.size.w); + this.image.rawNode.style.height=Math.max(h,this.size.h); + } + //this.rect.setShape({width:w,height:h}); + }; + p.getFit=function(){ + // assume fitting the parent node. +// var box=dojo.html.getContentBox(this.node.parentNode); + //the following should work under IE and FF, not sure about others though + var wF=(this.node.parentNode.clientWidth-5)/this.size.w; + var hF=(this.node.parentNode.clientHeight-5)/this.size.h; + return Math.min(wF, hF)*100; + }; + p.unzoom=function(){ + // restore original size. + this.zoomFactor=1; + this.surface.setDimensions(this.size.w, this.size.h); + this.group.setTransform(); + }; + + // object registry for drag handling. + p._add=function(obj){ this.obj[obj._key]=obj; }; + p._remove=function(obj){ + if(this.obj[obj._key]){ + delete this.obj[obj._key]; + } + }; + p._get=function(key){ + if(key&&key.indexOf("bounding")>-1) key=key.replace("-boundingBox",""); + return this.obj[key]; + }; + p._fromEvt=function(e){ + var key=e.target.id+""; + if(key.length==0){ + // ancestor tree until you get to the end (meaning this.surface) + var p=e.target.parentNode; + var node=this.surface.getEventSource(); + while(p && p.id.length==0 && p!=node){ + p=p.parentNode; + } + key=p.id; + } + return this._get(key); + }; + + p.add=function(annotation){ + for(var i=0; i<this.shapes.length; i++){ + if(this.shapes[i]==annotation){ return true; } + } + this.shapes.push(annotation); + return true; + }; + p.remove=function(annotation){ + var idx=-1; + for(var i=0; i<this.shapes.length; i++){ + if(this.shapes[i]==annotation){ + idx=i; + break; + } + } + if(idx>-1) this.shapes.splice(idx, 1); + return annotation; + }; + p.get=function(id){ + for(var i=0; i<this.shapes.length; i++){ + if(this.shapes[i].id==id) { + return this.shapes[i]; + } + } + return null; + }; + + p.convert=function(ann, t){ + // convert an existing annotation to a different kind of annotation + var ctor=t+"Annotation"; + if(!ta[ctor]) return; + var type=ann.type(), id=ann.id, label=ann.label, mode=ann.mode; tokenId=ann.tokenId; + var start, end, control, transform; + switch(type){ + case "Preexisting": + case "Lead":{ + transform={dx:ann.transform.dx, dy:ann.transform.dy }; + start={x:ann.start.x, y:ann.start.y}; + end={x:ann.end.x, y:ann.end.y }; + var cx=end.x-((end.x-start.x)/2); + var cy=end.y-((end.y-start.y)/2); + control={x:cx, y:cy}; + break; + } + case "SingleArrow": + case "DoubleArrow":{ + transform={dx:ann.transform.dx, dy:ann.transform.dy }; + start={x:ann.start.x, y:ann.start.y}; + end={x:ann.end.x, y:ann.end.y }; + control={x:ann.control.x, y:ann.control.y}; + break; + } + case "Underline":{ + transform={dx:ann.transform.dx, dy:ann.transform.dy }; + start={x:ann.start.x, y:ann.start.y}; + control={x:start.x+50, y:start.y+50 }; + end={x:start.x+100, y:start.y+100 }; + break; + } + case "Brace":{ } + } + var n=new ta[ctor](this, id); + + if(n.type()=="Underline"){ + // special handling, since we never move the start point. + n.transform={dx:transform.dx+start.x, dy:transform.dy+start.y }; + } else { + if(n.transform) n.transform=transform; + if(n.start) n.start=start; + } + if(n.end) n.end=end; + if(n.control) n.control=control; + n.label=label; + n.token=dojo.lang.shallowCopy(ann.token); + n.initialize(); + + this.replaceSelection(n, ann); + this._remove(ann); + this.remove(ann); + ann.destroy(); + + // this should do all the things we need it to do for getting it registered. + n.setMode(mode); + }; + p.setValue=function(text){ + var obj=dojox.xml.DomParser.parse(text); + var node=this.node; + this.load(obj,node); + this.zoom(this.zoomFactor*100); //zoom to orignal scale + }; + p.load=function(obj, n){ + // create from pseudo-DOM + if(this.surface){ this.destroy(true); } + var node=obj.documentElement; // should be either the document or the docElement + this.size={ w:parseFloat(node.getAttribute('width'),10), h:parseFloat(node.getAttribute('height'),10) }; + var g=node.childrenByName("g")[0]; + var img=g.childrenByName("image")[0]; + this.imageSrc=img.getAttribute("xlink:href"); + this.initialize(n); + + // now let's do the annotations. + var ann=g.childrenByName("g"); + for(var i=0; i<ann.length; i++) this._loadAnnotation(ann[i]); + if(this._loadDeferred){ + this._loadDeferred.callback(this); + this._loadDeferred=null; + } + this.onLoad(); + }; + p.onLoad=function(){}; + p._loadAnnotation=function(obj){ + var ctor=obj.getAttribute('dojoxsketch:type')+"Annotation"; + if(ta[ctor]){ + var a=new ta[ctor](this, obj.id); + a.initialize(obj); + this.nextKey(); + a.setMode(ta.Annotation.Modes.View); + this._add(a); + return a; + } + return null; + }; + + p.onUndo=function(){}; + p.onBeforeUndo=function(){}; + p.onRedo=function(){}; + p.onBeforeRedo=function(){}; + p.undo=function(){ + if(this.history){ + this.onBeforeUndo(); + this.history.undo(); + this.onUndo(); + } + }; + p.redo=function(){ + if(this.history){ + this.onBeforeRedo(); + this.history.redo(); + this.onRedo(); + } + }; + p.serialize=function(){ + var s='<svg xmlns="http://www.w3.org/2000/svg" ' + + 'xmlns:xlink="http://www.w3.org/1999/xlink" ' + + 'xmlns:dojoxsketch="http://dojotoolkit.org/dojox/sketch" ' + + 'width="' + this.size.w + '" height="' + this.size.h + '">' + + '<g>' + + '<image xlink:href="' + this.imageSrc + '" x="0" y="0" width="' + + this.size.w + '" height="' + this.size.h + '" />'; + for(var i=0; i<this.shapes.length; i++) s+= this.shapes[i].serialize(); + s += '</g></svg>'; + return s; + }; + p.getValue=p.serialize; +})(); + +} diff --git a/includes/js/dojox/sketch/LeadAnnotation.js b/includes/js/dojox/sketch/LeadAnnotation.js new file mode 100644 index 0000000..40e571e --- /dev/null +++ b/includes/js/dojox/sketch/LeadAnnotation.js @@ -0,0 +1,141 @@ +if(!dojo._hasResource["dojox.sketch.LeadAnnotation"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code. +dojo._hasResource["dojox.sketch.LeadAnnotation"] = true; +dojo.provide("dojox.sketch.LeadAnnotation"); +dojo.require("dojox.sketch.Annotation"); +dojo.require("dojox.sketch.Anchor"); + +(function(){ + var ta=dojox.sketch; + ta.LeadAnnotation=function(figure, id){ + ta.Annotation.call(this, figure, id); + this.transform={dx:0, dy:0 }; + this.start={ x:0, y:0 }; + this.control={x:100, y:-50}; + this.end={ x:200, y:0 }; + this.textPosition={ x:0, y:0 }; + this.textOffset=4; + this.textAlign="middle"; + this.textYOffset=10; + +// this.property('label',this.id); + this.pathShape=null; + this.labelShape=null; + + this.anchors.start=new ta.Anchor(this, "start"); + this.anchors.control=new ta.Anchor(this, "control"); + this.anchors.end=new ta.Anchor(this, "end"); + }; + ta.LeadAnnotation.prototype=new ta.Annotation; + var p=ta.LeadAnnotation.prototype; + p.constructor=ta.LeadAnnotation; + + p.type=function(){ return 'Lead'; } + p.getType=function(){ return ta.LeadAnnotation; }; + + p._pos=function(){ + var offset=this.textOffset, x=0, y=0; + var slope=this.calculate.slope(this.control, this.end); + if(Math.abs(slope)>=1){ + x=this.end.x+this.calculate.dx(this.control, this.end, offset); + if(this.control.y>this.end.y) y=this.end.y-offset; + else y=this.end.y+offset+this.textYOffset; + } else if(slope==0){ + x=this.end.x+offset; + y=this.end.y+this.textYOffset; + } else { + if(this.start.x>this.end.x){ + x=this.end.x-offset; + this.textAlign="end"; + } else { + x=this.end.x+offset; + this.textAlign="start"; + } + if(this.start.y<this.end.y) y=this.end.y+this.calculate.dy(this.control, this.end, offset)+this.textYOffset; + else y=this.end.y+this.calculate.dy(this.control, this.end, -offset); + } + this.textPosition={ x:x, y:y }; + }; + p.apply=function(obj){ + if(!obj) return; + if(obj.documentElement) obj=obj.documentElement; + this.readCommonAttrs(obj); + + for(var i=0; i<obj.childNodes.length; i++){ + var c=obj.childNodes[i]; + if(c.localName=="text") this.property('label',c.childNodes.length?c.childNodes[0].nodeValue:''); + else if(c.localName=="path"){ + // the line + var d=c.getAttribute('d').split(" "); + var s=d[0].split(","); + this.start.x=parseFloat(s[0].substr(1),10); + this.start.y=parseFloat(s[1],10); + s=d[1].split(","); + this.control.x=parseFloat(s[0].substr(1),10); + this.control.y=parseFloat(s[1],10); + s=d[2].split(","); + this.end.x=parseFloat(s[0],10); + this.end.y=parseFloat(s[1],10); + } + } + }; + + p.initialize=function(obj){ + var font=(ta.Annotation.labelFont)?ta.Annotation.labelFont:{family:"Times", size:"16px"}; + this.apply(obj); + this._pos(); + + // create either from scratch or based on the passed node + this.shape=this.figure.group.createGroup(); + this.shape.getEventSource().setAttribute("id", this.id); + if(this.transform.dx || this.transform.dy) this.shape.setTransform(this.transform); + this.pathShape=this.shape.createPath( + "M"+this.start.x+","+this.start.y+" Q"+this.control.x+","+this.control.y+" "+this.end.x+","+this.end.y+" l0,0" + ).setStroke(this.property('stroke')); + this.labelShape=this.shape.createText({ + x:this.textPosition.x, y:this.textPosition.y, text:this.property('label'), align:this.textAlign + }).setFont(font).setFill(this.property('fill')); + }; + p.destroy=function(){ + if(!this.shape) return; + this.shape.remove(this.pathShape); + this.shape.remove(this.labelShape); + this.figure.group.remove(this.shape); + this.shape=this.pathShape=this.labelShape=null; + }; + p.getBBox=function(){ + var x=Math.min(this.start.x, this.control.x, this.end.x); + var y=Math.min(this.start.y, this.control.y, this.end.y); + var w=Math.max(this.start.x, this.control.x, this.end.x)-x; + var h=Math.max(this.start.y, this.control.y, this.end.y)-y; + return { x:x, y:y, width:w, height:h }; + }; + p.draw=function(obj){ + this.apply(obj); + this._pos(); + this.shape.setTransform(this.transform); + this.pathShape.setShape( + "M"+this.start.x+","+this.start.y+" Q"+this.control.x+","+this.control.y+" "+this.end.x+","+this.end.y+" l0,0" + ).setStroke(this.property('stroke')); + this.labelShape.setShape({ x:this.textPosition.x, y:this.textPosition.y, text:this.property('label') }) + .setFill(this.property('fill')); + }; + p.serialize=function(){ + var stroke=this.property('stroke'); + return '<g '+this.writeCommonAttrs()+'>' + + '<path style="stroke:'+stroke.color+';stroke-width:'+stroke.width+';fill:none;" d="' + + "M"+this.start.x+","+this.start.y+" " + + "Q"+this.control.x+","+this.control.y+" " + + this.end.x+","+this.end.y + + '" />' + + '<text style="fill:'+stroke.color+';text-anchor:'+this.textAlign+'" font-weight="bold" ' + + 'x="' + this.textPosition.x + '" ' + + 'y="' + this.textPosition.y + '">' + + this.property('label') + + '</text>' + + '</g>'; + }; + + ta.Annotation.register("Lead"); +})(); + +} diff --git a/includes/js/dojox/sketch/PreexistingAnnotation.js b/includes/js/dojox/sketch/PreexistingAnnotation.js new file mode 100644 index 0000000..a8c123e --- /dev/null +++ b/includes/js/dojox/sketch/PreexistingAnnotation.js @@ -0,0 +1,121 @@ +if(!dojo._hasResource["dojox.sketch.PreexistingAnnotation"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code. +dojo._hasResource["dojox.sketch.PreexistingAnnotation"] = true; +dojo.provide("dojox.sketch.PreexistingAnnotation"); + +dojo.require("dojox.sketch.Annotation"); +dojo.require("dojox.sketch.Anchor"); + +(function(){ + var ta=dojox.sketch; + ta.PreexistingAnnotation=function(figure, id){ + ta.Annotation.call(this, figure, id); + this.transform={dx:0, dy:0}; + this.start={ x:0, y:0 }; + this.end={ x:200, y:200 }; + this.radius=8; + this.textPosition={ x:196, y:196 }; + this.textOffset=4; + this.textAlign="end"; + + this.property('label',this.id); + this.rectShape=null; + this.labelShape=null; + + this.anchors.start=new ta.Anchor(this, "start"); + this.anchors.end=new ta.Anchor(this, "end"); + }; + ta.PreexistingAnnotation.prototype=new ta.Annotation; + var p=ta.PreexistingAnnotation.prototype; + p.constructor=ta.PreexistingAnnotation; + + p.type=function(){ return 'Preexisting' }; + p.getType=function(){ return ta.PreexistingAnnotation; }; + + p._pos=function(){ + var x=Math.min(this.start.x, this.end.x); + var y=Math.min(this.start.y, this.end.y); + var w=Math.max(this.start.x, this.end.x); + var h=Math.max(this.start.y, this.end.y); + this.start={ x:x, y:y }; + this.end={ x:w, y:h }; + this.textPosition={ x:this.end.x-this.textOffset, y:this.end.y-this.textOffset }; + }; + p.apply=function(obj){ + if(!obj) return; + if(obj.documentElement) obj=obj.documentElement; + this.readCommonAttrs(obj); + + for(var i=0; i<obj.childNodes.length; i++){ + var c=obj.childNodes[i]; + if(c.localName=="text") this.property('label',c.childNodes.length?c.childNodes[0].nodeValue:''); + else if(c.localName=="rect"){ + if(c.getAttribute('x')!==null) this.start.x=parseFloat(c.getAttribute('x'), 10); + if(c.getAttribute('width')!==null) this.end.x=parseFloat(c.getAttribute('width'), 10)+parseFloat(c.getAttribute('x'), 10); + if(c.getAttribute('y')!==null) this.start.y=parseFloat(c.getAttribute('y'), 10); + if(c.getAttribute('height')!==null) this.end.y=parseFloat(c.getAttribute('height'), 10)+parseFloat(c.getAttribute('y'), 10); + if(c.getAttribute('r')!==null) this.radius=parseFloat(c.getAttribute('r'),10); + } + } + }; + p.initialize=function(obj){ + var font=(ta.Annotation.labelFont)?ta.Annotation.labelFont:{family:"Times", size:"16px"}; + this.apply(obj); + this._pos(); + + // create either from scratch or based on the passed node + this.shape=this.figure.group.createGroup(); + this.shape.getEventSource().setAttribute("id", this.id); + if(this.transform.dx || this.transform.dy) this.shape.setTransform(this.transform); + this.rectShape=this.shape.createRect({ + x:this.start.x, y: this.start.y, width: this.end.x-this.start.x, height:this.end.y-this.start.y, r:this.radius + }).setStroke({color:this.property('fill'), width:1}).setFill([255,255,255,0.1]); + this.rectShape.getEventSource().setAttribute("shape-rendering","crispEdges"); + this.labelShape=this.shape.createText({ + x:this.textPosition.x, y:this.textPosition.y, text:this.property('label'), align:this.textAlign + }).setFont(font).setFill(this.property('fill')); + }; + p.destroy=function(){ + if(!this.shape) return; + this.shape.remove(this.rectShape); + this.shape.remove(this.labelShape); + this.figure.group.remove(this.shape); + this.shape=this.rectShape=this.labelShape=null; + }; + p.getBBox=function(){ + var x=Math.min(this.start.x, this.end.x); + var y=Math.min(this.start.y, this.end.y); + var w=Math.max(this.start.x, this.end.x)-x; + var h=Math.max(this.start.y, this.end.y)-y; + return { x:x-2, y:y-2, width:w+4, height:h+4 }; + }; + p.draw=function(obj){ + this.apply(obj); + this._pos(); + this.shape.setTransform(this.transform); + this.rectShape.setShape({x:this.start.x, y: this.start.y, width: this.end.x-this.start.x, height:this.end.y-this.start.y, r:this.radius}) + .setStroke({ color:this.property('fill'), width:1 }).setFill([255,255,255,0.1]); + this.labelShape.setShape({ x:this.textPosition.x, y:this.textPosition.y, text:this.property('label') }).setFill(this.property('fill')); + }; + p.serialize=function(){ + var s=this.property('stroke'); + return '<g '+this.writeCommonAttrs()+'>' + + '<rect style="stroke:'+s.color+';stroke-weight:1;fill:none;" ' + + 'x="' + this.start.x + '" ' + + 'width="' + (this.end.x-this.start.x) + '" ' + + 'y="' + this.start.y + '" ' + + 'height="' + (this.end.y-this.start.y) + '" ' + + 'rx="' + this.radius + '" ' + + 'ry="' + this.radius + '" ' + + ' />' + + '<text style="fill:'+s.color+';text-anchor:'+this.textAlign+'" font-weight="bold" ' + + 'x="' + this.textPosition.x + '" ' + + 'y="' + this.textPosition.y + '">' + + this.property('label') + + '</text>' + + '</g>'; + }; + + ta.Annotation.register("Preexisting"); +})(); + +} diff --git a/includes/js/dojox/sketch/README b/includes/js/dojox/sketch/README new file mode 100644 index 0000000..85b2264 --- /dev/null +++ b/includes/js/dojox/sketch/README @@ -0,0 +1,58 @@ +-------------------------------------------------------------------------------
+dojox.sketch
+-------------------------------------------------------------------------------
+Version 0.1
+Release date: 28/01/2008
+-------------------------------------------------------------------------------
+Project state:
+experimental
+-------------------------------------------------------------------------------
+Credits
+ Contributed by TeamPatent (supported by National Science Foundation grant 638334)
+ Tom Trenka (ttrenka@gmail.com)
+ Heng Liu/LiuCougar (heng@teampatent.com)
+-------------------------------------------------------------------------------
+Project description
+
+A cross-browser drawing editor based on dojox.gfx.
+-------------------------------------------------------------------------------
+Dependencies:
+
+dijit (Toolbar, Button, Slider)
+dojox.gfx
+dojox.xml
+-------------------------------------------------------------------------------
+Documentation
+
+Currently, 5 shapes are supported: line, single arrow line, double arrow line,
+underline text and text. The first 3 shapes can have optinal text associated.
+
+Shapes can be added, deleted, moved and modified. All of these operations can
+be undo-ed or redo-ed.
+
+TODO:
+ * provide UI to change various properties on shapes (fill, stroke, text) and
+allow changing of background image
+ * serialize/unserialize in dojox.gfx to svg (and maybe vml as well?) (or another
+simplier format? such as a json based one, which is easier to parse, and then
+write a convertor to convert the json format to svg or any other format?)
+ * Move mousedown/up/move to each shape (to prepare for the following)
+ * Add shapes for other primitive shapes (needs to decide which primitive
+dojox.gfx.shapes are useful), and add in support for user to group any
+shapes/groups to form a single "compound shape" (need to add support to set
+fill/stroke properties on the entire compound shape, which shallpropagate to
+all children shapes)
+-------------------------------------------------------------------------------
+Installation instructions
+
+Install dijit, dojox.gfx and dojox.xml first
+
+Grab the following from the Dojo SVN Repository:
+http://svn.dojotoolkit.org/var/src/dojo/dojox/trunk/sketch.js
+http://svn.dojotoolkit.org/var/src/dojo/dojox/trunk/sketch/*
+
+Install into the following directory structure:
+/dojox/sketch/
+
+...which should be at the same level as your Dojo checkout.
+-------------------------------------------------------------------------------
diff --git a/includes/js/dojox/sketch/SingleArrowAnnotation.js b/includes/js/dojox/sketch/SingleArrowAnnotation.js new file mode 100644 index 0000000..29ad7f0 --- /dev/null +++ b/includes/js/dojox/sketch/SingleArrowAnnotation.js @@ -0,0 +1,183 @@ +if(!dojo._hasResource["dojox.sketch.SingleArrowAnnotation"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code. +dojo._hasResource["dojox.sketch.SingleArrowAnnotation"] = true; +dojo.provide("dojox.sketch.SingleArrowAnnotation"); +dojo.require("dojox.sketch.Annotation"); +dojo.require("dojox.sketch.Anchor"); + +(function(){ + var ta=dojox.sketch; + ta.SingleArrowAnnotation=function(figure, id){ + ta.Annotation.call(this, figure, id); + this.transform={ dx:0, dy:0 }; + this.start={x:0, y:0}; + this.control={x:100, y:-50}; + this.end={x:200, y:0}; + this.textPosition={ x:0, y:0 }; + this.textOffset=4; + this.textAlign="middle"; + this.textYOffset=10; + this.rotation=0; + +// this.property('label',this.id); +// this.label=this.id; + this.pathShape=null; + this.arrowhead=null; + this.arrowheadGroup=null; + this.labelShape=null; + + this.anchors.start=new ta.Anchor(this, "start"); + this.anchors.control=new ta.Anchor(this, "control"); + this.anchors.end=new ta.Anchor(this, "end"); + }; + ta.SingleArrowAnnotation.prototype=new ta.Annotation; + var p=ta.SingleArrowAnnotation.prototype; + p.constructor=ta.SingleArrowAnnotation; + + p.type=function(){ return 'SingleArrow'; }; + p.getType=function(){ return ta.SingleArrowAnnotation; }; + + // helper functions + p._rot=function(){ + // arrowhead rotation + var opp=this.start.y-this.control.y; + var adj=this.start.x-this.control.x; + if(!adj) adj=1; + this.rotation=Math.atan(opp/adj); + }; + p._pos=function(){ + // text position + var offset=this.textOffset, x=0, y=0; + var slope=this.calculate.slope(this.control, this.end); + if(Math.abs(slope)>=1){ + x=this.end.x+this.calculate.dx(this.control, this.end, offset); + if(this.control.y>this.end.y) y=this.end.y-offset; + else y=this.end.y+offset+this.textYOffset; + } else if(slope==0){ + x=this.end.x+offset; + y=this.end.y+this.textYOffset; + } else { + if(this.start.x>this.end.x){ + x=this.end.x-offset; + this.textAlign="end"; + } else { + x=this.end.x+offset; + this.textAlign="start"; + } + if(this.start.y<this.end.y) y=this.end.y+this.calculate.dy(this.control, this.end, offset)+this.textYOffset; + else y=this.end.y+this.calculate.dy(this.control, this.end, -offset); + } + this.textPosition={ x:x, y:y }; + }; + + p.apply=function(obj){ + if(!obj) return; + if(obj.documentElement) obj=obj.documentElement; + this.readCommonAttrs(obj); + + for(var i=0; i<obj.childNodes.length; i++){ + var c=obj.childNodes[i]; + if(c.localName=="text") this.property('label',c.childNodes.length?c.childNodes[0].nodeValue:''); + else if(c.localName=="path"){ + // the line + var d=c.getAttribute('d').split(" "); + var s=d[0].split(","); + this.start.x=parseFloat(s[0].substr(1),10); + this.start.y=parseFloat(s[1],10); + s=d[1].split(","); + this.control.x=parseFloat(s[0].substr(1),10); + this.control.y=parseFloat(s[1],10); + s=d[2].split(","); + this.end.x=parseFloat(s[0],10); + this.end.y=parseFloat(s[1],10); + } + } + }; + p.initialize=function(obj){ + // create, based on passed DOM node if available. + var font=(ta.Annotation.labelFont)?ta.Annotation.labelFont:{family:"Times", size:"16px"}; + this.apply(obj); + + // calculate the other positions + this._rot(); + this._pos(); + + // rotation matrix + var rot=this.rotation; + if(this.control.x>=this.end.x&&this.control.x<this.start.x) rot+=Math.PI; + var tRot=dojox.gfx.matrix.rotate(rot); + + // draw the shapes + this.shape=this.figure.group.createGroup(); + this.shape.getEventSource().setAttribute("id", this.id); + if(this.transform.dx||this.transform.dy) this.shape.setTransform(this.transform); + this.pathShape=this.shape.createPath( + "M"+this.start.x+","+this.start.y+" Q"+this.control.x+","+this.control.y+" "+this.end.x+","+this.end.y+" l0,0" + ).setStroke(this.property('stroke')); + this.arrowheadGroup=this.shape.createGroup().setTransform({ dx:this.start.x, dy:this.start.y }).applyTransform(tRot); + this.arrowhead=this.arrowheadGroup.createPath("M0,0 l20,-5 -3,5 3,5 Z").setFill(this.property('fill')); + this.labelShape=this.shape.createText({ + x:this.textPosition.x, y:this.textPosition.y, text:this.property('label'), align:this.textAlign + }).setFont(font).setFill(this.property('fill')); + }; + p.destroy=function(){ + if(!this.shape) return; + this.arrowheadGroup.remove(this.arrowhead); + this.shape.remove(this.arrowheadGroup); + this.shape.remove(this.pathShape); + this.shape.remove(this.labelShape); + this.figure.group.remove(this.shape); + this.shape=this.pathShape=this.labelShape=this.arrowheadGroup=this.arrowhead=null; + }; + p.draw=function(obj){ + this.apply(obj); + this._rot(); + this._pos(); + + // rotation matrix + var rot=this.rotation; + if(this.control.x<this.start.x) rot+=Math.PI; + var tRot=dojox.gfx.matrix.rotate(rot); + + this.shape.setTransform(this.transform); + this.pathShape.setShape( + "M"+this.start.x+","+this.start.y+" Q"+this.control.x+","+this.control.y+" "+this.end.x+","+this.end.y+" l0,0" + ).setStroke(this.property('stroke')); + this.arrowheadGroup.setTransform({dx:this.start.x,dy:this.start.y}).applyTransform(tRot); + this.arrowhead.setFill(this.property('fill')); + this.labelShape.setShape({x:this.textPosition.x, y:this.textPosition.y, text:this.property('label'), align:this.textAlign}) + .setFill(this.property('fill')); + }; + p.getBBox=function(){ + var x=Math.min(this.start.x, this.control.x, this.end.x); + var y=Math.min(this.start.y, this.control.y, this.end.y); + var w=Math.max(this.start.x, this.control.x, this.end.x)-x; + var h=Math.max(this.start.y, this.control.y, this.end.y)-y; + return { x:x, y:y, width:w, height:h }; + }; + p.serialize=function(){ + var s=this.property('stroke'); + var r=this.rotation*(180/Math.PI); + if(this.start.x>this.end.x) r-=180; + r=Math.round(r*Math.pow(10,4))/Math.pow(10,4); + return '<g '+this.writeCommonAttrs()+'>' + + '<path style="stroke:'+s.color+';stroke-width:'+s.width+';fill:none;" d="' + + "M"+this.start.x+","+this.start.y+" " + + "Q"+this.control.x+","+this.control.y+" " + + this.end.x+","+this.end.y + + '" />' + + '<g transform="translate(' + this.start.x + "," + this.start.y + ") " + + 'rotate(' + r + ')">' + + '<path style="fill:'+s.color+';" d="M0,0 l20,-5, -3,5, 3,5 Z" />' + + '</g>' + + '<text style="fill:'+s.color+';text-anchor:'+this.textAlign+'" font-weight="bold" ' + + 'x="' + this.textPosition.x + '" ' + + 'y="' + this.textPosition.y + '">' + + this.property('label') + + '</text>' + + '</g>'; + }; + + ta.Annotation.register("SingleArrow"); +})(); + +} diff --git a/includes/js/dojox/sketch/Slider.js b/includes/js/dojox/sketch/Slider.js new file mode 100644 index 0000000..e014e78 --- /dev/null +++ b/includes/js/dojox/sketch/Slider.js @@ -0,0 +1,31 @@ +if(!dojo._hasResource["dojox.sketch.Slider"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code. +dojo._hasResource["dojox.sketch.Slider"] = true; +dojo.provide("dojox.sketch.Slider"); + +dojo.require("dijit.form.Slider"); +dojo.declare("dojox.sketch.Slider",dojox.sketch._Plugin,{ + _initButton: function(){ + this.slider=new dijit.form.HorizontalSlider({minimum:20,maximum:200,value:20,style:"width:200px;float:right"}); + this.connect(this.slider,'onChange','_setZoom'); + this.connect(this.slider.sliderHandle,'ondblclick','_zoomToFit'); + }, + _zoomToFit: function(){ + this.slider.setValue(this.figure.getFit(),true); + }, + _setZoom: function(v){ + if(this.figure){ + this.figure.zoom(v); + } + }, + setToolbar: function(t){ + t.addChild(this.slider); + if(!t._reset2Zoom){ + t._reset2Zoom=true; + this.connect(t,'reset','_zoomToFit'); + } + } +}); + +dojox.sketch.registerTool("Slider", dojox.sketch.Slider); + +} diff --git a/includes/js/dojox/sketch/Toolbar.js b/includes/js/dojox/sketch/Toolbar.js new file mode 100644 index 0000000..73dc82c --- /dev/null +++ b/includes/js/dojox/sketch/Toolbar.js @@ -0,0 +1,96 @@ +if(!dojo._hasResource["dojox.sketch.Toolbar"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code. +dojo._hasResource["dojox.sketch.Toolbar"] = true; +dojo.provide("dojox.sketch.Toolbar"); + +dojo.require("dojox.sketch.Annotation"); +dojo.require("dijit.Toolbar"); +dojo.require("dijit.form.Button"); +dojo.require("dijit.form.Slider"); + +dojo.declare("dojox.sketch.ButtonGroup", null, { + constructor: function(){ + this._childMaps={}; + this._children=[]; + }, + add: function(/*_Plugin*/ plugin){ + this._childMaps[plugin]=plugin.connect(plugin,'onActivate',dojo.hitch(this,'_resetGroup',plugin)); + this._children.push(plugin); + }, +// remove: function(/*_Plugin*/ plugin){ +// widget.disconnect(this._childMaps[widget.id]); +// delete this._childMaps[widget.id]; +// this._children.splice(this._children.indexOf(widget.id),1); +// }, + _resetGroup: function(p){ + var cs=this._children; + dojo.forEach(cs,function(c){ + if(p!=c && c['attr']){ + c.attr('checked',false); + } + }); + } +}); + +dojo.declare("dojox.sketch.Toolbar", dijit.Toolbar, { + figure: null, + plugins: null, + postCreate: function(){ + this.inherited(arguments); + this.shapeGroup=new dojox.sketch.ButtonGroup; + + this.connect(this.figure,'onLoad','reset'); + if(!this.plugins){ + this.plugins=['Slider','Lead','SingleArrow','DoubleArrow','Underline','Preexisting']; + } + this._plugins=[]; + + dojo.forEach(this.plugins,function(obj){ + var name=dojo.isString(obj)?obj:obj.name; + var p=new dojox.sketch.tools[name](obj.args||{}); + this._plugins.push(p); + p.setFigure(this.figure); + p.setToolbar(this); + if(!this._defaultTool && p.button){ + this._defaultTool=p; + } + },this); + }, + destroy: function(){ + dojo.forEach(this._plugins,function(p){ + p.destroy(); + }); + this.inherited(arguments); + delete this._defaultTool; + delete this._plugins; + }, + addGroupItem: function(/*_Plugin*/item,group){ + if(group!='toolsGroup'){ + console.error('not supported group '+group); + return; + } + + this.shapeGroup.add(item); + }, + reset: function(){ + this._defaultTool.activate(); + }, + _setShape: function(s){ + if(!this.figure.surface) return; + // now do the action. + if(this.figure.hasSelections()){ + for(var i=0; i<this.figure.selected.length; i++){ + var before=this.figure.selected[i].serialize(); + this.figure.convert(this.figure.selected[i], s); + this.figure.history.add(ta.CommandTypes.Convert, this.figure.selected[i], before); + } + } + } +}); + +dojox.sketch.makeToolbar=function(node,figure){ + var toolbar=new dojox.sketch.Toolbar({"figure":figure}); + node.appendChild(toolbar.domNode); + return toolbar; +}; + +} diff --git a/includes/js/dojox/sketch/UnderlineAnnotation.js b/includes/js/dojox/sketch/UnderlineAnnotation.js new file mode 100644 index 0000000..7b67053 --- /dev/null +++ b/includes/js/dojox/sketch/UnderlineAnnotation.js @@ -0,0 +1,82 @@ +if(!dojo._hasResource["dojox.sketch.UnderlineAnnotation"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code. +dojo._hasResource["dojox.sketch.UnderlineAnnotation"] = true; +dojo.provide("dojox.sketch.UnderlineAnnotation"); +dojo.require("dojox.sketch.Annotation"); +dojo.require("dojox.sketch.Anchor"); + +(function(){ + var ta=dojox.sketch; + ta.UnderlineAnnotation=function(figure, id){ + ta.Annotation.call(this, figure, id); + this.transform={dx:0, dy:0}; + this.start={x:0, y:0}; + this.property('label',this.id); + this.labelShape=null; + this.lineShape=null; + this.anchors.start=new ta.Anchor(this, "start", false); + }; + ta.UnderlineAnnotation.prototype=new ta.Annotation; + var p=ta.UnderlineAnnotation.prototype; + p.constructor=ta.UnderlineAnnotation; + + p.type=function(){ return 'Underline'; }; + p.getType=function(){ return ta.UnderlineAnnotation; }; + + p.apply=function(obj){ + if(!obj) return; + if(obj.documentElement) obj=obj.documentElement; + this.readCommonAttrs(obj); + + for(var i=0; i<obj.childNodes.length; i++){ + var c=obj.childNodes[i]; + if(c.localName=="text") this.property('label',c.childNodes[0].nodeValue); + } + }; + + p.initialize=function(obj){ + var font=(ta.Annotation.labelFont)?ta.Annotation.labelFont:{family:"Times", size:"16px"}; + this.apply(obj); + + // create either from scratch or based on the passed node + this.shape=this.figure.group.createGroup(); + this.shape.getEventSource().setAttribute("id", this.id); + if(this.transform.dx || this.transform.dy) this.shape.setTransform(this.transform); + this.labelShape=this.shape.createText({ + x:0, y:0, text:this.property('label'), align:"start" + }).setFont(font).setFill(this.property('fill')); + this.lineShape=this.shape.createLine({ x1:1, x2:this.labelShape.getTextWidth(), y1:2, y2:2 }).setStroke({ color:this.property('fill'), width:1 }); + this.lineShape.getEventSource().setAttribute("shape-rendering","crispEdges"); + }; + p.destroy=function(){ + if(!this.shape) return; + this.shape.remove(this.labelShape); + this.shape.remove(this.lineShape); + this.figure.group.remove(this.shape); + this.shape=this.lineShape=this.labelShape=null; + }; + p.getBBox=function(){ + var b=this.getTextBox(); +// console.log('getBBox',b,this.getLabel()); + return { x:0, y:b.h*-1+4, width:b.w+2, height:b.h }; + }; + p.draw=function(obj){ + this.apply(obj); + this.shape.setTransform(this.transform); + this.labelShape.setShape({ x:0, y:0, text:this.property('label') }).setFill(this.property('fill')); + this.lineShape.setShape({ x1:1, x2:this.labelShape.getTextWidth()+1, y1:2, y2:2 }).setStroke({ color:this.property('fill'), width:1 }); + }; + p.serialize=function(){ + var s=this.property('stroke'); + return '<g '+this.writeCommonAttrs()+'>' + + '<line x1="1" x2="'+this.labelShape.getTextWidth()+1+'" y1="5" y2="5" style="stroke:'+s.color+';stroke-weight:'+s.width+'" />' + + '<text style="fill:'+this.property('fill')+';" font-weight="bold" ' + + 'x="0" y="0">' + + this.property('label') + + '</text>' + + '</g>'; + }; + + ta.Annotation.register("Underline"); +})(); + +} diff --git a/includes/js/dojox/sketch/UndoStack.js b/includes/js/dojox/sketch/UndoStack.js new file mode 100644 index 0000000..e711557 --- /dev/null +++ b/includes/js/dojox/sketch/UndoStack.js @@ -0,0 +1,104 @@ +if(!dojo._hasResource["dojox.sketch.UndoStack"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code. +dojo._hasResource["dojox.sketch.UndoStack"] = true; +dojo.provide("dojox.sketch.UndoStack"); +dojo.require("dojox.xml.DomParser"); + +(function(){ + var ta=dojox.sketch; + ta.CommandTypes={ Create:"Create", Move:"Move", Modify:"Modify", Delete:"Delete", Convert:"Convert"}; + + dojo.declare("dojox.sketch.UndoStack",null,{ + constructor: function(figure){ + this.figure=figure; + this._steps=[]; + this._undoedSteps=[]; + }, + apply: function(state, from, to){ + // the key here is to neutrally move from one state to another. + // we let the individual functions (i.e. undo and redo) actually + // determine the from and to; all we do here is implement it. + + // check whether this is a fullText step + if(!from && !to && state.fullText){ + this.figure.setValue(state.fullText); + return; + } + + var fromText=from.shapeText; + var toText=to.shapeText; + + if(fromText.length==0&&toText.length==0){ + // nothing to reapply? + return; + } + if(fromText.length==0){ + // We are creating. + var o=dojox.xml.DomParser.parse(toText).documentElement; + var a=this.figure._loadAnnotation(o); + if(a) this.figure._add(a); + return; + } + if(toText.length==0){ + // we are deleting. + var ann=this.figure.get(from.shapeId); + this.figure._delete([ann],true); + return; + } + + // we can simply reinit and draw from the shape itself, + // regardless of the actual command. + var nann=this.figure.get(to.shapeId); + var no=dojox.xml.DomParser.parse(toText).documentElement; + nann.draw(no); + this.figure.select(nann); + return; + }, + // stack methods. + add: function(/*String*/cmd, /*ta.Annotation?*/ann, /*String?*/before){ + var id=ann?ann.id:''; + //var bbox=ann?ann.getBBox():{}; + var after=ann?ann.serialize():""; + if(cmd==ta.CommandTypes.Delete) after=""; + + /*if(ann){ + // fix the bbox x/y coords + var t=ann.transform; + bbox.x+=t.dx; + bbox.y+=t.dy; + }*/ + var state={ + cmdname:cmd, + //bbox:bbox, +// fullText:fullText, + before:{ + shapeId: id, + shapeText:before||'' + }, + after:{ + shapeId: id, + shapeText:after + } + }; + //console.log('dojox.sketch history add',state); + this._steps.push(state); + this._undoedSteps = []; + }, + destroy: function(){}, + undo: function(){ + var state=this._steps.pop(); + if(state){ + this._undoedSteps.push(state); + this.apply(state,state.after,state.before); + } + }, + redo: function(){ + var state=this._undoedSteps.pop(); + if(state){ + this._steps.push(state); + this.apply(state,state.before,state.after); + } + } + }); +})(); + +} diff --git a/includes/js/dojox/sketch/_Plugin.js b/includes/js/dojox/sketch/_Plugin.js new file mode 100644 index 0000000..fb7cb93 --- /dev/null +++ b/includes/js/dojox/sketch/_Plugin.js @@ -0,0 +1,83 @@ +if(!dojo._hasResource["dojox.sketch._Plugin"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code. +dojo._hasResource["dojox.sketch._Plugin"] = true; +dojo.provide("dojox.sketch._Plugin"); +//dojo.require("dojox.sketch"); +dojo.require("dijit.form.Button"); + +dojo.declare("dojox.sketch._Plugin", null, { + // summary + // This represents a "plugin" to the dojox.sketch.Figure, which is basically + // a single button on the Toolbar and some associated code + constructor: function(/*Object?*/args){ + if(args){ + dojo.mixin(this, args); + } + this._connects=[]; + }, + + figure: null, + iconClassPrefix: "dojoxSketchIcon", + itemGroup: 'toolsGroup', + button: null, + queryCommand: null, + shape: "", + useDefaultCommand: true, + buttonClass: dijit.form.ToggleButton, + _initButton: function(){ + if(this.shape.length){ + //TODO: i18n +// var label = dojox.sketch.shapes[this.shape]; + var className = this.iconClassPrefix+" "+this.iconClassPrefix + this.shape.charAt(0).toUpperCase() + this.shape.substr(1); + if(!this.button){ + var props = { + label: this.shape, + showLabel: false, + iconClass: className, + dropDown: this.dropDown, + tabIndex: "-1" + }; + this.button = new this.buttonClass(props); + this.connect(this.button,'onClick','activate'); + } + } + }, + attr: function(name,/*?*/value){ + if(arguments.length>1){ + this.button.setAttribute(name,value); + }else{ + this.button.getAttribute(name); + } + }, + onActivate: function(){}, + activate: function(/*?*/e){ + this.onActivate(); + this.figure.setTool(this); + this.attr('checked',true); + }, + onMouseDown: function(e){}, + onMouseMove: function(e){}, + onMouseUp: function(e){}, + destroy: function(f){ + dojo.forEach(this._connects,dojo.disconnect); + }, + connect: function(o,f,tf){ + this._connects.push(dojo.connect(o,f,this,tf)); + }, + setFigure: function(/*Widget*/figure){ + // FIXME: detatch from previous figure!! + this.figure = figure; + + // FIXME: prevent creating this if we don't need to (i.e., figure can't handle our command) + this._initButton(); + }, + setToolbar: function(/*Widget*/toolbar){ + if(this.button){ + toolbar.addChild(this.button); + } + if(this.itemGroup){ + toolbar.addGroupItem(this,this.itemGroup); + } + } +}); + +} diff --git a/includes/js/dojox/sketch/resources/images/icons.gif b/includes/js/dojox/sketch/resources/images/icons.gif Binary files differnew file mode 100644 index 0000000..ab33b0a --- /dev/null +++ b/includes/js/dojox/sketch/resources/images/icons.gif diff --git a/includes/js/dojox/sketch/resources/sketch.css b/includes/js/dojox/sketch/resources/sketch.css new file mode 100644 index 0000000..7451395 --- /dev/null +++ b/includes/js/dojox/sketch/resources/sketch.css @@ -0,0 +1,17 @@ +.dojoxSketchIcon{ + background-repeat:no-repeat; + height:16px; + min-width:16px; + text-align:center; + width:16px; +} +.dojoxSketchIcon { background-image:url(images/icons.gif); } +.ShowCallouts{ background-position:0px 0px; } +.PreviousCallout{ background-position:0px -16px; } +.NextCallout{ background-position:0px -32px; } +.dojoxSketchIconLead{ background-position:0px -48px; } +.dojoxSketchIconUnderline{ background-position:0px -64px; } +.dojoxSketchIconSingleArrow{ background-position:0px -80px; } +.dojoxSketchIconBrace{ background-position:0px -96px; } +.dojoxSketchIconDoubleArrow{ background-position:0px -112px; } +.dojoxSketchIconPreexisting{ background-position:0px -128px; } diff --git a/includes/js/dojox/sketch/resources/sketch.css.commented.css b/includes/js/dojox/sketch/resources/sketch.css.commented.css new file mode 100644 index 0000000..7451395 --- /dev/null +++ b/includes/js/dojox/sketch/resources/sketch.css.commented.css @@ -0,0 +1,17 @@ +.dojoxSketchIcon{ + background-repeat:no-repeat; + height:16px; + min-width:16px; + text-align:center; + width:16px; +} +.dojoxSketchIcon { background-image:url(images/icons.gif); } +.ShowCallouts{ background-position:0px 0px; } +.PreviousCallout{ background-position:0px -16px; } +.NextCallout{ background-position:0px -32px; } +.dojoxSketchIconLead{ background-position:0px -48px; } +.dojoxSketchIconUnderline{ background-position:0px -64px; } +.dojoxSketchIconSingleArrow{ background-position:0px -80px; } +.dojoxSketchIconBrace{ background-position:0px -96px; } +.dojoxSketchIconDoubleArrow{ background-position:0px -112px; } +.dojoxSketchIconPreexisting{ background-position:0px -128px; } diff --git a/includes/js/dojox/sketch/tests/annotation.svg b/includes/js/dojox/sketch/tests/annotation.svg new file mode 100644 index 0000000..9638588 --- /dev/null +++ b/includes/js/dojox/sketch/tests/annotation.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:dojoxsketch="http://dojotoolkit.org/dojox/sketch" width="1000" height="1000"><g><image xlink:href="images/figure2.gif" x="0" y="0" width="1000" height="1000" /><g id="ann-1" dojoxsketch:type="Lead" transform="translate(437,169)"><path style="stroke:blue;stroke-width:2;fill:none;" d="M0,0 Q100,-50 200,0" /><text style="fill:blue;text-anchor:start" font-weight="bold" x="204" y="-2">1</text></g><g id="ann-2" dojoxsketch:type="Preexisting" transform="translate(526,408)"><rect style="stroke:blue;stroke-weight:1;fill:none;" x="0" width="104" y="0" height="210" rx="8" ry="8" /><text style="fill:blue;text-anchor:end" font-weight="bold" x="100" y="206">2</text></g><g id="ann-3" dojoxsketch:type="SingleArrow" transform="translate(537,804)"><path style="stroke:blue;stroke-width:2;fill:none;" d="M-44,13 Q-137,38 -162,-23" /><g transform="translate(-44,13) rotate(-195.0464)"><path style="fill:blue;" d="M0,0 l20,-5, -3,5, 3,5 Z" /></g><text style="fill:blue;text-anchor:middle" font-weight="bold" x="-160.36065573770492" y="-27">3</text></g><g id="ann-4" dojoxsketch:type="DoubleArrow" transform="translate(329,-7)"><path style="stroke:blue;stroke-width:2;fill:none;" d="M249,306 Q505,242 426,389" /><g transform="translate(249,306) rotate(-14.0362)"><path style="fill:blue;" d="M0,0 l20,-5, -3,5, 3,5 Z" /></g><g transform="rotate(-61.7458, 426, 389)"><path style="fill:blue;" d="M426,389 l-20,-5, 3,5, -3,5 Z" /></g><text style="fill:blue;text-anchor:middle" font-weight="bold" x="421.25" y="288.75">4</text></g><g id="ann-5" dojoxsketch:type="Underline" transform="translate(821,517)"><line x1="1" x2="91" y1="5" y2="5" style="stroke:blue;stroke-weight:2" /><text style="fill:blue;" font-weight="bold" x="0" y="0">5</text></g></g></svg>
\ No newline at end of file diff --git a/includes/js/dojox/sketch/tests/images/figure2.gif b/includes/js/dojox/sketch/tests/images/figure2.gif Binary files differnew file mode 100644 index 0000000..7218a4c --- /dev/null +++ b/includes/js/dojox/sketch/tests/images/figure2.gif diff --git a/includes/js/dojox/sketch/tests/images/testsBodyBg.gif b/includes/js/dojox/sketch/tests/images/testsBodyBg.gif Binary files differnew file mode 100644 index 0000000..4e0b4a7 --- /dev/null +++ b/includes/js/dojox/sketch/tests/images/testsBodyBg.gif diff --git a/includes/js/dojox/sketch/tests/test_full.html b/includes/js/dojox/sketch/tests/test_full.html new file mode 100644 index 0000000..b78c232 --- /dev/null +++ b/includes/js/dojox/sketch/tests/test_full.html @@ -0,0 +1,66 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+ "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+ <head>
+ <title>Annotator/Figure Testing</title>
+<style type="text/css">
+@import "../../../dojo/resources/dojo.css";
+@Import "../../../dijit/themes/tundra/tundra.css";
+</style>
+ <link href="../resources/sketch.css" type="text/css" rel="stylesheet"/>
+ <style type="text/css">
+ body {
+ background:#fff url("images/testsBodyBg.gif") repeat-x top left;
+ padding:1em 3em;
+ }
+ table { margin:0; width:100%;}
+ table tr td { padding:0; }
+ table tr td table { border:0; width:auto;}
+
+ #container{ width:600px; }
+ #toolbar{ width:100%; }
+ #canvas{ width:600px; height:600px; background-color:#fff;border:1px solid #ccc; overflow:auto;position:relative;}
+ </style>
+ <script>var djConfig={ isDebug: false };</script>
+ <script src="../../../dojo/dojo.js"></script>
+ <script src="../Toolbar.js"></script>
+ <script>
+ dojo.require("dojox.sketch");
+ dojo.require("dojox.sketch.Slider");
+ dojo.require("dojox.sketch.LeadAnnotation");
+ dojo.require("dojox.sketch.UnderlineAnnotation");
+ dojo.require("dojox.sketch.SingleArrowAnnotation");
+ dojo.require("dojox.sketch.DoubleArrowAnnotation");
+ dojo.require("dojox.sketch.PreexistingAnnotation");
+ var f, a, t;
+ function init(){
+ var ta=dojox.sketch;
+ f=new ta.Figure();
+ dojo.connect(f, "_mu", function(){ dojo.byId("output").value=f.serialize(); });
+
+ t=ta.makeToolbar(dojo.byId("toolbar"), f);
+
+ // test loading from an SVG file
+ dojo.xhrGet({
+ url:"annotation.svg",
+ preventCache:true,
+ load:function(data, ioArgs){
+ f.load(dojox.xml.DomParser.parse(data), dojo.byId("canvas"));
+ dojo.byId("output").value=f.serialize();
+ }
+ });
+ }
+ dojo.addOnLoad(init);
+ </script>
+ </head>
+ <body class="tundra">
+ <h1>Annotator/Figure Testing Platform</h1>
+ <p>This is a generic test to create a figure from an existing SVG file, to edit that figure, and to test the undo stack. Double click a shape to set new text for it.</p>
+ <div id="container">
+ <div id="toolbar"></div>
+ <div id="canvas"></div>
+ </div>
+ <h2>Serialized output</h2>
+ <textarea id="output" style="width:100%;height:180px;overflow:auto;font-size:0.8em;"></textarea>
+ </body>
+</html>
|