Skip to content

Commit 962af39

Browse files
committed
* Fixed issue #59: Implement a new type of separator for creating a menu with multiple columns.
1 parent b5ea9f1 commit 962af39

File tree

12 files changed

+147
-8
lines changed

12 files changed

+147
-8
lines changed

CHANGES

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ Changes for 0.7.0
44
* Using [File for Windows](https://github.com/Cirn09/file-windows) v5.38 with minimal changes.
55
* Using [PCRE2](http://www.pcre.org/) version 10.30
66
* Deprecated support for 32-bit Windows.
7+
* Fixed issue #59: Implement a new type of separator for creating a menu with multiple columns.
78
* Fixed issue #91: String encoding in source code.
89
* Fixed issue #96: Problems with Files > 2Gb
910
* Fixed issue #97: Files and folders together do not start MENU.

UserManual.md

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -188,10 +188,26 @@ Menu names supports _keyboard mnemonics_, see the [Mnemonics / keyboard shortcut
188188

189189
### separator attribute: ###
190190

191-
The `separator` attribute allows one to define a separator between menu options. To define a separator, one must set the `separator` attributes to one of the following values: `true`, `yes` or `on`. For example, add the following menu element in a *configuration file*:
191+
The `separator` attribute allows one to define an *horizontal* separator between menu options. To define an *horizontal* separator, one must set the `separator` attributes to one of the following values: `true`, `yes`, `on` or `horizontal`. For example, the following creates a separator between menu *foo* and *bar* :
192192

193193
```xml
194+
<menu name="foo" />
194195
<menu separator="true" />
196+
<menu name="bar" />
197+
```
198+
199+
ShellAnything also support creating *vertical* (or column) separators. When using such a separator, *Windows* renders the popup menu with multiple columns. The menus following a column separator are rendered in a new column. For example, look at [this image](docs/multiple_columns_menu.png?raw=true) to see a multi-column menu. To define a *vertical* separator, one must set the `separator` attributes to value `vertical` or `column`. For example, the following creates a two column menu :
200+
201+
```xml
202+
<menu name="Left" />
203+
<menu name="logical" />
204+
<menu name="analytical" />
205+
<menu name="objective" />
206+
<menu separator="column" />
207+
<menu name="Right" />
208+
<menu name="intuitive" />
209+
<menu name="creativity" />
210+
<menu name="subjective" />
195211
```
196212

197213

docs/multiple_columns_menu.png

3.38 KB
Loading

include/shellanything/Menu.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,18 @@ namespace shellanything
7979
/// <param name="separator">True to define the menu as a separator. False otherwise.</param>
8080
void SetSeparator(bool separator);
8181

82+
/// <summary>
83+
/// Returns true of the menu is a column separator.
84+
/// </summary>
85+
/// <returns>Returns true of the menu is a column separator. Returns false otherwise.</returns>
86+
bool IsColumnSeparator() const;
87+
88+
/// <summary>
89+
/// Sets the menu column separator property.
90+
/// </summary>
91+
/// <param name="separator">True to define the menu as a column separator. False otherwise.</param>
92+
void SetColumnSeparator(bool column_separator);
93+
8294
/// <summary>
8395
/// Returns true if the menu is a parent menu (if this menu have submenus).
8496
/// </summary>
@@ -247,6 +259,7 @@ namespace shellanything
247259
bool mVisible;
248260
bool mEnabled;
249261
bool mSeparator;
262+
bool mColumnSeparator;
250263
uint32_t mCommandId;
251264
std::string mName;
252265
int mNameMaxLength;

src/Menu.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ namespace shellanything
3333
Menu::Menu() : Node("Menu"),
3434
mNameMaxLength(DEFAULT_NAME_MAX_LENGTH),
3535
mSeparator(false),
36+
mColumnSeparator(false),
3637
mCommandId(INVALID_COMMAND_ID),
3738
mVisible(true),
3839
mEnabled(true)
@@ -76,6 +77,16 @@ namespace shellanything
7677
mSeparator = separator;
7778
}
7879

80+
bool Menu::IsColumnSeparator() const
81+
{
82+
return mColumnSeparator;
83+
}
84+
85+
void Menu::SetColumnSeparator(bool column_separator)
86+
{
87+
mColumnSeparator = column_separator;
88+
}
89+
7990
bool Menu::IsParentMenu() const
8091
{
8192
Menu::MenuPtrList sub_menus = FilterNodes<Menu*>(this->FindChildren("Menu"));

src/ObjectFactory.cpp

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -506,15 +506,30 @@ namespace shellanything
506506
//parse separator
507507
std::string menu_separator;
508508
bool have_separetor = ParseAttribute(element, "separator", true, true, menu_separator, error);
509-
bool is_separator = false;
509+
bool separator_parsed = false;
510510
if (have_separetor)
511511
{
512-
is_separator = ra::strings::ParseBoolean(menu_separator);
513-
if (is_separator)
512+
//try to parse this menu separator as a boolean
513+
bool is_horizontal_separator = false;
514+
separator_parsed = ra::strings::Parse(menu_separator, is_horizontal_separator);
515+
if (separator_parsed && is_horizontal_separator)
514516
{
515517
menu->SetSeparator(true);
516518
return menu;
517519
}
520+
521+
//try to parse as a string
522+
menu_separator = ra::strings::Lowercase(menu_separator);
523+
if (menu_separator == "horizontal")
524+
{
525+
menu->SetSeparator(true);
526+
return menu;
527+
}
528+
else if (menu_separator == "vertical" || menu_separator == "column")
529+
{
530+
menu->SetColumnSeparator(true);
531+
return menu;
532+
}
518533
}
519534

520535
//parse name

src/shellext.cpp

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -246,7 +246,7 @@ template <class T> class FlagDescriptor
246246
}
247247
};
248248

249-
void CContextMenu::BuildMenuTree(HMENU hMenu, shellanything::Menu * menu, UINT & insert_pos)
249+
void CContextMenu::BuildMenuTree(HMENU hMenu, shellanything::Menu * menu, UINT & insert_pos, bool & next_menu_is_column)
250250
{
251251
//Expanded the menu's strings
252252
shellanything::PropertyManager & pmgr = shellanything::PropertyManager::GetInstance();
@@ -257,6 +257,14 @@ void CContextMenu::BuildMenuTree(HMENU hMenu, shellanything::Menu * menu, UINT &
257257
bool menu_visible = menu->IsVisible();
258258
bool menu_enabled = menu->IsEnabled();
259259
bool menu_separator = menu->IsSeparator();
260+
bool menu_column = menu->IsColumnSeparator();
261+
262+
//Skip column separator, those are not menu item
263+
if (menu_column)
264+
{
265+
next_menu_is_column = true;
266+
return;
267+
}
260268

261269
//Skip this menu if not visible
262270
if (!menu_visible)
@@ -288,6 +296,7 @@ void CContextMenu::BuildMenuTree(HMENU hMenu, shellanything::Menu * menu, UINT &
288296
menuinfo.cbSize = sizeof(MENUITEMINFOW);
289297
menuinfo.fMask = MIIM_FTYPE | MIIM_STATE | MIIM_ID | MIIM_STRING;
290298
menuinfo.fType = (menu_separator ? MFT_SEPARATOR : MFT_STRING);
299+
menuinfo.fType += (next_menu_is_column ? MFT_MENUBARBREAK : 0);
291300
menuinfo.fState = (menu_enabled ? MFS_ENABLED : MFS_DISABLED);
292301
menuinfo.wID = menu_command_id;
293302
menuinfo.dwTypeData = (wchar_t*)title_utf16.c_str();
@@ -375,18 +384,27 @@ void CContextMenu::BuildMenuTree(HMENU hMenu, shellanything::Menu * menu, UINT &
375384
}
376385
}
377386

387+
//handle column separator
388+
if (next_menu_is_column)
389+
{
390+
menuinfo.fType |= MFT_MENUBARBREAK;
391+
}
392+
next_menu_is_column = false;
393+
378394
//handle submenus
379395
if (menu->IsParentMenu())
380396
{
381397
menuinfo.fMask |= MIIM_SUBMENU;
382398
HMENU hSubMenu = CreatePopupMenu();
383399

400+
bool next_sub_menu_is_column = false;
401+
384402
shellanything::Menu::MenuPtrList subs = menu->GetSubMenus();
385403
UINT sub_insert_pos = 0;
386404
for(size_t i=0; i<subs.size(); i++)
387405
{
388406
shellanything::Menu * submenu = subs[i];
389-
BuildMenuTree(hSubMenu, submenu, sub_insert_pos);
407+
BuildMenuTree(hSubMenu, submenu, sub_insert_pos, next_sub_menu_is_column);
390408
}
391409

392410
menuinfo.hSubMenu = hSubMenu;
@@ -425,6 +443,8 @@ void CContextMenu::BuildMenuTree(HMENU hMenu)
425443
m_BitmapCache.ResetCounters();
426444
}
427445

446+
bool next_menu_is_column = false;
447+
428448
//browse through all shellanything menus and build the win32 popup menus
429449

430450
//for each configuration
@@ -443,7 +463,7 @@ void CContextMenu::BuildMenuTree(HMENU hMenu)
443463
shellanything::Menu * menu = menus[j];
444464

445465
//Add this menu to the tree
446-
BuildMenuTree(hMenu, menu, insert_pos);
466+
BuildMenuTree(hMenu, menu, insert_pos, next_menu_is_column);
447467
}
448468
}
449469
}

src/shellext.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,7 @@ class CContextMenu : public IContextMenu, IShellExtInit
119119

120120
private:
121121
void BuildMenuTree(HMENU hMenu);
122-
void BuildMenuTree(HMENU hMenu, shellanything::Menu * menu, UINT & insert_pos);
122+
void BuildMenuTree(HMENU hMenu, shellanything::Menu * menu, UINT & insert_pos, bool & next_menu_is_column);
123123
};
124124

125125
#endif //SA_SHELLEXTENSION_H

test/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ set(CONFIGURATION_TEST_FILES ""
1818
${CMAKE_CURRENT_SOURCE_DIR}/test_files/TestObjectFactory.testParseActionMessage.xml
1919
${CMAKE_CURRENT_SOURCE_DIR}/test_files/TestObjectFactory.testParseActionPrompt.xml
2020
${CMAKE_CURRENT_SOURCE_DIR}/test_files/TestObjectFactory.testParseActionProperty.xml
21+
${CMAKE_CURRENT_SOURCE_DIR}/test_files/TestObjectFactory.testParseSeparator.xml
2122
${CMAKE_CURRENT_SOURCE_DIR}/test_files/TestObjectFactory.testParseValidator.xml
2223
${CMAKE_CURRENT_SOURCE_DIR}/test_files/TestObjectFactory.testParseDefaults.xml
2324
${CMAKE_CURRENT_SOURCE_DIR}/test_files/TestObjectFactory.testParseIcon.xml

test/TestConfiguration.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,7 @@ namespace shellanything { namespace test
119119
"test_files\\TestObjectFactory.testParseDefaults.xml",
120120
"test_files\\TestObjectFactory.testParseIcon.xml",
121121
"test_files\\TestObjectFactory.testParseMenuMaxLength.xml",
122+
"test_files\\TestObjectFactory.testParseSeparator.xml",
122123
"test_files\\TestObjectFactory.testParseValidator.xml",
123124
"test_files\\tests.xml",
124125
};

0 commit comments

Comments
 (0)