1 /* === S Y N F I G ========================================================= */
2 /*! \file dockdialog.cpp
3 ** \brief Template File
8 ** Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley
9 ** Copyright (c) 2007 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.
22 /* ========================================================================= */
24 /* === H E A D E R S ======================================================= */
34 #include <sigc++/adaptors/hide.h>
36 #include "dockdialog.h"
38 #include "dockmanager.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>
55 /* === U S I N G =========================================================== */
59 using namespace synfig;
60 using namespace studio;
62 /* === M A C R O S ========================================================= */
64 #define GRAB_HINT_DATA(y,default) { \
66 if(synfigapp::Main::settings().get_value(String("pref.")+y+"_hints",x)) \
68 set_type_hint((Gdk::WindowTypeHint)atoi(x.c_str())); \
70 set_type_hint(default); \
74 /* === G L O B A L S ======================================================= */
76 /* === P R O C E D U R E S ================================================= */
78 /* === M E T H O D S ======================================================= */
80 DockDialog::DockDialog():
81 Gtk::Window(Gtk::WINDOW_TOPLEVEL)
83 composition_selector_=false;
89 widget_comp_select=new Widget_CompSelect();
91 // Give ourselves an ID that is most likely unique
92 set_id(synfig::UniqueID().get_uid()^reinterpret_cast<long>(this));
94 set_role(strprintf("dock_dialog_%d",get_id()));
98 Gdk::WINDOW_TYPE_HINT_NORMAL
100 Gdk::WINDOW_TYPE_HINT_UTILITY
103 set_keep_above(false);
105 //! \todo can we set dialog windows transient for all normal windows, not just the toolbox?
106 //! paragraph 3 of http://standards.freedesktop.org/wm-spec/1.3/ar01s07.html suggests we can
107 // this seems to have bad effects on KDE, so leave it disabled by default
108 if(getenv("SYNFIG_TRANSIENT_DIALOGS"))
109 set_transient_for(*App::toolbox);
112 //set_type_hint(Gdk::WINDOW_TYPE_HINT_UTILITY);
113 set_title("Dock Dialog");
115 // Register with the dock manager
116 App::dock_manager->dock_dialog_list_.push_back(this);
119 // connect our signals
120 signal_delete_event().connect(
122 sigc::mem_fun(*this,&DockDialog::close)
127 App::signal_canvas_view_focus().connect(
131 &DockDialog::refresh_accel_group
137 add_accel_group(App::ui_manager()->get_accel_group());
138 App::signal_present_all().connect(sigc::mem_fun0(*this,&DockDialog::present));
142 DockDialog::~DockDialog()
144 empty_sig.disconnect();
148 // Remove all of the dock books
149 for(;!dock_book_list.empty();dock_book_list.pop_front())
151 dock_book_list.front()->clear();
153 //! \fixme: UGLY HACK
154 // The following line really should be uncommented,
155 // but it causes crashes. Without it, a small
156 // memory hole is created--but at least it doesn't crash
157 // delete dock_book_list.front();
159 // Oddly enough, the following line should
160 // theoretically do the same thing after this
161 // class is destroyed, but it doesn't seem to
162 // cause a crash. It does, however, trigger this warning:
164 // A floating object was finalized. This means that someone
165 // called g_object_unref() on an object that had only a
166 // floating reference; the initial floating reference is not
167 // owned by anyone and must be removed with g_object_ref_sink().
169 // manage(dock_book_list.front());
172 // Remove us from the dock manager
173 if(App::dock_manager)try{
174 std::list<DockDialog*>::iterator iter;
175 for(iter=App::dock_manager->dock_dialog_list_.begin();iter!=App::dock_manager->dock_dialog_list_.end();++iter)
178 App::dock_manager->dock_dialog_list_.erase(iter);
184 synfig::warning("DockDialog::~DockDialog(): Exception thrown when trying to remove from dock manager...?");
187 delete widget_comp_select;
191 DockDialog::drop_on_prepend(const Glib::RefPtr<Gdk::DragContext>& context, int, int, const Gtk::SelectionData& selection_data, guint, guint time)
193 if ((selection_data.get_length() >= 0) && (selection_data.get_format() == 8))
195 Dockable& dockable(**reinterpret_cast<Dockable**>(const_cast<guint8*>(selection_data.get_data())));
196 prepend_dock_book()->add(dockable);
197 context->drag_finish(true, false, time);
201 context->drag_finish(false, false, time);
205 DockDialog::drop_on_append(const Glib::RefPtr<Gdk::DragContext>& context, int, int, const Gtk::SelectionData& selection_data, guint, guint time)
207 if ((selection_data.get_length() >= 0) && (selection_data.get_format() == 8))
209 Dockable& dockable(**reinterpret_cast<Dockable**>(const_cast<guint8*>(selection_data.get_data())));
210 append_dock_book()->add(dockable);
211 context->drag_finish(true, false, time);
215 context->drag_finish(false, false, time);
220 DockDialog::on_hide()
222 Gtk::Window::on_hide();
227 DockDialog::prepend_dock_book()
229 if(is_deleting)return 0;
231 dock_book_list.push_front(new DockBook);
232 last_dock_book=dock_book_list.front();
235 last_dock_book->signal_empty().connect(
237 sigc::mem_fun(*this,&DockDialog::erase_dock_book),
242 dock_book_sizes_.insert(dock_book_sizes_.begin(),225);
244 return last_dock_book;
248 DockDialog::append_dock_book()
250 if(is_deleting)return 0;
252 dock_book_list.push_back(new DockBook);
253 last_dock_book=dock_book_list.back();
254 last_dock_book->signal_empty().connect(
256 sigc::mem_fun(*this,&DockDialog::erase_dock_book),
260 last_dock_book->signal_changed().connect(
261 sigc::mem_fun(*this,&DockDialog::refresh_title)
263 last_dock_book->signal_changed().connect(
264 sigc::mem_fun(*this,&DockDialog::refresh_title)
266 dock_book_sizes_.push_back(225);
268 //last_dock_book->show();
270 return last_dock_book;
274 DockDialog::erase_dock_book(DockBook* dock_book)
276 if(is_deleting)return;
278 std::list<DockBook*>::iterator iter;
279 for(iter=dock_book_list.begin();iter!=dock_book_list.end();++iter)
282 dock_book_list.erase(iter);
284 if(dock_book_list.empty())
292 if(last_dock_book==dock_book)
293 last_dock_book=dock_book_list.front();
303 DockDialog::refresh()
305 // synfig::info("dock_book_list.size()=%d",dock_book_list.size());
308 if(dock_book_list.empty())
312 box=(manage(is_horizontal?(Gtk::Box*)new Gtk::HBox:(Gtk::Box*)new Gtk::VBox));
315 box->pack_start(*widget_comp_select,false,true);
317 Gtk::Button* append_button(manage(new Gtk::Button));
318 Gtk::Button* prepend_button(manage(new Gtk::Button));
320 std::list<Gtk::TargetEntry> listTargets;
321 listTargets.push_back( Gtk::TargetEntry("DOCK") );
323 append_button->drag_dest_set(listTargets);
324 prepend_button->drag_dest_set(listTargets);
326 append_button->signal_drag_data_received().connect(
327 sigc::mem_fun(*this,&DockDialog::drop_on_append)
330 prepend_button->signal_drag_data_received().connect(
331 sigc::mem_fun(*this,&DockDialog::drop_on_prepend)
334 box->pack_start(*prepend_button,false,true);
335 box->pack_end(*append_button,false,true);
337 //prepend_button->show();
338 //append_button->show();
341 if(dock_book_list.size()==1)
343 box->pack_start(get_dock_book(),true,true);
347 Gtk::Paned* parent(manage(is_horizontal?(Gtk::Paned*)new Gtk::HPaned:(Gtk::Paned*)new Gtk::VPaned));
349 panels_.push_back(parent);
351 if(panels_.size()<=dock_book_sizes_.size())
352 panels_.back()->set_position(dock_book_sizes_[panels_.size()-1]);
353 panels_.back()->property_position().signal_changed().connect(
354 sigc::mem_fun(*this,&DockDialog::rebuild_sizes)
357 parent->add1(*dock_book_list.front());
358 //dock_book_list.front()->show();
360 box->pack_start(*parent,true,true);
362 std::list<DockBook*>::iterator iter,next;
363 for(next=dock_book_list.begin(),next++,iter=next++;next!=dock_book_list.end();iter=next++)
365 Gtk::Paned* current(manage(is_horizontal?(Gtk::Paned*)new Gtk::HPaned:(Gtk::Paned*)new Gtk::VPaned));
366 panels_.push_back(current);
368 if(panels_.size()<=dock_book_sizes_.size())
369 panels_.back()->set_position(dock_book_sizes_[panels_.size()-1]);
370 panels_.back()->property_position().signal_changed().connect(
371 sigc::mem_fun(*this,&DockDialog::rebuild_sizes)
375 parent->add2(*current);
377 current->add1(**iter);
383 parent->add2(**iter);
388 if(!composition_selector_)
389 widget_comp_select->hide();
394 DockDialog::rebuild_sizes()
397 dock_book_sizes_.clear();
398 for(i=0;i<panels_.size();i++)
400 dock_book_sizes_.push_back(panels_[i]->get_position());
405 DockDialog::set_dock_book_sizes(const std::vector<int>& new_sizes)
408 for(i=0;i<panels_.size() && i<new_sizes.size();i++)
410 panels_[i]->set_position(new_sizes[i]);
412 dock_book_sizes_=new_sizes;
417 DockDialog::refresh_accel_group()
420 if(last_accel_group_)
422 last_accel_group_->unlock();
423 remove_accel_group(last_accel_group_);
424 last_accel_group_=Glib::RefPtr<Gtk::AccelGroup>();
427 etl::loose_handle<CanvasView> canvas_view(App::get_selected_canvas_view());
430 last_accel_group_=canvas_view->get_accel_group();
431 last_accel_group_->lock();
432 add_accel_group(last_accel_group_);
435 etl::loose_handle<CanvasView> canvas_view(App::get_selected_canvas_view());
438 canvas_view->mainmenu.accelerate(*this);
445 synfig::info("DockDialog::close(): DELETED!");
446 empty_sig.disconnect();
447 //get_dock_book().clear();
453 DockDialog::get_dock_book()
456 return *append_dock_book();
457 return *last_dock_book;
461 DockDialog::get_dock_book()const
463 return *last_dock_book;
468 DockDialog::get_contents()const
472 std::list<DockBook*>::const_iterator iter;
473 for(iter=dock_book_list.begin();iter!=dock_book_list.end();++iter)
476 ret+=is_horizontal?" | ":" - ";
477 ret+=(*iter)->get_contents();
485 DockDialog::set_contents(const synfig::String& z)
490 synfig::String str(z);
493 synfig::String::size_type separator=str.find_first_of('-');
495 synfig::String::size_type sep2=str.find_first_of('|');
496 if(separator!=synfig::String::npos || sep2!=synfig::String::npos)
498 if((separator==synfig::String::npos || sep2<separator) && sep2!=synfig::String::npos)
508 synfig::String book_contents;
509 if(separator==synfig::String::npos)
516 book_contents=String(str.begin(),str.begin()+separator);
517 str=String(str.begin()+separator+1,str.end());
522 append_dock_book()->set_contents(book_contents);
530 DockDialog::set_composition_selector(bool x)
532 if(x==get_composition_selector())
534 composition_selector_=x;
536 widget_comp_select->show();
538 widget_comp_select->hide();
542 DockDialog::refresh_title()
544 if(is_deleting)return;
545 if(dock_book_list.size())
547 synfig::String title;
549 std::list<DockBook*>::const_iterator iter;
550 for(iter=dock_book_list.begin();iter!=dock_book_list.end();++iter)
554 title+=(*iter)->get_local_contents();
559 set_title(_("Empty Dock Dialog"));