[glom] Notebook_NoFrame: Switch to using a GtkStack instead of custom code.



commit 1ade6d449636163117363422f21c9de64bd614ff
Author: Murray Cumming <murrayc murrayc com>
Date:   Sat Oct 19 21:46:52 2013 +0200

    Notebook_NoFrame: Switch to using a GtkStack instead of custom code.

 glom/frame_glom.cc                       |    2 +-
 glom/frame_glom.h                        |    2 +-
 glom/mode_data/notebook_data.cc          |   37 +++----
 glom/mode_data/notebook_data.h           |    4 +-
 glom/mode_find/notebook_find.cc          |   17 ++--
 glom/mode_find/notebook_find.h           |    2 +
 glom/notebook_glom.cc                    |   16 ++--
 glom/notebook_glom.h                     |    3 +-
 glom/utility_widgets/notebook_noframe.cc |  162 +++++------------------------
 glom/utility_widgets/notebook_noframe.h  |   37 +++-----
 10 files changed, 79 insertions(+), 203 deletions(-)
---
diff --git a/glom/frame_glom.cc b/glom/frame_glom.cc
index b5ebf21..088bba6 100644
--- a/glom/frame_glom.cc
+++ b/glom/frame_glom.cc
@@ -2510,7 +2510,7 @@ void Frame_Glom::on_dialog_tables_hide()
   }
 }
 
-void Frame_Glom::on_notebook_data_switch_page(Gtk::Widget* /* page */, guint /* page_num */)
+void Frame_Glom::on_notebook_data_switch_page(Gtk::Widget* /* page */)
 {
   //Refill this menu, because it depends on whether list or details are visible:
   AppWindow* pApp = dynamic_cast<AppWindow*>(get_app_window());
diff --git a/glom/frame_glom.h b/glom/frame_glom.h
index 0d90ac5..203ac4d 100644
--- a/glom/frame_glom.h
+++ b/glom/frame_glom.h
@@ -227,7 +227,7 @@ private:
   void on_notebook_find_criteria(const Gnome::Gda::SqlExpr& where_clause);
   void on_button_quickfind();
   void on_button_find_all();
-  void on_notebook_data_switch_page(Gtk::Widget* page, guint page_num);
+  void on_notebook_data_switch_page(Gtk::Widget* page);
   void on_notebook_data_record_details_requested(const Glib::ustring& table_name, Gnome::Gda::Value 
primary_key_value);
   void on_userlevel_changed(AppState::userlevels userlevel);
 
diff --git a/glom/mode_data/notebook_data.cc b/glom/mode_data/notebook_data.cc
index 9f3acc5..ef18f7f 100644
--- a/glom/mode_data/notebook_data.cc
+++ b/glom/mode_data/notebook_data.cc
@@ -29,12 +29,13 @@
 namespace Glom
 {
 
+//TODO: Remove this:
 static const gchar gNotebookCss[] = "gtkmm__GtkNotebook#glomnotebook { padding: 0 0 0 0; }";
 
+const Glib::ustring Notebook_Data::m_pagename_details = "details";
+const Glib::ustring Notebook_Data::m_pagename_list = "list";
 
 Notebook_Data::Notebook_Data()
-:
-  m_iPage_Details(0), m_iPage_List(0)
 {
 
   //Hide the GtkNotebook border:
@@ -60,12 +61,10 @@ Notebook_Data::Notebook_Data()
    
   //Add Pages:
   //Translators: This is a noun. It is a notebook tab title.
-  append_page(m_Box_List, _("List"));
-  m_iPage_List = 0;
+  append_page(m_Box_List, m_pagename_list, _("List"));
 
   //Translators: This is a noun. It is a notebook tab title.
-  append_page(m_Box_Details, _("Details"));
-  m_iPage_Details = 1;
+  append_page(m_Box_Details, m_pagename_details, _("Details"));
 
   // Set accessible name for the notebook, to be able to access it via LDTP
 #ifdef GTKMM_ATKMM_ENABLED
@@ -292,29 +291,27 @@ FoundSet Notebook_Data::get_found_set_selected() const
 void Notebook_Data::set_current_view(dataview view)
 {
   if(view == DATA_VIEW_List)
-    set_current_page(m_iPage_List);
+    set_visible_child(m_pagename_list);
   else
-    set_current_page(m_iPage_Details);
+    set_visible_child(m_pagename_details);
 }
 
 void Notebook_Data::select_page_for_find_results()
 {
   if(m_Box_List.get_showing_multiple_records())
   {
-    set_current_page(m_iPage_List);
+    set_visible_child(m_pagename_list);
   }
   else
   {
-    set_current_page(m_iPage_Details);
+    set_visible_child(m_pagename_details);
   }
 }
 
 #ifndef GLOM_ENABLE_CLIENT_ONLY
 void Notebook_Data::do_menu_developer_layout()
 {
-  int iPageCurrent = get_current_page();
-
-  Gtk::Widget* pChild  = get_nth_page(iPageCurrent);
+  Gtk::Widget* pChild  = get_visible_child();
   if(pChild)
   {
     Box_Data* pBox = dynamic_cast<Box_Data*>(pChild);
@@ -333,9 +330,7 @@ void Notebook_Data::set_enable_layout_drag_and_drop(bool enable)
 
 void Notebook_Data::do_menu_file_print()
 {
-  const int iPageCurrent = get_current_page();
-
-  Gtk::Widget* pChild  = get_nth_page(iPageCurrent);
+  Gtk::Widget* pChild = get_visible_child();
   if(pChild)
   {
     Box_Data* pBox = dynamic_cast<Box_Data*>(pChild);
@@ -352,10 +347,10 @@ enum dataview
 
 Notebook_Data::dataview Notebook_Data::get_current_view() const
 {
-  const int current_page = get_current_page();
+  const Glib::ustring current_page = get_visible_child_name();
 
   dataview result = DATA_VIEW_Details;
-  if(current_page == (int)m_iPage_List)
+  if(current_page == m_pagename_list)
     result = DATA_VIEW_List;
 
   return result;
@@ -371,13 +366,13 @@ Notebook_Data::type_signal_record_selection_changed Notebook_Data::signal_record
   return m_signal_record_selection_changed;
 }
 
-void Notebook_Data::on_switch_page_handler(Gtk::Widget* pPage, guint uiPageNumber)
+void Notebook_Data::on_switch_page_handler(Gtk::Widget* pPage)
 {
   //Call base class:
-  Notebook_Glom::on_switch_page_handler(pPage, uiPageNumber);
+  Notebook_Glom::on_switch_page_handler(pPage);
 
   //Remember that currently-viewed layout, so we can show it again when the user comes back to this table 
from elsewhere:
-  Box_Data* box = dynamic_cast<Box_Data*>(get_nth_page(uiPageNumber));
+  Box_Data* box = dynamic_cast<Box_Data*>(get_visible_child());
   if(box)
   {
     Document* document = get_document();
diff --git a/glom/mode_data/notebook_data.h b/glom/mode_data/notebook_data.h
index c7b9236..88b0629 100644
--- a/glom/mode_data/notebook_data.h
+++ b/glom/mode_data/notebook_data.h
@@ -93,7 +93,7 @@ protected:
   //Signal handlers:
   virtual void on_list_user_requested_details(const Gnome::Gda::Value& primary_key_value);
 
-  virtual void on_switch_page_handler(Gtk::Widget* pPage, guint uiPageNumber);
+  virtual void on_switch_page_handler(Gtk::Widget* pPage);
 
 private:
 
@@ -104,7 +104,7 @@ protected:
   Box_Data_List m_Box_List;
   Box_Data_Details m_Box_Details;
 
-  guint m_iPage_Details, m_iPage_List;
+  static const Glib::ustring m_pagename_details, m_pagename_list;
   Glib::ustring m_table_name;
 
   type_signal_record_details_requested m_signal_record_details_requested;
diff --git a/glom/mode_find/notebook_find.cc b/glom/mode_find/notebook_find.cc
index 6010fa3..5924d5f 100644
--- a/glom/mode_find/notebook_find.cc
+++ b/glom/mode_find/notebook_find.cc
@@ -25,20 +25,19 @@
 namespace Glom
 {
 
+const Glib::ustring Notebook_Find::m_pagename_details = "details";
+const Glib::ustring Notebook_Find::m_pagename_list = "list";
+
 Notebook_Find::Notebook_Find()
-: m_iPage_Details(0),
-  m_iPage_List(0)
 {
-  append_page(m_Box_List, _("List"));
-  m_iPage_List = 0;
-  m_iPage_Details = 1;
+  append_page(m_Box_List, m_pagename_list, _("List"));
 
   //Fill composite view:
   add_view(&m_Box_List);
 
-  append_page(m_Box_Details, _("Details"));
+  append_page(m_Box_Details, m_pagename_details, _("Details"));
 
-  set_current_page(m_iPage_Details); //Show the details page by default. It's more obvious for a Find.
+  set_visible_child(m_pagename_details); //Show the details page by default. It's more obvious for a Find.
   //TODO: Show the same layout that is being edited at the time that the mode was changed.
 
   //Connect Signals:
@@ -74,9 +73,9 @@ bool Notebook_Find::init_db_details(const Glib::ustring& table_name, const Glib:
 void Notebook_Find::set_current_view(Notebook_Data::dataview view)
 {
   if(view == Notebook_Data::DATA_VIEW_List)
-    set_current_page(m_iPage_List);
+    set_visible_child(m_pagename_list);
   else
-    set_current_page(m_iPage_Details);
+    set_visible_child(m_pagename_details);
 }
 
 } //namespace Glom
diff --git a/glom/mode_find/notebook_find.h b/glom/mode_find/notebook_find.h
index 67c651a..19cfb4b 100644
--- a/glom/mode_find/notebook_find.h
+++ b/glom/mode_find/notebook_find.h
@@ -46,6 +46,8 @@ public:
 
 private:
 
+  static const Glib::ustring m_pagename_details, m_pagename_list;
+
   //Member widgets:
   Box_Data_List_Find m_Box_List;
   
diff --git a/glom/notebook_glom.cc b/glom/notebook_glom.cc
index 7643c5e..8fba0d7 100644
--- a/glom/notebook_glom.cc
+++ b/glom/notebook_glom.cc
@@ -26,8 +26,6 @@ namespace Glom
 
 Notebook_Glom::Notebook_Glom()
 {
-  m_uiPreviousPage = 0;
-
   //Connect signals:
   //We do this on on_show() instead, because otherwise GtkNotebook emits the signal (and we catch it) during 
show:
   //signal_switch_page().connect(sigc::mem_fun(*this, &Notebook_Glom::on_switch_page_handler));
@@ -45,6 +43,7 @@ void Notebook_Glom::on_show()
 {
   NotebookNoFrame::on_show();
 
+  //TODO: Check this for GtkStack.
   //We do this only in on_show() because otherwise GtkNotebook emits the signal (and we catch it) during 
show:
   if(!m_connection_switch_page)
     m_connection_switch_page = signal_switch_page().connect(sigc::mem_fun(*this, 
&Notebook_Glom::on_switch_page_handler));
@@ -57,7 +56,7 @@ Notebook_Glom::type_signal_leave_page Notebook_Glom::signal_leave_page()
 }
 */
 
-void Notebook_Glom::on_switch_page_handler(Gtk::Widget* /* pPage */, guint uiPageNumber)
+void Notebook_Glom::on_switch_page_handler(Gtk::Widget* page)
 {
   //Remove the help hint for the previous page:
   Gtk::Window* pApp = get_app_window();
@@ -67,11 +66,8 @@ void Notebook_Glom::on_switch_page_handler(Gtk::Widget* /* pPage */, guint uiPag
   //  pAppGlom->statusbar_clear();
  // }
 
-  //m_signal_leave_page.emit(m_uiPreviousPage);
-  m_uiPreviousPage = uiPageNumber; //Remember the current page for next time.
-
   //Load the page as we enter it:
-  Gtk::Widget* pChild = get_nth_page(uiPageNumber);
+  Gtk::Widget* pChild = get_visible_child();
   if(pChild)
   {
     Box_WithButtons* pBox = dynamic_cast<Box_WithButtons*>(pChild);
@@ -104,9 +100,11 @@ void Notebook_Glom::on_leave_page(guint uiPageNumber)
   //Tell the page to save itself:
   if(!m_destructor_in_progress)
   {
-    Gtk::Widget* pChild  = get_nth_page(uiPageNumber);
-    if(pChild)
+    typedef std::vector<Gtk::Widget*> type_vec_widgets;
+    type_vec_widgets children = get_page_children();
+    for(type_vec_widgets::iterator iter = children.begin(); iter != children.end(); ++iter)
     {
+      Gtk::Widget* pChild = *iter;
       Base_DB* pBox = dynamic_cast<Base_DB*>(pChild);
       if(pBox)
       {
diff --git a/glom/notebook_glom.h b/glom/notebook_glom.h
index 96b2a27..84486ac 100644
--- a/glom/notebook_glom.h
+++ b/glom/notebook_glom.h
@@ -56,12 +56,11 @@ protected:
   Gtk::Window* get_app_window();
 
   //Signal handlers:
-  virtual void on_switch_page_handler(Gtk::Widget* pPage, guint uiPageNumber);  //The _handler suffix is to 
avoid overriding the base class's method.
+  virtual void on_switch_page_handler(Gtk::Widget* pPage);  //The _handler suffix is to avoid overriding the 
base class's method.
   void on_leave_page(guint uiPageNumber);
 
   //type_signal_leave_page m_signal_leave_page; //Signals when the user leaves a page.
 
-  guint m_uiPreviousPage;
   bool m_destructor_in_progress; //A hack to prevent calling wrap() on dead C instances.
   sigc::connection m_connection_switch_page; //This allows us to delay connecting, and to block the handler 
temporarily.
 };
diff --git a/glom/utility_widgets/notebook_noframe.cc b/glom/utility_widgets/notebook_noframe.cc
index 5354041..c29af1f 100644
--- a/glom/utility_widgets/notebook_noframe.cc
+++ b/glom/utility_widgets/notebook_noframe.cc
@@ -29,18 +29,27 @@ namespace Glom
 {
 
 NotebookNoFrame::NotebookNoFrame()
-: m_current_page(0)
 {
   set_orientation(Gtk::ORIENTATION_VERTICAL);
   set_spacing(Utils::DEFAULT_SPACING_SMALL);
 
-  m_box_tabs.set_spacing(Utils::DEFAULT_SPACING_SMALL);
-  m_box_tabs.pack_start(m_box_action_left, Gtk::PACK_SHRINK);
-  m_box_tabs.pack_end(m_box_action_right, Gtk::PACK_SHRINK);
+  m_box_top.set_orientation(Gtk::ORIENTATION_HORIZONTAL);
+  m_box_top.set_spacing(Utils::DEFAULT_SPACING_SMALL);
+  m_box_top.pack_start(m_box_action_left, Gtk::PACK_SHRINK);
+  m_box_top.pack_start(m_box_tabs);
+  m_box_top.pack_end(m_box_action_right, Gtk::PACK_SHRINK);
+  pack_start(m_box_top, Gtk::PACK_SHRINK);
 
-  pack_start(m_box_tabs, Gtk::PACK_SHRINK);
-  m_box_tabs.show();
+  m_box_top.show();
+
+  //Let the StackSwitcher switch the Stack:
+  m_box_tabs.set_stack(m_box_pages);
+  m_box_pages.property_visible_child().signal_changed().connect(
+    sigc::mem_fun(*this, &NotebookNoFrame::on_visible_child_changed));
 
+  //m_box_tabs.set_spacing(Utils::DEFAULT_SPACING_SMALL);
+
+  m_box_tabs.show();
 
   pack_start(m_box_pages);
   m_box_pages.show();
@@ -55,150 +64,35 @@ NotebookNoFrame::type_signal_switch_page NotebookNoFrame::signal_switch_page()
   return m_signal_switch_page;
 }
 
-Gtk::Widget* NotebookNoFrame::get_nth_page(int page_num)
-{
-  if(page_num < 0)
-    return 0;
-
-  if(page_num >= (int)m_vec_page_widgets.size())
-    return 0;
-
-  Gtk::Box* box =  m_vec_page_widgets[page_num];
-  if(!box)
-    return 0;
-
-  std::vector<Gtk::Widget*> children = box->get_children();
-  if(children.empty())
-    return 0;
-
-  return children[0];
-}
-
-const Gtk::Widget* NotebookNoFrame::get_nth_page(int page_num) const
+Glib::ustring NotebookNoFrame::get_visible_child_name() const
 {
-  NotebookNoFrame* unconstThis = const_cast<NotebookNoFrame*>(this);
-  return unconstThis->get_nth_page(page_num);
+  return m_box_pages.get_visible_child_name();
 }
 
-int NotebookNoFrame::get_current_page() const
+Gtk::Widget* NotebookNoFrame::get_visible_child()
 {
-  return m_current_page;
+  return m_box_pages.get_visible_child();
 }
 
-void NotebookNoFrame::set_current_page(int page_num)
+void NotebookNoFrame::set_visible_child(const Glib::ustring& name)
 {
-  if(page_num < 0)
-    return;
-
-  const int size = (int)m_vec_page_widgets.size();
-  if(page_num >= size)
-    return;
-
-  m_current_page = page_num;
-
-  //TODO: Enable the tab button too.
-
-  //Show only the current page:
-  for(int i = 0; i < size; ++i)
-  {
-    Gtk::ToggleButton* tab = m_vec_tab_widgets[i];
-    if(!tab)
-      continue;
-
-    Gtk::Box* box = m_vec_page_widgets[i];
-    if(!box)
-      continue;
-
-    if(i == page_num)
-    {
-      if(!tab->get_active())
-        tab->set_active();
-
-      box->show();
-    }
-    else
-    {
-      if(tab->get_active())
-        tab->set_active(false);
-
-      box->hide();
-    }
-  }
+  m_box_pages.set_visible_child(name);
 }
 
-int NotebookNoFrame::append_page(Gtk::Widget& child, Gtk::Widget& tab_label)
+void NotebookNoFrame::append_page(Widget& child, const Glib::ustring& name, const Glib::ustring& tab_label, 
bool use_mnemonic)
 {
-  Gtk::ToggleButton* toggle = Gtk::manage(new Gtk::ToggleButton());
-  toggle->set_active(false);
-  toggle->add(tab_label);
-  toggle->show();
-  m_box_tabs.pack_start(*toggle, Gtk::PACK_SHRINK);
-  m_vec_tab_widgets.push_back(toggle);
-
-  //We put the child into a box so we can show or hide it regardless of
-  //whether the callers calls show() or hide() on the child widget.
-  //Note that this would make the public list of children incorrect, if we supported that anyway.
-  Gtk::Box* box = Gtk::manage(new Gtk::Box());
-  box->pack_start(child, Gtk::PACK_EXPAND_WIDGET);
-  m_box_pages.pack_start(*box, Gtk::PACK_EXPAND_WIDGET);
-  m_vec_page_widgets.push_back(box);
-
-  const int index = m_vec_page_widgets.size() - 1;
-
-  //Make sure that the first one is showing:
-  if(index == 0)
-  {
-    m_current_page = 0;
-    toggle->set_active();
-    box->show();
-  }
-  else
-  {
-    toggle->set_active(false);
-    box->hide();
-  }
-
-  set_current_page(index);
-
-  toggle->signal_toggled().connect(
-    sigc::bind(
-      sigc::mem_fun(*this, &NotebookNoFrame::on_tab_toggled),
-      index));
-
-  return index;
+  m_box_pages.add(child, name, tab_label);
 }
 
-int NotebookNoFrame::append_page(Widget& child, const Glib::ustring& tab_label, bool use_mnemonic)
+std::vector<Gtk::Widget*> NotebookNoFrame::get_page_children()
 {
-  Gtk::Label* pLabel = Gtk::manage( new Gtk::Label(tab_label, use_mnemonic) );
-  pLabel->show();
-  return append_page(child, *pLabel);
+  return m_box_pages.get_children();
 }
 
-void NotebookNoFrame::on_tab_toggled(int index)
+void NotebookNoFrame::on_visible_child_changed()
 {
-  Gtk::ToggleButton* tab = m_vec_tab_widgets[index];
-  if(!tab)
-    return;
-
-  int new_current_page = 0;
-  if(tab->get_active())
-  {
-    //A different page was selected by clicking on its tab, pressing the button down:
-    new_current_page = index;
-  }
-  else
-  {
-    //A different page was selected by clicking on another tab, raising it's button:
-    //So let's choose another one:
-    new_current_page = index + 1;
-    if(new_current_page >= (int)m_vec_tab_widgets.size())
-      new_current_page = 0;
-  }
-
-  set_current_page(new_current_page);
-  Gtk::Widget* child = get_nth_page(new_current_page);
-  m_signal_switch_page.emit(child, new_current_page);
+  Gtk::Widget* widget = get_visible_child();
+  m_signal_switch_page.emit(widget);
 }
 
 void NotebookNoFrame::set_action_widget(Gtk::Widget* widget, Gtk::PackType pack_type)
diff --git a/glom/utility_widgets/notebook_noframe.h b/glom/utility_widgets/notebook_noframe.h
index d752dd9..ed7dc60 100644
--- a/glom/utility_widgets/notebook_noframe.h
+++ b/glom/utility_widgets/notebook_noframe.h
@@ -23,7 +23,8 @@
 
 #include <gtkmm/box.h>
 #include <gtkmm/buttonbox.h>
-#include <gtkmm/togglebutton.h>
+#include <gtkmm/stack.h>
+#include <gtkmm/stackswitcher.h>
 
 namespace Glom
 {
@@ -38,41 +39,29 @@ public:
   explicit NotebookNoFrame();
   virtual ~NotebookNoFrame();
 
-  int append_page(Gtk::Widget& child, Gtk::Widget& tab_label);
-  /*
-  int append_page(Widget& child);
-  */
-  int append_page(Widget& child, const Glib::ustring& tab_label, bool use_mnemonic = false);
+  void append_page(Widget& child, const Glib::ustring& name, const Glib::ustring& tab_label, bool 
use_mnemonic = false);
 
-  Widget* get_nth_page(int page_num);
-  const Widget* get_nth_page(int page_num) const;
+  Gtk::Widget* get_visible_child();
+  Glib::ustring get_visible_child_name() const;
+  void set_visible_child(const Glib::ustring& name);
 
-  int get_current_page() const;
-  void set_current_page(int page_num);
+  std::vector<Gtk::Widget*> get_page_children();
 
   void set_action_widget(Gtk::Widget* widget, Gtk::PackType pack_type);
 
-  typedef sigc::signal<void, Gtk::Widget*, guint> type_signal_switch_page;
+  typedef sigc::signal<void, Gtk::Widget*> type_signal_switch_page;
 
   type_signal_switch_page signal_switch_page();
 
-protected:
-  void on_tab_toggled(int index);
+private:
+  void on_visible_child_changed();
 
-  Gtk::Box m_box_tabs;
-  Gtk::Box m_box_pages;
+  Gtk::Box m_box_top;
+  Gtk::StackSwitcher m_box_tabs;
+  Gtk::Stack m_box_pages;
   Gtk::Box m_box_action_left, m_box_action_right;
 
   type_signal_switch_page m_signal_switch_page;
-
-  //Caching the widget pointers is nicer than repeatedly calling Gtk::Container::get_children().
-  typedef std::vector<Gtk::ToggleButton*> type_vec_togglebuttons;
-  type_vec_togglebuttons m_vec_tab_widgets;
-
-  typedef std::vector<Gtk::Box*> type_vec_widgets;
-  type_vec_widgets m_vec_page_widgets;
-
-  int m_current_page;
 };
 
 } //namespace Glom


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