/* * dockwindow.c V1.5 * * dock window * * (c) 1991 by Stefan Becker * */ #include "ToolManager.h" /* Structures for window */ static struct Window *w; static struct AppWindow *aw; static struct MsgPort *wp; static struct RastPort *rp; static struct Screen *pubsc; /* Workbench screen */ static void *vi; /* Visual information is a *PRIVATE* data field! */ static WORD ww,wh; UWORD DockXPos=0,DockYPos=0; UWORD DockXSize=51,DockYSize=51; UWORD XOff,YOff; BOOL DockVertical=TRUE; BOOL DockToBack=TRUE; static BOOL DoDraw; /* Flag for SizeWindow() in progress */ /* Structures for window menu */ static struct Menu *wmn=NULL; #define OTMENU_ID 1 #define CDMENU_ID 2 #define ABMENU_ID 3 extern struct EasyStruct AboutES; #define QUMENU_ID 4 static struct NewMenu mdata[]={ {NM_TITLE,"TM Dock Menu" ,NULL,0,~0,NULL}, {NM_ITEM,"Open TM Window",NULL,0,~0,OTMENU_ID}, {NM_ITEM,"Close TM Dock" ,"C" ,0,~0,CDMENU_ID}, {NM_ITEM,NM_BARLABEL ,NULL,0,~0,NULL}, {NM_ITEM,"About..." ,NULL,0,~0,ABMENU_ID}, {NM_ITEM,NM_BARLABEL ,NULL,0,~0,NULL}, {NM_ITEM,"Quit" ,"Q" ,0,~0,QUMENU_ID}, {NM_END,NULL,NULL,0,~0,NULL}}; /* Structures for dock list */ static struct List DockList; /* Draw all images */ static void DrawDockImages(void) { int x=XOff,y=YOff; struct Node *dn=GetHead(&DockList); struct Region *reg,*oreg; struct Rectangle rect; /* Get memory for region */ if (!(reg=NewRegion())) goto die1; /* Init rectangle */ if (DockVertical) { rect.MinX=XOff; rect.MaxX=XOff+DockXSize-2; } else { rect.MinY=YOff; rect.MaxY=YOff+DockYSize-2; } /* Clear Window */ SetAPen(rp,0); SetDrMd(rp,JAM1); RectFill(rp,XOff-1,YOff-1,XOff+ww-2,YOff+wh-2); /* Draw all Docks */ while (dn) { /* Create clipping rectangle and add it to our window */ if (DockVertical) { rect.MinY=y; rect.MaxY=y+DockYSize-2; } else { rect.MinX=x; rect.MaxX=x+DockXSize-2; } if (!OrRectRegion(reg,&rect)) goto die2; oreg=InstallClipRegion(w->WLayer,reg); /* Draw Image */ DrawImage(rp,((struct ToolNode *) dn->ln_Name)->tn_Dock-> do_Gadget.GadgetRender,x,y); /* Remove clipping region */ InstallClipRegion(w->WLayer,oreg); ClearRegion(reg); /* Calculate next position */ if (DockVertical) y+=DockYSize; else x+=DockXSize; /* Next dock */ dn=GetSucc((struct ToolNode *) dn); } /* Something has gone wrong */ die2: DisposeRegion(reg); die1: DoDraw=FALSE; /* Drawing finished */ return; } /* Invert a dock image */ void SelectDock(struct ToolNode *tn, WORD dockx, WORD docky, BOOL sel) { WORD x,y; struct Gadget *g=&tn->tn_Dock->do_Gadget; if (DockVertical) { x=XOff; y=(docky-YOff)/DockYSize*DockYSize+YOff; } else { x=(dockx-XOff)/DockXSize*DockXSize+XOff; y=YOff; } /* Two image icon? */ if ((g->Flags&GFLG_GADGHIGHBITS)==GFLG_GADGHIMAGE) { struct Region *reg; /* Alloc clip region */ if (reg=NewRegion()) { struct Rectangle rect; /* Build rectangle */ rect.MinX=x; rect.MaxX=x+DockXSize-2; rect.MinY=y; rect.MaxY=y+DockYSize-2; /* Build clip region */ if (OrRectRegion(reg,&rect)) { struct Region *oreg; /* Install new clip region */ oreg=InstallClipRegion(w->WLayer,reg); /* Clear region */ SetDrMd(rp,JAM1); SetAPen(rp,0); RectFill(rp,x,y,rect.MaxX,rect.MaxY); /* Draw Image */ DrawImage(rp,sel?g->SelectRender:g->GadgetRender,x,y); /* Remove clipping region */ InstallClipRegion(w->WLayer,oreg); } /* Free region */ DisposeRegion(reg); } } else { /* One image icon, only complement it. Set draw mode */ SetDrMd(rp,COMPLEMENT); SetAPen(rp,0xff); RectFill(rp,x,y,x+DockXSize-2,y+DockYSize-2); } } /* Open dock window */ void OpenDockWindow(void) { struct TextFont *f; /* Are any docks active or window already open? */ if (!DockCount || dockwinsig) return; /* No, don't open window */ if (!(pubsc=LockPubScreen(WBScreenName))) /* Lock Workbench screen */ goto odw1; /* Get Offsets */ if (!(f=OpenFont(pubsc->Font))) goto odw2; XOff=pubsc->WBorLeft+1; YOff=pubsc->WBorTop+f->tf_YSize+2; CloseFont(f); if (!(vi=GetVisualInfo(pubsc,TAG_DONE))) /* Get visual information */ goto odw2; /* Create menus */ if (!(wmn=CreateMenus(mdata, GTMN_FullMenu,TRUE, TAG_DONE))) goto odw3; /* Layout menus */ if (!LayoutMenus(wmn,vi,TAG_DONE)) goto odw4; /* Calculate window size */ if (DockVertical) { ww=DockXSize+1; wh=DockYSize*DockCount+1; } else { ww=DockXSize*DockCount+1; wh=DockYSize+1; } /* Open window */ if (!(w=OpenWindowTags(NULL,WA_Left,DockXPos, WA_Top,DockYPos, WA_InnerWidth,ww, WA_InnerHeight,wh, WA_PubScreen,pubsc, WA_AutoAdjust,TRUE, WA_IDCMP,IDCMP_CLOSEWINDOW|IDCMP_MOUSEBUTTONS| IDCMP_CHANGEWINDOW|IDCMP_NEWSIZE| IDCMP_INACTIVEWINDOW|IDCMP_MENUPICK, WA_Flags,WFLG_CLOSEGADGET|WFLG_DRAGBAR| WFLG_DEPTHGADGET|WFLG_SMART_REFRESH, TAG_DONE))) goto odw4; if (DockToBack) WindowToBack(w); /* Add menu to window */ if (!SetMenuStrip(w,wmn)) goto odw5; /* Notify Workbench about window */ if (!(aw=AddAppWindowA(DOCKWINAPPID,NULL,w,MyMP,NULL))) goto odw6; /* Dock window open */ UnlockPubScreen(NULL,pubsc); rp=w->RPort; DrawDockImages(); wp=w->UserPort; dockwinsig=1L<mp_SigBit; globalsigs|=dockwinsig; ShowDock=TRUE; StatWinDockState(TRUE); return; /* Something has gone wrong... */ odw6: ClearMenuStrip(w); odw5: CloseWindow(w); odw4: FreeMenus(wmn); odw3: FreeVisualInfo(vi); odw2: UnlockPubScreen(NULL,pubsc); odw1: return; } /* Close dock window */ void CloseDockWindow(void) { if (dockwinsig) { RemoveAppWindow(aw); ClearMenuStrip(w); CloseWindow(w); FreeMenus(wmn); FreeVisualInfo(vi); globalsigs&=~dockwinsig; dockwinsig=0; ShowDock=FALSE; StatWinDockState(FALSE); } } /* Find dock that correspondences to X,Y position */ struct ToolNode *FindDock(WORD x, WORD y) { struct Node *dn; LONG i; /* Out of bounds? */ if ((x=(XOff+DockXSize)) return(NULL); } else { i=(x-XOff)/DockXSize; if (y>=(YOff+DockYSize)) return(NULL); } /* Out of bounds? */ if (i<0) return(NULL); /* Search tool */ dn=GetHead(&DockList); while (i && dn) { /* Next Dock */ dn=GetSucc((struct ToolNode *) dn); i--; } /* Retreive ToolNode */ if (dn) return(dn->ln_Name); else return(NULL); } /* Handle window events */ void HandleDockWinEvent(void) { static struct ToolNode *otn=NULL; static WORD ox,oy; BOOL clwin=FALSE; struct IntuiMessage *msg; while (msg=GetMsg(wp)) /* Get Intuition messages */ { switch (msg->Class) { case IDCMP_CLOSEWINDOW: /* User selected the close window gadget */ clwin=TRUE; break; case IDCMP_MOUSEBUTTONS: /* User pressed mouse buttons */ switch(msg->Code) { case SELECTDOWN: /* User pressed select button */ /* Save selected tool */ ox=msg->MouseX; /* Save coordinates */ oy=msg->MouseY; if (otn=FindDock(ox,oy)) /* Find selected tool */ SelectDock(otn,ox,oy,TRUE); /* If tool found, invert its image */ break; case SELECTUP: /* User released select button */ struct ToolNode *tn; /* Save selected tool */ tn=FindDock(msg->MouseX,msg->MouseY); /* Tool selected and same tool as button pressed? */ if (tn && (otn==tn)) StartTool(tn,NULL); /* Yes, start tool with no args */ /* Invert DockImage */ if (otn) { SelectDock(otn,ox,oy,FALSE); otn=NULL; /* invalidate pointer */ } } break; case IDCMP_INACTIVEWINDOW: /* Window has gone inactive */ /* Missed a SELECTUP???? */ if (otn) { SelectDock(otn,ox,oy,FALSE); /* Yes. Invert dock again */ otn=NULL; /* invalidate pointer */ } break; case IDCMP_CHANGEWINDOW: /* User has moved the window */ DockXPos=w->LeftEdge; /* Update window coordinates */ DockYPos=w->TopEdge; break; case IDCMP_NEWSIZE: /* Window has new size */ /* Was a SizeWindow() in progress? Yes, it is completed now. */ /* We can now draw the images safely. */ if (DoDraw) DrawDockImages(); break; case IDCMP_MENUPICK: /* User selected a menu */ USHORT mnum=msg->Code; while (mnum!=MENUNULL) /* Scan all menu events */ { struct MenuItem *mi=ItemAddress(wmn,mnum); switch(GTMENUITEM_USERDATA(mi)) { case OTMENU_ID: /* User selected open TM window menu item */ OpenStatusWindow(TRUE); break; case CDMENU_ID: /* User selected close TM dock menu item */ clwin=TRUE; break; case ABMENU_ID: /* User selected about menu item */ EasyRequest(w,&AboutES,NULL,""); break; case QUMENU_ID: /* User selected quit menu item */ if (!clwin) { SetQuitFlag(); if (!running) clwin=TRUE; } break; } /* Next selected menu */ mnum=mi->NextSelect; } break; } ReplyMsg((struct Message *) msg); /* Reply message */ } if (clwin) { otn=NULL; CloseDockWindow(); } } /* Redraw dock window */ static void RefreshDockWindow(BOOL added) { /* Not in initialization phase? */ if (ShowDock) /* Dock window open? */ if (dockwinsig) /* Yes, change window contents */ if (DockCount) { /* Dock added? */ if (added) if (DockVertical) /* Yes, enlarge window */ { SizeWindow(w,0,DockYSize); wh+=DockYSize; } else { SizeWindow(w,DockXSize,0); ww+=DockXSize; } else if (DockVertical) /* No, reduce window size */ { SizeWindow(w,0,-DockYSize); wh-=DockYSize; } else { SizeWindow(w,-DockXSize,0); ww-=DockXSize; } /* SizeWindow() in progress */ DoDraw=TRUE; } else CloseDockWindow(); /* No dock to show, so close the window */ else if (added) OpenDockWindow(); /* No, open window */ } /* Add a dock to the list */ BOOL AddDock(struct ToolNode *tn) { struct Node *dn; /* Get memory for new dock node */ if (!(dn=malloc(sizeof(struct Node)))) return(FALSE); /* Initialize dock list */ if (DockCount==0) NewList(&DockList); /* Append dock node at the of list */ dn->ln_Name=tn; AddTail(&DockList,dn); DockCount++; /* Refresh dock window */ RefreshDockWindow(TRUE); return(TRUE); } /* Remove a dock from the list */ void RemDock(struct ToolNode *tn) { struct Node *dn; /* Search node in dock list */ dn=GetHead(&DockList); while (dn) { /* Node found? Yes --> Leave loop */ if ((struct ToolNode *) dn->ln_Name==tn) break; /* Next node */ dn=GetSucc((struct ToolNode *) dn); } /* Remove node */ Remove(dn); DockCount--; /* Refresh dock window */ RefreshDockWindow(FALSE); }