my log
[synfig.git] / synfig-studio / trunk / src / gtkmm / layeractionmanager.cpp
1 /* === S Y N F I G ========================================================= */
2 /*!     \file template.cpp
3 **      \brief Template File
4 **
5 **      $Id: layeractionmanager.cpp,v 1.1.1.1 2005/01/07 03:34:36 darco Exp $
6 **
7 **      \legal
8 **      Copyright (c) 2002 Robert B. Quattlebaum Jr.
9 **
10 **      This software and associated documentation
11 **      are CONFIDENTIAL and PROPRIETARY property of
12 **      the above-mentioned copyright holder.
13 **
14 **      You may not copy, print, publish, or in any
15 **      other way distribute this software without
16 **      a prior written agreement with
17 **      the copyright holder.
18 **      \endlegal
19 */
20 /* ========================================================================= */
21
22 /* === H E A D E R S ======================================================= */
23
24 #ifdef USING_PCH
25 #       include "pch.h"
26 #else
27 #ifdef HAVE_CONFIG_H
28 #       include <config.h>
29 #endif
30
31 #include "layeractionmanager.h"
32 #include "layertree.h"
33 #include <synfigapp/action_param.h>
34 #include "instance.h"
35 #include <synfigapp/selectionmanager.h>
36
37 #endif
38
39 /* === U S I N G =========================================================== */
40
41 using namespace std;
42 using namespace etl;
43 using namespace synfig;
44 using namespace studio;
45
46 static const guint no_prev_popup((guint)-1);
47
48 /* === M A C R O S ========================================================= */
49
50 //#define ONE_ACTION_GROUP 1
51
52 /* === G L O B A L S ======================================================= */
53
54 /* === P R O C E D U R E S ================================================= */
55
56 /* === M E T H O D S ======================================================= */
57
58 LayerActionManager::LayerActionManager():
59         action_group_(Gtk::ActionGroup::create()),
60         action_group_copy_paste(Gtk::ActionGroup::create()),
61         popup_id_(no_prev_popup),
62         queued(false)
63 {
64         action_cut_=Gtk::Action::create(
65                 "cut",
66                 Gtk::StockID("gtk-cut")
67         );
68         action_cut_->signal_activate().connect(
69                 sigc::mem_fun(
70                         *this,
71                         &LayerActionManager::cut
72                 )
73         );
74         action_copy_=Gtk::Action::create(
75                 "copy",
76                 Gtk::StockID("gtk-copy")
77         );
78         action_copy_->signal_activate().connect(
79                 sigc::mem_fun(
80                         *this,
81                         &LayerActionManager::copy
82                 )
83         );
84         action_paste_=Gtk::Action::create(
85                 "paste",
86                 Gtk::StockID("gtk-paste")
87         );
88         action_paste_->signal_activate().connect(
89                 sigc::mem_fun(
90                         *this,
91                         &LayerActionManager::paste
92                 )
93         );
94         
95         
96         action_amount_inc_=Gtk::Action::create(
97                 "amount-inc",
98                 Gtk::StockID("gtk-add"),
99                 _("Increase Amount"),_("Increase Amount")
100         );
101         action_amount_inc_->signal_activate().connect(
102                 sigc::mem_fun(
103                         *this,
104                         &LayerActionManager::amount_inc
105                 )
106         );
107
108         action_amount_dec_=Gtk::Action::create(
109                 "amount-dec",
110                 Gtk::StockID("gtk-remove"),
111                 _("Decrease Amount"),_("Decrease Amount")
112         );
113         action_amount_dec_->signal_activate().connect(
114                 sigc::mem_fun(
115                         *this,
116                         &LayerActionManager::amount_dec
117                 )
118         );
119
120         action_amount_=Gtk::Action::create(
121                 "amount",
122                 Gtk::StockID("gtk-index"),
123                 _("Amount"),_("Amount")
124         );
125
126
127 }
128
129 LayerActionManager::~LayerActionManager()
130 {
131 }
132
133 void
134 LayerActionManager::set_ui_manager(const Glib::RefPtr<Gtk::UIManager> &x)
135 {
136         clear();
137
138 #ifdef ONE_ACTION_GROUP
139         if(ui_manager_) get_ui_manager()->remove_action_group(action_group_);
140         ui_manager_=x;
141         if(ui_manager_) get_ui_manager()->insert_action_group(action_group_);
142 #else
143         ui_manager_=x;
144 #endif
145 }
146
147 void
148 LayerActionManager::set_layer_tree(LayerTree* x)
149 {
150         selection_changed_connection.disconnect();
151         layer_tree_=x;
152         if(layer_tree_)
153         {
154                 selection_changed_connection=layer_tree_->get_selection()->signal_changed().connect(
155                         sigc::mem_fun(*this,&LayerActionManager::queue_refresh)
156                 );
157         }
158 }
159
160 void
161 LayerActionManager::set_canvas_interface(const etl::handle<synfigapp::CanvasInterface> &x)
162 {
163         canvas_interface_=x;
164 }
165
166 void
167 LayerActionManager::clear()
168 {
169         if(ui_manager_)
170         {
171                 // Clear out old stuff
172                 if(popup_id_!=no_prev_popup)
173                 {
174                         get_ui_manager()->remove_ui(popup_id_);
175                         if(action_group_)get_ui_manager()->ensure_update();
176                         popup_id_=no_prev_popup;
177                         if(action_group_)while(!action_group_->get_actions().empty())action_group_->remove(*action_group_->get_actions().begin());
178 #ifdef ONE_ACTION_GROUP
179 #else
180                         if(action_group_)get_ui_manager()->remove_action_group(action_group_);
181                         action_group_=Gtk::ActionGroup::create();
182 #endif
183                 }
184         }
185
186         while(!update_connection_list.empty())
187         {
188                 update_connection_list.front().disconnect();
189                 update_connection_list.pop_front();
190         }
191 }
192
193 void
194 LayerActionManager::queue_refresh()
195 {
196         if(queued)
197                 return;
198                 
199         //queue_refresh_connection.disconnect();
200         queue_refresh_connection=Glib::signal_idle().connect(
201                 sigc::bind_return(
202                         sigc::mem_fun(*this,&LayerActionManager::refresh),
203                         false
204                 )
205         );
206         
207         queued=true;
208 }
209
210 void
211 LayerActionManager::refresh()
212 {
213         if(queued)
214         {
215                 queued=false;
216                 //queue_refresh_connection.disconnect();
217         }
218
219
220         clear();
221         
222         // Make sure we are ready
223         if(!ui_manager_ || !layer_tree_ || !canvas_interface_)
224         {
225                 synfig::error("LayerActionManager::refresh(): Not ready!");
226                 return;
227         }
228         
229         
230         String ui_info;
231
232         action_paste_->set_sensitive(!clipboard_.empty());
233         action_group_->add(action_paste_);
234         
235         if(layer_tree_->get_selection()->count_selected_rows()!=0)
236         {
237                 bool multiple_selected(layer_tree_->get_selection()->count_selected_rows()>1);
238                 Layer::Handle layer(layer_tree_->get_selected_layer());
239                 
240                 {
241                         bool canvas_set(false);
242                         synfigapp::Action::ParamList param_list;
243                         param_list.add("time",get_canvas_interface()->get_time());
244                         param_list.add("canvas_interface",get_canvas_interface());
245                         {
246                                 synfigapp::SelectionManager::LayerList layer_list(layer_tree_->get_selected_layers());
247                                 synfigapp::SelectionManager::LayerList::iterator iter;
248                                 action_copy_->set_sensitive(!layer_list.empty());
249                                 action_cut_->set_sensitive(!layer_list.empty());
250                                 action_group_->add(action_copy_);
251                                 action_group_->add(action_cut_);
252
253                                 action_amount_inc_->set_sensitive(!layer_list.empty());
254                                 action_amount_dec_->set_sensitive(!layer_list.empty());
255                                 action_amount_->set_sensitive(!layer_list.empty());
256                                 action_group_->add(action_amount_inc_);
257                                 action_group_->add(action_amount_dec_);
258                                 action_group_->add(action_amount_);
259                                 
260                                 for(iter=layer_list.begin();iter!=layer_list.end();++iter)
261                                 {
262                                         update_connection_list.push_back(
263                                                 (*iter)->signal_changed().connect(
264                                                         sigc::mem_fun(*this, &LayerActionManager::queue_refresh)
265                                                 )
266                                         );
267                                         
268                                         if(!canvas_set)
269                                         {
270                                                 param_list.add("canvas",Canvas::Handle((*iter)->get_canvas()));
271                                                 canvas_set=true;
272                                                 update_connection_list.push_back(
273                                                         (*iter)->get_canvas()->signal_changed().connect(
274                                                                 sigc::mem_fun(*this, &LayerActionManager::queue_refresh)
275                                                         )
276                                                 );
277                                         }
278                                         param_list.add("layer",Layer::Handle(*iter));
279                                 }
280                         }
281                         
282                         if(!multiple_selected && layer->get_name()=="PasteCanvas")
283                         {
284                                 action_group_->add(Gtk::Action::create(
285                                         "select-all-child-layers",
286                                         _("Select All Child Layers")
287                                 ),
288                                         sigc::bind(
289                                                 sigc::mem_fun(
290                                                         *layer_tree_,
291                                                         &studio::LayerTree::select_all_children_layers
292                                                 ),
293                                                 Layer::LooseHandle(layer)
294                                         )
295                                 );
296                                 ui_info+="<menuitem action='select-all-child-layers'/>";
297                         }
298                         handle<studio::Instance>::cast_static(get_canvas_interface()->get_instance())->
299                                 add_actions_to_group(action_group_, ui_info,   param_list, synfigapp::Action::CATEGORY_LAYER);
300                 }
301         }
302         
303         ui_info="<ui><menubar action='menu-main'><menu action='menu-layer'>"+ui_info+"<separator/><menuitem action='cut' /><menuitem action='copy' /><menuitem action='paste' /><separator/></menu></menubar></ui>";
304         popup_id_=get_ui_manager()->add_ui_from_string(ui_info);        
305 #ifdef ONE_ACTION_GROUP
306 #else
307         get_ui_manager()->insert_action_group(action_group_);
308 #endif
309         DEBUGPOINT();
310 }
311
312 void
313 LayerActionManager::cut()
314 {
315         copy();
316         if(action_group_->get_action("action-layer_remove"))
317                 action_group_->get_action("action-layer_remove")->activate();
318 }
319
320 void
321 LayerActionManager::copy()
322 {
323         synfigapp::SelectionManager::LayerList layer_list(layer_tree_->get_selected_layers());
324         clipboard_.clear();
325         synfig::GUID guid;
326         
327         while(!layer_list.empty())
328         {
329                 clipboard_.push_back(layer_list.front()->clone(guid));
330                 layer_list.pop_front();
331         }
332
333         action_paste_->set_sensitive(!clipboard_.empty());
334         
335         //queue_refresh();
336 }
337
338 void
339 LayerActionManager::paste()
340 {
341         synfig::GUID guid;
342
343         // Create the action group
344         synfigapp::Action::PassiveGrouper group(get_canvas_interface()->get_instance().get(),_("Paste"));
345
346         Canvas::Handle canvas(get_canvas_interface()->get_canvas());
347         int depth(0);
348         
349         // we are temporarily using the layer to hold something
350         Layer::Handle layer(layer_tree_->get_selected_layer());
351         if(layer)
352         {
353                 depth=layer->get_depth();
354                 canvas=layer->get_canvas();
355         }
356         
357         synfigapp::SelectionManager::LayerList layer_selection;
358         
359         for(std::list<synfig::Layer::Handle>::iterator iter=clipboard_.begin();iter!=clipboard_.end();++iter)
360         {
361                 layer=(*iter)->clone(guid);
362                 layer_selection.push_back(layer);
363                 synfigapp::Action::Handle       action(synfigapp::Action::create("layer_add"));
364         
365                 assert(action);
366                 if(!action)
367                         return;
368                 
369                 action->set_param("canvas",canvas);
370                 action->set_param("canvas_interface",etl::loose_handle<synfigapp::CanvasInterface>(get_canvas_interface()));
371                 action->set_param("new",layer);
372                 
373                 if(!action->is_ready())
374                 {
375                         return;
376                 }
377                 
378                 if(!get_instance()->perform_action(action))
379                 {
380                         return;
381                 }
382         
383                 synfig::info("DEPTH=%d",depth);
384                 // Action to move the layer (if necessary)
385                 if(depth>0)
386                 {
387                         synfigapp::Action::Handle       action(synfigapp::Action::create("layer_move"));
388                 
389                         assert(action);
390                         if(!action)
391                                 return;
392                         
393                         action->set_param("canvas",canvas);
394                         action->set_param("canvas_interface",etl::loose_handle<synfigapp::CanvasInterface>(get_canvas_interface()));
395                         action->set_param("layer",layer);
396                         action->set_param("new_index",depth);
397                         
398                         if(!action->is_ready())
399                         {
400                                 //get_ui_interface()->error(_("Move Action Not Ready"));                        
401                                 //return 0;
402                                 return;
403                         }
404                         
405                         if(!get_instance()->perform_action(action))
406                         {
407                                 //get_ui_interface()->error(_("Move Action Not Ready"));                        
408                                 //return 0;
409                                 return;
410                         }
411                 }       
412                 depth++;
413         }
414         get_canvas_interface()->get_selection_manager()->clear_selected_layers();
415         get_canvas_interface()->get_selection_manager()->set_selected_layers(layer_selection);
416 }
417
418 void
419 LayerActionManager::amount_inc()
420 {
421         float adjust(0.1);
422         
423         // Create the action group
424         synfigapp::Action::PassiveGrouper group(get_canvas_interface()->get_instance().get(),_("Decrease Amount"));
425         
426         if(adjust>0)
427                 group.set_name(_("Increase Amount"));
428
429         synfigapp::SelectionManager::LayerList layer_list(layer_tree_->get_selected_layers());
430
431         while(!layer_list.empty())
432         {
433                 ValueBase value(layer_list.front()->get_param("amount"));
434                 if(value.same_as(Real()))
435                 {
436                         get_canvas_interface()->change_value(synfigapp::ValueDesc(layer_list.front(),"amount"),value.get(Real())+adjust);
437                 }
438                 layer_list.pop_front();
439         }
440 }
441
442 void
443 LayerActionManager::amount_dec()
444 {
445         float adjust(-0.1);
446         
447         // Create the action group
448         synfigapp::Action::PassiveGrouper group(get_canvas_interface()->get_instance().get(),_("Decrease Amount"));
449         
450         if(adjust>0)
451                 group.set_name(_("Increase Amount"));
452
453         synfigapp::SelectionManager::LayerList layer_list(layer_tree_->get_selected_layers());
454
455         while(!layer_list.empty())
456         {
457                 ValueBase value(layer_list.front()->get_param("amount"));
458                 if(value.same_as(Real()))
459                 {
460                         get_canvas_interface()->change_value(synfigapp::ValueDesc(layer_list.front(),"amount"),value.get(Real())+adjust);
461                 }
462                 layer_list.pop_front();
463         }
464 }