wip layout correction.
[AROS.git] / workbench / tools / SysExplorer / main.c
blobff946e747d14054d56fa844f977f157a7fd282ba
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 }
57 int sysExplGlobalCount;
60 * This lists contains handlers for known public classes.
61 * It specifies information window class, as well as function
62 * to enumerate children objects for the class.
64 * For proper operation CLIDs in this list should
65 * be sorted from subclasses to superclasses.
67 struct List seClassHandlers;
69 AROS_UFH3S(BOOL, enumFunc,
70 AROS_UFHA(struct Hook *, h, A0),
71 AROS_UFHA(OOP_Object*, obj, A2),
72 AROS_UFHA(void *, parent, A1))
74 AROS_USERFUNC_INIT
76 BOOL objValid = TRUE;
77 CONST_STRPTR name = NULL;
78 struct MUI_NListtree_TreeNode *tn;
79 ULONG flags = 0;
80 struct InsertObjectMsg msg =
82 .obj = obj,
83 .winClass = NULL
85 struct ClassHandlerNode *clHandlers = FindObjectHandler(obj, h->h_Data);
87 if (clHandlers)
89 if (clHandlers->muiClass)
90 msg.winClass = *(clHandlers->muiClass);
91 if (clHandlers->enumFunc)
92 flags = TNF_LIST|TNF_OPEN;
93 if (clHandlers->validFunc)
94 objValid = clHandlers->validFunc(obj, &flags);
97 if (objValid)
99 int objnum;
101 /* This is either HW or HIDD subclass */
102 OOP_GetAttr(obj, aHW_ClassName, (IPTR *)&name);
103 if (!name)
104 OOP_GetAttr(obj, aHidd_HardwareName, (IPTR *)&name);
106 objnum = ++sysExplGlobalCount;
107 tn = (APTR)DoMethod(hidd_tree, MUIM_NListtree_Insert, name, &msg,
108 parent, MUIV_NListtree_Insert_PrevNode_Sorted, flags);
110 D(bug("Inserted TreeNode 0x%p <%s> UserData 0x%p\n", tn, tn->tn_Name, tn->tn_User));
112 /* If we have enumerator for this class, call it now */
113 if (clHandlers && clHandlers->enumFunc && (flags & TNF_LIST))
114 clHandlers->enumFunc(obj, tn);
116 if (objnum == sysExplGlobalCount)
118 tn->tn_Flags &= ~flags;
121 return FALSE; /* Continue enumeration */
123 AROS_USERFUNC_EXIT
126 static struct Hook enum_hook =
128 .h_Entry = enumFunc,
129 .h_Data = &seClassHandlers
132 void hwEnum(OOP_Object *obj, struct MUI_NListtree_TreeNode *tn)
134 HW_EnumDrivers(obj, &enum_hook, tn);
137 struct ClassHandlerNode *FindClassHandler(CONST_STRPTR classid, struct List *_handlers)
139 struct ClassHandlerNode *curHandler;
141 ForeachNode(_handlers, curHandler)
143 if (!strncmp(classid, curHandler->ch_Node.ln_Name, strlen(classid)))
145 D(bug("[SysExplorer] Returning class '%s'\n", curHandler->ch_Node.ln_Name));
146 return curHandler;
149 return NULL;
152 struct ClassHandlerNode *FindObjectHandler(OOP_Object *obj, struct List *_handlers)
154 struct ClassHandlerNode *curHandler;
156 ForeachNode(_handlers, curHandler)
158 OOP_Class *cl;
159 D(bug("[SysExplorer] class '%s'\n", curHandler->ch_Node.ln_Name));
161 for (cl = OOP_OCLASS(obj); cl ; cl = cl->superclass)
163 D(bug("[SysExplorer] obj '%s'\n", cl->ClassNode.ln_Name));
164 if (!strncmp(cl->ClassNode.ln_Name, curHandler->ch_Node.ln_Name, strlen(curHandler->ch_Node.ln_Name)))
166 D(bug("[SysExplorer] Returning obj class '%s'\n", curHandler->ch_Node.ln_Name));
167 return curHandler;
171 return NULL;
174 AROS_UFH3S(void, closeFunc,
175 AROS_UFHA(struct Hook *, h, A0),
176 AROS_UFHA(Object*, obj, A2),
177 AROS_UFHA(struct ObjectUserData **, msg, A1))
179 AROS_USERFUNC_INIT
181 D(bug("closeFunc address 0x%p\n", closeFunc));
182 D(bug("Close window 0x%p, ObjectUserData 0x%p\n", obj, *msg));
184 SET(obj, MUIA_Window_Open, FALSE);
185 DoMethod(app, OM_REMMEMBER, obj);
186 DoMethod(app, MUIM_Application_PushMethod, obj, 1, OM_DISPOSE);
188 (*msg)->win = NULL;
190 AROS_USERFUNC_EXIT
193 static const struct Hook close_hook =
195 .h_Entry = closeFunc
198 AROS_UFH3S(APTR, constructFunc,
199 AROS_UFHA(struct Hook *, h, A0),
200 AROS_UFHA(Object*, obj, A2),
201 AROS_UFHA(struct MUIP_NListtree_ConstructMessage *, msg, A1))
203 AROS_USERFUNC_INIT
205 struct InsertObjectMsg *insertMsg = msg->UserData;
206 struct ObjectUserData *data = AllocPooled(msg->MemPool, sizeof(struct ObjectUserData));
208 D(bug("%s: insertMsg 0x%p ObjectUserData 0x%p\n", msg->Name, insertMsg, data));
209 if (data)
211 data->obj = insertMsg->obj;
212 data->winClass = insertMsg->winClass;
213 data->win = NULL;
215 return data;
217 AROS_USERFUNC_EXIT
220 AROS_UFH3S(void, destructFunc,
221 AROS_UFHA(struct Hook *, h, A0),
222 AROS_UFHA(Object*, obj, A2),
223 AROS_UFHA(struct MUIP_NListtree_DestructMessage *, msg, A1))
225 AROS_USERFUNC_INIT
227 FreePooled(msg->MemPool, msg->UserData, sizeof(struct ObjectUserData));
229 AROS_USERFUNC_EXIT
232 static const struct Hook constructHook =
234 .h_Entry = constructFunc
237 static const struct Hook destructHook =
239 .h_Entry = destructFunc
242 AROS_UFH3S(void, propertyFunc,
243 AROS_UFHA(struct Hook *, h, A0),
244 AROS_UFHA(Object*, obj, A2),
245 AROS_UFHA(struct MUI_NListtree_TreeNode **, tn, A1))
247 AROS_USERFUNC_INIT
249 struct MUI_NListtree_TreeNode *node = *tn;
250 struct ObjectUserData *data;
252 if (node == NULL)
254 /* if we were called from menu we must first find the current entry */
255 node = (struct MUI_NListtree_TreeNode *)XGET(hidd_tree, MUIA_NListtree_Active);
258 if (node == NULL)
260 /* Do nothing if still no current entry */
261 return;
264 data = node->tn_User;
265 D(bug("propertyFunc called: TreeNode 0x%p <%s> UserData 0x%p\n", node, node->tn_Name, data));
266 D(bug("Window 0x%p\n", data->win));
268 if (data->win)
270 /* The window is already open, show it to the user */
271 DoMethod(data->win, MUIM_Window_ToFront);
272 SET(data->win, MUIA_Window_Activate, TRUE);
273 return;
276 if (data->winClass)
278 /* We have information window class. Open the window. */
279 data->win = NewObject(data->winClass->mcc_Class, NULL,
280 MUIA_PropertyWin_Object, (IPTR)data->obj,
281 TAG_DONE);
282 D(bug("Created window 0x%p\n", data->win));
284 if (data->win)
286 DoMethod(app, OM_ADDMEMBER, data->win);
287 DoMethod(data->win, MUIM_Notify, MUIA_Window_CloseRequest, TRUE,
288 data->win, 3,
289 MUIM_CallHook, &close_hook, data);
290 SET(data->win, MUIA_Window_Open, TRUE);
294 AROS_USERFUNC_EXIT
297 static const struct Hook property_hook =
299 .h_Entry = propertyFunc
302 static BOOL GUIinit()
304 BOOL retval = FALSE;
306 app = ApplicationObject,
307 MUIA_Application_Title, (IPTR)APPNAME,
308 MUIA_Application_Version, (IPTR)VERSION,
309 MUIA_Application_Copyright, (IPTR)"(C) 2013, The AROS Development Team",
310 MUIA_Application_Author, (IPTR)"Pavel Fedin",
311 MUIA_Application_Base, (IPTR)APPNAME,
312 MUIA_Application_Description, __(MSG_DESCRIPTION),
314 MUIA_Application_Menustrip, (IPTR)(MenustripObject,
315 MUIA_Family_Child, (IPTR)(MenuObject,
316 MUIA_Menu_Title, __(MSG_MENU_PROJECT),
317 MUIA_Family_Child, (IPTR)(property_menu = MenuitemObject,
318 MUIA_Menuitem_Title, __(MSG_MENU_PROPERTIES),
319 End),
320 MUIA_Family_Child, (IPTR)(expand_menu = MenuitemObject,
321 MUIA_Menuitem_Title, __(MSG_MENU_EXPANDALL),
322 End),
323 MUIA_Family_Child, (IPTR)(collapse_menu = MenuitemObject,
324 MUIA_Menuitem_Title, __(MSG_MENU_COLLAPSEALL),
325 End),
326 MUIA_Family_Child, (IPTR)(quit_menu = MenuitemObject,
327 MUIA_Menuitem_Title, __(MSG_MENU_QUIT),
328 End),
329 End),
330 End),
332 SubWindow, (IPTR)(main_window = WindowObject,
333 MUIA_Window_Title, __(MSG_WINTITLE),
334 MUIA_Window_ID, MAKE_ID('S', 'Y', 'E', 'X'),
335 WindowContents, (IPTR)(HGroup,
336 Child, (IPTR)(NListviewObject,
337 MUIA_NListview_NList, (IPTR)(hidd_tree = NListtreeObject,
338 ReadListFrame,
339 MUIA_CycleChain, TRUE,
340 MUIA_NListtree_ConstructHook, (IPTR)&constructHook,
341 MUIA_NListtree_DestructHook, (IPTR)&destructHook,
342 MUIA_NListtree_DragDropSort, FALSE, /* forbid sorting by drag'n'drop */
343 End),
344 End),
345 End),
346 End),
347 End;
349 if (app)
351 OOP_Object *hwRoot = OOP_NewObject(NULL, CLID_HW_Root, NULL);
353 if (hwRoot)
355 sysExplGlobalCount = 0;
357 /* This will kick our recursive enumeration into action */
358 CALLHOOKPKT((struct Hook *)&enum_hook, hwRoot, MUIV_NListtree_Insert_ListNode_Root);
361 /* Quit application if the main window's closegadget or the esc key is pressed. */
362 DoMethod(main_window, MUIM_Notify, MUIA_Window_CloseRequest, TRUE,
363 app, 2,
364 MUIM_Application_ReturnID, MUIV_Application_ReturnID_Quit);
366 DoMethod(property_window, MUIM_Notify, MUIA_Window_CloseRequest, TRUE,
367 property_window, 3,
368 MUIM_Set, MUIA_Window_Open, FALSE);
371 DoMethod(property_menu, MUIM_Notify, MUIA_Menuitem_Trigger, MUIV_EveryTime,
372 app, 3,
373 MUIM_CallHook, &property_hook, 0);
375 DoMethod(expand_menu, MUIM_Notify, MUIA_Menuitem_Trigger, MUIV_EveryTime,
376 hidd_tree, 4,
377 MUIM_NListtree_Open, MUIV_NListtree_Open_ListNode_Root, MUIV_NListtree_Open_TreeNode_All, 0);
379 DoMethod(collapse_menu, MUIM_Notify, MUIA_Menuitem_Trigger, MUIV_EveryTime,
380 hidd_tree, 4,
381 MUIM_NListtree_Close, MUIV_NListtree_Close_ListNode_Root, MUIV_NListtree_Close_TreeNode_All, 0);
383 DoMethod(quit_menu, MUIM_Notify, MUIA_Menuitem_Trigger, MUIV_EveryTime,
384 app, 2,
385 MUIM_Application_ReturnID, MUIV_Application_ReturnID_Quit);
387 DoMethod(hidd_tree, MUIM_Notify, MUIA_NListtree_DoubleClick, MUIV_EveryTime,
388 app, 3,
389 MUIM_CallHook, &property_hook, MUIV_TriggerValue);
391 retval = TRUE;
394 return retval;
397 int __nocommandline = 1;
399 int main(void)
401 if (!Locale_Initialize())
402 return 20;
404 if (!OOP_ObtainAttrBases(abd))
406 Locale_Deinitialize();
407 return 20;
410 if (GUIinit())
412 SET(main_window, MUIA_Window_Open, TRUE);
414 if (XGET(main_window, MUIA_Window_Open))
416 DoMethod(app, MUIM_Application_Execute);
417 SET(main_window, MUIA_Window_Open, FALSE);
420 DisposeObject(app);
423 OOP_ReleaseAttrBases(abd);
425 Locale_Deinitialize();
426 return 0;
429 BOOL RegisterClassHandler(CONST_STRPTR classid, BYTE pri, struct MUI_CustomClass ** customwinclass, CLASS_ENUMFUNC enumfunc, CLASS_VALIDFUNC validfunc)
431 struct ClassHandlerNode *newClass;
432 BOOL add = TRUE;
433 if ((newClass = FindClassHandler(classid, &seClassHandlers)))
435 if (newClass->enumFunc != hwEnum)
436 return FALSE;
438 D(bug("[SysExplorer] Updating '%s'..\n", classid));
439 add = FALSE;
442 if (add)
444 D(bug("[SysExplorer] Registering '%s'..\n", classid));
445 newClass = AllocMem(sizeof(struct ClassHandlerNode), MEMF_CLEAR);
448 if (newClass)
450 newClass->ch_Node.ln_Name = (char *)classid;
451 newClass->ch_Node.ln_Pri = pri;
452 newClass->muiClass = customwinclass;
453 newClass->enumFunc = enumfunc;
454 newClass->validFunc = validfunc;
456 if (add)
457 Enqueue(&seClassHandlers, &newClass->ch_Node);
459 return TRUE;
461 return FALSE;
464 BOOL sysexplorer_init(void)
466 D(bug("[SysExplorer] Initialising..\n"));
467 NEWLIST(&seClassHandlers);
469 RegisterClassHandler(CLID_Hidd_Storage, 90, NULL, hwEnum, NULL);
470 RegisterClassHandler(CLID_Hidd_Gfx, 60, NULL, hwEnum, NULL);
471 RegisterClassHandler(CLID_Hidd_System, 30, NULL, hwEnum, NULL);
472 RegisterClassHandler(CLID_HW_Root, 0, &ComputerWindow_CLASS, hwEnum, NULL);
473 RegisterClassHandler(CLID_HW, -30, NULL, hwEnum, NULL);
474 RegisterClassHandler(CLID_Hidd, -60, &GenericWindow_CLASS, NULL, NULL);
476 D(bug("[SysExplorer] Init complete\n"));
478 return TRUE;
481 ADD2INIT(sysexplorer_init, 0);