[gnote] Use popover for text menu



commit 35725c7b2bc98b490edebb8cffaad8ffd04587cd
Author: Aurimas Černius <aurisc4 gmail com>
Date:   Sat Mar 12 21:16:18 2016 +0200

    Use popover for text menu

 src/actionmanager.cpp |   11 ++
 src/notewindow.cpp    |  476 +++++++++++++++++++++++++++----------------------
 src/notewindow.hpp    |   64 +++----
 3 files changed, 306 insertions(+), 245 deletions(-)
---
diff --git a/src/actionmanager.cpp b/src/actionmanager.cpp
index 11a89f1..06d5167 100644
--- a/src/actionmanager.cpp
+++ b/src/actionmanager.cpp
@@ -77,6 +77,17 @@ namespace gnote {
     register_main_window_action("enable-spell-check", &Glib::Variant<bool>::variant_type());
     register_main_window_action("new-notebook", NULL, false);
     register_main_window_action("move-to-notebook", &Glib::Variant<Glib::ustring>::variant_type(), false);
+    register_main_window_action("undo", NULL, true);
+    register_main_window_action("redo", NULL, true);
+    register_main_window_action("link", NULL, true);
+    register_main_window_action("change-font-bold", &Glib::Variant<bool>::variant_type(), true);
+    register_main_window_action("change-font-italic", &Glib::Variant<bool>::variant_type(), true);
+    register_main_window_action("change-font-strikeout", &Glib::Variant<bool>::variant_type(), true);
+    register_main_window_action("change-font-highlight", &Glib::Variant<bool>::variant_type(), true);
+    register_main_window_action("change-font-size", &Glib::Variant<Glib::ustring>::variant_type(), true);
+    register_main_window_action("enable-bullets", &Glib::Variant<bool>::variant_type(), true);
+    register_main_window_action("increase-indent", NULL, true);
+    register_main_window_action("decrease-indent", NULL, true);
   }
 
 
diff --git a/src/notewindow.cpp b/src/notewindow.cpp
index 9cdff9f..8dbbb26 100644
--- a/src/notewindow.cpp
+++ b/src/notewindow.cpp
@@ -23,6 +23,7 @@
 #endif
 
 #include <boost/bind.hpp>
+#include <boost/format.hpp>
 
 #include <glibmm/i18n.h>
 #include <gtkmm/grid.h>
@@ -109,7 +110,7 @@ namespace gnote {
     set_hexpand(true);
     set_vexpand(true);
 
-    m_text_menu = Gtk::manage(new NoteTextMenu(note.get_buffer(), note.get_buffer()->undoer()));
+    m_text_menu = Gtk::manage(new NoteTextMenu(*this, note.get_buffer(), note.get_buffer()->undoer()));
 
     m_embeddable_toolbar = manage(make_toolbar());
 
@@ -266,7 +267,7 @@ namespace gnote {
         m_global_keys->enabled(m_enabled);
       }
 
-      m_text_menu->set_accels(*m_global_keys, m_accel_group);
+      m_text_menu->set_accels(*m_global_keys);
     }
     else {
       window.add_accel_group(m_accel_group);
@@ -411,7 +412,7 @@ namespace gnote {
     text_button->show_all();
     grid->attach(*text_button, grid_col++, 0, 1, 1);
     text_button->set_tooltip_text(_("Set properties of text"));
-    m_text_menu->property_attach_widget() = text_button;
+    m_text_menu->set_relative_to(*text_button);
 
     grid->property_margin_left() = 12;
     grid->show_all();
@@ -595,7 +596,6 @@ namespace gnote {
   void NoteWindow::on_text_button_clicked()
   {
     m_text_menu->show_all();
-    utils::popup_menu(*m_text_menu, NULL);
   }
 
   void NoteWindow::enabled(bool enable)
@@ -810,240 +810,241 @@ namespace gnote {
   // Menu for font style and size, and set the active radio
   // menuitem depending on the cursor poition.
   //
-  NoteTextMenu::NoteTextMenu(const Glib::RefPtr<NoteBuffer> & buffer, UndoManager & undo_manager)
-    : Gtk::Menu()
+  NoteTextMenu::NoteTextMenu(EmbeddableWidget & widget, const Glib::RefPtr<NoteBuffer> & buffer, UndoManager 
& undo_manager)
+    : Gtk::PopoverMenu()
+    , m_widget(widget)
     , m_buffer(buffer)
     , m_undo_manager(undo_manager)
-    , m_link(_("_Link"), true)
-    , m_bold(_("<b>_Bold</b>"), true)
-    , m_italic(_("<i>_Italic</i>"), true)
-    , m_strikeout(_("<s>_Strikeout</s>"), true)
-    , m_highlight(Glib::ustring("<span background=\"yellow\">")
-                  + _("_Highlight") + "</span>", true)
-    , m_fontsize_group()
-    , m_normal(m_fontsize_group, _("_Normal"), true)
-    , m_huge(m_fontsize_group, Glib::ustring("<span size=\"x-large\">")
-             + _("Hu_ge") + "</span>", true)
-    , m_large(m_fontsize_group, Glib::ustring("<span size=\"large\">")
-            + _("_Large") + "</span>", true)
-       ,  m_small(m_fontsize_group, Glib::ustring("<span size=\"small\">")
-                  + _("S_mall") + "</span>", true)
-    , m_hidden_no_size(m_fontsize_group, "", true)
-    , m_bullets(_("Bullets"))
-    , m_increase_indent(Gtk::Stock::INDENT)
-    , m_decrease_indent(Gtk::Stock::UNINDENT)
     {
-      m_undo = manage(new Gtk::ImageMenuItem (Gtk::Stock::UNDO));
-      m_undo->signal_activate().connect(sigc::mem_fun(*this, &NoteTextMenu::undo_clicked));
-      m_undo->show();
-      append(*m_undo);
+      m_widget.signal_foregrounded.connect(sigc::mem_fun(*this, &NoteTextMenu::on_widget_foregrounded));
+      m_widget.signal_backgrounded.connect(sigc::mem_fun(*this, &NoteTextMenu::on_widget_backgrounded));
 
-      m_redo = manage(new Gtk::ImageMenuItem (Gtk::Stock::REDO));
-      m_redo->signal_activate().connect(sigc::mem_fun(*this, &NoteTextMenu::redo_clicked));
-      m_redo->show();
-      append(*m_redo);
+      set_position(Gtk::POS_BOTTOM);
+      Gtk::Grid *main_grid = manage(new Gtk::Grid);
+      int main_top = 0;
 
-      Gtk::SeparatorMenuItem *undo_spacer = manage(new Gtk::SeparatorMenuItem());
-      append(*undo_spacer);
+      Gtk::Grid *grid = manage(new Gtk::Grid);
+      utils::set_common_popover_widget_props(*grid);
+      int top = 0;
+
+      Gtk::Widget *undo = manage(utils::create_popover_button("win.undo", _("_Undo")));
+      grid->attach(*undo, 0, top++, 1, 1);
+
+      Gtk::Widget *redo = manage(utils::create_popover_button("win.redo", _("_Redo")));
+      grid->attach(*redo, 0, top++, 1, 1);
+      main_grid->attach(*grid, 0, main_top++, 1, 1);
 
       // Listen to events so we can sensitize and
       // enable keybinding
       undo_manager.signal_undo_changed().connect(sigc::mem_fun(*this, &NoteTextMenu::undo_changed));
 
       Glib::Quark tag_quark("Tag");
-      markup_label(m_link);
-      m_link.signal_activate()
-        .connect(sigc::mem_fun(*this, &NoteTextMenu::link_clicked));
-
-      markup_label(m_bold);
-      m_bold.set_data(tag_quark, const_cast<char*>("bold"));
-      m_bold.signal_activate()
-        .connect(sigc::bind(sigc::mem_fun(*this, &NoteTextMenu::font_style_clicked), &m_bold));
-
-      markup_label (m_italic);
-      m_italic.set_data(tag_quark, const_cast<char*>("italic"));
-      m_italic.signal_activate()
-        .connect(sigc::bind(sigc::mem_fun(*this, &NoteTextMenu::font_style_clicked), &m_italic));
-
-      markup_label (m_strikeout);
-      m_strikeout.set_data(tag_quark, const_cast<char*>("strikethrough"));
-      m_strikeout.signal_activate()
-        .connect(sigc::bind(sigc::mem_fun(*this, &NoteTextMenu::font_style_clicked), &m_strikeout));
-
-      markup_label (m_highlight);
-      m_highlight.set_data(tag_quark, const_cast<char*>("highlight"));
-      m_highlight.signal_activate()
-        .connect(sigc::bind(sigc::mem_fun(*this, &NoteTextMenu::font_style_clicked), &m_highlight));
-
-      markup_label(m_normal);
-      m_normal.set_active(true);
-      m_normal.signal_activate()
-        .connect(sigc::bind(sigc::mem_fun(*this, &NoteTextMenu::font_size_activated), &m_normal));
-
-      markup_label(m_huge);
-      m_huge.set_data(tag_quark, const_cast<char*>("size:huge"));
-      m_huge.signal_activate()
-        .connect(sigc::bind(sigc::mem_fun(*this, &NoteTextMenu::font_size_activated), &m_huge));
-
-      markup_label(m_large);
-      m_large.set_data(tag_quark, const_cast<char*>("size:large"));
-      m_large.signal_activate()
-        .connect(sigc::bind(sigc::mem_fun(*this, &NoteTextMenu::font_size_activated), &m_large));
-
-      markup_label(m_small);
-      m_small.set_data(tag_quark, const_cast<char*>("size:small"));
-      m_small.signal_activate()
-        .connect(sigc::bind(sigc::mem_fun(*this, &NoteTextMenu::font_size_activated), &m_small));
-
-      m_hidden_no_size.hide();
-
-      m_bullets_clicked_cid = m_bullets.signal_activate()
-        .connect(sigc::mem_fun(*this, &NoteTextMenu::toggle_bullets_clicked));
-
-      m_increase_indent.signal_activate()
-        .connect(sigc::mem_fun(*this, &NoteTextMenu::increase_indent_clicked));
-      m_increase_indent.show();
-
-      m_decrease_indent.signal_activate()
-        .connect(sigc::mem_fun(*this, &NoteTextMenu::decrease_indent_clicked));
-      m_decrease_indent.show();
+      Gtk::Widget *link = manage(utils::create_popover_button("win.link", _("_Link")));
+
+      Gtk::Widget *bold = create_font_item("win.change-font-bold", _("_Bold"), "b");
+      Gtk::Widget *italic = create_font_item("win.change-font-italic", _("_Italic"), "i");
+      Gtk::Widget *strikeout = create_font_item("win.change-font-strikeout", _("_Strikeout"), "s");
+
+      Gtk::Widget *highlight = manage(utils::create_popover_button("win.change-font-highlight", ""));
+      auto label = static_cast<Gtk::Label*>(static_cast<Gtk::Bin*>(highlight)->get_child());
+      Glib::ustring markup = str(boost::format("<span background=\"yellow\">%1%</span>") % _("_Highlight"));
+      label->set_markup_with_mnemonic(markup);
+
+      Gtk::Widget *normal = create_font_size_item(_("_Normal"), NULL, "");
+      Gtk::Widget *small = create_font_size_item(_("S_mall"), "small", "size:small");
+      Gtk::Widget *large = create_font_size_item(_("_Large"), "large", "size:large");
+      Gtk::Widget *huge = create_font_size_item(_("Hu_ge"), "x-large", "size:huge");
+
+      grid = manage(new Gtk::Grid);
+      top = 0;
+      grid->attach(*link, 0, top++, 1, 1);
+      main_grid->attach(*grid, 0, main_top++, 1, 1);
+
+      grid = manage(new Gtk::Grid);
+      top = 0;
+      grid->attach(*bold, 0, top++, 1, 1);
+      grid->attach(*italic, 0, top++, 1, 1);
+      grid->attach(*strikeout, 0, top++, 1, 1);
+      grid->attach(*highlight, 0, top++, 1, 1);
+      main_grid->attach(*grid, 0, main_top++, 1, 1);
+
+      grid = manage(new Gtk::Grid);
+      top = 0;
+      grid->attach(*small, 0, top++, 1, 1);
+      grid->attach(*normal, 0, top++, 1, 1);
+      grid->attach(*large, 0, top++, 1, 1);
+      grid->attach(*huge, 0, top++, 1, 1);
+      main_grid->attach(*grid, 0, main_top++, 1, 1);
+
+      grid = manage(new Gtk::Grid);
+      Gtk::Widget *bullets = manage(utils::create_popover_button("win.enable-bullets", _("⦁ Bullets")));
+      grid->attach(*bullets, 0, top++, 1, 1);
+      Gtk::Widget *increase_indent = manage(utils::create_popover_button("win.increase-indent", _("→ 
Increase indent")));
+      grid->attach(*increase_indent, 0, top++, 1, 1);
+      Gtk::Widget *decrease_indent = manage(utils::create_popover_button("win.decrease-indent", _("← 
Decrease indent")));
+      grid->attach(*decrease_indent, 0, top++, 1, 1);
+      main_grid->attach(*grid, 0, main_top++, 1, 1);
+
+      add(*main_grid);
 
       refresh_state();
+    }
+
+  Gtk::Widget *NoteTextMenu::create_font_item(const char *action, const char *label, const char *markup)
+  {
+    Gtk::Widget *widget = manage(utils::create_popover_button(action, ""));
+    auto lbl = static_cast<Gtk::Label*>(static_cast<Gtk::Bin*>(widget)->get_child());
+    Glib::ustring m = str(boost::format("<%1%>%2%</%1%>") % markup % label);
+    lbl->set_markup_with_mnemonic(m);
+    return widget;
+  }
 
-      append(m_link);
-      append(*manage(new Gtk::SeparatorMenuItem()));
-      append(m_bold);
-      append(m_italic);
-      append(m_strikeout);
-      append(m_highlight);
-      append(*manage(new Gtk::SeparatorMenuItem()));
-      append(m_small);
-      append(m_normal);
-      append(m_large);
-      append(m_huge);
-      append(*manage(new Gtk::SeparatorMenuItem()));
-      append(m_bullets);
-      append(m_increase_indent);
-      append(m_decrease_indent);
-      show_all ();
+  Gtk::Widget *NoteTextMenu::create_font_size_item(const char *label, const char *markup, const char *size)
+  {
+    Gtk::Widget *item = manage(utils::create_popover_button("win.change-font-size", ""));
+    auto lbl = static_cast<Gtk::Label*>(static_cast<Gtk::Bin*>(item)->get_child());
+    Glib::ustring mrkp;
+    if(markup != NULL) {
+      mrkp = str(boost::format("<span size=\"%1%\">%2%</span>") % markup % label);
+    }
+    else {
+      mrkp = label;
     }
+    lbl->set_markup_with_mnemonic(mrkp);
+    gtk_actionable_set_action_target_value(GTK_ACTIONABLE(item->gobj()), g_variant_new_string(size));
+    return item;
+  }
 
-  void NoteTextMenu::set_accels(utils::GlobalKeybinder & keybinder,
-                                const Glib::RefPtr<Gtk::AccelGroup> & accel_group)
-  {
-    set_accel_group(accel_group);
-    m_undo->add_accelerator("activate", accel_group,
-                            GDK_KEY_Z,
-                            Gdk::CONTROL_MASK,
-                            Gtk::ACCEL_VISIBLE);
-    m_redo->add_accelerator("activate", accel_group,
-                            GDK_KEY_Z,
-                            Gdk::CONTROL_MASK | Gdk::SHIFT_MASK,
-                            Gtk::ACCEL_VISIBLE);
-    m_link.add_accelerator("activate", accel_group,
-                           GDK_KEY_L, Gdk::CONTROL_MASK,
-                           Gtk::ACCEL_VISIBLE);
-    m_bold.add_accelerator("activate", accel_group,
-                           GDK_KEY_B,
-                           Gdk::CONTROL_MASK,
-                           Gtk::ACCEL_VISIBLE);
-    m_italic.add_accelerator("activate", accel_group,
-                             GDK_KEY_I,
-                             Gdk::CONTROL_MASK,
-                             Gtk::ACCEL_VISIBLE);
-    m_strikeout.add_accelerator("activate", accel_group,
-                                GDK_KEY_S,
-                                Gdk::CONTROL_MASK,
-                                Gtk::ACCEL_VISIBLE);
-    m_highlight.add_accelerator("activate", accel_group,
-                                GDK_KEY_H,
-                                Gdk::CONTROL_MASK,
-                                Gtk::ACCEL_VISIBLE);
+  void NoteTextMenu::set_accels(utils::GlobalKeybinder & keybinder)
+  {
+    keybinder.add_accelerator(sigc::mem_fun(*this, &NoteTextMenu::undo_clicked),
+                              GDK_KEY_Z, Gdk::CONTROL_MASK, Gtk::ACCEL_VISIBLE);
+    keybinder.add_accelerator(sigc::mem_fun(*this, &NoteTextMenu::redo_clicked),
+                              GDK_KEY_Z, Gdk::CONTROL_MASK | Gdk::SHIFT_MASK, Gtk::ACCEL_VISIBLE);
+    keybinder.add_accelerator(sigc::mem_fun(*this, &NoteTextMenu::link_clicked),
+                              GDK_KEY_L, Gdk::CONTROL_MASK, Gtk::ACCEL_VISIBLE);
+    keybinder.add_accelerator(sigc::mem_fun(*this, &NoteTextMenu::bold_pressed),
+                              GDK_KEY_B, Gdk::CONTROL_MASK, Gtk::ACCEL_VISIBLE);
+    keybinder.add_accelerator(sigc::mem_fun(*this, &NoteTextMenu::italic_pressed),
+                              GDK_KEY_I, Gdk::CONTROL_MASK, Gtk::ACCEL_VISIBLE);
+    keybinder.add_accelerator(sigc::mem_fun(*this, &NoteTextMenu::strikeout_pressed),
+                              GDK_KEY_S, Gdk::CONTROL_MASK, Gtk::ACCEL_VISIBLE);
+    keybinder.add_accelerator(sigc::mem_fun(*this, &NoteTextMenu::highlight_pressed),
+                              GDK_KEY_H, Gdk::CONTROL_MASK, Gtk::ACCEL_VISIBLE);
     keybinder.add_accelerator(sigc::mem_fun(*this, &NoteTextMenu::increase_font_clicked),
                               GDK_KEY_plus, Gdk::CONTROL_MASK, Gtk::ACCEL_VISIBLE);
     keybinder.add_accelerator(sigc::mem_fun(*this, &NoteTextMenu::decrease_font_clicked),
                               GDK_KEY_minus, Gdk::CONTROL_MASK, Gtk::ACCEL_VISIBLE);
-    m_increase_indent.add_accelerator("activate", accel_group,
-                                      GDK_KEY_Right,
-                                      Gdk::MOD1_MASK,
-                                      Gtk::ACCEL_VISIBLE);
-    m_decrease_indent.add_accelerator("activate", accel_group,
-                                      GDK_KEY_Left,
-                                      Gdk::MOD1_MASK,
-                                      Gtk::ACCEL_VISIBLE);
+    keybinder.add_accelerator(sigc::mem_fun(*this, &NoteTextMenu::increase_indent_pressed),
+                              GDK_KEY_Right, Gdk::MOD1_MASK, Gtk::ACCEL_VISIBLE);
+    keybinder.add_accelerator(sigc::mem_fun(*this, &NoteTextMenu::decrease_indent_pressed),
+                              GDK_KEY_Left, Gdk::MOD1_MASK, Gtk::ACCEL_VISIBLE);
   }
 
   void NoteTextMenu::on_show()
   {
     refresh_state();
-    Gtk::Menu::on_show();
-  }
-
-  void NoteTextMenu::markup_label (Gtk::MenuItem & item)
-  {
-    Gtk::Label *label = dynamic_cast<Gtk::Label*>(item.get_child());
-    if(label) {
-      label->set_use_markup(true);
-      label->set_use_underline(true);
-    }
+    Gtk::PopoverMenu::on_show();
   }
 
-
   void NoteTextMenu::refresh_sizing_state()
   {
+    EmbeddableWidgetHost *host = m_widget.host();
+    if(host == NULL) {
+      return;
+    }
+    auto action = host->find_action("change-font-size");
     Gtk::TextIter cursor = m_buffer->get_iter_at_mark(m_buffer->get_insert());
     Gtk::TextIter selection = m_buffer->get_iter_at_mark(m_buffer->get_selection_bound());
 
     // When on title line, activate the hidden menu item
     if ((cursor.get_line() == 0) || (selection.get_line() == 0)) {
-      m_hidden_no_size.set_active(true);
+      action->set_enabled(false);
       return;
     }
 
-    bool has_size = false;
-    bool active;
-    active = m_buffer->is_active_tag ("size:huge");
-    has_size |= active;
-    m_huge.set_active(active);
-    active = m_buffer->is_active_tag ("size:large");
-    has_size |= active;
-    m_large.set_active(active);
-    active = m_buffer->is_active_tag ("size:small");
-    has_size |= active;
-    m_small.set_active(active);
-
-    m_normal.set_active(!has_size);
-
+    action->set_enabled(true);
+    if(m_buffer->is_active_tag ("size:huge")) {
+      action->set_state(Glib::Variant<Glib::ustring>::create("size:huge"));
+    }
+    else if(m_buffer->is_active_tag ("size:large")) {
+      action->set_state(Glib::Variant<Glib::ustring>::create("size:large"));
+    }
+    else if(m_buffer->is_active_tag ("size:small")) {
+      action->set_state(Glib::Variant<Glib::ustring>::create("size:small"));
+    }
+    else {
+      action->set_state(Glib::Variant<Glib::ustring>::create(""));
+    }
   }
 
   void NoteTextMenu::refresh_state ()
   {
+    EmbeddableWidgetHost *host = m_widget.host();
+    if(host == NULL) {
+      return;
+    }
+
     m_event_freeze = true;
 
     Gtk::TextIter start, end;
-    m_link.set_sensitive(m_buffer->get_selection_bounds(start, end));
-    m_bold.set_active(m_buffer->is_active_tag("bold"));
-    m_italic.set_active(m_buffer->is_active_tag("italic"));
-    m_strikeout.set_active(m_buffer->is_active_tag("strikethrough"));
-    m_highlight.set_active(m_buffer->is_active_tag("highlight"));
+    host->find_action("link")->property_enabled() = m_buffer->get_selection_bounds(start, end);
+    
host->find_action("change-font-bold")->set_state(Glib::Variant<bool>::create(m_buffer->is_active_tag("bold")));
+    
host->find_action("change-font-italic")->set_state(Glib::Variant<bool>::create(m_buffer->is_active_tag("italic")));
+    
host->find_action("change-font-strikeout")->set_state(Glib::Variant<bool>::create(m_buffer->is_active_tag("strikethrough")));
+    
host->find_action("change-font-highlight")->set_state(Glib::Variant<bool>::create(m_buffer->is_active_tag("highlight")));
 
     bool inside_bullets = m_buffer->is_bulleted_list_active();
     bool can_make_bulleted_list = m_buffer->can_make_bulleted_list();
-    m_bullets_clicked_cid.block();
-    m_bullets.set_active(inside_bullets);
-    m_bullets_clicked_cid.unblock();
-    m_bullets.set_sensitive(can_make_bulleted_list);
-    m_increase_indent.set_sensitive(inside_bullets);
-    m_decrease_indent.set_sensitive(inside_bullets);
+    auto enable_bullets = host->find_action("enable-bullets");
+    enable_bullets->set_state(Glib::Variant<bool>::create(inside_bullets));
+    enable_bullets->property_enabled() = can_make_bulleted_list;
+    host->find_action("increase-indent")->property_enabled() = inside_bullets;
+    host->find_action("decrease-indent")->property_enabled() = inside_bullets;
 
     refresh_sizing_state ();
 
-    m_undo->set_sensitive(m_undo_manager.get_can_undo());
-    m_redo->set_sensitive(m_undo_manager.get_can_redo());
+    undo_changed();
 
     m_event_freeze = false;
   }
 
+  void NoteTextMenu::on_widget_foregrounded()
+  {
+    auto host = m_widget.host();
+
+    m_signal_cids.push_back(host->find_action("undo")->signal_activate()
+      .connect([this](const Glib::VariantBase&) { undo_clicked(); } ));
+    m_signal_cids.push_back(host->find_action("redo")->signal_activate()
+      .connect([this](const Glib::VariantBase&) { redo_clicked(); } ));
+    m_signal_cids.push_back(host->find_action("link")->signal_activate()
+      .connect([this](const Glib::VariantBase&) { link_clicked(); } ));
+    m_signal_cids.push_back(host->find_action("change-font-bold")->signal_change_state()
+      .connect(sigc::mem_fun(*this, &NoteTextMenu::bold_clicked)));
+    m_signal_cids.push_back(host->find_action("change-font-italic")->signal_change_state()
+      .connect(sigc::mem_fun(*this, &NoteTextMenu::italic_clicked)));
+    m_signal_cids.push_back(host->find_action("change-font-strikeout")->signal_change_state()
+      .connect(sigc::mem_fun(*this, &NoteTextMenu::strikeout_clicked)));
+    m_signal_cids.push_back(host->find_action("change-font-highlight")->signal_change_state()
+      .connect(sigc::mem_fun(*this, &NoteTextMenu::highlight_clicked)));
+    m_signal_cids.push_back(host->find_action("change-font-size")->signal_change_state()
+      .connect(sigc::mem_fun(*this, &NoteTextMenu::font_size_activated)));
+    m_signal_cids.push_back(host->find_action("enable-bullets")->signal_change_state()
+      .connect(sigc::mem_fun(*this, &NoteTextMenu::toggle_bullets_clicked)));
+    m_signal_cids.push_back(host->find_action("increase-indent")->signal_activate()
+      .connect(sigc::mem_fun(*this, &NoteTextMenu::increase_indent_clicked)));
+    m_signal_cids.push_back(host->find_action("decrease-indent")->signal_activate()
+      .connect(sigc::mem_fun(*this, &NoteTextMenu::decrease_indent_clicked)));
+  }
+
+  void NoteTextMenu::on_widget_backgrounded()
+  {
+    for(auto & cid : m_signal_cids) {
+      cid.disconnect();
+    }
+    m_signal_cids.clear();
+  }
+
   void NoteTextMenu::link_clicked()
   {
     if(m_event_freeze) {
@@ -1093,43 +1094,84 @@ namespace gnote {
   // Toggle the style tag for the current text.  Style tags are
   // stored in a "Tag" member of the menuitem's Data.
   //
-  void NoteTextMenu::font_style_clicked(Gtk::CheckMenuItem * item)
+  void NoteTextMenu::font_style_clicked(const char * tag)
   {
     if (m_event_freeze)
       return;
 
-    const char * tag = (const char *)item->get_data(Glib::Quark("Tag"));
-
-    if (tag)
+    if(tag) {
       m_buffer->toggle_active_tag(tag);
+    }
   }
 
-  //
-  // Font-style menu item activate
-  //
-  // Set the font size tag for the current text.  Style tags are
-  // stored in a "Tag" member of the menuitem's Data.
-  //
+  void NoteTextMenu::font_clicked(const char *action, const Glib::VariantBase & state, void 
(NoteTextMenu::*func)())
+  {
+    auto host = m_widget.host();
+    if(host == NULL) {
+      return;
+    }
+    host->find_action(action)->set_state(state);
+    (this->*func)();
+  }
+
+  void NoteTextMenu::bold_clicked(const Glib::VariantBase & state)
+  {
+    font_clicked("change-font-bold", state, &NoteTextMenu::bold_pressed);
+  }
+
+  void NoteTextMenu::bold_pressed()
+  {
+    font_style_clicked("bold");
+  }
 
-  // FIXME: Change this back to use FontSizeToggled instead of using the
-  // Activated signal.  Fix the Text menu so it doesn't show a specific
-  // font size already selected if multiple sizes are highlighted. The
-  // Activated event is used here to fix
-  // http://bugzilla.gnome.org/show_bug.cgi?id=412404.
-  void NoteTextMenu::font_size_activated(Gtk::RadioMenuItem *item)
+  void NoteTextMenu::italic_clicked(const Glib::VariantBase & state)
+  {
+    font_clicked("change-font-italic", state, &NoteTextMenu::italic_pressed);
+  }
+
+  void NoteTextMenu::italic_pressed()
+  {
+    font_style_clicked("italic");
+  }
+
+  void NoteTextMenu::strikeout_clicked(const Glib::VariantBase & state)
+  {
+    font_clicked("change-font-strikeout", state, &NoteTextMenu::strikeout_pressed);
+  }
+
+  void NoteTextMenu::strikeout_pressed()
+  {
+    font_style_clicked("strikethrough");
+  }
+
+  void NoteTextMenu::highlight_clicked(const Glib::VariantBase & state)
+  {
+    font_clicked("change-font-highlight", state, &NoteTextMenu::highlight_pressed);
+  }
+
+  void NoteTextMenu::highlight_pressed()
+  {
+    font_style_clicked("highlight");
+  }
+
+  // Font-style menu item activate
+  void NoteTextMenu::font_size_activated(const Glib::VariantBase & state)
   {
     if (m_event_freeze)
       return;
 
-    if (!item->get_active())
+    auto host = m_widget.host();
+    if(host == NULL) {
       return;
+    }
+    host->find_action("change-font-size")->set_state(state);
 
     m_buffer->remove_active_tag ("size:huge");
     m_buffer->remove_active_tag ("size:large");
     m_buffer->remove_active_tag ("size:small");
 
-    const char * tag = (const char *)item->get_data(Glib::Quark("Tag"));
-    if (tag)
+    auto tag = Glib::VariantBase::cast_dynamic<Glib::Variant<Glib::ustring>>(state).get();
+    if(!tag.empty())
       m_buffer->set_active_tag(tag);
   }
 
@@ -1175,7 +1217,7 @@ namespace gnote {
     }
   }
 
-  void NoteTextMenu::undo_clicked ()
+  void NoteTextMenu::undo_clicked()
   {
     if (m_undo_manager.get_can_undo()) {
       DBG_OUT("Running undo...");
@@ -1183,7 +1225,7 @@ namespace gnote {
     }
   }
 
-  void NoteTextMenu::redo_clicked ()
+  void NoteTextMenu::redo_clicked()
   {
     if (m_undo_manager.get_can_redo()) {
       DBG_OUT("Running redo...");
@@ -1193,25 +1235,39 @@ namespace gnote {
 
   void NoteTextMenu::undo_changed ()
   {
-    m_undo->set_sensitive(m_undo_manager.get_can_undo());
-    m_redo->set_sensitive(m_undo_manager.get_can_redo());
+    EmbeddableWidgetHost *host = m_widget.host();
+    if(host == NULL) {
+      return;
+    }
+    host->find_action("undo")->property_enabled() = m_undo_manager.get_can_undo();
+    host->find_action("redo")->property_enabled() = m_undo_manager.get_can_redo();
   }
 
 
     //
     // Bulleted list handlers
     //
-  void  NoteTextMenu::toggle_bullets_clicked()
+  void NoteTextMenu::toggle_bullets_clicked(const Glib::VariantBase&)
   {
     m_buffer->toggle_selection_bullets();
   }
 
-  void  NoteTextMenu::increase_indent_clicked()
+  void NoteTextMenu::increase_indent_clicked(const Glib::VariantBase&)
   {
     m_buffer->increase_cursor_depth();
   }
 
-  void  NoteTextMenu::decrease_indent_clicked()
+  void NoteTextMenu::increase_indent_pressed()
+  {
+    m_buffer->toggle_selection_bullets();
+  }
+
+  void NoteTextMenu::decrease_indent_clicked(const Glib::VariantBase&)
+  {
+    m_buffer->decrease_cursor_depth();
+  }
+
+  void NoteTextMenu::decrease_indent_pressed()
   {
     m_buffer->decrease_cursor_depth();
   }
diff --git a/src/notewindow.hpp b/src/notewindow.hpp
index e873a9b..429dee8 100644
--- a/src/notewindow.hpp
+++ b/src/notewindow.hpp
@@ -1,7 +1,7 @@
 /*
  * gnote
  *
- * Copyright (C) 2011-2015 Aurimas Cernius
+ * Copyright (C) 2011-2016 Aurimas Cernius
  * Copyright (C) 2009 Hubert Figuiere
  *
  * This program is free software: you can redistribute it and/or modify
@@ -25,13 +25,11 @@
 #define _NOTEWINDOW_HPP__
 
 #include <gtkmm/accelgroup.h>
+#include <gtkmm/checkbutton.h>
 #include <gtkmm/grid.h>
 #include <gtkmm/searchentry.h>
 #include <gtkmm/toolbutton.h>
-#include <gtkmm/menu.h>
-#include <gtkmm/checkmenuitem.h>
-#include <gtkmm/radiomenuitem.h>
-#include <gtkmm/imagemenuitem.h>
+#include <gtkmm/popovermenu.h>
 #include <gtkmm/textview.h>
 #include <gtkmm/scrolledwindow.h>
 
@@ -49,53 +47,49 @@ namespace gnote {
   class Note;
 
 class NoteTextMenu
-  : public Gtk::Menu
+  : public Gtk::PopoverMenu
 {
 public:
-  NoteTextMenu(const Glib::RefPtr<NoteBuffer> & buffer, UndoManager& undo_manager);
-  void set_accels(utils::GlobalKeybinder & keybinder, const Glib::RefPtr<Gtk::AccelGroup> &);
+  NoteTextMenu(EmbeddableWidget & widget, const Glib::RefPtr<NoteBuffer> & buffer, UndoManager& 
undo_manager);
+  void set_accels(utils::GlobalKeybinder & keybinder);
   void refresh_state();
-
-  static void markup_label (Gtk::MenuItem & item);
 protected:
   virtual void on_show() override;
 
 private:
+  void on_widget_foregrounded();
+  void on_widget_backgrounded();
   void refresh_sizing_state();
   void link_clicked();
-  void font_style_clicked(Gtk::CheckMenuItem * item);
-  void font_size_activated(Gtk::RadioMenuItem *item);
+  void font_clicked(const char *action, const Glib::VariantBase & state, void (NoteTextMenu::*func)());
+  void bold_clicked(const Glib::VariantBase & state);
+  void bold_pressed();
+  void italic_clicked(const Glib::VariantBase & state);
+  void italic_pressed();
+  void strikeout_clicked(const Glib::VariantBase & state);
+  void strikeout_pressed();
+  void highlight_clicked(const Glib::VariantBase & state);
+  void highlight_pressed();
+  Gtk::Widget *create_font_size_item(const char *label, const char *markup, const char *size);
+  void font_style_clicked(const char * tag);
+  void font_size_activated(const Glib::VariantBase & state);
   void undo_clicked();
   void redo_clicked();
   void undo_changed();
-  void toggle_bullets_clicked();
-  void increase_indent_clicked();
-  void decrease_indent_clicked();
+  void toggle_bullets_clicked(const Glib::VariantBase&);
+  void increase_indent_clicked(const Glib::VariantBase&);
+  void increase_indent_pressed();
+  void decrease_indent_clicked(const Glib::VariantBase&);
+  void decrease_indent_pressed();
   void increase_font_clicked();
   void decrease_font_clicked();
+  Gtk::Widget *create_font_item(const char *action, const char *label, const char *markup);
 
+  EmbeddableWidget     &m_widget;
   Glib::RefPtr<NoteBuffer> m_buffer;
   UndoManager          &m_undo_manager;
   bool                  m_event_freeze;
-  Gtk::ImageMenuItem   *m_undo;
-  Gtk::ImageMenuItem   *m_redo;
-  Gtk::MenuItem         m_link;
-  Gtk::CheckMenuItem    m_bold;
-  Gtk::CheckMenuItem    m_italic;
-  Gtk::CheckMenuItem    m_strikeout;
-  Gtk::CheckMenuItem    m_highlight;
-  Gtk::RadioButtonGroup m_fontsize_group;
-  Gtk::RadioMenuItem    m_normal;
-  Gtk::RadioMenuItem    m_huge;
-  Gtk::RadioMenuItem    m_large;
-  Gtk::RadioMenuItem    m_small;
-  // Active when the text size is indeterminable, such as when in
-  // the note's title line.
-  Gtk::RadioMenuItem    m_hidden_no_size;
-  Gtk::CheckMenuItem    m_bullets;
-  Gtk::ImageMenuItem    m_increase_indent;
-  Gtk::ImageMenuItem    m_decrease_indent;
-  sigc::connection      m_bullets_clicked_cid;
+  std::vector<sigc::connection> m_signal_cids;
 };
 
 class NoteFindHandler
@@ -209,7 +203,7 @@ public:
     {
       return m_editor;
     }
-  Gtk::Menu * text_menu() const
+  Gtk::PopoverMenu * text_menu() const
     {
       return m_text_menu;
     }


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]