Prevent the "** CRITICAL **: clearlooks_style_draw_box_gap: assertion `height >=...
[synfig.git] / synfig-studio / trunk / src / gtkmm / dockmanager.cpp
1 /* === S Y N F I G ========================================================= */
2 /*!     \file dockmanager.cpp
3 **      \brief Template File
4 **
5 **      $Id$
6 **
7 **      \legal
8 **      Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley
9 **      Copyright (c) 2007 Chris Moore
10 **
11 **      This package is free software; you can redistribute it and/or
12 **      modify it under the terms of the GNU General Public License as
13 **      published by the Free Software Foundation; either version 2 of
14 **      the License, or (at your option) any later version.
15 **
16 **      This package is distributed in the hope that it will be useful,
17 **      but WITHOUT ANY WARRANTY; without even the implied warranty of
18 **      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 **      General Public License for more details.
20 **      \endlegal
21 */
22 /* ========================================================================= */
23
24 /* === H E A D E R S ======================================================= */
25
26 #ifdef USING_PCH
27 #       include "pch.h"
28 #else
29 #ifdef HAVE_CONFIG_H
30 #       include <config.h>
31 #endif
32
33 #include "dockmanager.h"
34 #include <stdexcept>
35 #include "dockable.h"
36 #include "dockdialog.h"
37 #include <synfigapp/settings.h>
38 #include <synfigapp/main.h>
39 #include <gdkmm/general.h>
40
41 #endif
42
43 /* === U S I N G =========================================================== */
44
45 using namespace std;
46 using namespace etl;
47 using namespace synfig;
48 using namespace studio;
49
50 /* === M A C R O S ========================================================= */
51
52 /* === P R O C E D U R E S ================================================= */
53
54 class studio::DockSettings : public synfigapp::Settings
55 {
56         DockManager* dock_manager;
57
58 public:
59         DockSettings(DockManager* dock_manager):dock_manager(dock_manager)
60         {
61                 synfigapp::Main::settings().add_domain(this,"dock");
62         }
63
64         virtual ~DockSettings()
65         {
66                 synfigapp::Main::settings().remove_domain("dock");
67         }
68 #define SCALE_FACTOR    (1280)
69         virtual bool get_value(const synfig::String& key_, synfig::String& value)const
70         {
71                 int screen_w(Gdk::screen_width());
72                 int screen_h(Gdk::screen_height());
73
74                 if(key_.size()>6 && String(key_.begin(),key_.begin()+6)=="dialog")try
75                 {
76                         synfig::String key(key_.begin()+7,key_.end());
77                         synfig::String::size_type separator=key.find_first_of('.');
78                         int id(atoi(synfig::String(key.begin(),key.begin()+separator).c_str()));
79                         key=synfig::String(key.begin()+separator+1,key.end());
80
81                         DockDialog& dock_dialog(dock_manager->find_dock_dialog(id));
82
83                         if(key=="contents_size")
84                         {
85                                 dock_dialog.rebuild_sizes();
86                                 vector<int>::const_iterator iter(dock_dialog.get_dock_book_sizes().begin());
87                                 vector<int>::const_iterator end(dock_dialog.get_dock_book_sizes().end());
88                                 value.clear();
89                                 for(;iter!=end;++iter)
90                                         value+=strprintf("%d ",(*iter)*SCALE_FACTOR/screen_h);
91                                 return true;
92                         }
93                         if(key=="pos")
94                         {
95                                 int x,y; dock_dialog.get_position(x,y);
96                                 value=strprintf("%d %d",x*SCALE_FACTOR/screen_w,y*SCALE_FACTOR/screen_h);
97                                 return true;
98                         }
99                         if(key=="size")
100                         {
101                                 int x,y; dock_dialog.get_size(x,y);
102                                 value=strprintf("%d %d",x*SCALE_FACTOR/screen_w,y*SCALE_FACTOR/screen_h);
103                                 return true;
104                         }
105                         if(key=="contents")
106                         {
107                                 value=dock_dialog.get_contents();
108                                 return true;
109                         }
110                         if(key=="comp_selector")
111                         {
112                                 value=dock_dialog.get_composition_selector()?"1":"0";
113                                 return true;
114                         }
115                 }catch (...) { return false; }
116                 return synfigapp::Settings::get_value(key_,value);
117         }
118
119         virtual bool set_value(const synfig::String& key_,const synfig::String& value)
120         {
121                 int screen_w(Gdk::screen_width());
122                 int screen_h(Gdk::screen_height());
123
124                 if(key_.size()>6 && String(key_.begin(),key_.begin()+6)=="dialog")
125                 {
126                         synfig::String key(key_.begin()+7,key_.end());
127                         synfig::String::size_type separator=key.find_first_of('.');
128                         int id(atoi(synfig::String(key.begin(),key.begin()+separator).c_str()));
129                         key=synfig::String(key.begin()+separator+1,key.end());
130
131                         DockDialog& dock_dialog(dock_manager->find_dock_dialog(id));
132
133                         if(key=="contents_size")
134                         {
135                                 try {
136                                 int width, height;
137                                 Gtk::IconSize::lookup(Gtk::IconSize(4),width,height);
138                                 vector<int> data;
139                                 String::size_type n=0;
140                                 String value_(value);
141                                 while(value_.size() && value_.size()>n){
142                                         value_=String(value_.begin()+n,value_.end());
143                                         int size;
144                                         if(!strscanf(value_,"%d",&size))
145                                                 break;
146                                         size=size*screen_h/SCALE_FACTOR;
147
148                                         // prevent errors like this, by allowing space for at least the dockable's icon:
149                                         // ** CRITICAL **: clearlooks_style_draw_box_gap: assertion `height >= -1' failed
150                                         if (size < height + 9) size = height + 9;
151
152                                         data.push_back(size);
153
154                                         n=value_.find(" ");
155                                         if(n==String::npos)
156                                                 break;
157                                         n++;
158                                 }
159                                 dock_dialog.set_dock_book_sizes(data);
160                                 }
161                                 catch(...)
162                                 {
163                                         synfig::error("Exception caught!!!");
164                                         return false;
165                                 }
166                                 return true;
167                         }
168                         if(key=="pos")
169                         {
170                                 int x,y;
171                                 if(!strscanf(value,"%d %d",&x, &y))
172                                         return false;
173                                 x=x*screen_w/SCALE_FACTOR;
174                                 y=y*screen_h/SCALE_FACTOR;
175                                 dock_dialog.move(x,y);
176                                 return true;
177                         }
178                         if(key=="size")
179                         {
180                                 int x,y;
181                                 if(!strscanf(value,"%d %d",&x, &y))
182                                         return false;
183                                 x=x*screen_w/SCALE_FACTOR;
184                                 y=y*screen_h/SCALE_FACTOR;
185                                 dock_dialog.set_default_size(x,y);
186                                 dock_dialog.resize(x,y);
187                                 return true;
188                         }
189                         if(key=="contents")
190                         {
191                                 dock_dialog.set_contents(value);
192                                 return true;
193                         }
194                         if(key=="comp_selector")
195                         {
196                                 if(value.empty() || value[0]=='0')
197                                         dock_dialog.set_composition_selector(false);
198                                 else
199                                         dock_dialog.set_composition_selector(true);
200                                 return true;
201                         }
202                 }
203                 return synfigapp::Settings::set_value(key_,value);
204         }
205
206         virtual KeyList get_key_list()const
207         {
208                 synfigapp::Settings::KeyList ret(synfigapp::Settings::get_key_list());
209
210                 std::list<DockDialog*>::const_iterator iter;
211                 for(iter=dock_manager->dock_dialog_list_.begin();iter!=dock_manager->dock_dialog_list_.end();++iter)
212                 {
213                         ret.push_back(strprintf("dialog.%d.contents",(*iter)->get_id()));
214                         ret.push_back(strprintf("dialog.%d.comp_selector",(*iter)->get_id()));
215                         ret.push_back(strprintf("dialog.%d.pos",(*iter)->get_id()));
216                         ret.push_back(strprintf("dialog.%d.size",(*iter)->get_id()));
217                         ret.push_back(strprintf("dialog.%d.contents_size",(*iter)->get_id()));
218                 }
219                 return ret;
220         }
221 };
222
223 /* === M E T H O D S ======================================================= */
224
225 DockManager::DockManager():
226         dock_settings(new DockSettings(this))
227 {
228 }
229
230 DockManager::~DockManager()
231 {
232         while(!dock_dialog_list_.empty())
233         {
234                 dock_dialog_list_.back()->close();
235         }
236         while(!dockable_list_.empty())
237         {
238                 Dockable* dockable(dockable_list_.back());
239                 // synfig::info("DockManager::~DockManager(): Deleting dockable \"%s\"",dockable->get_name().c_str());
240                 dockable_list_.pop_back();
241                 delete dockable;
242         }
243 }
244
245 void
246 DockManager::register_dockable(Dockable& x)
247 {
248         dockable_list_.push_back(&x);
249         // synfig::info("DockManager::register_dockable(): Registered dockable \"%s\"",dockable_list_.back()->get_name().c_str());
250         signal_dockable_registered()(&x);
251 }
252
253 bool
254 DockManager::unregister_dockable(Dockable& x)
255 {
256         std::list<Dockable*>::iterator iter;
257         for(iter=dockable_list_.begin();iter!=dockable_list_.end();++iter)
258         {
259                 if(&x==*iter)
260                 {
261                         x.detach();
262                         dockable_list_.erase(iter);
263                         synfig::info("DockManager::unregister_dockable(): \"%s\" has been Unregistered",x.get_name().c_str());
264                         return true;
265                 }
266         }
267         return false;
268 }
269
270 Dockable&
271 DockManager::find_dockable(const synfig::String& x)
272 {
273         std::list<Dockable*>::iterator iter;
274         for(iter=dockable_list_.begin();iter!=dockable_list_.end();++iter)
275                 if((*iter)->get_name()==x)
276                         return **iter;
277
278         throw std::runtime_error("DockManager::find_dockable(): not found");
279 }
280
281 void
282 DockManager::present(synfig::String x)
283 {
284         try
285         {
286                 find_dockable(x).present();
287         }
288         catch(...)
289         {
290         }
291 }
292
293 DockDialog&
294 DockManager::find_dock_dialog(int id)
295 {
296         std::list<DockDialog*>::iterator iter;
297         for(iter=dock_dialog_list_.begin();iter!=dock_dialog_list_.end();++iter)
298                 if((*iter)->get_id()==id)
299                         return **iter;
300
301         DockDialog* dock_dialog(new DockDialog());
302         dock_dialog->set_id(id);
303         dock_dialog->show();
304         return *dock_dialog;
305 }
306
307 const DockDialog&
308 DockManager::find_dock_dialog(int id)const
309 {
310         std::list<DockDialog*>::const_iterator iter;
311         for(iter=dock_dialog_list_.begin();iter!=dock_dialog_list_.end();++iter)
312                 if((*iter)->get_id()==id)
313                         return **iter;
314
315         throw std::runtime_error("DockManager::find_dock_dialog(int id)const: not found");
316 }