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(¤tSection->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=¤tMap->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=¤tSection->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=¤tSection->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=¤tSection->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=¤tSection->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(¤tSection->items[i])) MoveItem(¤tSection->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=¤tMap->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(¤tSection->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; @