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