1 /* === S Y N F I G ========================================================= */
2 /*! \file dockbook.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 <synfig/general.h>
34
35 #include "docks/dockbook.h"
36 #include "docks/dockable.h"
37 #include "app.h"
38 #include "docks/dockmanager.h"
39 #include "docks/dockdroparea.h"
40
41 #include <gtkmm/image.h>
42 #include <gtkmm/eventbox.h>
43 #include <gtkmm/menu.h>
44 #include <gtkmm/imagemenuitem.h>
45
46 #include <gui/localization.h>
47
48 #include "canvasview.h"
49
50 #endif
51
52 /* === U S I N G =========================================================== */
53
54 using namespace std;
55 using namespace etl;
56 using namespace synfig;
57 using namespace studio;
58
59 /* === M A C R O S ========================================================= */
60
61 /* === G L O B A L S ======================================================= */
62
63 /* === P R O C E D U R E S ================================================= */
64
65 /* === M E T H O D S ======================================================= */
66
DockBook()67 DockBook::DockBook():
68 allow_empty(false)
69 {
70 std::vector<Gtk::TargetEntry> listTargets;
71 listTargets.push_back( Gtk::TargetEntry("SYNFIG_DOCK") );
72
73 drag_dest_set(listTargets);
74 //set_sensitive(true);
75 set_receives_default(true);
76 set_can_default(true);
77 //add_events(Gdk::ALL_EVENTS_MASK);
78 //set_extension_events(Gdk::EXTENSION_EVENTS_ALL);
79 set_show_tabs(true);
80 set_scrollable(true);
81 deleting_=false;
82
83 DockDropArea *dock_area = manage(new DockDropArea(this));
84 dock_area->show();
85 set_action_widget(dock_area, Gtk::PACK_END);
86 }
87
~DockBook()88 DockBook::~DockBook()
89 {
90 DockManager::containers_to_remove_.erase(this);
91 deleting_=true;
92 clear();
93 }
94
95 void
clear()96 DockBook::clear()
97 {
98 while(get_n_pages())
99 remove(static_cast<Dockable&>(*get_nth_page(get_n_pages()-1)));
100 }
101
102 void
on_drag_data_received(const Glib::RefPtr<Gdk::DragContext> & context,int,int,const Gtk::SelectionData & selection_data,guint,guint time)103 DockBook::on_drag_data_received(const Glib::RefPtr<Gdk::DragContext>& context, int, int, const Gtk::SelectionData& selection_data, guint, guint time)
104 {
105 if ((selection_data.get_length() >= 0) && (selection_data.get_format() == 8))
106 {
107 Dockable& dockable(**reinterpret_cast<Dockable**>(const_cast<guint8*>(selection_data.get_data())));
108 if(dockable.get_parent()!=this)
109 add(dockable);
110 dockable.present();
111 context->drag_finish(true, false, time);
112 return;
113 }
114
115 context->drag_finish(false, false, time);
116 }
117
118 void
add(Dockable & dockable,int position)119 DockBook::add(Dockable& dockable, int position)
120 {
121 DockManager::remove_widget_recursive(dockable);
122
123 if(position==-1)
124 append_page(dockable, " ");
125 else
126 insert_page(dockable, " ", position);
127
128 refresh_tab(&dockable);
129
130 dockable.signal_stock_id_changed().connect(
131 sigc::bind(
132 sigc::mem_fun(
133 *this,
134 &DockBook::refresh_tab
135 ),
136 &dockable
137 )
138 );
139
140 dockable.show();
141
142 signal_changed_();
143 }
144
145 void
refresh_tab(Dockable * dockable)146 DockBook::refresh_tab(Dockable* dockable)
147 {
148 Gtk::Widget* label(dockable->create_tab_label());
149
150 label->signal_button_press_event().connect(
151 sigc::bind(
152 sigc::mem_fun(
153 *this,
154 &DockBook::tab_button_pressed
155 ),
156 dockable
157 )
158 );
159
160 set_tab_label(*dockable, *label);
161 label->show();
162 }
163
164
165 void
remove(Dockable & dockable)166 DockBook::remove(Dockable& dockable)
167 {
168 dockable.hide();
169 remove_page(dockable);
170
171 if(!deleting_)
172 {
173 signal_changed_();
174
175 if(get_n_pages()==0)
176 signal_empty()();
177 }
178 }
179
180 void
present()181 DockBook::present()
182 {
183 show();
184 }
185
186 synfig::String
get_local_contents() const187 DockBook::get_local_contents()const
188 {
189 synfig::String ret;
190
191 for(int i(0);i!=const_cast<DockBook*>(this)->get_n_pages();i++)
192 {
193 Dockable& dockable(static_cast<Dockable&>(*const_cast<DockBook*>(this)->get_nth_page(i)));
194
195 if(i)
196 ret+=", ";
197 ret+=dockable.get_local_name();
198 }
199
200 return ret;
201 }
202
203 synfig::String
get_contents() const204 DockBook::get_contents()const
205 {
206 synfig::String ret;
207
208 for(int i(0);i!=const_cast<DockBook*>(this)->get_n_pages();i++)
209 {
210 Dockable& dockable(static_cast<Dockable&>(*const_cast<DockBook*>(this)->get_nth_page(i)));
211
212 if(i)
213 ret+=' ';
214 ret+=dockable.get_name();
215 }
216
217 return ret;
218 }
219
220 void
set_contents(const synfig::String & x)221 DockBook::set_contents(const synfig::String& x)
222 {
223 synfig::String str(x);
224 while(!str.empty())
225 {
226 synfig::String::size_type separator=str.find_first_of(' ');
227 synfig::String dock;
228 if(separator==synfig::String::npos)
229 {
230 dock=str;
231 str.clear();
232 }
233 else
234 {
235 dock=String(str.begin(),str.begin()+separator);
236 str=String(str.begin()+separator+1,str.end());
237 }
238
239 try
240 {
241 add(App::dock_manager->find_dockable(dock));
242 }catch(...) { }
243 }
244 }
245
246 bool
tab_button_pressed(GdkEventButton * event,Dockable * dockable)247 DockBook::tab_button_pressed(GdkEventButton* event, Dockable* dockable)
248 {
249 CanvasView *canvas_view = dynamic_cast<CanvasView*>(dockable);
250 if (canvas_view && canvas_view != App::get_selected_canvas_view())
251 App::set_selected_canvas_view(canvas_view);
252
253 if(event->button!=3)
254 return false;
255
256 Gtk::Menu *tabmenu=manage(new class Gtk::Menu());
257 tabmenu->signal_hide().connect(sigc::bind(sigc::ptr_fun(&delete_widget), tabmenu));
258
259 Gtk::MenuItem *item = manage(new Gtk::ImageMenuItem(Gtk::StockID("gtk-close")));
260 item->signal_activate().connect(
261 sigc::bind(sigc::ptr_fun(&DockManager::remove_widget_by_pointer_recursive), dockable) );
262
263 tabmenu->append(*item);
264 item->show();
265 tabmenu->popup(event->button,gtk_get_current_event_time());
266
267 return true;
268 }
269
270 void
on_switch_page(Gtk::Widget * page,guint page_num)271 DockBook::on_switch_page(Gtk::Widget* page, guint page_num)
272 {
273 if (page != NULL && this->page_num(*page)) {
274 CanvasView *canvas_view = dynamic_cast<CanvasView*>(page);
275 if (canvas_view && canvas_view != App::get_selected_canvas_view())
276 App::set_selected_canvas_view(canvas_view);
277 }
278 Notebook::on_switch_page(page, page_num);
279 }
280