Remove obsolete includes.
[synfig.git] / synfig-studio / src / gtkmm / dockable.cpp
1 /* === S Y N F I G ========================================================= */
2 /*!     \file dockable.cpp
3 **      \brief Template File
4 **
5 **      $Id$
6 **
7 **      \legal
8 **      Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley
9 **
10 **      This package is free software; you can redistribute it and/or
11 **      modify it under the terms of the GNU General Public License as
12 **      published by the Free Software Foundation; either version 2 of
13 **      the License, or (at your option) any later version.
14 **
15 **      This package is distributed in the hope that it will be useful,
16 **      but WITHOUT ANY WARRANTY; without even the implied warranty of
17 **      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 **      General Public License for more details.
19 **      \endlegal
20 */
21 /* ========================================================================= */
22
23 /* === H E A D E R S ======================================================= */
24
25 #ifdef USING_PCH
26 #       include "pch.h"
27 #else
28 #ifdef HAVE_CONFIG_H
29 #       include <config.h>
30 #endif
31
32 #include "app.h"
33 #include <sigc++/hide.h>
34
35 #include "dockable.h"
36 #include "dockmanager.h"
37 #include "dockbook.h"
38 #include "dockdialog.h"
39 #include <synfig/general.h>
40 #include <gtkmm/table.h>
41
42 #include "general.h"
43
44 #endif
45
46 /* === U S I N G =========================================================== */
47
48 using namespace std;
49 using namespace etl;
50 using namespace synfig;
51 using namespace studio;
52
53 /* === M A C R O S ========================================================= */
54
55 #ifdef WIN32
56 #       ifdef IMAGE_DIR
57 #               undef IMAGE_DIR
58 #               define IMAGE_DIR "share\\pixmaps"
59 #       endif
60 #endif
61
62 #ifndef IMAGE_DIR
63 #       define IMAGE_DIR "/usr/local/share/pixmaps"
64 #endif
65
66 #ifndef IMAGE_EXT
67 #       define IMAGE_EXT        "png"
68 #endif
69
70 /* === G L O B A L S ======================================================= */
71
72 /* === P R O C E D U R E S ================================================= */
73
74 /* === M E T H O D S ======================================================= */
75
76 Dockable::Dockable(const synfig::String& name,const synfig::String& local_name,Gtk::StockID stock_id_):
77 //      Gtk::Window(Gtk::WINDOW_TOPLEVEL),
78         name_(name),
79         local_name_(local_name),
80 //      dialog_settings(this,name),
81         title_label_(local_name,Gtk::ALIGN_LEFT),
82         stock_id_(stock_id_)
83 {
84         parent_=0;
85         scrolled_=0;
86
87         use_scrolled_=true;
88
89         //set_title(local_name);
90         //set_type_hint(Gdk::WINDOW_TYPE_HINT_UTILITY);
91
92
93         title_label_.show();
94
95         attach_dnd_to(title_label_);
96
97         //scrolled_.set_policy(Gtk::POLICY_AUTOMATIC,Gtk::POLICY_AUTOMATIC);
98         //scrolled_.show();
99         //scrolled_.set_shadow_type(Gtk::SHADOW_NONE);
100
101         toolbar_=0;
102         //button_box_.show();
103
104         Gtk::Table* table(this);
105
106         {
107                 title_label_.set_padding(0,0);
108                 Gtk::EventBox* event_box(manage(new Gtk::EventBox()));
109                 event_box->set_border_width(0);
110                 event_box->add(title_label_);
111                 //table->attach(*event_box, 0, 1, 0,1, Gtk::EXPAND|Gtk::FILL, Gtk::SHRINK|Gtk::FILL, 0, 0);
112
113                 header_box_.pack_start(*event_box);
114
115                 attach_dnd_to(*event_box);
116                 event_box->show();
117         //      event_box->set_events(Gdk::ALL_EVENTS_MASK); //!< \todo change this to only allow what is necessary for DnD
118
119
120                 Gtk::Button* bttn_close(manage(new Gtk::Button(_("X"))));
121                 //table->attach(*bttn_close, 1, 2, 0,1, Gtk::SHRINK|Gtk::FILL, Gtk::SHRINK|Gtk::FILL, 0, 0);
122                 header_box_.pack_end(*bttn_close,false,false);
123                 bttn_close->show();
124                 bttn_close->set_relief(Gtk::RELIEF_NONE);
125                 bttn_close->signal_clicked().connect(sigc::mem_fun(*this,&Dockable::detach));
126                 bttn_close->set_border_width(0);
127                 dynamic_cast<Gtk::Misc*>(bttn_close->get_child())->set_padding(0,0);
128         }
129
130         prev_widget_=manage(new Gtk::Label(" "));
131
132         //table->attach(header_box_, 0, 1, 0,1, Gtk::SHRINK|Gtk::FILL, Gtk::SHRINK|Gtk::FILL, 0, 0);
133         table->attach(*prev_widget_, 0, 1, 1,2, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
134         //table->attach(*toolbar_, 0, 1, 2,3, Gtk::EXPAND|Gtk::FILL, Gtk::SHRINK|Gtk::FILL, 0, 0);
135         set_toolbar(*manage(new Gtk::Toolbar));
136         table->show();
137
138         prev_widget_->show();
139
140         set_size_request(175,120);
141         //scrolled_.set_shadow_type(Gtk::SHADOW_NONE);
142
143 }
144
145 Dockable::~Dockable()
146 {
147         if(scrolled_)
148         {
149                 delete scrolled_;
150                 scrolled_=0;
151         }
152
153         /*if(App::dock_manager)try{
154                 App::dock_manager->unregister_dockable(*this);
155                 std::list<Dockable*>::iterator iter;
156                 for(iter=App::dock_manager->dockable_list_.begin();iter!=App::dock_manager->dockable_list_.end();++iter)
157                         if(*iter==this)
158                         {
159                                 App::dock_manager->dockable_list_.erase(iter);
160                                 return;
161                         }
162         } catch(...) { }
163 */
164         //if(App::dock_manager)
165         //      App::dock_manager->dockable_list_.erase(this);
166 }
167
168 void
169 Dockable::attach_dnd_to(Gtk::Widget& widget)
170 {
171         std::list<Gtk::TargetEntry> listTargets;
172         listTargets.push_back( Gtk::TargetEntry("DOCK") );
173
174         widget.drag_source_set(listTargets);
175         widget.drag_source_set_icon(get_stock_id());
176         widget.drag_dest_set(listTargets);
177
178
179         widget.signal_drag_data_get().connect(sigc::mem_fun(*this,&Dockable::on_drag_data_get));
180         widget.signal_drag_end().connect(sigc::mem_fun(*this,&Dockable::on_drag_end));
181         widget.signal_drag_begin().connect(sigc::mem_fun(*this,&Dockable::on_drag_begin));
182         widget.signal_drag_data_received().connect(sigc::mem_fun(*this,&Dockable::on_drag_data_received));
183 }
184
185 void
186 Dockable::on_drag_data_received(const Glib::RefPtr<Gdk::DragContext>& context, int, int, const Gtk::SelectionData& selection_data, guint, guint time)
187 {
188         if ((selection_data.get_length() >= 0) && (selection_data.get_format() == 8))
189         {
190                 Dockable& dockable(**reinterpret_cast<Dockable**>(const_cast<guint8*>(selection_data.get_data())));
191
192                 if(dockable.parent_ != parent_)
193                         parent_->add(dockable,parent_->page_num(*this));
194                 else
195                         parent_->reorder_child(dockable,parent_->page_num(*this));
196                 dockable.present();
197                 context->drag_finish(true, false, time);
198                 return;
199         }
200
201         context->drag_finish(false, false, time);
202 }
203
204 void
205 Dockable::on_drag_end(const Glib::RefPtr<Gdk::DragContext>&/*context*/)
206 {
207         if(!dnd_success_)
208         {
209                 detach();
210                 present();
211         }
212 }
213
214 void
215 Dockable::on_drag_begin(const Glib::RefPtr<Gdk::DragContext>&/*context*/)
216 {
217         dnd_success_=false;
218 }
219
220 void
221 Dockable::on_drag_data_get(const Glib::RefPtr<Gdk::DragContext>&, Gtk::SelectionData& selection_data, guint /*info*/, guint /*time*/)
222 {
223         Dockable* tmp(this);
224         dnd_success_=true;
225
226         selection_data.set(8, reinterpret_cast<const guchar*>(&tmp), 4);
227 }
228
229 void
230 Dockable::set_local_name(const synfig::String& local_name)
231 {
232         //set_title(local_name);
233         title_label_.set_text(local_name);
234 }
235
236 void
237 Dockable::clear()
238 {
239         //if(!toolbar_->children().empty())
240         //      toolbar_->children().clear();
241         set_toolbar(*manage(new Gtk::Toolbar));
242
243 }
244
245 void
246 Dockable::set_toolbar(Gtk::Toolbar& toolbar)
247 {
248         if(toolbar_)remove(*toolbar_);
249         toolbar_=0;
250         toolbar_=&toolbar;
251         if(toolbar_)
252         {
253                 attach(*toolbar_, 0, 1, 2,3, Gtk::EXPAND|Gtk::FILL, Gtk::SHRINK|Gtk::FILL, 0, 0);
254                 gtk_toolbar_set_icon_size(toolbar_->gobj(),GtkIconSize(1)/*GTK_ICON_SIZE_MENU*/);
255                 toolbar_->show();
256         }
257 }
258
259 bool
260 Dockable::clear_previous()
261 {
262         prev_widget_=0;
263         prev_widget_delete_connection.disconnect();
264         return false;
265 }
266
267 void
268 Dockable::add(Gtk::Widget& x)
269 {
270         if(prev_widget_)
271         {
272                 remove(*prev_widget_);
273                 //prev_widget_=0;
274                 clear_previous();
275         }
276
277         if(scrolled_)
278         {
279                 delete scrolled_;
280                 scrolled_=0;
281         }
282
283         if(use_scrolled_)
284         {
285                 scrolled_=new Gtk::ScrolledWindow;
286
287                 scrolled_->add(x);
288
289                 attach(*scrolled_, 0, 1, 1,2, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
290
291                 x.show();
292
293                 scrolled_->show();
294
295                 scrolled_->set_shadow_type(Gtk::SHADOW_NONE);
296                 scrolled_->set_policy(Gtk::POLICY_AUTOMATIC,Gtk::POLICY_AUTOMATIC);
297                 prev_widget_=scrolled_;
298         }
299         else
300         {
301                 attach(x, 0, 1, 1,2, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
302                 x.show();
303                 prev_widget_=&x;
304         }
305         prev_widget_delete_connection=prev_widget_->signal_delete_event().connect(
306                 sigc::hide(
307                         sigc::mem_fun(
308                                 *this,
309                                 &Dockable::clear_previous
310                         )
311                 )
312         );
313 }
314
315 Gtk::ToolButton*
316 Dockable::add_button(const Gtk::StockID& stock_id, const synfig::String& tooltip)
317 {
318         if(!toolbar_)
319                 set_toolbar(*manage(new Gtk::Toolbar));
320
321         //Gtk::IconSize iconsize(4);
322         //Gtk::IconSize iconsize(Gtk::IconSize::from_name("synfig-small_icon"));
323
324         Gtk::ToolButton* ret(manage(new Gtk::ToolButton(stock_id)));
325         //Gtk::Image* icon(manage(new Gtk::Image(stock_id,iconsize)));
326         //ret->add(*icon);
327         //ret->set_relief(Gtk::RELIEF_HALF);
328         //ret->set_relief(Gtk::RELIEF_NONE);
329         ret->set_label(tooltip);
330         if (toolbar_->get_tooltips_object())
331                 toolbar_->get_tooltips_object()->set_tip(*ret,tooltip);
332
333         ret->show();
334         //icon->show();
335         toolbar_->set_tooltips(true);
336
337         toolbar_->append(*ret);
338         //button_box_.pack_start(*ret,false,false);
339         //get_action_area()->pack_start(*ret,false,false);
340         //add_action_widget(*ret,1);
341         return ret;
342 }
343
344
345 void
346 Dockable::detach()
347 {
348         if(parent_)
349                 parent_->remove(*this);
350 }
351
352 void
353 Dockable::present()
354 {
355         if(parent_)
356         {
357                 parent_->set_current_page(parent_->page_num(*this));
358                 parent_->present();
359         }
360         else
361         {
362                 DockDialog* dock_dialog(new DockDialog());
363                 dock_dialog->get_dock_book().add(*this);
364                 //if(get_name()=="canvases")
365                 //      dock_dialog->set_composition_selector(true);
366                 dock_dialog->present();
367         }
368 }
369
370 Gtk::Widget*
371 Dockable::create_tab_label()
372 {
373         Gtk::EventBox* event_box(manage(new Gtk::EventBox()));
374
375         attach_dnd_to(*event_box);
376
377         {
378                 Gtk::StockID stock_id(get_stock_id());
379                 Gtk::StockItem item;
380
381                 // Check to make sure the icon is valid
382                 if(Gtk::Stock::lookup(stock_id,item))
383                 {
384                         Gtk::Image* icon(manage(new Gtk::Image(stock_id,Gtk::IconSize(4))));
385                         event_box->add(*icon);
386                         tooltips_.set_tip(*event_box,get_local_name());
387                         icon->show();
388                 }
389                 else
390                 {
391                         // Bad icon, try to make a label
392
393                         Glib::ustring text(get_local_name());
394
395                         Gtk::Label* label(manage(new Gtk::Label(text)));
396                         event_box->add(*label);
397                         label->show();
398                 }
399         }
400
401         return event_box;
402 }