#+
#+ 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