From a4fbcfec49ed3a1f64e02bc65f48af66861810a8 Mon Sep 17 00:00:00 2001 From: Joel Holdsworth Date: Wed, 15 Apr 2009 12:24:34 +0100 Subject: [PATCH] Added panel splitting --- src/gui/widgets/panel-bar.cpp | 13 ++++ src/gui/widgets/panel-bar.hpp | 6 ++ src/gui/workspace/panel-manager.cpp | 108 ++++++++++++++++++++++------ src/gui/workspace/panel-manager.hpp | 65 +++++++++++++---- 4 files changed, 160 insertions(+), 32 deletions(-) diff --git a/src/gui/widgets/panel-bar.cpp b/src/gui/widgets/panel-bar.cpp index 76f33c239..474579cdf 100644 --- a/src/gui/widgets/panel-bar.cpp +++ b/src/gui/widgets/panel-bar.cpp @@ -81,6 +81,13 @@ PanelBar::setup_panel_button() lockItem = dynamic_cast(&list.back()); ENSURE(lockItem); lockItem->set_active(panel.is_locked()); + + list.push_back( Menu_Helpers::MenuElem(_("Split _Horizontal"), + bind(mem_fun(*this, &PanelBar::on_split_panel), + ORIENTATION_HORIZONTAL) ) ); + list.push_back( Menu_Helpers::MenuElem(_("Split _Vertical"), + bind(mem_fun(*this, &PanelBar::on_split_panel), + ORIENTATION_VERTICAL) ) ); } void @@ -166,5 +173,11 @@ PanelBar::on_lock() } } +void +PanelBar::on_split_panel(Gtk::Orientation split_direction) +{ + panel.get_panel_manager().split_panel(panel, split_direction); +} + } // widgets } // gui diff --git a/src/gui/widgets/panel-bar.hpp b/src/gui/widgets/panel-bar.hpp index 000a28a33..afccaa91c 100644 --- a/src/gui/widgets/panel-bar.hpp +++ b/src/gui/widgets/panel-bar.hpp @@ -89,6 +89,12 @@ private: * Event handler for when the "Lock" menu item is clicked **/ void on_lock(); + + /** + * Event handler for when the split panel menu item is clicked + * @param split_direction The direction to split in. + **/ + void on_split_panel(Gtk::Orientation split_direction); private: diff --git a/src/gui/workspace/panel-manager.cpp b/src/gui/workspace/panel-manager.cpp index 56be3570e..a2f1fb5e7 100644 --- a/src/gui/workspace/panel-manager.cpp +++ b/src/gui/workspace/panel-manager.cpp @@ -30,6 +30,7 @@ using namespace boost; using namespace std; +using namespace Gtk; namespace gui { namespace workspace { @@ -146,11 +147,40 @@ void PanelManager::switch_panel(panels::Panel &old_panel, *this, dock_item)); g_object_unref(dock_item); - new_panel->show_all(); - panels.push_back(new_panel); } +void +PanelManager::split_panel(panels::Panel &panel, + Gtk::Orientation split_direction) +{ + // Create the new panel + const int index = get_panel_type(&panel); + shared_ptr new_panel = create_panel_by_index(index); + + // Add it to the list + panels.push_back(new_panel); + + // Dock the panel + GdlDockPlacement placement = GDL_DOCK_NONE; + switch(split_direction) + { + case ORIENTATION_HORIZONTAL: + placement = GDL_DOCK_RIGHT; + break; + case ORIENTATION_VERTICAL: + placement = GDL_DOCK_BOTTOM; + break; + default: + ERROR(gui, "Unrecognisized split_direction: %d", split_direction); + return; + break; + } + + gdl_dock_object_dock(GDL_DOCK_OBJECT(panel.get_dock_item()), + GDL_DOCK_OBJECT(new_panel->get_dock_item()), placement, NULL); +} + int PanelManager::get_panel_description_count() { @@ -186,30 +216,68 @@ PanelManager::create_panels() panels.push_back(resourcesPanel); } -shared_ptr -PanelManager::create_panel_by_name(const char* class_name) -{ +int +PanelManager::find_panel_description(const char* class_name) const +{ + REQUIRE(class_name); + const int count = get_panel_description_count(); for(int i = 0; i < count; i++) { if(strstr(panelDescriptionList[i].get_class_name(), class_name)) - { - // Make a unique name for the panel - char name[5]; - snprintf(name, sizeof(name), "%X", panelID++); - - // Create a dock item - GdlDockItem *dock_item = GDL_DOCK_ITEM( - gdl_dock_item_new(name, "", GDL_DOCK_ITEM_BEH_NORMAL)); - - // Create the panel object - return shared_ptr( - panelDescriptionList[i].create(*this, dock_item)); - } + return i; } - ERROR(gui, "Unable to create a panel with class name %s", class_name); - return shared_ptr(); + ERROR(gui, "Unable to find a description with class name %s", + class_name); + return -1; +} + +shared_ptr +PanelManager::create_panel_by_index(const int index) +{ + REQUIRE(index >= 0 && index < get_panel_description_count()); + + // Make a unique name for the panel + char name[5]; + snprintf(name, sizeof(name), "%X", panelID++); + + // Create a dock item + GdlDockItem *dock_item = GDL_DOCK_ITEM( + gdl_dock_item_new(name, "", GDL_DOCK_ITEM_BEH_NORMAL)); + + // Create the panel object + shared_ptr panel( + panelDescriptionList[index].create(*this, dock_item)); + ENSURE(panel); + panel->show_all(); + + return panel; +} + +shared_ptr +PanelManager::create_panel_by_name(const char* class_name) +{ + REQUIRE(class_name); + const int index = find_panel_description(class_name); + return create_panel_by_index(index); +} + +int +PanelManager::get_panel_type(panels::Panel *panel) const +{ + REQUIRE(panel); + + const type_info &info = typeid(*panel); + const int count = get_panel_description_count(); + for(int i = 0; i < count; i++) + { + if(info == panelDescriptionList[i].get_class_info()) + return i; + } + + ERROR(gui, "Unable to find a description with with this class type"); + return -1; } } // namespace workspace diff --git a/src/gui/workspace/panel-manager.hpp b/src/gui/workspace/panel-manager.hpp index 1c462264e..4928cf8ae 100644 --- a/src/gui/workspace/panel-manager.hpp +++ b/src/gui/workspace/panel-manager.hpp @@ -29,6 +29,7 @@ #define PANEL_MANAGER_HPP #include +#include #include "../panels/panel.hpp" @@ -90,6 +91,14 @@ public: **/ void switch_panel(panels::Panel &old_panel, int new_panel_description_index); + + /** + * Splits a panel into two panels of the same type. + * @param panel The panel to split. + * @param split_direction The direction to split the panel in. + **/ + void split_panel(panels::Panel &panel, + Gtk::Orientation split_direction); public: @@ -111,14 +120,39 @@ private: * Creates the standard panel layout. **/ void create_panels(); + + /** + * Find the index of a panel description given the class name. + * @param class_name The name of the object class to search for. + * @return Returns the index of the panel description found, or -1 + * if no description was found for this type. + **/ + int find_panel_description(const char* class_name) const; + + /** + * Creates a panel by description index. + * @param index The index of the description to instantiate. + * @return Returns a pointer to the new instantiated panel object. + **/ + boost::shared_ptr create_panel_by_index( + const int index); /** * Creates a panel by class name. * @param class_name The name of the object class to create. + * @return Returns a pointer to the new instantiated panel object. **/ boost::shared_ptr create_panel_by_name( const char* class_name); + /** + * Gets the type of a given panel. + * @param panel The Panel to get the type of + * @return Returns the index of the panel description found, or -1 + * if no description was found for this type. + **/ + int get_panel_type(panels::Panel *panel) const; + private: /** @@ -175,32 +209,39 @@ private: protected: /** * Constructor - * @param class_name The name of the Panel class + * @param classInfo The typeid of the Panel class * @param title The localized title that will be shown on the * panel. * @param stock_id The Stock ID for this type of panel. * @param create_panel_proc A pointer to a function that will * instantiate the panel object. **/ - PanelDescription(const char* class_name, const char *title, - const gchar *stock_id, CreatePanelProc create_panel_proc) : - className(class_name), + PanelDescription(const std::type_info &class_info, + const char *title, const gchar *stock_id, + CreatePanelProc create_panel_proc) : + classInfo(class_info), titleName(title), stockID(stock_id), createPanelProc(create_panel_proc) { - REQUIRE(className); REQUIRE(titleName); } public: /** - * Returns a pointer to the string name of class. + * Returns a reference to the typeid of the class. + **/ + const std::type_info& get_class_info() const + { + return classInfo; + } + + /** + * Returns a pointer to the string name of the class. **/ const char* get_class_name() const { - ENSURE(className); - return className; + return classInfo.name(); } /** @@ -236,9 +277,9 @@ private: private: /** - * A pointer to the string name of class. - **/ - const char* const className; + * A reference to the typeid of this class + **/ + const std::type_info &classInfo; /** * The localized title that will be shown on the panel. @@ -268,7 +309,7 @@ private: * Constructor **/ Panel() : - PanelDescription(typeid(P).name(), P::get_title(), + PanelDescription(typeid(P), P::get_title(), P::get_stock_id(), Panel::create_panel) {}