/* panel-manager.cpp - Definition of the panel manager object Copyright (C) Lumiera.org 2008, Joel Holdsworth This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * *****************************************************/ #include "panel-manager.hpp" #include "../panels/resources-panel.hpp" #include "../panels/viewer-panel.hpp" #include "../panels/timeline-panel.hpp" #include "include/logging.h" using namespace boost; using namespace std; using namespace Gtk; namespace gui { namespace workspace { const PanelManager::PanelDescription PanelManager::panelDescriptionList[] = { PanelManager::Panel(), PanelManager::Panel(), PanelManager::Panel() }; unsigned short PanelManager::panelID = 0; PanelManager::PanelManager(WorkspaceWindow &workspace_window) : workspaceWindow(workspace_window), dock(NULL), dockBar(NULL), dockLayout(NULL) { memset(&dockPlaceholders, 0, sizeof(dockPlaceholders)); } PanelManager::~PanelManager() { if(dock) g_object_unref(dock); if(dockBar) g_object_unref(dockBar); if(dockLayout) g_object_unref(dockLayout); for(int i = 0; i < 4; i++) if(dockPlaceholders[i]) g_object_unref(dockPlaceholders[i]); } void PanelManager::setup_dock() { REQUIRE(dock == NULL); dock = GDL_DOCK(gdl_dock_new()); ENSURE(dock); REQUIRE(dockBar == NULL); dockBar = GDL_DOCK_BAR(gdl_dock_bar_new(dock)); ENSURE(dockBar); REQUIRE(dockLayout == NULL); dockLayout = GDL_DOCK_LAYOUT(gdl_dock_layout_new(dock)); ENSURE(dockLayout); REQUIRE(dockPlaceholders[0] == NULL && dockPlaceholders[1] == NULL && dockPlaceholders[2] == NULL && dockPlaceholders[3] == NULL); dockPlaceholders[0] = GDL_DOCK_PLACEHOLDER(gdl_dock_placeholder_new( "ph1", GDL_DOCK_OBJECT(dock), GDL_DOCK_TOP, FALSE)); dockPlaceholders[1] = GDL_DOCK_PLACEHOLDER(gdl_dock_placeholder_new( "ph2", GDL_DOCK_OBJECT(dock), GDL_DOCK_BOTTOM, FALSE)); dockPlaceholders[2] = GDL_DOCK_PLACEHOLDER(gdl_dock_placeholder_new( "ph3", GDL_DOCK_OBJECT(dock), GDL_DOCK_LEFT, FALSE)); dockPlaceholders[3] = GDL_DOCK_PLACEHOLDER(gdl_dock_placeholder_new( "ph4", GDL_DOCK_OBJECT(dock), GDL_DOCK_RIGHT, FALSE)); ENSURE(dockPlaceholders[0] && dockPlaceholders[1] && dockPlaceholders[2] && dockPlaceholders[3]); create_panels(); } GdlDock* PanelManager::get_dock() const { ENSURE(dock); return dock; } GdlDockBar* PanelManager::get_dock_bar() const { ENSURE(dockBar); return dockBar; } WorkspaceWindow& PanelManager::get_workspace_window() { return workspaceWindow; } void PanelManager::show_panel(const int description_index) { // Try and find the panel and present it if possible list< boost::shared_ptr >::iterator i; for(i = panels.begin(); i != panels.end(); i++) { const shared_ptr panel = *i; if(get_panel_type(panel.get()) == description_index) { panel->show(); GdlDockItem *dock_item = panel->get_dock_item(); ENSURE(dock_item); gdl_dock_object_present(GDL_DOCK_OBJECT(dock_item), NULL); return; } } // Create the new panel shared_ptr new_panel = create_panel_by_index(description_index); // Dock the item gdl_dock_add_item(dock, new_panel->get_dock_item(), GDL_DOCK_FLOATING); } void PanelManager::switch_panel(panels::Panel &old_panel, const int description_index) { REQUIRE(description_index >= 0 && description_index < get_panel_description_count()); // Get the dock item GdlDockItem *dock_item = old_panel.get_dock_item(); g_object_ref(dock_item); // Release the old panel list< boost::shared_ptr >::iterator i; for(i = panels.begin(); i != panels.end(); i++) { if((*i).get() == &old_panel) { panels.erase(i); break; } } // Create the new panel shared_ptr new_panel( panelDescriptionList[description_index].create(*this, dock_item)); g_object_unref(dock_item); } 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); // 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() { return sizeof(panelDescriptionList) / sizeof(PanelDescription); } const gchar* PanelManager::get_panel_stock_id(int index) { REQUIRE(index >= 0 && index < get_panel_description_count()); return panelDescriptionList[index].get_stock_id(); } const char* PanelManager::get_panel_title(int index) { REQUIRE(index >= 0 && index < get_panel_description_count()); return panelDescriptionList[index].get_title(); } void PanelManager::create_panels() { shared_ptr resourcesPanel( create_panel_by_name("ResourcesPanel")); shared_ptr viewerPanel( create_panel_by_name("ViewerPanel")); shared_ptr timelinePanel( create_panel_by_name("TimelinePanel")); gdl_dock_add_item(dock, resourcesPanel->get_dock_item(), GDL_DOCK_LEFT); gdl_dock_add_item(dock, timelinePanel->get_dock_item(), GDL_DOCK_BOTTOM); gdl_dock_add_item(dock, viewerPanel->get_dock_item(), GDL_DOCK_RIGHT); } 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)) return i; } 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(); // Connect event handlers panel->signal_hide_panel().connect(bind( mem_fun(*this, &PanelManager::on_panel_shown), panel)); // Add the panel to the list panels.push_back(panel); 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; } void PanelManager::on_panel_shown(boost::weak_ptr panel_ptr) { if(panel_ptr.expired()) return; shared_ptr panel(panel_ptr); REQUIRE(panel); if(panel->is_shown() || panel->is_iconified()) return; // Release the panel list< boost::shared_ptr >::iterator i; for(i = panels.begin(); i != panels.end(); i++) { if((*i) == panel) { panels.erase(i); break; } } } } // namespace workspace } // namespace gui