Lumiera  0.pre.03
»edit your freedom«
dock-area.cpp
Go to the documentation of this file.
1 /*
2  DockArea - maintain a docking area within the WorkspaceWindow
3 
4  Copyright (C) Lumiera.org
5  2008, Joel Holdsworth <joel@airwebreathe.org.uk>
6  2018, Hermann Vosseler <Ichthyostega@web.de>
7 
8  This program is free software; you can redistribute it and/or
9  modify it under the terms of the GNU General Public License as
10  published by the Free Software Foundation; either version 2 of
11  the License, or (at your option) any later version.
12 
13  This program is distributed in the hope that it will be useful,
14  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  GNU General Public License for more details.
17 
18  You should have received a copy of the GNU General Public License
19  along with this program; if not, write to the Free Software
20  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 
22 * *****************************************************/
23 
24 
31 
37 
42 
43 #include "include/logging.h"
44 #include "lib/util-foreach.hpp"
45 
46 using namespace boost;
47 using namespace std;
48 using namespace Gtk;
49 
50 namespace stage {
51 namespace workspace {
52 
53  const DockArea::PanelDescription
54  DockArea::panelDescriptionList[] = {
55 #if false
56  DockArea::Panel<TimelinePanel>(),
57  DockArea::Panel<InfoBoxPanel>(),
58  DockArea::Panel<ViewerPanel>(),
59  DockArea::Panel<AssetsPanel>()
60 #endif
61  };
62 
63  unsigned short DockArea::panelID = 0;
64 
65 
66 
67  DockArea::DockArea (WorkspaceWindow& owner)
68  : workspaceWindow_(owner)
69  , dock_()
70  , dockBar_(dock_)
71  , dockLayout_()
72  {
73  /* Create the DockLayout */
74  dockLayout_ = Gdl::DockLayout::create(dock_);
75 
76  /* Setup the Switcher Style */
77  Glib::RefPtr<Gdl::DockMaster> dock_master = dock_.property_master();
78  dock_master->property_switcher_style() = Gdl::SWITCHER_STYLE_ICON;
79 
80  memset(&dockPlaceholders_, 0, sizeof(dockPlaceholders_));
81  }
82 
83 
84 
85  DockArea::~DockArea()
86  {
89 
90 #if false
91  for(int i = 0; i < 4; i++)
93  if(dockPlaceholders_[i])
94  g_object_unref(dockPlaceholders_[i]);
95 
96  clearPanels();
97 #endif
98  }
99 
100 
101 
102  void
103  DockArea::setupDock()
104  {
106 
107  REQUIRE(dockPlaceholders_[0] == NULL && dockPlaceholders_[1] == NULL &&
108  dockPlaceholders_[2] == NULL && dockPlaceholders_[3] == NULL);
109  dockPlaceholders_[0] = GDL_DOCK_PLACEHOLDER(gdl_dock_placeholder_new(
110  "ph1", GDL_DOCK_OBJECT(dock_.gobj()), GDL_DOCK_TOP, FALSE));
111  dockPlaceholders_[1] = GDL_DOCK_PLACEHOLDER(gdl_dock_placeholder_new(
112  "ph2", GDL_DOCK_OBJECT(dock_.gobj()), GDL_DOCK_BOTTOM, FALSE));
113  dockPlaceholders_[2] = GDL_DOCK_PLACEHOLDER(gdl_dock_placeholder_new(
114  "ph3", GDL_DOCK_OBJECT(dock_.gobj()), GDL_DOCK_LEFT, FALSE));
115  dockPlaceholders_[3] = GDL_DOCK_PLACEHOLDER(gdl_dock_placeholder_new(
116  "ph4", GDL_DOCK_OBJECT(dock_.gobj()), GDL_DOCK_RIGHT, FALSE));
117  ENSURE(dockPlaceholders_[0] && dockPlaceholders_[1] &&
118  dockPlaceholders_[2] && dockPlaceholders_[3]);
119 
120  createPanels();
121  }
122 
123 
124  Gdl::Dock&
125  DockArea::getDock()
126  {
127  return dock_;
128  }
129 
130 
131  Gdl::DockBar&
132  DockArea::getDockBar()
133  {
134  return dockBar_;
135  }
136 
137 
139  DockArea::getWorkspaceWindow()
140  {
141  return workspaceWindow_;
142  }
143 
144 
145  bool
146  DockArea::hasPanel (const int description_index)
147  {
148  return util::has_any (panels_, [=](panel::Panel* panel)
149  {
150  return getPanelType(panel) == description_index;
151  });
152  }
153 
154  panel::Panel&
155  DockArea::showPanel (const int description_index)
156  {
157  // Try and find the panel and present it if possible
158  list< panel::Panel* >::iterator i;
159  for(i = panels_.begin(); i != panels_.end(); i++)
160  {
161  panel::Panel* const panel = *i;
162  if (getPanelType(panel) == description_index)
163  {
164  if (!panel->is_shown()) panel->show();
165 
166  Gdl::DockItem &dock_item = panel->getDockItem();
167  // ENSURE(dock_item);
168  dock_item.present(dock_);
169  ENSURE (panel);
170  return *panel;
171  }
172  }
173 
174  // Create the new panel
175  panel::Panel *new_panel = createPanel_by_index (description_index);
176 
177  // Dock the item
178  dock_.add_item(new_panel->getDockItem(), Gdl::DOCK_FLOATING);
179 
180  ENSURE (new_panel);
181  return *new_panel;
182  }
183 
184 
185  void
186  DockArea::switchPanel (panel::Panel& old_panel, const int description_index)
187  {
188  REQUIRE (description_index >= 0 &&
189  description_index < getPanelDescriptionCount());
190 
191  // Get the dock item
192  Gdl::DockItem &dock_item = old_panel.getDockItem();
193 
194  // Release the old panel
195  removePanel (&old_panel);
196 
197  // Create the new panel
198  createPanel_by_index (description_index, dock_item);
199  }
200 
201 
202  void
203  DockArea::splitPanel (panel::Panel& panel, Gtk::Orientation split_direction)
204  {
205 
206  // Create the new panel
207  const int index = getPanelType(&panel);
208  panel::Panel *new_panel = createPanel_by_index(index);
209 
210  // Dock the panel
211  Gdl::DockPlacement placement = Gdl::DOCK_NONE;
212  switch(split_direction)
213  {
214  case ORIENTATION_HORIZONTAL:
215  placement = Gdl::DOCK_RIGHT;
216  break;
217 
218  case ORIENTATION_VERTICAL:
219  placement = Gdl::DOCK_BOTTOM;
220  break;
221 
222  default:
223  ERROR(stage, "Unknown split_direction: %d", split_direction);
224  return;
225  break;
226  }
227 
228  panel.getDockItem().dock(
229  new_panel->getDockItem(),placement);
230  }
231 
232 
233  int
234  DockArea::getPanelDescriptionCount()
235  {
236  return sizeof(panelDescriptionList) / sizeof(PanelDescription);
237  }
238 
239 
240  const gchar*
241  DockArea::getPanelStockID (int index)
242  {
243  REQUIRE (index >= 0 && index < getPanelDescriptionCount());
244  return panelDescriptionList[index].getStockID();
245  }
246 
247 
248  const char*
249  DockArea::getPanelTitle (int index)
250  {
251  REQUIRE (index >= 0 && index < getPanelDescriptionCount());
252  return panelDescriptionList[index].getTitle();
253  }
254 
255 
256  void
257  DockArea::createPanels()
258  {
260  panel::Panel* assetsPanel = createPanel_by_name("AssetsPanel");
261  panel::Panel* viewerPanel = createPanel_by_name("InfoBoxPanel");
262  panel::Panel* timelinePanel = createPanel_by_name("TimelinePanel");
263 
264  dock_.add_item(assetsPanel->getDockItem(),Gdl::DOCK_LEFT);
265  dock_.add_item(timelinePanel->getDockItem(),Gdl::DOCK_BOTTOM);
266  dock_.add_item(viewerPanel->getDockItem(),Gdl::DOCK_RIGHT);
267  }
268 
269 
270  int
271  DockArea::findPanelDescription (const char* class_name)
272  {
273  REQUIRE(class_name);
274 
275  const int count = getPanelDescriptionCount();
276  for(int i = 0; i < count; i++)
277  {
278  if (strstr(panelDescriptionList[i].getClassName(), class_name))
279  return i;
280  }
281 
282  ERROR (stage, "Unable to find a description with class name %s", class_name);
283  return -1;
284  }
285 
286 
287  panel::Panel*
288  DockArea::createPanel_by_index (const int index)
289  {
290  REQUIRE(index >= 0 && index < getPanelDescriptionCount());
291 
292  // Make a unique name for the panel
293  char name[5];
294  snprintf(name, sizeof(name), "%X", panelID++);
295 
296  // Create a dock item
297  return createPanel_by_index(index,
298  *new Gdl::DockItem(name,"",Gdl::DOCK_ITEM_BEH_NORMAL));
299  }
300 
301 
302  panel::Panel*
303  DockArea::createPanel_by_index (const int index, Gdl::DockItem &dock_item)
304  {
305  // Create the panel object
306  panel::Panel *panel = panelDescriptionList[index].create(*this, dock_item);
307  ENSURE(panel);
308  panel->show_all();
309 
310  // Connect event handlers
311  panel->signal_hidePanel().connect(sigc::bind(
312  sigc::mem_fun(*this, &DockArea::on_panel_shown), panel));
313 
314  // Add the panel to the list
315  panels_.push_back(panel);
316 
317  return panel;
318  }
319 
320 
321  panel::Panel*
322  DockArea::createPanel_by_name (const char* class_name)
323  {
324  REQUIRE(class_name);
325  const int index = findPanelDescription(class_name);
326  return createPanel_by_index(index);
327  }
328 
329 
330  int
331  DockArea::getPanelType (panel::Panel* const panel) const
332  {
333  REQUIRE(panel);
334 
335  const type_info &info = typeid(*panel);
336  const int count = getPanelDescriptionCount();
337  for(int i = 0; i < count; i++)
338  {
339  if(info == panelDescriptionList[i].getClassInfo())
340  return i;
341  }
342 
343  ERROR(stage, "Unable to find a description with with this class type");
344  return -1;
345  }
346 
347 
348  void
349  DockArea::removePanel (panel::Panel* const panel)
350  {
351  REQUIRE(panel);
352 
353  list< panel::Panel* >::iterator i;
354  for(i = panels_.begin(); i != panels_.end(); i++)
355  {
356  if(*i == panel)
357  {
358  delete panel;
359  panels_.erase(i);
360  break;
361  }
362  }
363  }
364 
365 
366  void
367  DockArea::clearPanels()
368  {
370 
371  list< panel::Panel* >::iterator i;
372  for(i = panels_.begin(); i != panels_.end(); i++)
373  delete *i;
374  panels_.clear();
375  }
376 
377 
378  void
379  DockArea::on_panel_shown (panel::Panel* panel)
380  {
381  REQUIRE(panel);
382  if(panel->is_shown() || panel->is_iconified()) return;
383 
384  removePanel(panel);
385  }
386 
387 
388 
389 }}// namespace stage::workspace
Management of dockable panels within each top-level WorkspaceWindow.
Definition: trait.hpp:69
STL namespace.
This header is for including and configuring NoBug.
bool is_iconified() const
Definition: panel.cpp:122
void show(bool show=true)
Shows or hides the panel.
Definition: panel.cpp:101
A (dockable) panel to organise the assets of a project.
The base class for all dockable panels.
Definition: panel.hpp:49
Lumiera GTK UI implementation root.
Definition: guifacade.cpp:46
A class to describe and instantiate Panel types.
Definition: dock-area.hpp:241
A (dockable) panel to display and manage information and parameters.
The main Lumiera workspace window.
Definition of a dockable panel to hold the video viewers.
sigc::signal< void > & signal_hidePanel()
fires when the dock item gets hidden.
Definition: panel.cpp:160
Gdl::DockItem & getDockItem()
Definition: panel.cpp:95
Perform operations "for each element" of a collection.
ElementBoxWidget::Config::Qualifier name(string id)
define the name-ID displayed in the caption
A dockable container to hold a notebook of timeline displays.