Allow PasteCanvas layers with unset canvas parameters to be exported.
[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, 2008 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 #include "general.h"
42
43 #endif
44
45 /* === U S I N G =========================================================== */
46
47 using namespace std;
48 using namespace etl;
49 using namespace synfig;
50 using namespace studio;
51
52 /* === M A C R O S ========================================================= */
53
54 /* === P R O C E D U R E S ================================================= */
55
56 class studio::DockSettings : public synfigapp::Settings
57 {
58         DockManager* dock_manager;
59
60 public:
61         DockSettings(DockManager* dock_manager):dock_manager(dock_manager)
62         {
63                 synfigapp::Main::settings().add_domain(this,"dock");
64         }
65
66         virtual ~DockSettings()
67         {
68                 synfigapp::Main::settings().remove_domain("dock");
69         }
70 #define SCALE_FACTOR    (1280)
71         virtual bool get_value(const synfig::String& key_, synfig::String& value)const
72         {
73                 int screen_w(Gdk::screen_width());
74                 int screen_h(Gdk::screen_height());
75
76                 if(key_.size()>6 && String(key_.begin(),key_.begin()+6)=="dialog")try
77                 {
78                         synfig::String key(key_.begin()+7,key_.end());
79                         synfig::String::size_type separator=key.find_first_of('.');
80                         int id(atoi(synfig::String(key.begin(),key.begin()+separator).c_str()));
81                         key=synfig::String(key.begin()+separator+1,key.end());
82
83                         DockDialog& dock_dialog(dock_manager->find_dock_dialog(id));
84
85                         if(key=="contents_size")
86                         {
87                                 dock_dialog.rebuild_sizes();
88                                 vector<int>::const_iterator iter(dock_dialog.get_dock_book_sizes().begin());
89                                 vector<int>::const_iterator end(dock_dialog.get_dock_book_sizes().end());
90                                 value.clear();
91                                 for(;iter!=end;++iter)
92                                         value+=strprintf("%d ",(*iter)*SCALE_FACTOR/screen_h);
93                                 return true;
94                         }
95                         if(key=="pos")
96                         {
97                                 int x,y; dock_dialog.get_position(x,y);
98                                 value=strprintf("%d %d",x*SCALE_FACTOR/screen_w,y*SCALE_FACTOR/screen_h);
99                                 return true;
100                         }
101                         if(key=="size")
102                         {
103                                 int x,y; dock_dialog.get_size(x,y);
104                                 value=strprintf("%d %d",x*SCALE_FACTOR/screen_w,y*SCALE_FACTOR/screen_h);
105                                 return true;
106                         }
107                         if(key=="contents")
108                         {
109                                 value=dock_dialog.get_contents();
110                                 return true;
111                         }
112                         if(key=="comp_selector")
113                         {
114                                 value=dock_dialog.get_composition_selector()?"1":"0";
115                                 return true;
116                         }
117                 }catch (...) { return false; }
118                 return synfigapp::Settings::get_value(key_,value);
119         }
120
121         virtual bool set_value(const synfig::String& key_,const synfig::String& value)
122         {
123                 int screen_w(Gdk::screen_width());
124                 int screen_h(Gdk::screen_height());
125
126                 if(key_.size()>6 && String(key_.begin(),key_.begin()+6)=="dialog")
127                 {
128                         synfig::String key(key_.begin()+7,key_.end());
129                         synfig::String::size_type separator=key.find_first_of('.');
130                         int id(atoi(synfig::String(key.begin(),key.begin()+separator).c_str()));
131                         key=synfig::String(key.begin()+separator+1,key.end());
132
133                         DockDialog& dock_dialog(dock_manager->find_dock_dialog(id));
134
135                         if(key=="contents_size")
136                         {
137                                 try {
138                                 int width, height;
139                                 Gtk::IconSize::lookup(Gtk::IconSize(4),width,height);
140                                 vector<int> data;
141                                 String::size_type n=0;
142                                 String value_(value);
143                                 while(value_.size() && value_.size()>n){
144                                         value_=String(value_.begin()+n,value_.end());
145                                         int size;
146                                         if(!strscanf(value_,"%d",&size))
147                                                 break;
148                                         if (size > SCALE_FACTOR) size = SCALE_FACTOR - 150;
149                                         if (size < 0) size = 0;
150                                         size=size*screen_h/SCALE_FACTOR;
151
152                                         // prevent errors like this, by allowing space for at least the dockable's icon:
153                                         // ** CRITICAL **: clearlooks_style_draw_box_gap: assertion `height >= -1' failed
154                                         if (size < height + 9) size = height + 9;
155
156                                         data.push_back(size);
157
158                                         n=value_.find(" ");
159                                         if(n==String::npos)
160                                                 break;
161                                         n++;
162                                 }
163                                 dock_dialog.set_dock_book_sizes(data);
164                                 }
165                                 catch(...)
166                                 {
167                                         synfig::error("Exception caught!!!");
168                                         return false;
169                                 }
170                                 return true;
171                         }
172                         if(key=="pos")
173                         {
174                                 int x,y;
175                                 if(!strscanf(value,"%d %d",&x, &y))
176                                         return false;
177                                 if (x > SCALE_FACTOR) x = SCALE_FACTOR - 150; if (x < 0) x = 0;
178                                 if (y > SCALE_FACTOR) y = SCALE_FACTOR - 150; if (y < 0) y = 0;
179                                 x=x*screen_w/SCALE_FACTOR;
180                                 y=y*screen_h/SCALE_FACTOR;
181                                 if(getenv("SYNFIG_WINDOW_POSITION_X_OFFSET"))
182                                         x += atoi(getenv("SYNFIG_WINDOW_POSITION_X_OFFSET"));
183                                 if(getenv("SYNFIG_WINDOW_POSITION_Y_OFFSET"))
184                                         y += atoi(getenv("SYNFIG_WINDOW_POSITION_Y_OFFSET"));
185                                 dock_dialog.move(x,y);
186                                 return true;
187                         }
188                         if(key=="size")
189                         {
190                                 int x,y;
191                                 if(!strscanf(value,"%d %d",&x, &y))
192                                         return false;
193                                 if (x > SCALE_FACTOR) x = 150; if (x < 0) x = 0;
194                                 if (y > SCALE_FACTOR) y = 150; if (y < 0) y = 0;
195                                 x=x*screen_w/SCALE_FACTOR;
196                                 y=y*screen_h/SCALE_FACTOR;
197                                 dock_dialog.set_default_size(x,y);
198                                 dock_dialog.resize(x,y);
199                                 return true;
200                         }
201                         if(key=="contents")
202                         {
203                                 dock_dialog.set_contents(value);
204                                 return true;
205                         }
206                         if(key=="comp_selector")
207                         {
208                                 if(value.empty() || value[0]=='0')
209                                         dock_dialog.set_composition_selector(false);
210                                 else
211                                         dock_dialog.set_composition_selector(true);
212                                 return true;
213                         }
214                 }
215                 return synfigapp::Settings::set_value(key_,value);
216         }
217
218         virtual KeyList get_key_list()const
219         {
220                 synfigapp::Settings::KeyList ret(synfigapp::Settings::get_key_list());
221
222                 std::list<DockDialog*>::const_iterator iter;
223                 for(iter=dock_manager->dock_dialog_list_.begin();iter!=dock_manager->dock_dialog_list_.end();++iter)
224                 {
225                         ret.push_back(strprintf("dialog.%d.contents",(*iter)->get_id()));
226                         ret.push_back(strprintf("dialog.%d.comp_selector",(*iter)->get_id()));
227                         ret.push_back(strprintf("dialog.%d.pos",(*iter)->get_id()));
228                         ret.push_back(strprintf("dialog.%d.size",(*iter)->get_id()));
229                         ret.push_back(strprintf("dialog.%d.contents_size",(*iter)->get_id()));
230                 }
231                 return ret;
232         }
233 };
234
235 /* === M E T H O D S ======================================================= */
236
237 DockManager::DockManager():
238         dock_settings(new DockSettings(this))
239 {
240 }
241
242 DockManager::~DockManager()
243 {
244         while(!dock_dialog_list_.empty())
245         {
246                 dock_dialog_list_.back()->close();
247         }
248         while(!dockable_list_.empty())
249         {
250                 Dockable* dockable(dockable_list_.back());
251                 // synfig::info("DockManager::~DockManager(): Deleting dockable \"%s\"",dockable->get_name().c_str());
252                 dockable_list_.pop_back();
253                 delete dockable;
254         }
255 }
256
257 void
258 DockManager::register_dockable(Dockable& x)
259 {
260         dockable_list_.push_back(&x);
261         // synfig::info("DockManager::register_dockable(): Registered dockable \"%s\"",dockable_list_.back()->get_name().c_str());
262         signal_dockable_registered()(&x);
263 }
264
265 bool
266 DockManager::unregister_dockable(Dockable& x)
267 {
268         std::list<Dockable*>::iterator iter;
269         for(iter=dockable_list_.begin();iter!=dockable_list_.end();++iter)
270         {
271                 if(&x==*iter)
272                 {
273                         x.detach();
274                         dockable_list_.erase(iter);
275                         synfig::info("DockManager::unregister_dockable(): \"%s\" has been Unregistered",x.get_name().c_str());
276                         return true;
277                 }
278         }
279         return false;
280 }
281
282 Dockable&
283 DockManager::find_dockable(const synfig::String& x)
284 {
285         std::list<Dockable*>::iterator iter;
286         for(iter=dockable_list_.begin();iter!=dockable_list_.end();++iter)
287                 if((*iter)->get_name()==x)
288                         return **iter;
289
290         throw std::runtime_error("DockManager::find_dockable(): not found");
291 }
292
293 void
294 DockManager::present(synfig::String x)
295 {
296         try
297         {
298                 find_dockable(x).present();
299         }
300         catch(...)
301         {
302         }
303 }
304
305 DockDialog&
306 DockManager::find_dock_dialog(int id)
307 {
308         std::list<DockDialog*>::iterator iter;
309         for(iter=dock_dialog_list_.begin();iter!=dock_dialog_list_.end();++iter)
310                 if((*iter)->get_id()==id)
311                         return **iter;
312
313         DockDialog* dock_dialog(new DockDialog());
314         dock_dialog->set_id(id);
315         dock_dialog->show();
316         return *dock_dialog;
317 }
318
319 const DockDialog&
320 DockManager::find_dock_dialog(int id)const
321 {
322         std::list<DockDialog*>::const_iterator iter;
323         for(iter=dock_dialog_list_.begin();iter!=dock_dialog_list_.end();++iter)
324                 if((*iter)->get_id()==id)
325                         return **iter;
326
327         throw std::runtime_error("DockManager::find_dock_dialog(int id)const: not found");
328 }