silence debug unless it has been requested
[AROS.git] / workbench / tools / SysExplorer / main.c
blob037ec479967bd2457cf0622ddb7247b73ef2357e
1 /*
2 Copyright (C) 2013-2017, The AROS Development Team.
3 $Id$
4 */
6 #include <aros/debug.h>
8 #define MUIMASTER_YES_INLINE_STDARG
10 #include <exec/memory.h>
11 #include <hidd/hidd.h>
12 #include <hidd/system.h>
13 #include <hidd/gfx.h>
14 #include <hidd/storage.h>
15 #include <libraries/asl.h>
16 #include <mui/NListtree_mcc.h>
17 #include <mui/NListview_mcc.h>
18 #include <utility/tagitem.h>
19 #include <utility/hooks.h>
21 #include <proto/alib.h>
22 #include <proto/dos.h>
23 #include <proto/exec.h>
24 #include <proto/muimaster.h>
25 #include <proto/oop.h>
26 #include <proto/utility.h>
27 #include <proto/intuition.h>
29 #include <ctype.h>
30 #include <stdio.h>
31 #include <stdlib.h>
33 #include "locale.h"
34 #include "classes.h"
36 #include "enums.h"
38 #define APPNAME "SysExplorer"
39 #define VERSION "SysExplorer 0.2"
41 const char version[] = "$VER: " VERSION " (" ADATE ")\n";
43 static Object *app, *main_window, *property_window;
44 static Object *property_menu, *expand_menu, *collapse_menu, *quit_menu;
45 Object *hidd_tree;
47 OOP_AttrBase HiddAttrBase;
48 OOP_AttrBase HWAttrBase;
50 const struct OOP_ABDescr abd[] =
52 {IID_Hidd , &HiddAttrBase },
53 {IID_HW , &HWAttrBase },
54 {NULL , NULL }
58 * This lists contains handlers for known public classes.
59 * It specifies information window class, as well as function
60 * to enumerate children objects for the class.
62 * For proper operation CLIDs in this list should
63 * be sorted from subclasses to superclasses.
65 struct List seClassHandlers;
67 AROS_UFH3S(BOOL, enumFunc,
68 AROS_UFHA(struct Hook *, h, A0),
69 AROS_UFHA(OOP_Object*, obj, A2),
70 AROS_UFHA(void *, parent, A1))
72 AROS_USERFUNC_INIT
74 BOOL objValid = TRUE;
75 CONST_STRPTR name = NULL;
76 struct MUI_NListtree_TreeNode *tn;
77 ULONG flags = 0;
78 struct InsertObjectMsg msg =
80 .obj = obj,
81 .winClass = NULL
83 struct ClassHandlerNode *clHandlers = FindObjectHandler(obj, h->h_Data);
85 if (clHandlers)
87 if (clHandlers->muiClass)
88 msg.winClass = *(clHandlers->muiClass);
89 if (clHandlers->enumFunc)
90 flags = TNF_LIST|TNF_OPEN;
91 if (clHandlers->validFunc)
92 objValid = clHandlers->validFunc(obj, &flags);
95 if (objValid)
97 /* This is either HW or HIDD subclass */
98 OOP_GetAttr(obj, aHW_ClassName, (IPTR *)&name);
99 if (!name)
100 OOP_GetAttr(obj, aHidd_HardwareName, (IPTR *)&name);
102 tn = (APTR)DoMethod(hidd_tree, MUIM_NListtree_Insert, name, &msg,
103 parent, MUIV_NListtree_Insert_PrevNode_Sorted, flags);
104 D(bug("Inserted TreeNode 0x%p <%s> UserData 0x%p\n", tn, tn->tn_Name, tn->tn_User));
106 /* If we have enumerator for this class, call it now */
107 if (clHandlers && clHandlers->enumFunc && (flags & TNF_LIST))
108 clHandlers->enumFunc(obj, tn);
110 return FALSE; /* Continue enumeration */
112 AROS_USERFUNC_EXIT
115 static struct Hook enum_hook =
117 .h_Entry = enumFunc,
118 .h_Data = &seClassHandlers
121 void hwEnum(OOP_Object *obj, struct MUI_NListtree_TreeNode *tn)
123 HW_EnumDrivers(obj, &enum_hook, tn);
126 struct ClassHandlerNode *FindClassHandler(CONST_STRPTR classid, struct List *_handlers)
128 struct ClassHandlerNode *curHandler;
130 ForeachNode(_handlers, curHandler)
132 if (!strncmp(classid, curHandler->ch_Node.ln_Name, strlen(classid)))
134 D(bug("[SysExplorer] Returning class '%s'\n", curHandler->ch_Node.ln_Name));
135 return curHandler;
138 return NULL;
141 struct ClassHandlerNode *FindObjectHandler(OOP_Object *obj, struct List *_handlers)
143 struct ClassHandlerNode *curHandler;
145 ForeachNode(_handlers, curHandler)
147 OOP_Class *cl;
148 D(bug("[SysExplorer] class '%s'\n", curHandler->ch_Node.ln_Name));
150 for (cl = OOP_OCLASS(obj); cl ; cl = cl->superclass)
152 D(bug("[SysExplorer] obj '%s'\n", cl->ClassNode.ln_Name));
153 if (!strncmp(cl->ClassNode.ln_Name, curHandler->ch_Node.ln_Name, strlen(curHandler->ch_Node.ln_Name)))
155 D(bug("[SysExplorer] Returning obj class '%s'\n", curHandler->ch_Node.ln_Name));
156 return curHandler;
160 return NULL;
163 AROS_UFH3S(void, closeFunc,
164 AROS_UFHA(struct Hook *, h, A0),
165 AROS_UFHA(Object*, obj, A2),
166 AROS_UFHA(struct ObjectUserData **, msg, A1))
168 AROS_USERFUNC_INIT
170 D(bug("closeFunc address 0x%p\n", closeFunc));
171 D(bug("Close window 0x%p, ObjectUserData 0x%p\n", obj, *msg));
173 SET(obj, MUIA_Window_Open, FALSE);
174 DoMethod(app, OM_REMMEMBER, obj);
175 DoMethod(app, MUIM_Application_PushMethod, obj, 1, OM_DISPOSE);
177 (*msg)->win = NULL;
179 AROS_USERFUNC_EXIT
182 static const struct Hook close_hook =
184 .h_Entry = closeFunc
187 AROS_UFH3S(APTR, constructFunc,
188 AROS_UFHA(struct Hook *, h, A0),
189 AROS_UFHA(Object*, obj, A2),
190 AROS_UFHA(struct MUIP_NListtree_ConstructMessage *, msg, A1))
192 AROS_USERFUNC_INIT
194 struct InsertObjectMsg *insertMsg = msg->UserData;
195 struct ObjectUserData *data = AllocPooled(msg->MemPool, sizeof(struct ObjectUserData));
197 D(bug("%s: insertMsg 0x%p ObjectUserData 0x%p\n", msg->Name, insertMsg, data));
198 if (data)
200 data->obj = insertMsg->obj;
201 data->winClass = insertMsg->winClass;
202 data->win = NULL;
204 return data;
206 AROS_USERFUNC_EXIT
209 AROS_UFH3S(void, destructFunc,
210 AROS_UFHA(struct Hook *, h, A0),
211 AROS_UFHA(Object*, obj, A2),
212 AROS_UFHA(struct MUIP_NListtree_DestructMessage *, msg, A1))
214 AROS_USERFUNC_INIT
216 FreePooled(msg->MemPool, msg->UserData, sizeof(struct ObjectUserData));
218 AROS_USERFUNC_EXIT
221 static const struct Hook constructHook =
223 .h_Entry = constructFunc
226 static const struct Hook destructHook =
228 .h_Entry = destructFunc
231 AROS_UFH3S(void, propertyFunc,
232 AROS_UFHA(struct Hook *, h, A0),
233 AROS_UFHA(Object*, obj, A2),
234 AROS_UFHA(struct MUI_NListtree_TreeNode **, tn, A1))
236 AROS_USERFUNC_INIT
238 struct MUI_NListtree_TreeNode *node = *tn;
239 struct ObjectUserData *data;
241 if (node == NULL)
243 /* if we were called from menu we must 1st find the current entry */
244 node = (struct MUI_NListtree_TreeNode *)XGET(hidd_tree, MUIA_NListtree_Active);
247 if (node == NULL)
249 /* Do nothing if still no current entry */
250 return;
253 data = node->tn_User;
254 D(bug("propertyFunc called: TreeNode 0x%p <%s> UserData 0x%p\n", node, node->tn_Name, data));
255 D(bug("Window 0x%p\n", data->win));
257 if (data->win)
259 /* The window is already open, show it to the user */
260 DoMethod(data->win, MUIM_Window_ToFront);
261 SET(data->win, MUIA_Window_Activate, TRUE);
262 return;
265 if (data->winClass)
267 /* We have information window class. Open the window. */
268 data->win = NewObject(data->winClass->mcc_Class, NULL,
269 MUIA_PropertyWin_Object, (IPTR)data->obj,
270 TAG_DONE);
271 D(bug("Created window 0x%p\n", data->win));
273 if (data->win)
275 DoMethod(app, OM_ADDMEMBER, data->win);
276 DoMethod(data->win, MUIM_Notify, MUIA_Window_CloseRequest, TRUE,
277 data->win, 3,
278 MUIM_CallHook, &close_hook, data);
279 SET(data->win, MUIA_Window_Open, TRUE);
283 AROS_USERFUNC_EXIT
286 static const struct Hook property_hook =
288 .h_Entry = propertyFunc
291 static BOOL GUIinit()
293 BOOL retval = FALSE;
295 app = ApplicationObject,
296 MUIA_Application_Title, (IPTR)APPNAME,
297 MUIA_Application_Version, (IPTR)VERSION,
298 MUIA_Application_Copyright, (IPTR)"(C) 2013, The AROS Development Team",
299 MUIA_Application_Author, (IPTR)"Pavel Fedin",
300 MUIA_Application_Base, (IPTR)APPNAME,
301 MUIA_Application_Description, __(MSG_DESCRIPTION),
303 MUIA_Application_Menustrip, (IPTR)(MenustripObject,
304 MUIA_Family_Child, (IPTR)(MenuObject,
305 MUIA_Menu_Title, __(MSG_MENU_PROJECT),
306 MUIA_Family_Child, (IPTR)(property_menu = MenuitemObject,
307 MUIA_Menuitem_Title, __(MSG_MENU_PROPERTIES),
308 End),
309 MUIA_Family_Child, (IPTR)(expand_menu = MenuitemObject,
310 MUIA_Menuitem_Title, __(MSG_MENU_EXPANDALL),
311 End),
312 MUIA_Family_Child, (IPTR)(collapse_menu = MenuitemObject,
313 MUIA_Menuitem_Title, __(MSG_MENU_COLLAPSEALL),
314 End),
315 MUIA_Family_Child, (IPTR)(quit_menu = MenuitemObject,
316 MUIA_Menuitem_Title, __(MSG_MENU_QUIT),
317 End),
318 End),
319 End),
321 SubWindow, (IPTR)(main_window = WindowObject,
322 MUIA_Window_Title, __(MSG_WINTITLE),
323 MUIA_Window_ID, MAKE_ID('S', 'Y', 'E', 'X'),
324 WindowContents, (IPTR)(HGroup,
325 Child, (IPTR)(NListviewObject,
326 MUIA_NListview_NList, (IPTR)(hidd_tree = NListtreeObject,
327 ReadListFrame,
328 MUIA_CycleChain, TRUE,
329 MUIA_NListtree_ConstructHook, (IPTR)&constructHook,
330 MUIA_NListtree_DestructHook, (IPTR)&destructHook,
331 MUIA_NListtree_DragDropSort, FALSE, /* forbid sorting by drag'n'drop */
332 End),
333 End),
334 End),
335 End),
336 End;
338 if (app)
340 OOP_Object *hwRoot = OOP_NewObject(NULL, CLID_HW_Root, NULL);
342 if (hwRoot)
344 /* This will kick our recursive enumeration into action */
345 CALLHOOKPKT((struct Hook *)&enum_hook, hwRoot, MUIV_NListtree_Insert_ListNode_Root);
348 /* Quit application if the main window's closegadget or the esc key is pressed. */
349 DoMethod(main_window, MUIM_Notify, MUIA_Window_CloseRequest, TRUE,
350 app, 2,
351 MUIM_Application_ReturnID, MUIV_Application_ReturnID_Quit);
353 DoMethod(property_window, MUIM_Notify, MUIA_Window_CloseRequest, TRUE,
354 property_window, 3,
355 MUIM_Set, MUIA_Window_Open, FALSE);
358 DoMethod(property_menu, MUIM_Notify, MUIA_Menuitem_Trigger, MUIV_EveryTime,
359 app, 3,
360 MUIM_CallHook, &property_hook, 0);
362 DoMethod(expand_menu, MUIM_Notify, MUIA_Menuitem_Trigger, MUIV_EveryTime,
363 hidd_tree, 4,
364 MUIM_NListtree_Open, MUIV_NListtree_Open_ListNode_Root, MUIV_NListtree_Open_TreeNode_All, 0);
366 DoMethod(collapse_menu, MUIM_Notify, MUIA_Menuitem_Trigger, MUIV_EveryTime,
367 hidd_tree, 4,
368 MUIM_NListtree_Close, MUIV_NListtree_Close_ListNode_Root, MUIV_NListtree_Close_TreeNode_All, 0);
370 DoMethod(quit_menu, MUIM_Notify, MUIA_Menuitem_Trigger, MUIV_EveryTime,
371 app, 2,
372 MUIM_Application_ReturnID, MUIV_Application_ReturnID_Quit);
374 DoMethod(hidd_tree, MUIM_Notify, MUIA_NListtree_DoubleClick, MUIV_EveryTime,
375 app, 3,
376 MUIM_CallHook, &property_hook, MUIV_TriggerValue);
378 retval = TRUE;
381 return retval;
384 int __nocommandline = 1;
386 int main(void)
388 if (!Locale_Initialize())
389 return 20;
391 if (!OOP_ObtainAttrBases(abd))
393 Locale_Deinitialize();
394 return 20;
397 if (GUIinit())
399 SET(main_window, MUIA_Window_Open, TRUE);
401 if (XGET(main_window, MUIA_Window_Open))
403 DoMethod(app, MUIM_Application_Execute);
404 SET(main_window, MUIA_Window_Open, FALSE);
407 DisposeObject(app);
410 OOP_ReleaseAttrBases(abd);
412 Locale_Deinitialize();
413 return 0;
416 BOOL RegisterClassHandler(CONST_STRPTR classid, BYTE pri, struct MUI_CustomClass ** customwinclass, CLASS_ENUMFUNC enumfunc, CLASS_VALIDFUNC validfunc)
418 struct ClassHandlerNode *newClass;
419 BOOL add = TRUE;
420 if ((newClass = FindClassHandler(classid, &seClassHandlers)))
422 if (newClass->enumFunc != hwEnum)
423 return FALSE;
425 D(bug("[SysExplorer] Updating '%s'..\n", classid));
426 add = FALSE;
429 if (add)
431 D(bug("[SysExplorer] Registering '%s'..\n", classid));
432 newClass = AllocMem(sizeof(struct ClassHandlerNode), MEMF_CLEAR);
435 if (newClass)
437 newClass->ch_Node.ln_Name = (char *)classid;
438 newClass->ch_Node.ln_Pri = pri;
439 newClass->muiClass = customwinclass;
440 newClass->enumFunc = enumfunc;
441 newClass->validFunc = validfunc;
443 if (add)
444 Enqueue(&seClassHandlers, &newClass->ch_Node);
446 return TRUE;
448 return FALSE;
451 BOOL sysexplorer_init(void)
453 D(bug("[SysExplorer] Initialising..\n"));
454 NEWLIST(&seClassHandlers);
456 RegisterClassHandler(CLID_Hidd_Storage, 90, NULL, hwEnum, NULL);
457 RegisterClassHandler(CLID_Hidd_Gfx, 60, NULL, hwEnum, NULL);
458 RegisterClassHandler(CLID_Hidd_System, 30, NULL, hwEnum, NULL);
459 RegisterClassHandler(CLID_HW_Root, 0, &ComputerWindow_CLASS, hwEnum, NULL);
460 RegisterClassHandler(CLID_HW, -30, NULL, hwEnum, NULL);
461 RegisterClassHandler(CLID_Hidd, -60, &GenericWindow_CLASS, NULL, NULL);
463 D(bug("[SysExplorer] Init complete\n"));
465 return TRUE;
468 ADD2INIT(sysexplorer_init, 0);