Add actions (add to group, ,remove from group, export, un-export, set layer descripti...
[synfig.git] / synfig-studio / src / gtkmm / layergrouptree.cpp
1 /* === S Y N F I G ========================================================= */
2 /*!     \file layergrouptree.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) 2008 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/layer.h>
34 #include "layergrouptree.h"
35 #include <gtkmm/treemodelsort.h>
36 #include <ETL/misc>
37
38 #include "general.h"
39
40 #endif
41
42 /* === U S I N G =========================================================== */
43
44 using namespace std;
45 using namespace etl;
46 using namespace synfig;
47 using namespace studio;
48
49 /* === M A C R O S ========================================================= */
50
51 /* === G L O B A L S ======================================================= */
52
53 /* === P R O C E D U R E S ================================================= */
54
55 /* === M E T H O D S ======================================================= */
56
57 LayerGroupTree::LayerGroupTree()
58 {
59         const LayerGroupTreeStore::Model model;
60
61
62         {       // --- O N / O F F ----------------------------------------------------
63                 int index;
64                 index=append_column_editable(_(" "),model.active);
65                 //Gtk::TreeView::Column* column = get_column(index-1);
66         }
67         {       // --- I C O N --------------------------------------------------------
68                 int index;
69                 index=append_column(_(" "),model.icon);
70                 Gtk::TreeView::Column* column = get_column(index-1);
71                 set_expander_column(*column);
72         }
73         {       // --- N A M E --------------------------------------------------------
74                 int index;
75                 index=append_column_editable(_("Name"),model.label);
76                 label_column = get_column(index-1);
77
78                 //column->set_sort_column(layer_model.index);
79
80                 //set_expander_column(*column);
81                 //column->set_reorderable();
82                 //column->set_resizable();
83                 //column->set_clickable(false);
84
85                 //Gtk::CellRendererPixbuf* icon_cellrenderer = Gtk::manage( new Gtk::CellRendererPixbuf() );
86                 //column->pack_start(*icon_cellrenderer,false);
87                 //column->add_attribute(icon_cellrenderer->property_pixbuf(), layer_model.icon);
88         }
89
90         set_enable_search(true);
91         set_search_column(model.label);
92         set_search_equal_func(sigc::ptr_fun(&studio::LayerGroupTreeStore::search_func));
93
94         // This makes things easier to read.
95         set_rules_hint();
96
97         // Make us more sensitive to several events
98         add_events(Gdk::BUTTON_PRESS_MASK | Gdk::BUTTON_RELEASE_MASK | Gdk::BUTTON1_MOTION_MASK | Gdk::BUTTON2_MOTION_MASK|Gdk::POINTER_MOTION_MASK);
99
100         set_reorderable(true);
101
102         get_selection()->set_mode(Gtk::SELECTION_MULTIPLE);
103
104         //set_flags(get_flags()|Gtk::RECEIVES_DEFAULT|Gtk::HAS_GRAB);
105
106         //std::list<Gtk::TargetEntry> listTargets;
107         //listTargets.push_back( Gtk::TargetEntry("LAYER") );
108         //listTargets.push_back( Gtk::TargetEntry("GROUP") );
109         //drag_dest_set(listTargets);
110 }
111
112 LayerGroupTree::~LayerGroupTree()
113 {
114         if (getenv("SYNFIG_DEBUG_DESTRUCTORS"))
115                 synfig::info("LayerGroupTree::~LayerGroupTree(): Deleted");
116 }
117
118 void
119 LayerGroupTree::set_model(Glib::RefPtr<LayerGroupTreeStore> layer_group_tree_store)
120 {
121         layer_group_tree_store_=layer_group_tree_store;
122         LayerGroupTreeStore::Model model;
123
124 #if 0
125         {
126                 Glib::RefPtr<Gtk::TreeModelSort> sorted_store(Gtk::TreeModelSort::create(layer_group_tree_store_));
127                 sorted_store->set_default_sort_func(sigc::ptr_fun(&studio::LayerGroupTreeStore::time_sorter));
128                 sorted_store->set_sort_func(model.time.index(),sigc::ptr_fun(&studio::LayerGroupTreeStore::time_sorter));
129                 sorted_store->set_sort_column(model.time.index(), Gtk::SORT_ASCENDING);
130                 Gtk::TreeView::set_model(sorted_store);
131         }
132 #else
133                 Gtk::TreeView::set_model(layer_group_tree_store);
134 #endif
135 }
136
137 void
138 LayerGroupTree::set_editable(bool x)
139 {
140         editable_=x;
141 /*
142         if(editable_)
143         {
144                 cell_renderer_time->property_editable()=true;
145                 cell_renderer_time_delta->property_editable()=true;
146                 cell_renderer_description->property_editable()=true;
147         }
148         else
149         {
150                 cell_renderer_time->property_editable()=false;
151                 cell_renderer_time_delta->property_editable()=false;
152                 cell_renderer_description->property_editable()=false;
153         }
154 */
155 }
156 /*
157 void
158 LayerGroupTree::on_edited_time(const Glib::ustring&path_string,synfig::Time time)
159 {
160         Gtk::TreePath path(path_string);
161
162         const Gtk::TreeRow row(*(get_model()->get_iter(path)));
163
164         synfig::Keyframe keyframe(row[model.keyframe]);
165         if(time!=keyframe.get_time())
166         {
167                 row[model.time]=time;
168                 //keyframe.set_time(time);
169                 //signal_edited_time()(keyframe,time);
170                 //signal_edited()(keyframe);
171         }
172 }
173
174 void
175 LayerGroupTree::on_edited_time_delta(const Glib::ustring&path_string,synfig::Time time)
176 {
177         Gtk::TreePath path(path_string);
178
179         const Gtk::TreeRow row(*(get_model()->get_iter(path)));
180
181         if(row)row[model.time_delta]=time;
182 }
183
184 void
185 LayerGroupTree::on_edited_description(const Glib::ustring&path_string,const Glib::ustring &desc)
186 {
187         Gtk::TreePath path(path_string);
188
189         const Gtk::TreeRow row = *(get_model()->get_iter(path));
190
191         const synfig::String description(desc);
192         synfig::Keyframe keyframe(row[model.keyframe]);
193         if(description!=keyframe.get_description())
194         {
195                 row[model.description]=desc;
196                 keyframe.set_description(description);
197                 signal_edited_description()(keyframe,description);
198                 signal_edited()(keyframe);
199         }
200 }
201 */
202
203 bool
204 LayerGroupTree::on_event(GdkEvent *event)
205 {
206     switch(event->type)
207     {
208         case GDK_BUTTON_PRESS:
209                 {
210                         Gtk::TreeModel::Path path;
211                         Gtk::TreeViewColumn *column;
212                         int cell_x, cell_y;
213                         int wx(round_to_int(event->button.x)),wy(round_to_int(event->button.y));
214                         //tree_to_widget_coords (,, wx, wy);
215                         if(!get_path_at_pos(
216                                 wx,wy,  // x, y
217                                 path, // TreeModel::Path&
218                                 column, //TreeViewColumn*&
219                                 cell_x,cell_y //int&cell_x,int&cell_y
220                                 )
221                         ) break;
222                         const Gtk::TreeRow row = *(get_model()->get_iter(path));
223
224                         if(row[model.is_layer] && event->button.button==3)
225                         {
226                                 signal_popup_layer_menu()((Layer::Handle)row[model.layer]);
227                                 return true;
228                         }
229
230                         /*signal_user_click()(event->button.button,row,(ColumnID)column->get_sort_column_id());
231                         if((ColumnID)column->get_sort_column_id()==COLUMNID_JUMP)
232                         {
233                                 layer_group_tree_store_->canvas_interface()->set_time(row[model.time]);
234                         }*/
235                 }
236                 break;
237         case GDK_2BUTTON_PRESS:
238                 {
239                         Gtk::TreeModel::Path path;
240                         Gtk::TreeViewColumn *column;
241                         int cell_x, cell_y;
242                         if(!get_path_at_pos(
243                                 int(event->button.x),int(event->button.y),      // x, y
244                                 path, // TreeModel::Path&
245                                 column, //TreeViewColumn*&
246                                 cell_x,cell_y //int&cell_x,int&cell_y
247                                 )
248                         ) break;
249                         const Gtk::TreeRow row = *(get_model()->get_iter(path));
250
251                         LayerList layer_list(row[model.all_layers]);
252                         if(!layer_list.empty())
253                         {
254                                 if(!(event->button.state&GDK_CONTROL_MASK))
255                                 {
256                                         layer_group_tree_store_->canvas_interface()->get_selection_manager()->clear_selected_layers();
257                                 }
258                                 layer_group_tree_store_->canvas_interface()->get_selection_manager()->set_selected_layers(layer_list);
259                                 return true;
260                         }
261                 }
262                 break;
263         case GDK_BUTTON_RELEASE:
264                 break;
265         default:
266                 break;
267         }
268         return Gtk::TreeView::on_event(event);
269         //return false;
270 }
271
272 static inline void __group_grabber(const Gtk::TreeModel::iterator& iter, std::list<synfig::String>* ret)
273 {
274         const LayerGroupTreeStore::Model model;
275         if((bool)(*iter)[model.is_group])
276                 ret->push_back((Glib::ustring)(*iter)[model.group_name]);
277 }
278
279 std::list<synfig::String>
280 LayerGroupTree::get_selected_groups()const
281 {
282         Glib::RefPtr<Gtk::TreeSelection> selection=const_cast<LayerGroupTree&>(*this).get_selection();
283
284         if(!selection)
285                 return std::list<synfig::String>();
286
287         std::list<synfig::String> ret;
288
289         selection->selected_foreach_iter(
290                 sigc::bind(
291                         sigc::ptr_fun(
292                                 &__group_grabber
293                         ),
294                         &ret
295                 )
296         );
297
298         return ret;
299 }
300
301 static inline void __layer_grabber(const Gtk::TreeModel::iterator& iter, LayerGroupTree::LayerList* ret)
302 {
303         const LayerGroupTreeStore::Model model;
304         if((bool)(*iter)[model.is_layer])
305                 ret->push_back((Layer::Handle)(*iter)[model.layer]);
306 }
307
308 LayerGroupTree::LayerList
309 LayerGroupTree::get_selected_layers()const
310 {
311         Glib::RefPtr<Gtk::TreeSelection> selection=const_cast<LayerGroupTree&>(*this).get_selection();
312
313         if(!selection)
314                 return LayerList();
315
316         LayerList ret;
317
318         selection->selected_foreach_iter(
319                 sigc::bind(
320                         sigc::ptr_fun(
321                                 &__layer_grabber
322                         ),
323                         &ret
324                 )
325         );
326
327         return ret;
328 }
329
330 void
331 LayerGroupTree::set_cursor(const Gtk::TreeModel::Path& path, bool start_editing)
332 {
333         Gtk::TreeView::set_cursor(path, *label_column, start_editing);
334 }