2 Copyright (C) 2013-2017, The AROS Development Team.
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>
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>
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
;
47 OOP_AttrBase HiddAttrBase
;
48 OOP_AttrBase HWAttrBase
;
50 const struct OOP_ABDescr abd
[] =
52 {IID_Hidd
, &HiddAttrBase
},
53 {IID_HW
, &HWAttrBase
},
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
))
77 CONST_STRPTR name
= NULL
;
78 struct MUI_NListtree_TreeNode
*tn
;
80 struct InsertObjectMsg msg
=
85 struct ClassHandlerNode
*clHandlers
= FindObjectHandler(obj
, h
->h_Data
);
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
);
101 /* This is either HW or HIDD subclass */
102 OOP_GetAttr(obj
, aHW_ClassName
, (IPTR
*)&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 */
126 static struct Hook enum_hook
=
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
));
152 struct ClassHandlerNode
*FindObjectHandler(OOP_Object
*obj
, struct List
*_handlers
)
154 struct ClassHandlerNode
*curHandler
;
156 ForeachNode(_handlers
, curHandler
)
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
));
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
))
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
);
193 static const struct Hook close_hook
=
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
))
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
));
211 data
->obj
= insertMsg
->obj
;
212 data
->winClass
= insertMsg
->winClass
;
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
))
227 FreePooled(msg
->MemPool
, msg
->UserData
, sizeof(struct ObjectUserData
));
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
))
249 struct MUI_NListtree_TreeNode
*node
= *tn
;
250 struct ObjectUserData
*data
;
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
);
260 /* Do nothing if still no current entry */
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
));
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
);
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
,
282 D(bug("Created window 0x%p\n", data
->win
));
286 DoMethod(app
, OM_ADDMEMBER
, data
->win
);
287 DoMethod(data
->win
, MUIM_Notify
, MUIA_Window_CloseRequest
, TRUE
,
289 MUIM_CallHook
, &close_hook
, data
);
290 SET(data
->win
, MUIA_Window_Open
, TRUE
);
297 static const struct Hook property_hook
=
299 .h_Entry
= propertyFunc
302 static BOOL
GUIinit()
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
),
320 MUIA_Family_Child
, (IPTR
)(expand_menu
= MenuitemObject
,
321 MUIA_Menuitem_Title
, __(MSG_MENU_EXPANDALL
),
323 MUIA_Family_Child
, (IPTR
)(collapse_menu
= MenuitemObject
,
324 MUIA_Menuitem_Title
, __(MSG_MENU_COLLAPSEALL
),
326 MUIA_Family_Child
, (IPTR
)(quit_menu
= MenuitemObject
,
327 MUIA_Menuitem_Title
, __(MSG_MENU_QUIT
),
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
,
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 */
351 OOP_Object
*hwRoot
= OOP_NewObject(NULL
, CLID_HW_Root
, NULL
);
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
,
364 MUIM_Application_ReturnID
, MUIV_Application_ReturnID_Quit
);
366 DoMethod(property_window
, MUIM_Notify
, MUIA_Window_CloseRequest
, TRUE
,
368 MUIM_Set
, MUIA_Window_Open
, FALSE
);
371 DoMethod(property_menu
, MUIM_Notify
, MUIA_Menuitem_Trigger
, MUIV_EveryTime
,
373 MUIM_CallHook
, &property_hook
, 0);
375 DoMethod(expand_menu
, MUIM_Notify
, MUIA_Menuitem_Trigger
, MUIV_EveryTime
,
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
,
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
,
385 MUIM_Application_ReturnID
, MUIV_Application_ReturnID_Quit
);
387 DoMethod(hidd_tree
, MUIM_Notify
, MUIA_NListtree_DoubleClick
, MUIV_EveryTime
,
389 MUIM_CallHook
, &property_hook
, MUIV_TriggerValue
);
397 int __nocommandline
= 1;
401 if (!Locale_Initialize())
404 if (!OOP_ObtainAttrBases(abd
))
406 Locale_Deinitialize();
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
);
423 OOP_ReleaseAttrBases(abd
);
425 Locale_Deinitialize();
429 BOOL
RegisterClassHandler(CONST_STRPTR classid
, BYTE pri
, struct MUI_CustomClass
** customwinclass
, CLASS_ENUMFUNC enumfunc
, CLASS_VALIDFUNC validfunc
)
431 struct ClassHandlerNode
*newClass
;
433 if ((newClass
= FindClassHandler(classid
, &seClassHandlers
)))
435 if (newClass
->enumFunc
!= hwEnum
)
438 D(bug("[SysExplorer] Updating '%s'..\n", classid
));
444 D(bug("[SysExplorer] Registering '%s'..\n", classid
));
445 newClass
= AllocMem(sizeof(struct ClassHandlerNode
), MEMF_CLEAR
);
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
;
457 Enqueue(&seClassHandlers
, &newClass
->ch_Node
);
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"));
481 ADD2INIT(sysexplorer_init
, 0);