Moving and resizing

Determine the box item at the position (x, y). A box Item is a Location or a Text. «*»= Item * getBoxItem(int x, int y) int i;

for(i=0;i<currentSection->itemNum;i++)

switch(currentSection->items[i].type) case LOCATION: case TEXT: if(x>=currentSection->items[i].bounds.topLeft.x && x<=currentSection->items[i].bounds.topLeft.x+ currentSection->items[i].bounds.extent.x && y>=currentSection->items[i].bounds.topLeft.y && y<=currentSection->items[i].bounds.topLeft.y+ currentSection->items[i].bounds.extent.y) return(&currentSection->items[i]); break; default: break; return(NULL); @

Determines if the vertex [[k]] is on the border of the location [[loc]]. This is used to move the connection with the selected locations. «*»= Boolean onLoc(Item *loc, Vertex *k) short left=loc->bounds.topLeft.x; short right=loc->bounds.topLeft.x+ loc->bounds.extent.x; short top=loc->bounds.topLeft.y; short bottom=loc->bounds.topLeft.y+ loc->bounds.extent.y;

if(left == k->x && k->y>=top && k->y<=bottom) return(true);

if(top == k->y && k->x>=left && k->x<=right) return(true);

if(right == k->x && k->y>=top && k->y<=bottom) return(true);

if(bottom == k->y && k->x>=left && k->x<=right) return(true);

return(false); @

You can resize locations via a small rectangular area in the bottom right corner. «*»= Boolean insideResize(Item *loc, int x, int y) if(x>(loc->bounds.topLeft.x+ loc->bounds.extent.x-currentSection->si.xoffset)* currentSection->si.scale-RESIZEWIDTH && y>(loc->bounds.topLeft.y+ loc->bounds.extent.y-currentSection->si.yoffset)* currentSection->si.scale-RESIZEWIDTH) return(true); return(false); @

«Globals»= static Boolean PenIsDown=false; static Item *selItem; @

«*»= Boolean MainFormHandleEvent (EventPtr e) Boolean handled = false; FormPtr frm; ListPtr lst; int i;

CALLBACK_PROLOGUE

switch (e->eType) case frmOpenEvent: frm = FrmGetActiveForm(); updateSectionList(); lst=GetObjectPtr(frm,MSectionList); LstSetListChoices(lst,sectionNames, allocedSecNames);

LstSetSelection(lst,section); if(currentMap->sectionNum>10) LstSetHeight(lst,10); else LstSetHeight(lst,currentMap->sectionNum); CtlSetLabel(GetObjectPtr(frm,MSections), currentSection->Name); FrmDrawForm(frm);

ensureSectionLoaded(currentMap,section); SetZoom(currentSection->si.scale); RecalcTextExtents(currentSection); Redraw(true); SetMode(mode); handled = true; break;

case menuEvent: MenuEraseStatus(NULL);

«Edit menu event»

menuDisplayed=false; handled = true; break; case popSelectEvent: switch(e->data.popSelect.controlID) case MSections: section=e->data.popSelect.selection; currentSection=&currentMap->sections[section]; ensureSectionLoaded(currentMap,section); SetZoom(currentSection->si.scale); RecalcTextExtents(currentSection); frm=FrmGetActiveForm(); CtlSetLabel(GetObjectPtr(frm,MSections), currentSection->Name); Redraw(false); break; handled=true; break;

case penDownEvent: if(e->screenY<MAPAREAHEIGHT) int i,j; int x,y;

PenIsDown=true;

x=(e->screenX+currentSection->si.gridsize/2)/currentSection->si.scale+ currentSection->si.xoffset; y=(e->screenY+currentSection->si.gridsize/2)/currentSection->si.scale+ currentSection->si.yoffset;

downX=x; downY=y;

switch(mode) case MOVE_ITEM: case RESIZE_LOC: if( (selItem=getBoxItem(x,y)) != NULL ) if(selItem->type == LOCATION && insideResize(selItem,e->screenX,e->screenY)) SetMode(RESIZE_LOC); else SetMode(MOVE_ITEM); if(isSelected(selItem)) selectItem(selItem,false); else selectItem(selItem,true);

DeselectConnections(); SelectConnections(); Redraw(false); modified=true; break; case NEW_LOC: selItem=NewItem(currentSection); InitLocation(selItem);

selItem->bounds.topLeft.x=x; selItem->bounds.topLeft.y=y; selItem->bounds.extent.x=1; selItem->bounds.extent.y=1; SetMode(RESIZE_LOC); downX=x-1; downY=y-1; Redraw(false); modified=true; break; case DEL_ITEM: Item *ti; UInt dist=160*160; UInt tdist;

selItem=NULL;

for(i=0;i<currentSection->itemNum;i++) ti=&currentSection->items[i]; if( (tdist=Dist(ti,x,y))<dist ) selItem=ti; dist=tdist;

if(selItem != NULL) if(prefs.verbose) int ans=1; switch(selItem->type) case LOCATION: ans=FrmCustomAlert(ConfirmDialog, "Really delete the selected Location?", "",""); break; case CONNECTION: ans=FrmCustomAlert(ConfirmDialog, "Really delete the selected Connection?", "",""); break; case TEXT: ans=FrmCustomAlert(ConfirmDialog, "Really delete the selected Text?", "",""); break; if(ans==0) DeleteItem(currentSection,selItem); else DeleteItem(currentSection,selItem); selItem=NULL; modified=true; break; case EDIT_ITEM: selItem=getBoxItem(x,y); if(selItem != NULL) if(selItem->type == LOCATION) FrmGotoForm(EditLocForm); if(selItem->type == TEXT) FrmGotoForm(EditTextForm); modified=true; break; case NEW_CONNECTION: if(selItem->itemdata.con.vertexnum>0) selItem->itemdata.con.vertices=(Vertex *)realloc(selItem->itemdata.con.vertices, sizeof(Vertex)*(selItem->itemdata.con.vertexnum), sizeof(Vertex)*(selItem->itemdata.con.vertexnum+1)); else selItem->itemdata.con.vertices=MemPtrNew(sizeof(Vertex)); selItem->itemdata.con.vertices[selItem->itemdata.con.vertexnum].x=x; selItem->itemdata.con.vertices[selItem->itemdata.con.vertexnum].y=y; selItem->itemdata.con.vertexnum++; RecalcConnectionBox(selItem); Redraw(true); modified=true; break; case ADD_TEXT: selItem=NewItem(currentSection); InitText(selItem);

selItem->bounds.topLeft.x=x; selItem->bounds.topLeft.y=y;

selItem->itemdata.text.anchor.x=x; selItem->itemdata.text.anchor.y=y; RecalcTextBox(currentSection,selItem); FrmGotoForm(EditTextForm); modified=true; break; case DEL_VERTEX: Item *sel=NULL; int dist=160*160; int tdist; int index=0;

for(j=0;j<currentSection->itemNum;j++) if(currentSection->items[j].type == CONNECTION) for(i=0;i<currentSection->items[j].itemdata.con.vertexnum;i++) if(dist>(tdist=euklid(x-currentSection->items[j].itemdata.con.vertices[i].x, y-currentSection->items[j].itemdata.con.vertices[i].y))) dist=tdist; sel=&currentSection->items[j]; index=i; if(sel != NULL) DeleteVertex(currentSection,sel,index); modified=true; break; case INSERT_VERTEX: Item *sel=NULL; int dist=160*160; int index=0; int tdist;

for(j=0;j<currentSection->itemNum;j++) if(currentSection->items[j].type == CONNECTION) for(i=0;i<currentSection->items[j].itemdata.con.vertexnum;i++) tdist=euklid(x-currentSection->items[j].itemdata.con.vertices[i].x, y-currentSection->items[j].itemdata.con.vertices[i].y); if(dist>tdist) dist=tdist; sel=&currentSection->items[j]; index=i; if(sel != NULL) InsertVertex(sel,index,x,y); selVertex=&sel->itemdata.con.vertices[index+1]; SetMode(MOVE_VERTEX); Redraw(true); modified=true; break; case MOVE_VERTEX: int dist=160*160; int tdist;

for(j=0;j<currentSection->itemNum;j++) if(currentSection->items[j].type == CONNECTION) for(i=0;i<currentSection->items[j].itemdata.con.vertexnum;i++) tdist=euklid(currentSection->items[j].itemdata.con.vertices[i].x-x, currentSection->items[j].itemdata.con.vertices[i].y-y); if(tdist<dist) dist=tdist; selVertex=&(currentSection->items[j].itemdata.con.vertices[i]); modified=true; break; case PARAMS: Item *ti; UInt dist=160*160; UInt tdist;

selItem=NULL;

for(i=0;i<currentSection->itemNum;i++) ti=&currentSection->items[i]; if( (tdist=Dist(ti,x,y))<dist ) selItem=ti; dist=tdist;

if(selItem != NULL) switch(selItem->type) case CONNECTION: FrmPopupForm(ConnectionParams); break; case LOCATION: FrmPopupForm(LocParams); break; case TEXT: FrmPopupForm(TextParams); break; modified=true; break; handled=true; break;

case penMoveEvent: int i; int x,y;

x=(e->screenX+currentSection->si.gridsize/2)/currentSection->si.scale+currentSection->si.xoffset; y=(e->screenY+currentSection->si.gridsize/2)/currentSection->si.scale+currentSection->si.yoffset;

switch(mode) case MOVE_ITEM: if(x!=downX || y!=downY) SelectedVertexSet *s;

for(i=0;i<currentSection->itemNum;i++) if(isSelected(&currentSection->items[i])) MoveItem(&currentSection->items[i],x-downX,y-downY); for(s=selSet;s!=NULL;s=s->next) if(s->begin && s->end) for(i=0;i<s->c->itemdata.con.vertexnum;i++) s->c->itemdata.con.vertices[i].x-=downX-x; s->c->itemdata.con.vertices[i].y-=downY-y; else if(s->begin) s->c->itemdata.con.vertices[0].x-=downX-x; s->c->itemdata.con.vertices[0].y-=downY-y; else int evertex=s->c->itemdata.con.vertexnum-1; s->c->itemdata.con.vertices[evertex].x-=downX-x; s->c->itemdata.con.vertices[evertex].y-=downY-y; Redraw(false); downX=x; downY=y; break; case RESIZE_LOC: if(selItem != NULL) if(x!=downX || y!=downY) selItem->bounds.extent.x+=x-downX; selItem->bounds.extent.y+=y-downY; downX=x; downY=y; Redraw(false); break; case MOVE_VERTEX: if(selVertex != NULL) selVertex->x+=x-downX; selVertex->y+=y-downY; downX=x; downY=y; Redraw(false); break; handled=true; break; break;

case penUpEvent: PenIsDown=false; switch(mode) case MOVE_ITEM: DeselectConnections(); break; Redraw(true); handled=true; break;

case keyDownEvent: switch(e->data.keyDown.chr) case hard2Chr: currentSection->si.xoffset-=20/currentSection->si.scale; handled=true; break; case hard3Chr: currentSection->si.xoffset+=20/currentSection->si.scale; handled=true; break; case pageUpChr: currentSection->si.yoffset-=20/currentSection->si.scale; handled=true; break; case pageDownChr: currentSection->si.yoffset+=20/currentSection->si.scale; handled=true; break; case hard1Chr: ZoomOut(); handled=true; break; case hard4Chr: ZoomIn(); handled=true; break; case menuChr: menuDisplayed=!menuDisplayed; break; if(handled) Redraw(true); break;

case nilEvent: if(PenIsDown) if(e->screenY<MAPAREAHEIGHT) if(e->screenY<SCROLLBORDERHEIGHT) currentSection->si.yoffset-=20/currentSection->si.scale; Redraw(false); if(e->screenY>MAPAREAHEIGHT-SCROLLBORDERHEIGHT) currentSection->si.yoffset+=20/currentSection->si.scale; Redraw(false); if(e->screenX<SCROLLBORDERHEIGHT) currentSection->si.xoffset-=20/currentSection->si.scale; Redraw(false); if(e->screenX>MAPAREAWIDTH-SCROLLBORDERHEIGHT) currentSection->si.xoffset+=20/currentSection->si.scale; Redraw(false);

handled=true; break;

default: break;

CALLBACK_EPILOGUE

return handled; @

«Edit menu event»= switch(e->data.menu.itemID) case zoomin: ZoomIn(); Redraw(true); break; case zoomout: ZoomOut(); Redraw(true); break; «Mode selection» @

For renaming a section a modal form is popped up to enter the new name and the name list ist updated. «Edit menu event»= case rensec: FormPtr nf=FrmInitForm(NameForm); FormPtr frm;

if(FrmDoDialog(nf) == OkButton) FieldPtr nameField; CharPtr name;

nameField=GetObjectPtr(nf,NameField); name=FldGetTextPtr(nameField); if(name != NULL) MemPtrFree(currentSection->Name); currentSection->Name=MemPtrNew(StrLen(name+1)); StrCopy(currentSection->Name,name); updateSectionList(); FrmDeleteForm(nf); frm=FrmGetActiveForm(); modified=true; break; @

«Edit menu event»= case newsec: FormPtr nf=FrmInitForm(NameForm); FormPtr frm;

if(FrmDoDialog(nf) == OkButton) FieldPtr nameField; CharPtr name;

nameField=GetObjectPtr(nf,NameField); name=FldGetTextPtr(nameField); if(name != NULL) UInt snum=currentMap->sectionNum; currentMap->sections=(Section *)realloc(currentMap->sections, snum*sizeof(Section), (snum+1)*sizeof(Section)); currentMap->sections[snum].Name=MemPtrNew(StrLen(name)+1); StrCopy(currentMap->sections[snum].Name,name); currentMap->sectionNum++; section=snum; currentSection=&currentMap->sections[snum]; currentSection->items=NULL; currentSection->itemNum=0; currentSection->si.xoffset=0; currentSection->si.yoffset=0; currentSection->si.scale=8; currentSection->si.gridsize=prefs.gridsize; currentSection->loaded=true; updateSectionList(); FrmDeleteForm(nf); frm=FrmGetActiveForm(); lst=GetObjectPtr(frm,MSectionList); LstSetListChoices(lst,sectionNames, allocedSecNames);

if(currentMap->sectionNum>10) LstSetHeight(lst,10); else LstSetHeight(lst,currentMap->sectionNum); modified=true; break; @

«Edit menu event»= case menu_find: FormPtr nf=FrmInitForm(FindForm);

if(FrmDoDialog(nf) == OkButton) FieldPtr nameField; CharPtr name;

nameField=GetObjectPtr(nf,NameField); name=FldGetTextPtr(nameField);

if(name != NULL) if(searchString != NULL) MemPtrFree(searchString); searchString=MemPtrNew(StrLen(name)+1); StrCopy(searchString,name); searchIndex=-1; searchSection=searchStart=currentSection;

searchFlag=CtlGetValue(GetObjectPtr(nf,findall)); SearchItems(); Redraw(true); else FrmCustomAlert(ErrorDialog,"No item found","",""); FrmDeleteForm(nf); break; case menu_findagain: if(searchString != NULL) SearchItems(); else FrmCustomAlert(ErrorDialog,"No searchstring set","",""); break; case exitprg: if(modified) DisplayMessage("Saving..."); saveMap(currentMap); exitEdit(); break; @

«Edit menu event»= case menu_savemap: DisplayMessage("Saving..."); saveMap(currentMap); modified=false; break; case menu_abort: if(prefs.verbose) if(FrmCustomAlert(ConfirmDialog, "Really Abort?changes will be lost!", "","") == 0) exitEdit(); else exitEdit(); break; @

«Edit menu event»= case menu_selall: for(i=0;i<currentSection->itemNum;i++) selectItem(&currentSection->items[i],true); Redraw(true); break; case menu_unselall: DeselectAll(); Redraw(true); break; @

«Edit menu event»= case menu_cut: CutToClip(); modified=true; break; case menu_copy: CopyToClip(); break; case menu_paste: PasteFromClip(); Redraw(true); modified=true; break; @

«Edit menu event»= case smallfont: fontResize–; RecalcTextExtents(currentSection); break; case largefont: fontResize++; RecalcTextExtents(currentSection); break; @

«Edit menu event»= case menu_options: doOptions(); break; case movehome: if(currentSection->itemNum>0) currentSection->si.xoffset=currentSection->items[0].bounds.topLeft.x; currentSection->si.yoffset=currentSection->items[0].bounds.topLeft.y; Redraw(true); break; @

«Edit menu event»= case unimplemented: FrmCustomAlert(InfoDialog,"Not implemented yet","",""); break; @

Mode selection mostly sets [[mode]] to prepare for further events and sets the label with a call to [[SetMode]]. «Mode selection»= case newloc: SetMode(NEW_LOC); break; @

The connection is created right here, that means if you don�t add any vertices you end up with a degenerate connection. These connections are deleted when saving. «Mode selection»= case newconnection: selItem=NewItem(currentSection); InitConnection(selItem); SetMode(NEW_CONNECTION); break; case delitem: SetMode(DEL_ITEM); break; case moveitem: SetMode(MOVE_ITEM); break; case edititem: SetMode(EDIT_ITEM); break; case movevertex: SetMode(MOVE_VERTEX); break; case insvertex: SetMode(INSERT_VERTEX); break; case delvertex: SetMode(DEL_VERTEX); break; case addtext: SetMode(ADD_TEXT); break; case params: SetMode(PARAMS); break; @