lumiera_documentation/src/gui/workspace/panel-manager.cpp
Ichthyostega 670c670d55 style-adjustment: GUI indentation, naming and braces
over time, a specific Lumiera code writing style has emerged.
The GUI, as it stood, used somewhat different conventions,
which now have been aligned to the common standard.

Basically we use GNU style, with some adjustments for OO-programming,
we prefer CamelCase, and write TypeNames uppercase, variableNames lowercase
2015-05-29 04:44:58 +02:00

355 lines
9.6 KiB
C++

/*
PanelManager - management of dockable GDL panels
Copyright (C) Lumiera.org
2008, Joel Holdsworth <joel@airwebreathe.org.uk>
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 "gui/workspace/panel-manager.hpp"
#include "gui/panel/assets-panel.hpp"
#include "gui/panel/viewer-panel.hpp"
#include "gui/panel/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<TimelinePanel>(),
PanelManager::Panel<ViewerPanel>(),
PanelManager::Panel<AssetsPanel>()
};
unsigned short PanelManager::panelID = 0;
PanelManager::PanelManager (WorkspaceWindow& owner)
: workspaceWindow_(owner)
, dock_()
, dockBar_(dock_)
, dockLayout_()
{
/* Create the DockLayout */
dockLayout_ = Gdl::DockLayout::create(dock_);
/* Setup the Switcher Style */
Glib::RefPtr<Gdl::DockMaster> dock_master = dock_.property_master();
dock_master->property_switcher_style() = Gdl::SWITCHER_STYLE_ICON;
memset(&dockPlaceholders_, 0, sizeof(dockPlaceholders_));
}
PanelManager::~PanelManager()
{
///////////////////////////////////////////////////////TICKET #195 : violation of policy, dtors must not do any work
///////////////////////////////////////////////////////TICKET #172 : observed as a reason for crashes when closing the GUI. It was invoked after end of main, when the GUI as already gone.
#if false ///////////////////////////////////////////////////TICKET #937 : disabled for GTK-3 transition. TODO investigate why this logic existed...
for(int i = 0; i < 4; i++)
if(dockPlaceholders_[i])
g_object_unref(dockPlaceholders_[i]);
clearPanels();
#endif ///////////////////////////////////////////////////TICKET #937 : (End)disabled for GTK-3 transition.
}
void
PanelManager::setupDock()
{
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_.gobj()), GDL_DOCK_TOP, FALSE));
dockPlaceholders_[1] = GDL_DOCK_PLACEHOLDER(gdl_dock_placeholder_new(
"ph2", GDL_DOCK_OBJECT(dock_.gobj()), GDL_DOCK_BOTTOM, FALSE));
dockPlaceholders_[2] = GDL_DOCK_PLACEHOLDER(gdl_dock_placeholder_new(
"ph3", GDL_DOCK_OBJECT(dock_.gobj()), GDL_DOCK_LEFT, FALSE));
dockPlaceholders_[3] = GDL_DOCK_PLACEHOLDER(gdl_dock_placeholder_new(
"ph4", GDL_DOCK_OBJECT(dock_.gobj()), GDL_DOCK_RIGHT, FALSE));
ENSURE(dockPlaceholders_[0] && dockPlaceholders_[1] &&
dockPlaceholders_[2] && dockPlaceholders_[3]);
createPanels();
}
Gdl::Dock&
PanelManager::getDock()
{
return dock_;
}
Gdl::DockBar&
PanelManager::getDockBar()
{
return dockBar_;
}
WorkspaceWindow&
PanelManager::getWorkspaceWindow()
{
return workspaceWindow_;
}
void
PanelManager::showPanel (const int description_index)
{
// Try and find the panel and present it if possible
list< panel::Panel* >::iterator i;
for(i = panels_.begin(); i != panels_.end(); i++)
{
panel::Panel* const panel = *i;
if (getPanelType(panel) == description_index)
{
if (!panel->is_shown()) panel->show();
Gdl::DockItem &dock_item = panel->getDockItem();
// ENSURE(dock_item);
dock_item.present(dock_);
return;
}
}
// Create the new panel
panel::Panel *new_panel = createPanel_by_index (description_index);
// Dock the item
dock_.add_item(new_panel->getDockItem(), Gdl::DOCK_FLOATING);
}
void
PanelManager::switchPanel (panel::Panel& old_panel, const int description_index)
{
REQUIRE (description_index >= 0 &&
description_index < getPanelDescriptionCount());
// Get the dock item
Gdl::DockItem &dock_item = old_panel.getDockItem();
// Release the old panel
removePanel (&old_panel);
// Create the new panel
createPanel_by_index (description_index, dock_item);
}
void
PanelManager::splitPanel (panel::Panel& panel, Gtk::Orientation split_direction)
{
// Create the new panel
const int index = getPanelType(&panel);
panel::Panel *new_panel = createPanel_by_index(index);
// Dock the panel
Gdl::DockPlacement 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, "Unknown split_direction: %d", split_direction);
return;
break;
}
panel.getDockItem().dock(
new_panel->getDockItem(),placement);
}
int
PanelManager::getPanelDescriptionCount()
{
return sizeof(panelDescriptionList) / sizeof(PanelDescription);
}
const gchar*
PanelManager::getPanelStockID (int index)
{
REQUIRE (index >= 0 && index < getPanelDescriptionCount());
return panelDescriptionList[index].getStockID();
}
const char*
PanelManager::getPanelTitle (int index)
{
REQUIRE (index >= 0 && index < getPanelDescriptionCount());
return panelDescriptionList[index].getTitle();
}
void
PanelManager::createPanels()
{
panel::Panel* assetsPanel = createPanel_by_name("AssetsPanel");
panel::Panel* viewerPanel = createPanel_by_name("ViewerPanel");
panel::Panel* timelinePanel = createPanel_by_name("TimelinePanel");
dock_.add_item(assetsPanel->getDockItem(),Gdl::DOCK_LEFT);
dock_.add_item(timelinePanel->getDockItem(),Gdl::DOCK_BOTTOM);
dock_.add_item(viewerPanel->getDockItem(),Gdl::DOCK_RIGHT);
}
int
PanelManager::findPanelDescription (const char* class_name) const
{
REQUIRE(class_name);
const int count = getPanelDescriptionCount();
for(int i = 0; i < count; i++)
{
if (strstr(panelDescriptionList[i].getClassName(), class_name))
return i;
}
ERROR (gui, "Unable to find a description with class name %s", class_name);
return -1;
}
panel::Panel*
PanelManager::createPanel_by_index (const int index)
{
REQUIRE(index >= 0 && index < getPanelDescriptionCount());
// Make a unique name for the panel
char name[5];
snprintf(name, sizeof(name), "%X", panelID++);
// Create a dock item
return createPanel_by_index(index,
*new Gdl::DockItem(name,"",Gdl::DOCK_ITEM_BEH_NORMAL));
}
panel::Panel*
PanelManager::createPanel_by_index (const int index, Gdl::DockItem &dock_item)
{
// Create the panel object
panel::Panel *panel = panelDescriptionList[index].create(*this, dock_item);
ENSURE(panel);
panel->show_all();
// Connect event handlers
panel->signal_hidePanel().connect(sigc::bind(
sigc::mem_fun(*this, &PanelManager::on_panel_shown), panel));
// Add the panel to the list
panels_.push_back(panel);
return panel;
}
panel::Panel*
PanelManager::createPanel_by_name (const char* class_name)
{
REQUIRE(class_name);
const int index = findPanelDescription(class_name);
return createPanel_by_index(index);
}
int
PanelManager::getPanelType (panel::Panel* const panel) const
{
REQUIRE(panel);
const type_info &info = typeid(*panel);
const int count = getPanelDescriptionCount();
for(int i = 0; i < count; i++)
{
if(info == panelDescriptionList[i].getClassInfo())
return i;
}
ERROR(gui, "Unable to find a description with with this class type");
return -1;
}
void
PanelManager::removePanel (panel::Panel* const panel)
{
REQUIRE(panel);
list< panel::Panel* >::iterator i;
for(i = panels_.begin(); i != panels_.end(); i++)
{
if(*i == panel)
{
delete panel;
panels_.erase(i);
break;
}
}
}
void
PanelManager::clearPanels()
{
///////////////////////////////////////////////////////TICKET #195 : this whole approach smells like an obsolete "C-style" approach. We should strive to let the runtime system do such stuff for us whenever possible, eg. by using smart pointers
list< panel::Panel* >::iterator i;
for(i = panels_.begin(); i != panels_.end(); i++)
delete *i;
panels_.clear();
}
void
PanelManager::on_panel_shown (panel::Panel* panel)
{
REQUIRE(panel);
if(panel->is_shown() || panel->is_iconified()) return;
removePanel(panel);
}
}}// namespace gui::workspace