I've been away from my journal for too long. I started writing an article I was going to reawaken the journal with, but since stuff like SUMMER VACATION constantly reminds itself by interrupting my work I thought I'd just post small progress reports on MediatorMenu!
The actual shell extension is hooked up to Windows, so when I right click on a file or folder I see my context menu. The menu is generated from a XML file. A main menu is created from the XML in the DllMain, so the XML parsing is only done once for the lifetime of the loaded DLL. Then when the shell extension is asked to build a menu, it goes through that main menu (with a visitor) and filtering out a menu that's suitable for the items that were selected when right clicking. Some constraints on that are:
- When clicking on a .jpg file only commands that can operate on JPEG's should be visible.
- Adding to that constraint is several files, like a .jpg and a .tga should only show commands that can operate on both.
- If there are no available commands in a submenu, the submenu itself shouldn't be visible. I.e. "Modify image >" shouldn't show up in the context menu when clicking on a text file.
The menu system is a classic tree structure. An iMenuNode base class and MenuItem and SubMenu that derive from it. MenuItem is essentially the command item in the menu and SubMenu is the menu that holds them or other sub menus. I derived a MenuRoot from SubMenu as it's an specialization of it, it's only there to hold children and doesn't count itself in any operations (MediatorMenu doesn't force you to have a root node in the context menu, because this root holds them).
To battle the file constraints all MenuItem's have a set of Filter's. So last night I started implementing the filtering when clicking on different files (TDD style!). I started by revisiting my MenuVisitor, which was lacking support for pruning away whole subtrees. The solution was an evolved Visitor pattern called Hierarchial Visitor Pattern. To enable filtering like it'd expect to find them, all SubMenu's must have a collective filtering for what its children can operate on. Right? Wrong!
Consider a menu that operates on files like this:
- What's my name? ("*")
- Image operations
|- Compress JPEG (".jpg")
\- Index images ("Folder")
Now, select a folder and a JPEG file and right click. The collective filter in "Image operations" will agree that there are commands for those, while none of the commands work on both types (req. nr 2). Making an empty submenu "Image Operations >". Sadness :(
So now I'm stuck on that. The first thought was to build the menu recursively, i.e. only build SubMenu's if any MenuItem's actually passed the filter. But I'm not sure Windows likes this so I'll have to check it out more.
Until next time! And enjoy the global warming!