Workbook: Use LayoutIconA() to speed up repeated icon rendering
[AROS.git] / workbench / system / Workbook / wbwindow.c
blobd66da16101eacd03cd26f25996e4a1f702b21f9b
1 /*
2 Copyright © 2011, The AROS Development Team. All rights reserved.
3 $Id$
5 Desc: Workbook Window Class
6 Lang: english
7 */
9 #define DEBUG 0
10 #include <aros/debug.h>
12 #include <string.h>
13 #include <limits.h>
14 #include <intuition/icclass.h>
16 #include <proto/dos.h>
17 #include <proto/exec.h>
18 #include <proto/intuition.h>
19 #include <proto/utility.h>
20 #include <proto/gadtools.h>
21 #include <proto/workbench.h>
22 #include <proto/graphics.h>
23 #include <proto/layers.h>
24 #include <proto/icon.h>
26 #include <intuition/classusr.h>
27 #include <libraries/gadtools.h>
28 #include <exec/rawfmt.h>
31 #include "workbook_intern.h"
32 #include "workbook_menu.h"
33 #include "classes.h"
35 static inline WORD max(WORD a, WORD b)
37 return (a > b) ? a : b;
40 struct wbWindow_Icon {
41 struct MinNode wbwiNode;
42 Object *wbwiObject;
45 struct wbWindow {
46 STRPTR Path;
47 BPTR Lock;
48 struct Window *Window;
49 struct Menu *Menu;
50 Object *ScrollH;
51 Object *ScrollV;
52 Object *Area; /* Virual area of icons */
53 Object *Set; /* Set of icons */
55 ULONG Flags;
56 IPTR Tick;
58 /* Temporary path buffer */
59 TEXT PathBuffer[PATH_MAX];
60 TEXT ScreenTitle[256];
62 /* List of icons in this window */
63 struct MinList IconList;
66 #define WBWF_USERPORT (1 << 0) /* Window has a custom port */
68 #define Broken NM_ITEMDISABLED |
70 static const struct NewMenu WBWindow_menu[] = {
71 WBMENU_TITLE(WBMENU_WB),
72 WBMENU_ITEM(WBMENU_WB_BACKDROP),
73 WBMENU_ITEM(WBMENU_WB_EXECUTE),
74 WBMENU_ITEM(WBMENU_WB_SHELL),
75 WBMENU_ITEM(WBMENU_WB_ABOUT),
76 WBMENU_BAR,
77 WBMENU_ITEM(WBMENU_WB_QUIT),
78 WBMENU_ITEM(WBMENU_WB_SHUTDOWN),
79 WBMENU_TITLE(WBMENU_WN),
80 WBMENU_ITEM(WBMENU_WN_NEW_DRAWER),
81 WBMENU_ITEM(WBMENU_WN_OPEN_PARENT),
82 WBMENU_ITEM(WBMENU_WN_UPDATE),
83 WBMENU_ITEM(WBMENU_WN_SELECT_ALL),
84 WBMENU_ITEM(WBMENU_WN_SELECT_NONE),
85 WBMENU_SUBTITLE(WBMENU_WN__SNAP),
86 WBMENU_SUBITEM(WBMENU_WN__SNAP_WINDOW),
87 WBMENU_SUBITEM(WBMENU_WN__SNAP_ALL),
88 WBMENU_SUBTITLE(WBMENU_WN__SHOW),
89 WBMENU_SUBITEM(WBMENU_WN__SHOW_ICONS),
90 WBMENU_SUBITEM(WBMENU_WN__SHOW_ALL),
91 WBMENU_SUBTITLE(WBMENU_WN__VIEW),
92 WBMENU_SUBITEM(WBMENU_WN__VIEW_ICON),
93 WBMENU_SUBITEM(WBMENU_WN__VIEW_DETAILS),
94 WBMENU_TITLE(WBMENU_IC),
95 WBMENU_ITEM(WBMENU_IC_OPEN),
96 WBMENU_ITEM(WBMENU_IC_COPY),
97 WBMENU_ITEM(WBMENU_IC_RENAME),
98 WBMENU_ITEM(WBMENU_IC_INFO),
99 WBMENU_BAR,
100 WBMENU_ITEM(WBMENU_IC_SNAPSHOT),
101 WBMENU_ITEM(WBMENU_IC_UNSNAPSHOT),
102 WBMENU_ITEM(WBMENU_IC_LEAVE_OUT),
103 WBMENU_ITEM(WBMENU_IC_PUT_AWAY),
104 WBMENU_BAR,
105 WBMENU_ITEM(WBMENU_IC_DELETE),
106 WBMENU_ITEM(WBMENU_IC_FORMAT),
107 WBMENU_ITEM(WBMENU_IC_EMPTY_TRASH),
108 { NM_END },
111 static BOOL wbMenuEnable(Class *cl, Object *obj, int id, BOOL onoff)
113 struct WorkbookBase *wb = (APTR)cl->cl_UserData;
114 struct wbWindow *my = INST_DATA(cl, obj);
115 int i, menu = -1, item = -1, sub = -1;
116 UWORD MenuNumber = MENUNULL;
117 BOOL rc = FALSE;
119 for (i = 0; WBWindow_menu[i].nm_Type != NM_END; i++) {
120 const struct NewMenu *nm = &WBWindow_menu[i];
122 switch (nm->nm_Type) {
123 case NM_TITLE:
124 menu++;
125 item = -1;
126 sub = -1;
127 break;
128 case IM_ITEM:
129 case NM_ITEM:
130 item++;
131 sub = -1;
132 break;
133 case IM_SUB:
134 case NM_SUB:
135 sub++;
136 break;
139 if (nm->nm_UserData == (APTR)(IPTR)id) {
140 MenuNumber = FULLMENUNUM(menu, item, sub);
141 break;
145 if (MenuNumber != MENUNULL) {
146 if (onoff)
147 OnMenu(my->Window, MenuNumber);
148 else
149 OffMenu(my->Window, MenuNumber);
151 rc = TRUE;
154 return rc;
157 AROS_UFH3(ULONG, wbIgnoreInfo_Hook,
158 AROS_UFHA(struct Hook*, hook, A0),
159 AROS_UFHA(struct ExAllData*, ead, A2),
160 AROS_UFHA(LONG *, type, A1))
162 int i;
164 AROS_USERFUNC_INIT
166 i = strlen(ead->ed_Name);
167 if (i >= 5 && stricmp(&ead->ed_Name[i-5], ".info") == 0)
168 return FALSE;
169 if (stricmp(ead->ed_Name, ".backdrop") == 0)
170 return FALSE;
171 return TRUE;
173 AROS_USERFUNC_EXIT
176 static int wbwiIconCmp(Class *cl, Object *obj, Object *a, Object *b)
178 struct WorkbookBase *wb = (APTR)cl->cl_UserData;
180 CONST_STRPTR al = NULL, bl = NULL;
182 GetAttr(WBIA_Label, a, (IPTR *)&al);
183 GetAttr(WBIA_Label, b, (IPTR *)&bl);
185 if (al == bl)
186 return 0;
188 if (al == NULL)
189 return 1;
191 if (bl == NULL)
192 return -1;
194 return Stricmp(al, bl);
197 static void wbwiAppend(Class *cl, Object *obj, Object *iobj)
199 struct WorkbookBase *wb = (APTR)cl->cl_UserData;
200 struct wbWindow *my = INST_DATA(cl, obj);
201 struct wbWindow_Icon *wbwi;
203 wbwi = AllocMem(sizeof(*wbwi), MEMF_ANY);
204 if (!wbwi) {
205 DisposeObject(iobj);
206 } else {
207 struct wbWindow_Icon *tmp, *pred = NULL;
208 wbwi->wbwiObject = iobj;
210 /* Insert in Alpha order */
211 ForeachNode((struct List *)&my->IconList, tmp) {
212 if (wbwiIconCmp(cl, obj, tmp->wbwiObject, wbwi->wbwiObject) < 0)
213 break;
214 pred = tmp;
217 Insert((struct List *)&my->IconList, (struct Node *)wbwi, (struct Node *)pred);
221 static void wbAddFiles(Class *cl, Object *obj)
223 struct WorkbookBase *wb = (APTR)cl->cl_UserData;
224 struct wbWindow *my = INST_DATA(cl, obj);
225 struct ExAllControl *eac;
226 struct ExAllData *ead;
227 const ULONG eadSize = sizeof(struct ExAllData) + 1024;
229 ead = AllocVec(eadSize, MEMF_CLEAR);
230 if (ead != NULL) {
231 eac = AllocDosObject(DOS_EXALLCONTROL, NULL);
232 if (eac != NULL) {
233 struct Hook hook;
234 BOOL more = TRUE;
236 hook.h_Entry = (APTR)wbIgnoreInfo_Hook;
238 eac->eac_MatchFunc = &hook;
239 while (more) {
240 struct ExAllData *tmp = ead;
241 int i;
243 more = ExAll(my->Lock, ead, eadSize, ED_NAME, eac);
244 for (i = 0; i < eac->eac_Entries; i++, tmp=tmp->ed_Next) {
245 Object *iobj = NewObject(WBIcon, NULL,
246 WBIA_Lock, my->Lock,
247 WBIA_File, tmp->ed_Name,
248 WBIA_Label, tmp->ed_Name,
249 WBIA_Screen, my->Window->WScreen,
250 TAG_END);
251 if (iobj != NULL)
252 wbwiAppend(cl, obj, iobj);
255 FreeDosObject(DOS_EXALLCONTROL, eac);
257 FreeVec(ead);
261 static void wbAddVolumeIcons(Class *cl, Object *obj)
263 struct WorkbookBase *wb = (APTR)cl->cl_UserData;
264 struct wbWindow *my = INST_DATA(cl, obj);
265 struct DosList *dl;
266 char text[NAME_MAX];
268 /* Add all the DOS disks */
269 dl = LockDosList(LDF_VOLUMES | LDF_READ);
271 if (dl != BNULL) {
272 struct DosList *tdl;
274 tdl = dl;
275 while ((tdl = NextDosEntry(tdl, LDF_VOLUMES))) {
276 Object *iobj;
278 CopyMem(AROS_BSTR_ADDR(tdl->dol_Name), text, AROS_BSTR_strlen(tdl->dol_Name));
279 CopyMem(":",&text[AROS_BSTR_strlen(tdl->dol_Name)],2);
281 iobj = NewObject(WBIcon, NULL,
282 WBIA_File, text,
283 WBIA_Label, AROS_BSTR_ADDR(tdl->dol_Name),
284 WBIA_Screen, my->Window->WScreen,
285 TAG_END);
286 D(bug("Volume: %s => %p\n", text, iobj));
287 if (iobj)
288 wbwiAppend(cl, obj, iobj);
290 UnLockDosList(LDF_VOLUMES | LDF_READ);
294 static void wbAddAppIcons(Class *cl, Object *obj)
296 struct WorkbookBase *wb = (APTR)cl->cl_UserData;
297 struct wbWindow *my = INST_DATA(cl, obj);
298 struct DiskObject *icon;
299 char text[NAME_MAX];
301 /* Add all the AppIcons */
302 icon = NULL;
303 while ((icon = GetNextAppIcon(icon, &text[0]))) {
304 Object *iobj = NewObject(WBIcon, NULL,
305 WBIA_Icon, icon,
306 WBIA_Screen, my->Window->WScreen,
307 TAG_END);
308 if (iobj != NULL)
309 wbwiAppend(cl, obj, iobj);
313 static void wbRedimension(Class *cl, Object *obj)
315 struct WorkbookBase *wb = (APTR)cl->cl_UserData;
316 struct wbWindow *my = INST_DATA(cl, obj);
317 struct Window *win = my->Window;
318 struct IBox real; /* pos & size of the inner window area */
320 real.Left = win->BorderLeft;
321 real.Top = win->BorderTop;
322 real.Width = win->Width - (win->BorderLeft + win->BorderRight);
323 real.Height= win->Height- (win->BorderTop + win->BorderBottom);
325 D(bug("%s: Real (%d,%d) %dx%d\n", __func__,
326 real.Left, real.Top, real.Width, real.Height));
327 D(bug("%s: Border (%d,%d) %dx%d\n", __func__,
328 my->Window->BorderLeft, my->Window->BorderTop,
329 my->Window->BorderRight, my->Window->BorderBottom));
331 SetAttrs(my->Area, GA_Top, real.Top,
332 GA_Left, real.Left,
333 GA_Width, real.Width,
334 GA_Height, real.Height,
335 TAG_END);
337 SetAttrs(my->ScrollH, PGA_Visible, real.Width,
338 GA_Left, real.Left,
339 GA_RelBottom, -(my->Window->BorderBottom - 2),
340 GA_Width, real.Width,
341 GA_Height, my->Window->BorderBottom - 3,
342 TAG_END);
344 SetAttrs(my->ScrollV, PGA_Visible, real.Height,
345 GA_RelRight, -(my->Window->BorderRight - 2),
346 GA_Top, real.Top,
347 GA_Width, my->Window->BorderRight - 3,
348 GA_Height, real.Height,
349 TAG_END);
352 IPTR tot = 0, vis = 0;
353 GetAttr(PGA_Visible, my->ScrollV, &vis);
354 GetAttr(PGA_Total, my->ScrollV, &tot);
355 D(bug("%s: VScroll Total=%d Visible=%d\n", __func__, tot, vis));
359 /* Rescan the Lock for new entries */
360 static void wbRescan(Class *cl, Object *obj)
362 struct WorkbookBase *wb = (APTR)cl->cl_UserData;
363 struct wbWindow *my = INST_DATA(cl, obj);
364 struct wbWindow_Icon *wbwi;
366 /* We're going to busy for a while */
367 D(bug("BUSY....\n"));
368 SetWindowPointer(my->Window, WA_BusyPointer, TRUE, TAG_END);
370 /* Remove and undisplay any existing icons */
371 while ((wbwi = (struct wbWindow_Icon *)REMHEAD(&my->IconList)) != NULL) {
372 DoMethod(my->Set, OM_REMMEMBER, wbwi->wbwiObject);
373 DisposeObject(wbwi->wbwiObject);
374 FreeMem(wbwi, sizeof(*wbwi));
377 /* Scan for new icons, and add them to the list
379 if (my->Lock == BNULL) {
380 /* Root window */
381 wbAddVolumeIcons(cl, obj);
382 wbAddAppIcons(cl, obj);
383 } else {
384 /* Directory window */
385 wbAddFiles(cl, obj);
388 /* Display the new icons */
389 ForeachNode((struct List *)&my->IconList, wbwi)
390 DoMethod(my->Set, OM_ADDMEMBER, wbwi->wbwiObject);
392 /* Adjust the scrolling regions */
393 wbRedimension(cl, obj);
395 /* Return the point back to normal */
396 SetWindowPointer(my->Window, WA_BusyPointer, FALSE, TAG_END);
397 D(bug("Not BUSY....\n"));
401 const struct TagItem scrollv2window[] = {
402 { PGA_Top, WBVA_VirtTop },
403 { TAG_END, 0 },
405 const struct TagItem scrollh2window[] = {
406 { PGA_Top, WBVA_VirtLeft },
407 { TAG_END, 0 },
409 const struct TagItem set2window[] = {
410 { GA_Width, WBVA_VirtWidth },
411 { GA_Height, WBVA_VirtHeight },
412 { TAG_END, 0 },
415 static void wbFixBorders(struct Window *win)
417 int bb, br;
419 bb = 16 - win->BorderBottom;
420 br = 16 - win->BorderRight;
422 win->BorderBottom += bb;
423 win->BorderRight += br;
426 static IPTR WBWindowNew(Class *cl, Object *obj, struct opSet *ops)
428 struct WorkbookBase *wb = (APTR)cl->cl_UserData;
429 struct wbWindow *my;
430 struct MsgPort *userport;
431 CONST_STRPTR path;
432 ULONG idcmp;
433 IPTR rc = 0;
434 APTR vis;
435 struct wbWindow_Icon *wbwi;
437 rc = DoSuperMethodA(cl, obj, (Msg)ops);
438 if (rc == 0)
439 return rc;
441 obj = (Object *)rc;
442 my = INST_DATA(cl, obj);
444 NEWLIST(&my->IconList);
446 path = (CONST_STRPTR)GetTagData(WBWA_Path, (IPTR)NULL, ops->ops_AttrList);
447 if (path == NULL) {
448 my->Lock = BNULL;
449 my->Path = NULL;
450 } else {
451 my->Lock = Lock(path, SHARED_LOCK);
452 if (my->Lock == BNULL)
453 goto error;
455 my->Path = AllocVec(strlen(path)+1, MEMF_ANY);
456 if (my->Path == NULL)
457 goto error;
459 strcpy(my->Path, path);
462 /* Create icon set */
463 my->Set = NewObject(WBSet, NULL,
464 ICA_TARGET, (IPTR)obj,
465 ICA_MAP, (IPTR)set2window,
466 TAG_END);
468 idcmp = IDCMP_MENUPICK | IDCMP_INTUITICKS;
469 if (my->Path == NULL) {
470 my->Window = OpenWindowTags(NULL,
471 WA_IDCMP, 0,
472 WA_Backdrop, TRUE,
473 WA_WBenchWindow, TRUE,
474 WA_Borderless, TRUE,
475 WA_Activate, TRUE,
476 WA_SmartRefresh, TRUE,
477 WA_NewLookMenus, TRUE,
478 WA_PubScreen, NULL,
479 TAG_MORE, ops->ops_AttrList );
480 my->Window->BorderTop = my->Window->WScreen->BarHeight+1;
481 } else {
482 struct DiskObject *icon;
483 struct NewWindow *nwin = NULL;
484 struct TagItem extra[] = {
485 { WA_Left, 64 },
486 { WA_Top, 64 },
487 { WA_Width, 200, },
488 { WA_Height, 150, },
489 { TAG_MORE, (IPTR)ops->ops_AttrList },
492 icon = GetDiskObjectNew(my->Path);
493 if (icon == NULL)
494 goto error;
496 if (icon->do_DrawerData) {
497 nwin = &icon->do_DrawerData->dd_NewWindow;
498 D(bug("%s: NewWindow %p\n", __func__, nwin));
499 extra[0].ti_Tag = TAG_MORE;
500 extra[0].ti_Data = (IPTR)ops->ops_AttrList;
503 idcmp |= IDCMP_NEWSIZE | IDCMP_CLOSEWINDOW;
504 my->Window = OpenWindowTags(nwin,
505 WA_IDCMP, 0,
506 WA_MinWidth, 100,
507 WA_MinHeight, 100,
508 WA_MaxWidth, ~0,
509 WA_MaxHeight, ~0,
510 WA_Backdrop, FALSE,
511 WA_WBenchWindow, TRUE,
512 WA_Title, my->Path,
513 WA_SmartRefresh, TRUE,
514 WA_SizeGadget, TRUE,
515 WA_DragBar, TRUE,
516 WA_DepthGadget, TRUE,
517 WA_CloseGadget, TRUE,
518 WA_Activate, TRUE,
519 WA_NewLookMenus, TRUE,
520 WA_AutoAdjust, TRUE,
521 WA_PubScreen, NULL,
522 TAG_MORE, (IPTR)&extra[0] );
524 if (my->Window)
525 wbFixBorders(my->Window);
527 FreeDiskObject(icon);
530 if (!my->Window)
531 goto error;
533 /* If we want a shared port, do it. */
534 userport = (struct MsgPort *)GetTagData(WBWA_UserPort, (IPTR)NULL, ops->ops_AttrList);
535 if (userport) {
536 my->Flags |= WBWF_USERPORT;
537 my->Window->UserPort = userport;
539 ModifyIDCMP(my->Window, idcmp);
541 /* The gadgets' layout will be performed during wbRedimension
543 AddGadget(my->Window, (struct Gadget *)(my->Area = NewObject(WBVirtual, NULL,
544 WBVA_Gadget, (IPTR)my->Set,
545 TAG_END)), 0);
547 /* Add the verical scrollbar */
548 AddGadget(my->Window, (struct Gadget *)(my->ScrollV = NewObject(NULL, "propgclass",
549 GA_RightBorder, TRUE,
551 ICA_TARGET, (IPTR)obj,
552 ICA_MAP, (IPTR)scrollv2window,
553 PGA_Freedom, FREEVERT,
554 PGA_NewLook, TRUE,
555 PGA_Borderless, TRUE,
556 PGA_Total, 1,
557 PGA_Visible, 1,
558 PGA_Top, 0,
559 TAG_END)), 0);
561 /* Add the horizontal scrollbar */
562 AddGadget(my->Window, (struct Gadget *)(my->ScrollH = NewObject(NULL, "propgclass",
563 ICA_TARGET, (IPTR)obj,
564 ICA_MAP, (IPTR)scrollh2window,
565 PGA_Freedom, FREEHORIZ,
566 PGA_NewLook, TRUE,
567 PGA_Borderless, TRUE,
568 PGA_Total, 1,
569 PGA_Visible, 1,
570 PGA_Top, 0,
571 TAG_END)), 0);
573 /* Send first intuitick */
574 DoMethod(obj, WBWM_INTUITICK);
576 wbRescan(cl, obj);
578 my->Menu = CreateMenusA((struct NewMenu *)WBWindow_menu, NULL);
579 if (my->Menu == NULL)
580 goto error;
582 vis = GetVisualInfo(my->Window->WScreen, TAG_END);
583 LayoutMenus(my->Menu, vis, TAG_END);
584 FreeVisualInfo(vis);
586 SetMenuStrip(my->Window, my->Menu);
588 /* Disable opening the parent for root window
589 * and disk paths.
591 if (my->Lock == BNULL) {
592 wbMenuEnable(cl, obj, WBMENU_ID(WBMENU_WN_OPEN_PARENT), FALSE);
593 } else {
594 BPTR lock = ParentDir(my->Lock);
595 if (lock == BNULL) {
596 wbMenuEnable(cl, obj, WBMENU_ID(WBMENU_WN_OPEN_PARENT), FALSE);
597 } else {
598 UnLock(lock);
602 SetAttrs(my->Set, WBSA_MaxWidth, my->Window->Width - (my->Window->BorderLeft + my->Window->BorderRight));
603 RefreshGadgets(my->Window->FirstGadget, my->Window, NULL);
605 return rc;
607 error:
608 while ((wbwi = (APTR)GetHead(&my->IconList))) {
609 Remove((struct Node *)wbwi);
610 FreeMem(wbwi, sizeof(*wbwi));
613 if (my->Set)
614 DisposeObject(my->Set);
616 if (my->Window)
617 CloseWindow(my->Window);
619 if (my->Path)
620 FreeVec(my->Path);
622 if (my->Lock != BNULL)
623 UnLock(my->Lock);
625 DoSuperMethod(cl, obj, OM_DISPOSE, 0);
626 return 0;
629 static IPTR WBWindowDispose(Class *cl, Object *obj, Msg msg)
631 struct WorkbookBase *wb = (APTR)cl->cl_UserData;
632 struct wbWindow *my = INST_DATA(cl, obj);
633 struct wbWindow_Icon *wbwi;
635 ClearMenuStrip(my->Window);
636 FreeMenus(my->Menu);
638 /* If we have a custom user port, be paranoid.
639 * See the Autodocs for CloseWindow().
641 if (my->Flags & WBWF_USERPORT) {
642 struct IntuiMessage *msg;
643 struct Node *succ;
645 Forbid();
646 msg = (APTR)my->Window->UserPort->mp_MsgList.lh_Head;
647 while ((succ = msg->ExecMessage.mn_Node.ln_Succ )) {
648 if (msg->IDCMPWindow == my->Window) {
649 Remove((APTR)msg);
650 ReplyMsg((struct Message *)msg);
653 msg = (struct IntuiMessage *) succ;
656 my->Window->UserPort = NULL;
657 ModifyIDCMP(my->Window, 0);
659 Permit();
662 /* We won't need our list of icons anymore */
663 while ((wbwi = (APTR)GetHead(&my->IconList))) {
664 Remove((struct Node *)wbwi);
665 FreeMem(wbwi, sizeof(*wbwi));
668 /* As a side effect, this will close all the
669 * gadgets attached to it.
671 CloseWindow(my->Window);
673 /* .. except for my->Set */
674 DisposeObject(my->Set);
676 if (my->Path)
677 FreeVec(my->Path);
679 if (my->Lock != BNULL)
680 UnLock(my->Lock);
682 return DoSuperMethodA(cl, obj, msg);
685 // OM_GET
686 static IPTR WBWindowGet(Class *cl, Object *obj, struct opGet *opg)
688 struct wbWindow *my = INST_DATA(cl, obj);
689 IPTR rc = TRUE;
691 switch (opg->opg_AttrID) {
692 case WBWA_Path:
693 *(opg->opg_Storage) = (IPTR)my->Path;
694 break;
695 case WBWA_Window:
696 *(opg->opg_Storage) = (IPTR)my->Window;
697 break;
698 default:
699 rc = DoSuperMethodA(cl, obj, (Msg)opg);
700 break;
703 return rc;
706 // OM_UPDATE
707 static IPTR WBWindowUpdate(Class *cl, Object *obj, struct opUpdate *opu)
709 struct WorkbookBase *wb = (APTR)cl->cl_UserData;
710 struct wbWindow *my = INST_DATA(cl, obj);
711 const struct TagItem *tstate;
712 struct TagItem *tag;
713 IPTR rc;
715 rc = DoSuperMethodA(cl, obj, (Msg)opu);
717 /* Also send these to the Area */
718 rc |= DoMethodA(my->Area, (Msg)opu);
720 /* Update scrollbars if needed */
721 tstate = opu->opu_AttrList;
722 while ((tag = NextTagItem(&tstate))) {
723 switch (tag->ti_Tag) {
724 case WBVA_VirtLeft:
725 rc = TRUE;
726 break;
727 case WBVA_VirtTop:
728 rc = TRUE;
729 break;
730 case WBVA_VirtWidth:
731 SetAttrs(my->ScrollH, PGA_Total, tag->ti_Data, TAG_END);
732 rc = TRUE;
733 break;
734 case WBVA_VirtHeight:
735 SetAttrs(my->ScrollV, PGA_Total, tag->ti_Data, TAG_END);
736 rc = TRUE;
737 break;
741 if (rc && !(opu->opu_Flags & OPUF_INTERIM))
742 RefreshGadgets(my->Window->FirstGadget, my->Window, NULL);
744 return rc;
747 // WBWM_NEWSIZE
748 static IPTR WBWindowNewSize(Class *cl, Object *obj, Msg msg)
750 struct WorkbookBase *wb = (APTR)cl->cl_UserData;
751 struct wbWindow *my = INST_DATA(cl, obj);
753 SetAttrs(my->Set, WBSA_MaxWidth, my->Window->Width - (my->Window->BorderLeft + my->Window->BorderRight));
754 wbRedimension(cl, obj);
755 BeginRefresh(my->Window);
756 RefreshWindowFrame(my->Window);
757 RefreshGadgets(my->Window->FirstGadget, my->Window, NULL);
758 EndRefresh(my->Window, TRUE);
760 return 0;
763 static void NewCLI(Class *cl, Object *obj)
765 struct WorkbookBase *wb = (APTR)cl->cl_UserData;
766 struct wbWindow *my = INST_DATA(cl, obj);
768 BPTR dir;
770 SetWindowPointer(my->Window, WA_BusyPointer, TRUE, TAG_END);
771 dir = CurrentDir(my->Lock);
772 Execute("", BNULL, BNULL);
773 CurrentDir(dir);
774 SetWindowPointer(my->Window, WA_BusyPointer, FALSE, TAG_END);
777 static IPTR WBWindowForSelectedIcons(Class *cl, Object *obj, IPTR MethodID)
779 struct WorkbookBase *wb = (APTR)cl->cl_UserData;
780 struct wbWindow *my = INST_DATA(cl, obj);
781 struct wbWindow_Icon *wbwi;
782 IPTR rc = 0;
784 ForeachNode(&my->IconList, wbwi) {
785 IPTR selected = FALSE;
787 GetAttr(GA_Selected, wbwi->wbwiObject, &selected);
788 if (selected)
789 rc |= DoMethodA(wbwi->wbwiObject, (Msg)&MethodID);
792 return rc;
795 // WBWM_MENUPICK
796 static IPTR WBWindowMenuPick(Class *cl, Object *obj, struct wbwm_MenuPick *wbwmp)
798 struct WorkbookBase *wb = (APTR)cl->cl_UserData;
799 struct wbWindow *my = INST_DATA(cl, obj);
800 struct MenuItem *item = wbwmp->wbwmp_MenuItem;
801 BPTR lock;
802 BOOL rc = TRUE;
804 switch (WBMENU_ITEM_ID(item)) {
805 case WBMENU_ID(WBMENU_WN_OPEN_PARENT):
806 if (my->Lock != BNULL) {
807 lock = ParentDir(my->Lock);
808 if (NameFromLock(lock, my->PathBuffer, sizeof(my->PathBuffer))) {
809 OpenWorkbenchObject(my->PathBuffer, TAG_END);
811 UnLock(lock);
813 break;
814 case WBMENU_ID(WBMENU_WB_SHELL):
815 NewCLI(cl, obj);
816 break;
817 case WBMENU_ID(WBMENU_IC_OPEN):
818 rc = WBWindowForSelectedIcons(cl, obj, WBIM_Open);
819 break;
820 case WBMENU_ID(WBMENU_IC_COPY):
821 rc = WBWindowForSelectedIcons(cl, obj, WBIM_Copy);
822 break;
823 case WBMENU_ID(WBMENU_IC_RENAME):
824 rc = WBWindowForSelectedIcons(cl, obj, WBIM_Rename);
825 break;
826 case WBMENU_ID(WBMENU_IC_INFO):
827 rc = WBWindowForSelectedIcons(cl, obj, WBIM_Info);
828 break;
829 case WBMENU_ID(WBMENU_IC_SNAPSHOT):
830 rc = WBWindowForSelectedIcons(cl, obj, WBIM_Snapshot);
831 break;
832 case WBMENU_ID(WBMENU_IC_UNSNAPSHOT):
833 rc = WBWindowForSelectedIcons(cl, obj, WBIM_Unsnapshot);
834 break;
835 case WBMENU_ID(WBMENU_IC_LEAVE_OUT):
836 rc = WBWindowForSelectedIcons(cl, obj, WBIM_Leave_Out);
837 break;
838 case WBMENU_ID(WBMENU_IC_PUT_AWAY):
839 rc = WBWindowForSelectedIcons(cl, obj, WBIM_Put_Away);
840 break;
841 case WBMENU_ID(WBMENU_IC_DELETE):
842 rc = WBWindowForSelectedIcons(cl, obj, WBIM_Delete);
843 break;
844 case WBMENU_ID(WBMENU_IC_FORMAT):
845 rc = WBWindowForSelectedIcons(cl, obj, WBIM_Format);
846 break;
847 case WBMENU_ID(WBMENU_IC_EMPTY_TRASH):
848 rc = WBWindowForSelectedIcons(cl, obj, WBIM_Empty_Trash);
849 break;
850 default:
851 rc = FALSE;
852 break;
855 return rc;
858 // WBWM_INTUITICK
859 static IPTR WBWindowIntuiTick(Class *cl, Object *obj, Msg msg)
861 struct WorkbookBase *wb = (APTR)cl->cl_UserData;
862 struct wbWindow *my = INST_DATA(cl, obj);
863 IPTR rc = FALSE;
865 if (my->Tick == 0) {
866 IPTR val[5];
868 val[0] = WB_VERSION;
869 val[1] = WB_REVISION;
870 val[2] = AvailMem(MEMF_CHIP) / 1024;
871 val[3] = AvailMem(MEMF_FAST) / 1024;
872 val[4] = AvailMem(MEMF_ANY) / 1024;
874 /* Update the window's title */
875 RawDoFmt("Workbook %ld.%ld Chip: %ldk, Fast: %ldk, Any: %ldk", val,
876 RAWFMTFUNC_STRING, my->ScreenTitle);
878 SetWindowTitles(my->Window, (CONST_STRPTR)-1, my->ScreenTitle);
879 rc = TRUE;
882 /* Approx 10 IntuiTicks per second */
883 my->Tick = (my->Tick + 1) % 10;
885 return rc;
888 static IPTR dispatcher(Class *cl, Object *obj, Msg msg)
890 IPTR rc = 0;
892 switch (msg->MethodID) {
893 case OM_NEW: rc = WBWindowNew(cl, obj, (APTR)msg); break;
894 case OM_DISPOSE: rc = WBWindowDispose(cl, obj, (APTR)msg); break;
895 case OM_GET: rc = WBWindowGet(cl, obj, (APTR)msg); break;
896 case OM_UPDATE: rc = WBWindowUpdate(cl, obj, (APTR)msg); break;
897 case WBWM_NEWSIZE: rc = WBWindowNewSize(cl, obj, (APTR)msg); break;
898 case WBWM_MENUPICK: rc = WBWindowMenuPick(cl, obj, (APTR)msg); break;
899 case WBWM_INTUITICK: rc = WBWindowIntuiTick(cl, obj, (APTR)msg); break;
900 default: rc = DoSuperMethodA(cl, obj, msg); break;
903 return rc;
906 Class *WBWindow_MakeClass(struct WorkbookBase *wb)
908 Class *cl;
910 cl = MakeClass( NULL, "rootclass", NULL,
911 sizeof(struct wbWindow),
913 if (cl != NULL) {
914 cl->cl_Dispatcher.h_Entry = HookEntry;
915 cl->cl_Dispatcher.h_SubEntry = dispatcher;
916 cl->cl_Dispatcher.h_Data = NULL;
917 cl->cl_UserData = (IPTR)wb;
920 return cl;