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