EDIT: this was splitted from the original topic, labeled "Code::Blocks Menus and Shortcuts revamping" (http://forums.next.codeblocks.org/index.php?topic=1377.0)[/url].
These last couple of days, I 've been coding an initial implementation of an ActionsManager. I will now describe where I 'm at and listen to comments.
------------------
We have Actions. They can be constructed in one of two ways:
Action(int id, const Shortcut& shortcut);
// or
Action(const wxString& script, const Shortcut& shortcut);
All constructor arguments have default values, except the
script one.
This means that we can have two types of actions:
- Code actions. These are implemented as wx events, hence the required ID, so ActionsManager can call the correct event handler using the action's ID.
- Script actions. When launched, these actions load and run a script file.
The application can add Actions to ActionsManager in two ways:
- One at a time:
Action action(idActionFileOpen);
action.description = _("Opens a file");
action.shortcut = Shortcut(AK_O, false, true, false); // args are: key, alt, ctrl, shift
ActionsManager::Get()->Add(_T("File.Open"), action); // add the action named as "File.Open"
// etc
- Many actions at once. For this, a special struct is provided:
ActionRegistrar actions[] =
{
{ _T("File.Open"), Action(idActionOpen, Shortcut(AK_O, false, true, false)) },
{ _T("App.Quit"), Action(idActionQuit, Shortcut(AK_Q, false, true, false)) },
{ _T("App.About"), Action(idActionAbout, Shortcut(AK_F1, false, false, false)) },
{ _T("App.Test"), Action(idActionTest) },
{ _T("App.Test2"), Action(idActionTest2) },
EndOfActionRegistrar // this just helps ActionsManager to see the end of this array
};
// register all actions at once
ActionsManager::Get()->Add(&actions[0]);
Now that actions are registered, you can "launch" an action at any time using
ActionsManager::Get()->Launch(action_name).
Actions can be enabled/disabled using
ActionsManager::Get()->Enable(action_name, true|false). Automatically, all menu entries or toolbars bound to the specified action become enabled/disabled accordingly.
ActionsManager will offer all that is needed to create menubars, popup menus and toolbars. Only toolbars are not implemented yet.
ActionsManager* am = ActionsManager::Get();
// create main menubar layout
// add a "File" menu in "MainMenu"
int id = am->AddMenu(_T("MainMenu"), _("&File"));
// add "Open" entry (under "File") and bind to action "File.Open"
am->AddMenuEntry(id, _("&Open"), _T("File.Open"));
// just add a separator
am->AddMenuSeparator(id);
// add "Quit" entry and bind to action "App.Quit"
am->AddMenuEntry(id, _("&Quit"), _T("App.Quit"));
// ask ActionsManager for the "MainMenu" menubar
// it will be created on-the-fly
SetMenuBar(am->GetMenuBar(_T("MainMenu"));
// create a menu for the editor popup "EditorCtxMenu"
id = am->AddMenu(_T("EditorCtxMenu"), _("Editor menu"));
am->AddMenuEntry(id, _("&Enable quit"), _T("App.Test2"));
// when you want to launch the editor popup menu, use:
// wxMenu* menu = new wxMenu;
// ActionsManager::Get()->CreateContextMenu(&menu, _T("EditorCtxMenu"));
// PopupMenu(menu);
// delete menu;
Here's the current to-do:
// TODO (mandrav#1#): Serialize actions
// TODO (mandrav#1#): Create toolbar(s) from actions
// TODO (mandrav#1#): Create UI to edit menus/toolbars
// TODO (mandrav#1#): Add support for check/radio actions
Serialization should be trivial to do. The actions configuration file will be loaded after all modules have finished registering their actions and menu/toolbar layouts. This way, the actions configuration will override any in-program settings.
Actions not registered by the application will not be serialized. The exception to this are script-actions. The user will be able to add script actions freely.
So, comments?
Bump. I think this is important. And it took me
10 minutes to find the thead again.
Not ignoring this, just trying to get my
head around it.
pecan
Quote from: mandrav on December 17, 2005, 08:44:47 PM
So, comments?
Sounds nice to me, hence I have a question to clarify: Are the action declarations itself "hard-coded" or will they be loaded via a configuration file and then implemented at run-time? I think of personalities and whether a new personality would allow me to switch the actions to be registered then.
Morten.
Quote from: MortenMacFly on December 18, 2005, 05:58:38 PM
Sounds nice to me, hence I have a question to clarify: Are the action declarations itself "hard-coded" or will they be loaded via a configuration file and then implemented at run-time? I think of personalities and whether a new personality would allow me to switch the actions to be registered then.
As mentioned above:
Quote from: mandravThe actions configuration file will be loaded after all modules have finished registering their actions and menu/toolbar layouts. This way, the actions configuration will override any in-program settings.
Actions not registered by the application will not be serialized. The exception to this are script-actions. The user will be able to add script actions freely.
In other words, the user will be able to restructure all the menus (main menubar, context menus, etc) by adding/removing actions to them. The same goes for the toolbar.
Also, the user will be able to
add actions that call user-defined scripts. That is, add functionality not known to C::B at compile-time.
Quote from: mandrav on December 18, 2005, 07:05:02 PM
As mentioned above:
Sorry, I've got that wording wrong, so I missed that part. :oops:
Quote from: mandrav on December 18, 2005, 07:05:02 PM
In other words, [...]
...great! I couldn't think of anything that's missing. :P
Morten.
Quote from: mandrav on December 18, 2005, 07:05:02 PM
In other words, the user will be able to restructure all the menus (main menubar, context menus, etc) by adding/removing actions to them. The same goes for the toolbar.
Also, the user will be able to add actions that call user-defined scripts. That is, add functionality not known to C::B at compile-time.
Personally, I think that this is a very good idea. Actions would enable C::B to adpat itself to the different user's requirements and prefernces and therefore make its use easier and more pleasant.
Michael
I guess you know my comment: This is really amazing! :o
I don't know how it'll handle the logic separation of the bindings (toolbars, menus, etc) from the actions (idActionOpen, etc).
So, itsn't missing a BindingsManager counterpart? Or the handling of bindings would be done in another way?
Because I'm thinking that the actions would be the same, but doing a pluggable architecture, the user can add another bindings (a mouse gesture, vim-like command, voice recognition, etc) through plugins.
That would be even more flexible and powerful. :D
But I must say I'm surprised, Yiannis you're so fast! I though this would made in 2.0 or so being optimistic, but I was wrong :D
Quote from: mandrav on December 17, 2005, 08:44:47 PM
Actions not registered by the application will not be serialized. The exception to this are script-actions. The user will be able to add script actions freely.
Does this mean a user/plugin could record the scintilla macros
(using the macro recorder) and add/delete them as individual actions
at the users whim?
Does this mean a set of macros could be loaded from an external
source (eg, {Ctrl+Enter}={END+ENTER+TAB+TAB}) and register each as an action?
Edit:
Will there be plugin fights over menu/taskbar items? Is arbitration needed?
Nothin' like a good plugin fight! :)
thanks
pecan
Just adding a reply to the feature request post to allow people to backtrack what's being discussed to get relavent information to form an informed opinion.
http://forums.next.codeblocks.org/index.php?topic=1377.0
jmccay
Quote from: Pecan on December 19, 2005, 12:50:58 AM
Quote from: mandrav on December 17, 2005, 08:44:47 PM
Actions not registered by the application will not be serialized. The exception to this are script-actions. The user will be able to add script actions freely.
Does this mean a user/plugin could record the scintilla macros
(using the macro recorder) and add/delete them as individual actions
at the users whim?
Does this mean a set of macros could be loaded from an external
source (eg, {Ctrl+Enter}={END+ENTER+TAB+TAB}) and register each as an action?
Yes, plugins will be able to register/unregister actions. Actually it will be the only way to add menu/toolbar items.
Quote from: Pecan on December 19, 2005, 12:50:58 AM
Edit:
Will there be plugin fights over menu/taskbar items? Is arbitration needed?
Nothin' like a good plugin fight! :)
This is handled by the ActionsManager.
If ActionsManager handles the add menu/toolbar items, how one could add another binding such as mouse gestures?
Will it be a way to add new bindings to actions provided by plugins?
Do you have code which recognizes mouse gestures?
Quote from: Takeshi Miya on December 19, 2005, 09:06:21 PM
If ActionsManager handles the add menu/toolbar items, how one could add another binding such as mouse gestures?
Will it be a way to add new bindings to actions provided by plugins?
Well, given the availability of this:
Quote from: mandrav on December 17, 2005, 08:44:47 PM
Now that actions are registered, you can "launch" an action at any time using ActionsManager::Get()->Launch(action_name).
I'd say adding a mouse gestures plugin wouldn't be much harder than:
- Providing a config dialog to allow the user to bind gestures to actions. This assumes of course that plugins are able to obtain a list of the names of currently registered actions from the action manager. Mandrav's post didn't provide examples of this, but if he hasn't implemented it yet it should be fairly trivial to do so, I think
- Detecting when mouse gestures are performed (probably the hardest part).
- Launching the appropriate actions using the action manager, as in above quote.
That's why I asked... the rest is really trivial.
Quote from: thomas on December 19, 2005, 10:01:34 PM
That's why I asked... the rest is really trivial.
You posted while I was still composing my post, but I didn't want to throw away the entire post just because you beat me ;).
Quote from: Urxae on December 19, 2005, 09:54:40 PM
This assumes of course that plugins are able to obtain a list of the names of currently registered actions from the action manager. Mandrav's post didn't provide examples of this...
Oh well, I was only worried if the SDK wasn't going to provide that. :)
struct Action
{
wxString title;
...
...
};
WX_DECLARE_STRING_HASH_MAP(Action, ActionsMap);
const ActionsMap& ActionsManager::GetActions();
Is this ok? ;)
It seems. :D
So are you writing the mouse gestures plugin?
No, I was only worried about future bindings like mouse gesture and VIM-like command entries. But there are far more important things like Unicode support now.