Put a space between the parameter name and its description when prompting for it.
[synfig.git] / synfig-studio / trunk / src / gtkmm / dockdialog.cpp
blob614e8dbb0c1edf122327edb6ddc309d64a8f60e1
1 /* === S Y N F I G ========================================================= */
2 /*! \file dockdialog.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
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.
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
22 /* ========================================================================= */
24 /* === H E A D E R S ======================================================= */
26 #ifdef USING_PCH
27 # include "pch.h"
28 #else
29 #ifdef HAVE_CONFIG_H
30 # include <config.h>
31 #endif
33 #include "app.h"
34 #include <sigc++/adaptors/hide.h>
36 #include "dockdialog.h"
37 #include "dockbook.h"
38 #include "dockmanager.h"
39 #include "toolbox.h"
40 #include "widget_compselect.h"
41 #include <synfig/general.h>
42 #include <synfig/uniqueid.h>
43 #include <gtkmm/table.h>
44 #include <sigc++/hide.h>
45 #include <sigc++/slot.h>
46 #include <sigc++/retype_return.h>
47 #include <sigc++/retype.h>
48 #include "canvasview.h"
49 #include <gtkmm/paned.h>
50 #include <gtkmm/box.h>
51 #include <synfigapp/main.h>
53 #include "general.h"
55 #endif
57 /* === U S I N G =========================================================== */
59 using namespace std;
60 using namespace etl;
61 using namespace synfig;
62 using namespace studio;
64 /* === M A C R O S ========================================================= */
66 #define GRAB_HINT_DATA(y,default) { \
67 String x; \
68 if(synfigapp::Main::settings().get_value(String("pref.")+y+"_hints",x)) \
69 { \
70 set_type_hint((Gdk::WindowTypeHint)atoi(x.c_str())); \
71 } else {\
72 set_type_hint(default); \
73 } \
76 /* === G L O B A L S ======================================================= */
78 /* === P R O C E D U R E S ================================================= */
80 /* === M E T H O D S ======================================================= */
82 DockDialog::DockDialog():
83 Gtk::Window(Gtk::WINDOW_TOPLEVEL)
85 composition_selector_=false;
86 is_deleting=false;
87 is_horizontal=false;
88 last_dock_book=0;
89 box=0;
91 widget_comp_select=new Widget_CompSelect();
93 // Give ourselves an ID that is most likely unique
94 set_id(synfig::UniqueID().get_uid()^reinterpret_cast<long>(this));
96 set_role(strprintf("dock_dialog_%d",get_id()));
97 GRAB_HINT_DATA(
98 "dock_dialog",
99 #ifdef __APPLE__
100 Gdk::WINDOW_TYPE_HINT_NORMAL
101 #else
102 Gdk::WINDOW_TYPE_HINT_UTILITY
103 #endif
105 set_keep_above(false);
107 //! \todo can we set dialog windows transient for all normal windows, not just the toolbox?
108 //! paragraph 3 of http://standards.freedesktop.org/wm-spec/1.3/ar01s07.html suggests we can
109 // this seems to have bad effects on KDE, so leave it disabled by default
110 if(getenv("SYNFIG_TRANSIENT_DIALOGS"))
111 set_transient_for(*App::toolbox);
113 // Set up the window
114 //set_type_hint(Gdk::WINDOW_TYPE_HINT_UTILITY);
115 set_title(_("Dock Panel"));
117 // Register with the dock manager
118 App::dock_manager->dock_dialog_list_.push_back(this);
121 // connect our signals
122 signal_delete_event().connect(
123 sigc::hide(
124 sigc::mem_fun(*this,&DockDialog::close)
129 App::signal_canvas_view_focus().connect(
130 sigc::hide(
131 sigc::mem_fun(
132 *this,
133 &DockDialog::refresh_accel_group
139 add_accel_group(App::ui_manager()->get_accel_group());
140 App::signal_present_all().connect(sigc::mem_fun0(*this,&DockDialog::present));
144 DockDialog::~DockDialog()
146 empty_sig.disconnect();
148 is_deleting=true;
150 // Remove all of the dock books
151 for(;!dock_book_list.empty();dock_book_list.pop_front())
153 dock_book_list.front()->clear();
155 //! \todo Fix this UGLY HACK
156 // The following line really should be uncommented,
157 // but it causes crashes. Without it, a small
158 // memory hole is created--but at least it doesn't crash
159 // delete dock_book_list.front();
161 // Oddly enough, the following line should
162 // theoretically do the same thing after this
163 // class is destroyed, but it doesn't seem to
164 // cause a crash. It does, however, trigger this warning:
166 // A floating object was finalized. This means that someone
167 // called g_object_unref() on an object that had only a
168 // floating reference; the initial floating reference is not
169 // owned by anyone and must be removed with g_object_ref_sink().
171 // manage(dock_book_list.front());
174 // Remove us from the dock manager
175 if(App::dock_manager)try{
176 std::list<DockDialog*>::iterator iter;
177 for(iter=App::dock_manager->dock_dialog_list_.begin();iter!=App::dock_manager->dock_dialog_list_.end();++iter)
178 if(*iter==this)
180 App::dock_manager->dock_dialog_list_.erase(iter);
181 break;
184 catch(...)
186 synfig::warning("DockDialog::~DockDialog(): Exception thrown when trying to remove from dock manager...?");
189 delete widget_comp_select;
192 void
193 DockDialog::drop_on_prepend(const Glib::RefPtr<Gdk::DragContext>& context, int, int, const Gtk::SelectionData& selection_data, guint, guint time)
195 if ((selection_data.get_length() >= 0) && (selection_data.get_format() == 8))
197 Dockable& dockable(**reinterpret_cast<Dockable**>(const_cast<guint8*>(selection_data.get_data())));
198 prepend_dock_book()->add(dockable);
199 context->drag_finish(true, false, time);
200 return;
203 context->drag_finish(false, false, time);
206 void
207 DockDialog::drop_on_append(const Glib::RefPtr<Gdk::DragContext>& context, int, int, const Gtk::SelectionData& selection_data, guint, guint time)
209 if ((selection_data.get_length() >= 0) && (selection_data.get_format() == 8))
211 Dockable& dockable(**reinterpret_cast<Dockable**>(const_cast<guint8*>(selection_data.get_data())));
212 append_dock_book()->add(dockable);
213 context->drag_finish(true, false, time);
214 return;
217 context->drag_finish(false, false, time);
221 void
222 DockDialog::on_hide()
224 Gtk::Window::on_hide();
225 close();
228 DockBook*
229 DockDialog::prepend_dock_book()
231 if(is_deleting)return 0;
233 dock_book_list.push_front(new DockBook);
234 last_dock_book=dock_book_list.front();
237 last_dock_book->signal_empty().connect(
238 sigc::bind(
239 sigc::mem_fun(*this,&DockDialog::erase_dock_book),
240 last_dock_book
244 dock_book_sizes_.insert(dock_book_sizes_.begin(),225);
245 refresh();
246 return last_dock_book;
249 DockBook*
250 DockDialog::append_dock_book()
252 if(is_deleting)return 0;
254 dock_book_list.push_back(new DockBook);
255 last_dock_book=dock_book_list.back();
256 last_dock_book->signal_empty().connect(
257 sigc::bind(
258 sigc::mem_fun(*this,&DockDialog::erase_dock_book),
259 last_dock_book
262 last_dock_book->signal_changed().connect(
263 sigc::mem_fun(*this,&DockDialog::refresh_title)
265 last_dock_book->signal_changed().connect(
266 sigc::mem_fun(*this,&DockDialog::refresh_title)
268 dock_book_sizes_.push_back(225);
270 //last_dock_book->show();
271 refresh();
272 return last_dock_book;
275 void
276 DockDialog::erase_dock_book(DockBook* dock_book)
278 if(is_deleting)return;
280 std::list<DockBook*>::iterator iter;
281 for(iter=dock_book_list.begin();iter!=dock_book_list.end();++iter)
282 if(*iter==dock_book)
284 dock_book_list.erase(iter);
286 if(dock_book_list.empty())
288 last_dock_book=0;
289 close();
290 return;
292 else
294 if(last_dock_book==dock_book)
295 last_dock_book=dock_book_list.front();
298 refresh();
300 return;
304 void
305 DockDialog::refresh()
307 // synfig::info("dock_book_list.size()=%d",dock_book_list.size());
308 //remove();
310 if(dock_book_list.empty())
311 return;
313 if(box)delete box;
314 box=(manage(is_horizontal?(Gtk::Box*)new Gtk::HBox:(Gtk::Box*)new Gtk::VBox));
315 add(*box);
317 box->pack_start(*widget_comp_select,false,true);
319 Gtk::Button* append_button(manage(new Gtk::Button));
320 Gtk::Button* prepend_button(manage(new Gtk::Button));
322 std::list<Gtk::TargetEntry> listTargets;
323 listTargets.push_back( Gtk::TargetEntry("DOCK") );
325 append_button->drag_dest_set(listTargets);
326 prepend_button->drag_dest_set(listTargets);
328 append_button->signal_drag_data_received().connect(
329 sigc::mem_fun(*this,&DockDialog::drop_on_append)
332 prepend_button->signal_drag_data_received().connect(
333 sigc::mem_fun(*this,&DockDialog::drop_on_prepend)
336 box->pack_start(*prepend_button,false,true);
337 box->pack_end(*append_button,false,true);
339 //prepend_button->show();
340 //append_button->show();
341 panels_.clear();
343 if(dock_book_list.size()==1)
345 box->pack_start(get_dock_book(),true,true);
347 else
349 Gtk::Paned* parent(manage(is_horizontal?(Gtk::Paned*)new Gtk::HPaned:(Gtk::Paned*)new Gtk::VPaned));
351 panels_.push_back(parent);
353 if(panels_.size()<=dock_book_sizes_.size())
354 panels_.back()->set_position(dock_book_sizes_[panels_.size()-1]);
355 panels_.back()->property_position().signal_changed().connect(
356 sigc::mem_fun(*this,&DockDialog::rebuild_sizes)
358 //parent->show();
359 parent->add1(*dock_book_list.front());
360 //dock_book_list.front()->show();
362 box->pack_start(*parent,true,true);
364 std::list<DockBook*>::iterator iter,next;
365 for(next=dock_book_list.begin(),next++,iter=next++;next!=dock_book_list.end();iter=next++)
367 Gtk::Paned* current(manage(is_horizontal?(Gtk::Paned*)new Gtk::HPaned:(Gtk::Paned*)new Gtk::VPaned));
368 panels_.push_back(current);
370 if(panels_.size()<=dock_book_sizes_.size())
371 panels_.back()->set_position(dock_book_sizes_[panels_.size()-1]);
372 panels_.back()->property_position().signal_changed().connect(
373 sigc::mem_fun(*this,&DockDialog::rebuild_sizes)
377 parent->add2(*current);
379 current->add1(**iter);
380 //(*iter)->show();
381 //current->show();
383 parent=current;
385 parent->add2(**iter);
386 //(*iter)->show();
389 box->show_all();
390 if(!composition_selector_)
391 widget_comp_select->hide();
392 rebuild_sizes();
395 void
396 DockDialog::rebuild_sizes()
398 unsigned int i=0;
399 dock_book_sizes_.clear();
400 for(i=0;i<panels_.size();i++)
402 dock_book_sizes_.push_back(panels_[i]->get_position());
406 void
407 DockDialog::set_dock_book_sizes(const std::vector<int>& new_sizes)
409 unsigned int i=0;
410 for(i=0;i<panels_.size() && i<new_sizes.size();i++)
412 panels_[i]->set_position(new_sizes[i]);
414 dock_book_sizes_=new_sizes;
415 //rebuild_sizes();
418 void
419 DockDialog::refresh_accel_group()
422 if(last_accel_group_)
424 last_accel_group_->unlock();
425 remove_accel_group(last_accel_group_);
426 last_accel_group_=Glib::RefPtr<Gtk::AccelGroup>();
429 etl::loose_handle<CanvasView> canvas_view(App::get_selected_canvas_view());
430 if(canvas_view)
432 last_accel_group_=canvas_view->get_accel_group();
433 last_accel_group_->lock();
434 add_accel_group(last_accel_group_);
437 etl::loose_handle<CanvasView> canvas_view(App::get_selected_canvas_view());
438 if(canvas_view)
440 canvas_view->mainmenu.accelerate(*this);
444 bool
445 DockDialog::close()
447 if (getenv("SYNFIG_DEBUG_DESTRUCTORS"))
448 synfig::info("DockDialog::close(): Deleted");
450 empty_sig.disconnect();
451 //get_dock_book().clear();
452 delete this;
453 return true;
456 DockBook&
457 DockDialog::get_dock_book()
459 if(!last_dock_book)
460 return *append_dock_book();
461 return *last_dock_book;
464 const DockBook&
465 DockDialog::get_dock_book()const
467 return *last_dock_book;
471 synfig::String
472 DockDialog::get_contents()const
474 synfig::String ret;
476 std::list<DockBook*>::const_iterator iter;
477 for(iter=dock_book_list.begin();iter!=dock_book_list.end();++iter)
479 if(!ret.empty())
480 ret+=is_horizontal?" | ":" - ";
481 ret+=(*iter)->get_contents();
485 return ret;
488 void
489 DockDialog::set_contents(const synfig::String& z)
491 int x,y;
492 get_size(x,y);
494 synfig::String str(z);
495 while(!str.empty())
497 synfig::String::size_type separator=str.find_first_of('-');
499 synfig::String::size_type sep2=str.find_first_of('|');
500 if(separator!=synfig::String::npos || sep2!=synfig::String::npos)
502 if((separator==synfig::String::npos || sep2<separator) && sep2!=synfig::String::npos)
504 separator=sep2;
505 is_horizontal=true;
507 else
508 is_horizontal=false;
512 synfig::String book_contents;
513 if(separator==synfig::String::npos)
515 book_contents=str;
516 str.clear();
518 else
520 book_contents=String(str.begin(),str.begin()+separator);
521 str=String(str.begin()+separator+1,str.end());
526 append_dock_book()->set_contents(book_contents);
527 }catch(...) { }
530 resize(x,y);
533 void
534 DockDialog::set_composition_selector(bool x)
536 if(x==get_composition_selector())
537 return;
538 composition_selector_=x;
539 if(x)
540 widget_comp_select->show();
541 else
542 widget_comp_select->hide();
545 void
546 DockDialog::refresh_title()
548 if(is_deleting)return;
549 if(dock_book_list.size())
551 synfig::String title;
553 std::list<DockBook*>::const_iterator iter;
554 for(iter=dock_book_list.begin();iter!=dock_book_list.end();++iter)
556 if(!title.empty())
557 title+=", ";
558 title+=(*iter)->get_local_contents();
560 set_title(title);
562 else
563 set_title(_("Empty Dock Panel"));