#+ #+ This library provides functions to paint screen canvas #+ drawings, drawn with the ui.fgldraw #+ functions on !!!PXML reports. The program canvas.4gl #+ demonstrates the usage of this library. #+ If more sophisticated drawing capabilities are required, the #+ !!!PXML drawing elements should be used directly. Particulary #+ the CANVASPATH #+ layout node should be considered as is covers most of the #+ capabilities of the screen drawing library, providing some #+ additional features such as cubic and quadratic bezier curves. #+ See also PXML Layout Nodes for Drawing #+ and PXML Layout Nodes for Text Output. #+ Some examples of drawings, using these elements can be found #+ here. #+ #+ define globalWidthExpr String define globalHeightExpr String define globalFontSize integer globals DEFINE __fgldraw_theCanvas om.DomNode DEFINE __fgldraw_theCanvas_lineWidth INTEGER end globals #+ #+ !!!PxmlExpression specifying the width of the paint area. #+ The drawing coordinate values (0..1000) are scaled into the #+ specified width. If for example a width of "10.01cm" is specified, then #+ then and object specified at coordinate x=499 will be drawn at #+ position x=5cm. #+ #+ #+ !!!PxmlExpression specifying the height of the paint area. #+ The drawing coordinate values (0..1000) are scaled into the #+ specified height. If for example a height of "10.01cm" is specified, then #+ then and object specified at coordinate y=499 will be drawn at #+ position y=5cm. #+ #+ #+ Font size in point. #+ "widthExpr" and "heightExpr" are inserted as "width" and "length" #+ values in the generated PXML root node. Further scaleX is set to #+ widthExpr/1000 and scaleY to heightExpr/1000. fontSize is set to #+ 12*heightExpr/1000. #+ #+ #+ FUNCTION drawSetSize(widthExpr,heightExpr,fontSize) define widthExpr String define heightExpr String define fontSize integer let globalWidthExpr=widthExpr let globalHeightExpr=heightExpr let globalFontSize=fontSize END FUNCTION function initDefaults() if globalWidthExpr is null then let globalWidthExpr="10cm" end if if globalHeightExpr is null then let globalHeightExpr="10cm" end if if globalFontSize is null then let globalFontSize=12 end if end function #+ #+ SaxDocumentHandler receiving PXML markup. #+ Does not modify the current canvas Dom tree. #+ #+ May generate different output between calls if global variables are modified. #+ #+ function outputCurrentCanvasToPXML(out) define out om.SaxDocumentHandler call initDefaults() call outputCanvasToPXML(out,__fgldraw_theCanvas) end function function outputCanvasToPXML(out,canvasRoot) define out om.SaxDocumentHandler define canvasRoot om.DomNode define n om.DomNode call outputMappedNodePre(out,canvasRoot) let n=canvasRoot.getFirstChild() while n is not null call outputCanvasToPxml(out,n) let n=n.getNext() end while call outputMappedNodePost(out,canvasRoot) end function function outputMappedNodePre(out,node) define out om.SaxDocumentHandler define node om.DomNode define a om.SaxAttributes define name,s String let name=node.getTagName() if name.equals("CanvasLine") then call outputCanvasLinePre(out,node) else if name.equals("CanvasText") then call outputCanvastextPre(out,node) else if name.equals("CanvasRectangle") then call outputCanvasRectanglePre(out,node) else if name.equals("CanvasCircle") then call outputCanvasCirclePre(out,node) else if name.equals("CanvasOval") then call outputCanvasOvalPre(out,node) else if name.equals("CanvasPolygon") then call outputCanvasPolygonPre(out,node) else if name.equals("CanvasArc") then call outputCanvasArcPre(out,node) else call outputCanvasRootPre(out,node) end if end if end if end if end if end if end if end function function outputMappedNodePost(out,node) define out om.SaxDocumentHandler define node om.DomNode define name String let name=node.getTagName() if name.equals("CanvasLine") then call outputCanvasLinePost(out) else if name.equals("CanvasText") then call outputCanvasTextPost(out) else if name.equals("CanvasRectangle") then call outputCanvasRectanglePost(out) else if name.equals("CanvasCircle") then call outputCanvasCirclePost(out) else if name.equals("CanvasOval") then call outputCanvasOvalPost(out) else if name.equals("CanvasPolygon") then call outputCanvasPolygonPost(out) else if name.equals("CanvasArc") then call outputCanvasArcPost(out) else call outputCanvasRootPost(out) end if end if end if end if end if end if end if end function function getLineWidth() return getLineWidth1(__fgldraw_theCanvas_lineWidth) end function function getLineWidth1(lineWidth) define lineWidth integer define s String let s=globalHeightExpr||"/1000point" return lineWidth||"/("||s||")" end function function outputCanvasLinePre(out,node) define out om.SaxDocumentHandler define node om.DomNode define s String define a om.SaxAttributes LET a=om.SaxAttributes.create() call a.addAttribute("startX",node.getAttribute("startX")) call a.addAttribute("startY",node.getAttribute("startY")) call a.addAttribute("endX",node.getAttribute("endX")) call a.addAttribute("endY",node.getAttribute("endY")) #CanvasLine is the only node type where the lineWidth is passed in the #DOM tree. call a.addAttribute("lineWidth",getLineWidth1(node.getAttribute("width"))) let s=getAttributeValueDom(node,"fillColor") #when color is null -> black if s is null then call a.addAttribute("lineColor","black") else call a.addAttribute("lineColor",s) end if if not compatibleWith704() then call a.addAttribute("layoutDirection","swapped") call a.addAttribute("swapX","swapped") end if call out.startElement("CANVASLINE",a) end function function outputCanvasLinePost(out) define out om.SaxDocumentHandler call out.endElement("CANVASLINE") end function #feature request, not compatible to gui clients, leads to incompatibilities #in test suite where large text overwrites background in some cases. function setTextBackground(a,node) define a om.SaxAttributes define node om.DomNode define bgColor String let bgColor=node.getAttribute("fillColor") #treat "white" as transparent #if you need white write "#ffffff" instead. if not bgColor.equals("white") then call a.addAttribute("bgColor",bgColor) end if end function function outputCanvasTextPre(out,node) define out om.SaxDocumentHandler define node om.DomNode define s,bgColor String define a om.SaxAttributes LET a=om.SaxAttributes.create() call a.addAttribute("text",node.getAttribute("text")) # call setTextBackground(a,node) let s=getAttributeValueDom(node,"anchor") if s is null then call a.addAttribute("x",node.getAttribute("startX")) call a.addAttribute("y",node.getAttribute("startY")) else if s.equals("sw") or s.equals("ws") then call a.addAttribute("x",node.getAttribute("startX")) call a.addAttribute("y",node.getAttribute("startY")) else if s.equals("se") or s.equals("es") then call a.addAttribute("x",node.getAttribute("startX")||"-length(\""||quote(node.getAttribute("text"))||"\")") call a.addAttribute("y",node.getAttribute("startY")) else if s.equals("ne") or s.equals("en") then call a.addAttribute("x",node.getAttribute("startX")||"-width(\""||quote(node.getAttribute("text"))||"\")") call a.addAttribute("y",node.getAttribute("startY")||"-length(\""||quote(node.getAttribute("text"))||"\")") else if s.equals("nw") or s.equals("wn") then call a.addAttribute("x",node.getAttribute("startX")) call a.addAttribute("y",node.getAttribute("startY")||"-length(\""||quote(node.getAttribute("text"))||"\")") else if s.equals("s") then call a.addAttribute("x",node.getAttribute("startX")||"-width(\""||quote(node.getAttribute("text"))||"\")/2") call a.addAttribute("y",node.getAttribute("startY")) else if s.equals("n") then call a.addAttribute("x",node.getAttribute("startX")||"-width(\""||quote(node.getAttribute("text"))||"\")/2") call a.addAttribute("y",node.getAttribute("startY")||"-length(\""||quote(node.getAttribute("text"))||"\")") else if s.equals("e") then call a.addAttribute("x",node.getAttribute("startX")||"-width(\""||quote(node.getAttribute("text"))||"\")") call a.addAttribute("y",node.getAttribute("startY")||"-length(\""||quote(node.getAttribute("text"))||"\")/2") else if s.equals("w") then call a.addAttribute("x",node.getAttribute("startX")) call a.addAttribute("y",node.getAttribute("startY")||"-length(\""||quote(node.getAttribute("text"))||"\")/2") end if end if end if end if end if end if end if end if end if call a.addAttribute("selfPlacing","true"); call a.addAttribute("selfAdjusting","true"); if compatibleWith704() then call a.addAttribute("orientation","vertical"); call a.addAttribute("fillingDirection","lrtb"); call a.addAttribute("mirrored","true"); end if call out.startElement("WORDBOX",a) end function function outputCanvasTextPost(out) define out om.SaxDocumentHandler call out.endElement("WORDBOX") end function function outputCanvasRectanglePre(out,node) define out om.SaxDocumentHandler define node om.DomNode define s String define a om.SaxAttributes LET a=om.SaxAttributes.create() #here the attachment point is "se" call a.addAttribute("lineColor","black") call a.addAttribute("lineWidth",getLineWidth()) call a.addAttribute("color",node.getAttribute("fillColor")) call a.addAttribute("xyList",node.getAttribute("startX")||" "|| node.getAttribute("startY")||" "|| node.getAttribute("endX")||" "|| node.getAttribute("startY")||" "|| node.getAttribute("endX")||" "|| node.getAttribute("endY")||" "|| node.getAttribute("startX")||" "|| node.getAttribute("endY")) if not compatibleWith704() then call a.addAttribute("layoutDirection","swapped") call a.addAttribute("swapX","swapped") end if call out.startElement("CANVASPOLYGON",a) end function function outputCanvasRectanglePost(out) define out om.SaxDocumentHandler call out.endElement("CANVASPOLYGON") end function function outputCanvasCirclePre(out,node) define out om.SaxDocumentHandler define node om.DomNode define s String define a om.SaxAttributes LET a=om.SaxAttributes.create() call a.addAttribute("lineColor","black") call a.addAttribute("lineWidth",getLineWidth()) call a.addAttribute("color",node.getAttribute("fillColor")) #Attachment point is "ne" of bounding rect call a.addAttribute("startX",node.getAttribute("startX")||"+0.5*"||node.getAttribute("diameter")) call a.addAttribute("startY",node.getAttribute("startY")||"-0.5*"||node.getAttribute("diameter")) call a.addAttribute("radius",node.getAttribute("diameter")||"/2") if not compatibleWith704() then call a.addAttribute("layoutDirection","swapped") call a.addAttribute("swapX","swapped") end if call out.startElement("CANVASOVAL",a) end function function outputCanvasCirclePost(out) define out om.SaxDocumentHandler call out.endElement("CANVASOVAL") end function function outputCanvasOvalPre(out,node) define out om.SaxDocumentHandler define node om.DomNode define s String define a om.SaxAttributes LET a=om.SaxAttributes.create() call a.addAttribute("lineColor","black") call a.addAttribute("lineWidth",getLineWidth()) call a.addAttribute("color",node.getAttribute("fillColor")) call a.addAttribute("radiusX","0.5*("||node.getAttribute("endX")||"-"||node.getAttribute("startX")||")") call a.addAttribute("radiusY","0.5*("||node.getAttribute("endY")||"-"||node.getAttribute("startY")||")") #Attachment point is "ne" of bounding rect call a.addAttribute("startX",node.getAttribute("startX")||"+"||a.getValue("radiusX")) call a.addAttribute("startY",node.getAttribute("startY")||"+"||a.getValue("radiusY")) if not compatibleWith704() then call a.addAttribute("layoutDirection","swapped") call a.addAttribute("swapX","swapped") end if call out.startElement("CANVASOVAL",a) end function function outputCanvasOvalPost(out) define out om.SaxDocumentHandler call out.endElement("CANVASOVAL") end function function outputCanvasPolygonPre(out,node) define out om.SaxDocumentHandler define node om.DomNode define s String define a om.SaxAttributes LET a=om.SaxAttributes.create() #Canvas is drawn without border #call a.addAttribute("lineColor","black") #call a.addAttribute("lineWidth",getLineWidth()) call a.addAttribute("color",node.getAttribute("fillColor")) #list is really a yxList call a.addAttribute("swapXY","true") call a.addAttribute("xyList",node.getAttribute("xyList")) if not compatibleWith704() then call a.addAttribute("layoutDirection","swapped") call a.addAttribute("swapX","swapped") end if call out.startElement("CANVASPOLYGON",a) end function function outputCanvasPolygonPost(out) define out om.SaxDocumentHandler call out.endElement("CANVASPOLYGON") end function function outputCanvasArcPre(out,node) define out om.SaxDocumentHandler define node om.DomNode define s String define a om.SaxAttributes LET a=om.SaxAttributes.create() call a.addAttribute("lineColor","black") call a.addAttribute("lineWidth",getLineWidth()) call a.addAttribute("color",node.getAttribute("fillColor")) #Attachment point is "ne" of bounding rect call a.addAttribute("startX",node.getAttribute("startX")||"+0.5*"||node.getAttribute("diameter")) call a.addAttribute("startY",node.getAttribute("startY")||"-0.5*"||node.getAttribute("diameter")) call a.addAttribute("radius",node.getAttribute("diameter")||"/2") call a.addAttribute("startDegrees",node.getAttribute("startDegrees")) call a.addAttribute("extentDegrees",node.getAttribute("extentDegrees")) #call a.addAttribute("startAngle","rad("||node.getAttribute("startDegrees")||")") #call a.addAttribute("extendAngle","rad("||node.getAttribute("extentDegrees")||")") if not compatibleWith704() then call a.addAttribute("layoutDirection","swapped") call a.addAttribute("swapX","swapped") end if call out.startElement("CANVASARC",a) end function function outputCanvasArcPost(out) define out om.SaxDocumentHandler call out.endElement("CANVASARC") end function function outputCanvasRootPre(out,node) define out om.SaxDocumentHandler define node om.DomNode define s String define a om.SaxAttributes LET a=om.SaxAttributes.create() if compatibleWith704() then call a.addAttribute("orientation","vertical") call a.addAttribute("fillingDirection","rlbt") else call a.addAttribute("layoutDirection","bottomToTop") end if call a.addAttribute("width","1000point") call a.addAttribute("length","1000point") call a.addAttribute("scaleX",globalWidthExpr||"/1000point") call a.addAttribute("scaleY",globalHeightExpr||"/1000point") call a.addAttribute("fontSize",globalFontSize||"/("||a.getValue("scaleY")||")") #call a.addAttribute("bgColor","#c0c0c0") call out.startElement("LAYOUTNODE",a) end function function outputCanvasRootPost(out) define out om.SaxDocumentHandler call out.endElement("LAYOUTNODE") end function function quote(s) define s,result,c String define i,l integer let result=" "; let result=result.trim() let l=s.getLength() for i =1 to l let c=s.getCharAt(i) if c.equals("\\") then let result=result||c end if let result=result||c end for return result end function