Objects

Connections are drawn as lines (with the specified line type) and rectangles for the vertices.

«*»= static void RedrawConnections() int i; RectangleType r;

for(i=0;i<currentSection->itemNum;i++) if(currentSection->items[i].type == CONNECTION) int j; Word pat; Connection *con=&currentSection->items[i].itemdata.con;

if(currentSection->items[i].itemdata.con.vertexnum>0) «set line pattern» for(j=0;j<currentSection->items[i].itemdata.con.vertexnum-1;j++) «prepare vertex coordinates» «draw vertex»

DrawLine((con->vertices[j].x-currentSection->si.xoffset)*currentSection->si.scale, (con->vertices[j].y-currentSection->si.yoffset)*currentSection->si.scale, (con->vertices[j+1].x-currentSection->si.xoffset)*currentSection->si.scale, (con->vertices[j+1].y-currentSection->si.yoffset)*currentSection->si.scale,pat);

«prepare last vertex coordinates» «draw last vertex» «draw arrow head»

@

«set line pattern»= switch(currentSection->items[i].itemdata.con.linetype) case LINE0: pat=Line0Pattern; break; case LINE1: pat=Line1Pattern; break; case LINE2: pat=Line2Pattern; break; case LINE3: pat=Line3Pattern; break; @

«prepare vertex coordinates»= r.topLeft.x=(con->vertices[j].x-currentSection->si.xoffset)*currentSection->si.scale-VERTEXRECT/2; r.topLeft.y=(con->vertices[j].y-currentSection->si.yoffset)*currentSection->si.scale-VERTEXRECT/2; r.extent.x=VERTEXRECT; r.extent.y=VERTEXRECT; @

«prepare last vertex coordinates»= r.topLeft.x=(con->vertices[j].x-currentSection->si.xoffset)*currentSection->si.scale-VERTEXRECT/2; r.topLeft.y=(con->vertices[j].y-currentSection->si.yoffset)*currentSection->si.scale-VERTEXRECT/2; r.extent.x=VERTEXRECT; r.extent.y=VERTEXRECT; @

«draw vertex»= if(mode==INSERT_VERTEX || mode==MOVE_VERTEX || mode==DEL_VERTEX) WinDrawRectangleFrame(simpleFrame,&r); @

«draw last vertex»= if(mode==INSERT_VERTEX || mode==MOVE_VERTEX || mode==DEL_VERTEX) WinDrawRectangleFrame(simpleFrame,&r); @

«draw arrow head»= if(con->vertexnum>1 && con->flags & ARROW) DrawArrowHead((con->vertices[j-1].x-currentSection->si.xoffset)*currentSection->si.scale, (con->vertices[j-1].y-currentSection->si.yoffset)*currentSection->si.scale, (con->vertices[j].x-currentSection->si.xoffset)*currentSection->si.scale, (con->vertices[j].y-currentSection->si.yoffset)*currentSection->si.scale); @

«*»= static void RedrawGrid() int i,j;

for(j=(currentSection->si.gridsize-currentSection->si.yoffsetj<160;j+=currentSection->si.gridsize*currentSection->si.scale) for(i=(currentSection->si.gridsize-currentSection->si.xoffseti<160;i+=currentSection->si.gridsize*currentSection->si.scale) WinDrawLine(i-1,j,i+1,j); WinDrawLine(i,j-1,i,j+1);

static void RedrawLocations() int i;

for(i=0;i<currentSection->itemNum;i++) if(currentSection->items[i].type == LOCATION) DrawLocation(&currentSection->items[i]);

static void DrawLocation(Item *l) RectangleType sr,scaled,sctest; int fontsize;

RctCopyRectangle(&(l->bounds),&scaled);

scaled.topLeft.x-=currentSection->si.xoffset; scaled.topLeft.y-=currentSection->si.yoffset;

scaled.topLeft.x*=currentSection->si.scale; scaled.topLeft.y*=currentSection->si.scale;

scaled.extent.x*=currentSection->si.scale; scaled.extent.y*=currentSection->si.scale;

scaled.extent.x++; scaled.extent.y++;

RctGetIntersection(&scaled,&screenRect,&sctest);

if(sctest.extent.x==0 || sctest.extent.y==0) return;

fontsize=((l->itemdata.loc.flags & FONTMASK)»FONTSHIFT)+fontResize; fontsize=MIN(fontsize,FONT3); fontsize=MAX(fontsize,FONT0);

switch(fontsize) case FONT0: FntSetFont(129); break; case FONT1: FntSetFont(0); break; case FONT2: FntSetFont(1); break; case FONT3: FntSetFont(2); break;

if(l->itemdata.loc.flags & CIRCLE) RectangleType textbox;

if(l->itemdata.loc.flags & SELECTED) FillCircle(scaled.topLeft.x,scaled.topLeft.y, MIN(scaled.extent.x,scaled.extent.y),DottedPattern); DrawCircle(scaled.topLeft.x,scaled.topLeft.y, MIN(scaled.extent.x,scaled.extent.y));

RctCopyRectangle(&(l->bounds),&textbox);

textbox.topLeft.x-=currentSection->si.xoffset; textbox.topLeft.y-=currentSection->si.yoffset;

textbox.topLeft.x*=currentSection->si.scale; textbox.topLeft.y*=currentSection->si.scale;

textbox.extent.x=MIN(l->bounds.extent.x, l->bounds.extent.y); textbox.extent.y=MIN(l->bounds.extent.x, l->bounds.extent.y); textbox.extent.x*=currentSection->si.scale; textbox.extent.y*=currentSection->si.scale;

textbox.extent.x++; textbox.extent.y++;

FitLabel(l->itemdata.loc.Name,&textbox); else WinDrawRectangle(&scaled,RECTRADIUS);

sr.topLeft.x=scaled.topLeft.x+1; sr.topLeft.y=scaled.topLeft.y+1; sr.extent.x=scaled.extent.x-2; sr.extent.y=scaled.extent.y-2;

if(l->itemdata.loc.flags & SELECTED) WinSetPattern(DottedPattern); else WinSetPattern(EmptyPattern); WinFillRectangle(&sr,RECTRADIUS);

if(prefs.overwriteFrame) RctCopyRectangle(&scaled,&sr);

FitLabel(l->itemdata.loc.Name,&sr);

scaled.topLeft.x+=l->bounds.extent.x*currentSection->si.scale-RESIZEWIDTH; scaled.topLeft.y+=l->bounds.extent.y*currentSection->si.scale-RESIZEWIDTH; scaled.extent.x=RESIZEWIDTH; scaled.extent.y=RESIZEWIDTH; if(mode==RESIZE_LOC || mode==MOVE_ITEM) WinDrawRectangle(&scaled,0);

FntSetFont(0); @

This code borders on black magic, don't try to understand it. «*»= static void FitLabel(char *label, RectanglePtr r) char *s=MemPtrNew(StrLen(label)+2); char *endadress; char *mem; char *sp,*lp; int y=0; short fontheight=FntCharHeight(); int lines=0; int topoffset,leftoffset; int i;

MemSet(s,StrLen(label)+2,0); StrCopy(s,label); endadress=s+StrLen(s);

mem=sp=s; while(s<endadress && *s != ''&& *sp != '' && y+fontheight<r->extent.y) lp=sp; sp=MyStrTok(sp,' '); if(FntCharsWidth(s,sp-s) > r->extent.x-2) if(MyStrTok(s,' ') != sp) y+=fontheight; *(lp-1)=''; lines++; sp=s=lp; else int len=sp-s;

while(len>0 && FntCharsWidth(s,len)>r->extent.x-2) len–; endadress–; if(len>0) y+=fontheight; *(s+len)=''; lines++; StrCopy(s+len+1,sp+1); sp=s=lp=s+len+1; //endaddress-=sp-(s+len); else s=endadress+1; else sp++;

*sp=''; if(*s != '') lines++;

s=mem; topoffset=(r->extent.y-lines*fontheight)/2+r->topLeft.y; for(i=0;i<lines;i++) leftoffset=(r->extent.x-FntCharsWidth(s,StrLen(s)))/2+r->topLeft.x; WinDrawChars(s,StrLen(s),leftoffset,topoffset); topoffset+=fontheight; s+=StrLen(s)+1;

MemPtrFree(mem); @

Text is special, because it can't be scaled. To compensate this you can define the position, where the text is anchored. «*»= static void DrawText(Item *t) char *s; UInt slen=0; UInt x,y,flags; SWord w,sbw; RectangleType scaled,ar;

if(t->type != TEXT) return;

SetTextFont(t);

if(isSelected(t)) WinSetPattern(DottedPattern); else WinSetPattern(EmptyPattern);

RctCopyRectangle(&(t->bounds),&scaled);

scaled.topLeft.x-=currentSection->si.xoffset; scaled.topLeft.y-=currentSection->si.yoffset;

scaled.topLeft.x*=currentSection->si.scale; scaled.topLeft.y*=currentSection->si.scale;

scaled.extent.x*=currentSection->si.scale; scaled.extent.y*=currentSection->si.scale;

scaled.extent.x++; scaled.extent.y++;

WinFillRectangle(&scaled,RECTRADIUS);

«Calculate y-position from alignment»

x=t->bounds.topLeft.x-currentSection->si.xoffset; x*=currentSection->si.scale;

x+=t->itemdata.text.xoffset;

sbw=t->bounds.extent.x*currentSection->si.scale;

«Output text»

if(mode == MOVE_ITEM) ar.topLeft.x=(t->itemdata.text.anchor.x-currentSection->si.xoffset)* currentSection->si.scale-(VERTEXRECT+2)/2; ar.topLeft.y=(t->itemdata.text.anchor.y-currentSection->si.yoffset)* currentSection->si.scale-(VERTEXRECT+2)/2; ar.extent.x=VERTEXRECT+2; ar.extent.y=VERTEXRECT+2; WinDrawRectangle(&ar,0);

FntSetFont(0); @

The calculation of the y–Position is completely straight forward: «Calculate y-position from alignment»= flags=(t->itemdata.text.flags & TEXTANCHOR_YMASK)»TEXTANCHOR_YSHIFT; switch(flags) case TEXTANCHOR_TOP: y=t->itemdata.text.anchor.y-currentSection->si.yoffset; y*=currentSection->si.scale; break; case TEXTANCHOR_CENTER: y=t->itemdata.text.anchor.y-currentSection->si.yoffset; y*=currentSection->si.scale; y-=t->itemdata.text.lines*FntCharHeight()/2; break; case TEXTANCHOR_BOTTOM: y=t->itemdata.text.anchor.y-currentSection->si.yoffset; y*=currentSection->si.scale; y-=t->itemdata.text.lines*FntCharHeight(); break;

y+=t->itemdata.text.yoffset; @

The x-position has to be calculated individually for each line of text, to account for the alignment. «Output text»= for(s=t->itemdata.text.text; *(s+slen)!= '' ; slen++) if(*(s+slen)=='') switch((t->itemdata.text.flags&TEXTALIGN_MASK)»TEXTALIGN_SHIFT) case TEXTALIGN_LEFT: WinDrawChars(s,slen,x,y); break; case TEXTALIGN_CENTER: w=sbw-FntCharsWidth(s,slen); WinDrawChars(s,slen,x+w/2,y); break; case TEXTALIGN_RIGHT: w=FntCharsWidth(s,slen); WinDrawChars(s,slen,x+sbw-w,y); break; y+=FntCharHeight(); s+=slen+1; slen=0;

switch((t->itemdata.text.flags&TEXTALIGN_MASK)»TEXTALIGN_SHIFT) case TEXTALIGN_LEFT: WinDrawChars(s,slen,x,y); break; case TEXTALIGN_CENTER: w=sbw-FntCharsWidth(s,slen); WinDrawChars(s,slen,x+w/2,y); break; case TEXTALIGN_RIGHT: w=FntCharsWidth(s,slen); WinDrawChars(s,slen,x+sbw-w,y); break; @

«*»= void SetTextFont(Item *t) int fontsize;

fontsize=((t->itemdata.text.flags & FONTMASK)»FONTSHIFT)+fontResize; fontsize=MIN(fontsize,FONT3); fontsize=MAX(fontsize,FONT0);

switch(fontsize) case FONT0: FntSetFont(129); break; case FONT1: FntSetFont(0); break; case FONT2: FntSetFont(1); break; case FONT3: FntSetFont(2); break; @