On Tue, 2013-10-01 at 12:15 +0200, Murray Cumming wrote:
> Here is a description of the gtkmm menu API that should replace
> GtkUIManager. I'll reply with some opinions about the API and reasons
> why I don't think we should actually deprecate UIManager yet.
> 
> For a fairly complete example, just look here:
> https://git.gnome.org/browse/gtkmm-documentation/tree/examples/book/menus/main_menu/examplewindow.cc
> 
> * Actions:
> 
> We can replace Gtk::Action/Gtk::ToggleAction/Gtk::RadioAction instances
> with Gio::Action. You'll actually want to use Gio::SimpleAction in most
> cases, because it has useful API.
> See
> https://developer.gnome.org/glibmm/unstable/classGio_1_1SimpleAction.html
> 
> We replace Gtk::ActionGroup with Gio::ActionGroup, though you'll want to
> actually use Gio::SimpleActionGroup because you can add actions to it.
> See
> https://developer.gnome.org/glibmm/unstable/classGio_1_1SimpleActionGroup.html

I find it annoying that the classes we actually use in applications have
this "Simple" in their name, cluttering up our application code. It
feels like GAction should be GActionBase and GSimpleAction should be
GAction. GSimpleAction feel like "GGoodEnoughToActuallyUseAction".

> We replace calls to
>   Gtk::ActionGroup::add("action-name", "Action Title", signal_handler)
> with
>   Gio::SimpleActionGroup::add_action("action-name", signal_handler)

See
https://developer.gnome.org/glibmm/2.37/classGio_1_1ActionMap.html#a784dfa4573e994ac452d5e2dd56a5909

> The Action Title now becomes just a menu item title and is specified in
> the XML.

Notice that this means you'll need to put that XML in an external file
so that it can be translated by intltools (now yelp-tools). That's not
so bad though. You probably already have external .glade (or .ui) files
that you can add the <menu> to.

However, watch out. Glade doesn't yet support the <menu> syntax. If you
open and save your .glade file in Glade then it will silently remove
your <menu> nodes.
This Glade bug might track that:
https://bugzilla.gnome.org/show_bug.cgi?id=692669


> We replace GtkUIManager with GtkBuilder, using its <menu> syntax instead
> of the old <ui> syntax.
> 
> 
> * Toggle and Radio items:
> 
> Toggle items and Radio items are a bit strange. Both are demonstrated
> here, and are not as simple as the old GtkToggleAction and
> GtkRadioAction:
> https://git.gnome.org/browse/gtkmm-documentation/tree/examples/book/menus/main_menu/examplewindow.cc
> 
> 
> ** Toggle items:
> For a toggle item we add a "bool" action, which is just a regular
> GAction with a boolean "state". For instance, with gtkmm:
>   m_refToggle = refActionGroup->add_action_bool("sometoggle",
>     sigc::mem_fun(*this, &ExampleWindow::on_menu_toggle),
>     false); //false is the default value

Notice that this is nicer in gtkmm than in GTK+. In this bug (now a
duplicate) I described the nasty C API for it:
https://bugzilla.gnome.org/show_bug.cgi?id=705655

We added similar convenience API in TreeView. For instance,
append_column_numeric():
https://developer.gnome.org/gtkmm/stable/classGtk_1_1TreeView.html#a8affe8dc5cf35c8c4df0c8ec666661d8

We also hide the "parameter" parameter from the signal handler in the
common case, because it's an unusual and confusing thing that you
usually won't need. There's add_action_with_parameter() if you need it:
https://developer.gnome.org/glibmm/2.37/classGio_1_1ActionMap.html#a3548d329e7abda0d6325c1f75a799da6

But I still find our API a bit strange. We could add our own
Gio::SimpleToggleAction and Gio::SimpleRadioAction classes to make the
API nicer, but I'd rather delay that because I suspect that they might
appear in the C API itself sometime:
https://bugzilla.gnome.org/show_bug.cgi?id=667973
 
> And we would lay that out in the glade file like any other menu item.
> 
> Unlike with GtkAction, in the signal handler, we must now explicitly
> toggle that state. Otherwise clicking the menu item won't change it's
> appearance at all. For instance:
>   void ExampleWindow::on_menu_toggle()
>   {
>     bool active = false;
>     m_refToggle->get_state(active);
>     m_refToggle->change_state(!active);
> 
> Obviously, it's good that this gives you the chance to reject the change
> and complain to the user, though I feel that that's the unusual case and
> shouldn't be the default.

Maybe we could add some code in gtkmm to change the state automatically,
making auto_state_change an extra boolean parameter to add_action_bool()
and Action::create_bool(). We do much the same thing in the TreeView
API, by providing append_column_editable().
https://developer.gnome.org/gtkmm/stable/classGtk_1_1TreeView.html#a2b7e3001fa1bb1aa415da76be91dc65f

> ** Radio items:
> 
> Radio items are even stranger. Unlike GtkRadioAction, we now have just
> one GAction to represent, for instance, 3 radio menu items. That GAction
> has a state, whose type you must choose. gtkmm has convenience methods
> to create string-based or integer-based radio actions. For instance:
>   m_refChoice = refActionGroup->add_action_radio_string("choice",
>     sigc::mem_fun(*this, &ExampleWindow::on_menu_choices),
>     "a"); //"a" is the default value.
> 
> Unlike with toggle items, we get the chosen state via the action's
> "parameter". Like toggle items, we need to actually set the state to see
> any visual effect. For instance:
>    void ExampleWindow::on_menu_choices(const Glib::ustring& parameter)
>    {
>      m_refChoice->change_state(parameter);
> 
> Again, I find this a bit tedious.
> 
> We specify the possible states in the XML, as "target" values for an
> <item>. Several radio items can have the same action name, but different
> target values.

I think this confusion/conflation of "state", "parameter" and "target"
is a big mistake, made worse by the different use of state and parameter
depending on whether it's a toggle or radio item, or just a regular
action with a parameter. I complained about that here, but it seems far
too late to fix it now:
https://bugzilla.gnome.org/show_bug.cgi?id=704392#c11
See also
https://bugzilla.gnome.org/show_bug.cgi?id=705133#c4

I also don't like duplicating these magic state values across both the
code and the XML file. If we could use enums then it would at least be
more structured. See bug
  https://bugzilla.gnome.org/show_bug.cgi?id=705483

> * Summary
> 
> As a complete porting example, this commit replaces the use of UIManager
> +GtkMenu with Builder+GMenu in one of our examples:
> https://git.gnome.org/browse/gtkmm-documentation/commit/?id=9ce75deddf75822fe06406f1b86123661c64b02d
> And this one adds back the toolbar:
> https://git.gnome.org/browse/gtkmm-documentation/commit/?id=8ffa9a16fc773a472f6fa13d262cc20a9a31c318

There are some other issues that remain unresolved or unclear to me:

1. The accelerators in a main menu will not work unless you also use
Gtk::Application, Gtk::ApplicationWindow and
Gtk::Applicatin::add_accelerator(). It's been suggested that building a
GtkMenuBar from a GMenu, as we do in our examples, should not be done.
https://bugzilla.gnome.org/show_bug.cgi?id=708905
1.1 But the alternative, using Gtk::Application::set_menu_bar(), as
shown in one of our examples, does not seem to allow for separate menu
bars in separate windows, while also taking the menu-creating code away
from the window's implementation.

https://git.gnome.org/browse/gtkmm-documentation/tree/examples/book/application/app_and_win_menus/exampleapplication.cc#n52

1.2 Those "accel" attributes in the XML are not well documented anyway,
and will soon be deprecated:
https://bugzilla.gnome.org/show_bug.cgi?id=708908#c3


2. I don't understand when or why we should use the standard "app" and
"win" action groups instead of custom action groups such as our
"example" ones. I asked here:
  https://mail.gnome.org/archives/gtk-list/2013-September/msg00033.html


3. There is no replacement for GtkRecentAction:
  https://bugzilla.gnome.org/show_bug.cgi?id=707422
though there is some suggestion that there shouldn't be:

https://mail.gnome.org/archives/gtk-devel-list/2013-September/msg00022.html


4. There is no similar XML markup for toolbars, to replace the <toolbar>
markup with GtkUIManager. So our examples just create the Gtk::Toolbar
in code and call 
  gtk_actionable_set_detailed_action_name (GTK_ACTIONABLE
(button->gobj()), "example.quit");
For instance, in our example:
https://git.gnome.org/browse/gtkmm-documentation/tree/examples/book/menus/main_menu/examplewindow.cc#n201
We can't use just
  button->set_detailed_action_name("example.quit");
because we'd have to break ABI to add a new base class.


Overall, I think we should take the unusual step of undeprecating
Gtk::UIManager and friends in gtkmm before our stable release, even
though the underlying C API is deprecated. Many C developers also seem
to feel that the deprecation in GTK+ was rushed, but we had no response
to requests to delay it. Hopefully things will be clearer for gtkmm
3.12.

-- 
Murray Cumming
murr...@murrayc.com
www.murrayc.com
www.openismus.com

_______________________________________________
gtkmm-list mailing list
gtkmm-list@gnome.org
https://mail.gnome.org/mailman/listinfo/gtkmm-list

Reply via email to