Put a space between the parameter name and its description when prompting for it.
[synfig.git] / synfig-studio / trunk / src / gtkmm / layerparamtreestore.cpp
blob90a88c086f8ff0a7fb793010afad4472d98259af
1 /* === S Y N F I G ========================================================= */
2 /*! \file layerparamtreestore.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 "layerparamtreestore.h"
34 #include "iconcontroller.h"
35 #include <gtkmm/button.h>
36 #include <synfig/paramdesc.h>
37 #include "layertree.h"
38 #include <synfigapp/action_system.h>
39 #include <synfigapp/instance.h>
40 #include "app.h"
41 #include <ETL/clock>
43 #include "general.h"
45 #endif
47 /* === U S I N G =========================================================== */
49 using namespace std;
50 using namespace etl;
51 using namespace synfig;
52 using namespace studio;
54 /* === M A C R O S ========================================================= */
56 class Profiler : private etl::clock
58 const std::string name;
59 public:
60 Profiler(const std::string& name):name(name) { reset(); }
61 ~Profiler() { float time(operator()()); synfig::info("%s: took %f msec",name.c_str(),time*1000); }
64 /* === G L O B A L S ======================================================= */
66 /* === P R O C E D U R E S ================================================= */
68 /* === M E T H O D S ======================================================= */
70 static LayerParamTreeStore::Model& ModelHack()
72 static LayerParamTreeStore::Model* model(0);
73 if(!model)model=new LayerParamTreeStore::Model;
74 return *model;
77 LayerParamTreeStore::LayerParamTreeStore(etl::loose_handle<synfigapp::CanvasInterface> canvas_interface_,LayerTree* layer_tree):
78 Gtk::TreeStore (ModelHack()),
79 CanvasTreeStore (canvas_interface_),
80 layer_tree (layer_tree)
82 queued=false;
83 // Connect all the signals
84 canvas_interface()->signal_value_node_changed().connect(sigc::mem_fun(*this,&studio::LayerParamTreeStore::on_value_node_changed));
85 canvas_interface()->signal_value_node_renamed().connect(sigc::mem_fun(*this,&studio::LayerParamTreeStore::on_value_node_renamed));
86 canvas_interface()->signal_value_node_added().connect(sigc::mem_fun(*this,&studio::LayerParamTreeStore::on_value_node_added));
87 canvas_interface()->signal_value_node_deleted().connect(sigc::mem_fun(*this,&studio::LayerParamTreeStore::on_value_node_deleted));
88 canvas_interface()->signal_value_node_replaced().connect(sigc::mem_fun(*this,&studio::LayerParamTreeStore::on_value_node_replaced));
89 canvas_interface()->signal_layer_param_changed().connect(sigc::mem_fun(*this,&studio::LayerParamTreeStore::on_layer_param_changed));
91 canvas_interface()->signal_value_node_child_added().connect(sigc::mem_fun(*this,&studio::LayerParamTreeStore::on_value_node_child_added));
92 canvas_interface()->signal_value_node_child_removed().connect(sigc::mem_fun(*this,&studio::LayerParamTreeStore::on_value_node_child_removed));
95 layer_tree->get_selection()->signal_changed().connect(sigc::mem_fun(*this,&LayerParamTreeStore::queue_rebuild));
97 signal_changed().connect(sigc::mem_fun(*this,&LayerParamTreeStore::queue_refresh));
98 rebuild();
101 LayerParamTreeStore::~LayerParamTreeStore()
103 while(!changed_connection_list.empty())
105 changed_connection_list.back().disconnect();
106 changed_connection_list.pop_back();
109 if (getenv("SYNFIG_DEBUG_DESTRUCTORS"))
110 synfig::info("LayerParamTreeStore::~LayerParamTreeStore(): Deleted");
113 Glib::RefPtr<LayerParamTreeStore>
114 LayerParamTreeStore::create(etl::loose_handle<synfigapp::CanvasInterface> canvas_interface_, LayerTree*layer_tree)
116 return Glib::RefPtr<LayerParamTreeStore>(new LayerParamTreeStore(canvas_interface_,layer_tree));
121 void
122 LayerParamTreeStore::get_value_vfunc (const Gtk::TreeModel::iterator& iter, int column, Glib::ValueBase& value)const
124 if(column<0)
126 synfig::error("LayerParamTreeStore::get_value_vfunc(): Bad column!");
127 return;
130 /* if(column==model.label.index())
132 synfig::Layer::Handle layer((*iter)[model.layer]);
134 if(!layer)return;
136 Glib::Value<Glib::ustring> x;
137 g_value_init(x.gobj(),x.value_type());
139 x.set(layer->get_non_empty_description());
141 g_value_init(value.gobj(),x.value_type());
142 g_value_copy(x.gobj(),value.gobj());
144 else
146 if(column==model.label.index())
148 synfigapp::ValueDesc value_desc((*iter)[model.value_desc]);
149 Glib::ustring label;
151 if(!(*iter)[model.is_toplevel])
152 return CanvasTreeStore::get_value_vfunc(iter,column,value);
153 synfig::ParamDesc param_desc((*iter)[model.param_desc]);
154 label=param_desc.get_local_name();
156 if(!(*iter)[model.is_inconsistent])
157 if(value_desc.is_value_node() && value_desc.get_value_node()->is_exported())
159 label+=strprintf(" (%s)",value_desc.get_value_node()->get_id().c_str());
162 Glib::Value<Glib::ustring> x;
163 g_value_init(x.gobj(),x.value_type());
165 x.set(label);
167 g_value_init(value.gobj(),x.value_type());
168 g_value_copy(x.gobj(),value.gobj());
170 else
171 if(column==model.is_toplevel.index())
173 Glib::Value<bool> x;
174 g_value_init(x.gobj(),x.value_type());
176 TreeModel::Path path(get_path(iter));
178 x.set(path.get_depth()<=1);
180 g_value_init(value.gobj(),x.value_type());
181 g_value_copy(x.gobj(),value.gobj());
183 else
184 if(column==model.is_inconsistent.index())
186 if((*iter)[model.is_toplevel])
188 CanvasTreeStore::get_value_vfunc(iter,column,value);
189 return;
192 Glib::Value<bool> x;
193 g_value_init(x.gobj(),x.value_type());
195 x.set(false);
197 g_value_init(value.gobj(),x.value_type());
198 g_value_copy(x.gobj(),value.gobj());
200 else
201 CanvasTreeStore::get_value_vfunc(iter,column,value);
206 void
207 LayerParamTreeStore::set_value_impl(const Gtk::TreeModel::iterator& iter, int column, const Glib::ValueBase& value)
209 //if(!iterator_sane(row))
210 // return;
212 if(column>=get_n_columns_vfunc())
214 g_warning("LayerTreeStore::set_value_impl: Bad column (%d)",column);
215 return;
218 if(!g_value_type_compatible(G_VALUE_TYPE(value.gobj()),get_column_type_vfunc(column)))
220 g_warning("LayerTreeStore::set_value_impl: Bad value type");
221 return;
226 if(column==model.value.index())
228 Glib::Value<synfig::ValueBase> x;
229 g_value_init(x.gobj(),model.value.type());
230 g_value_copy(value.gobj(),x.gobj());
232 if((bool)(*iter)[model.is_toplevel])
234 synfigapp::Action::PassiveGrouper group(canvas_interface()->get_instance().get(),_("Set Layer Params"));
236 synfig::ParamDesc param_desc((*iter)[model.param_desc]);
238 LayerList::iterator iter2(layer_list.begin());
240 for(;iter2!=layer_list.end();++iter2)
242 if(!canvas_interface()->change_value(synfigapp::ValueDesc(*iter2,param_desc.get_name()),x.get()))
244 // ERROR!
245 group.cancel();
246 App::dialog_error_blocking(_("Error"),_("Unable to set all layer parameters."));
248 return;
252 else
254 canvas_interface()->change_value((*iter)[model.value_desc],x.get());
256 return;
258 else
260 if(column==model.active.index())
262 synfig::Layer::Handle layer((*iter)[model.layer]);
264 if(!layer)return;
266 Glib::Value<bool> x;
267 g_value_init(x.gobj(),model.active.type());
268 g_value_copy(value.gobj(),x.gobj());
270 synfigapp::Action::Handle action(synfigapp::Action::create("layer_activate"));
272 if(!action)
273 return;
275 action->set_param("canvas",canvas_interface()->get_canvas());
276 action->set_param("canvas_interface",canvas_interface());
277 action->set_param("layer",layer);
278 action->set_param("new_status",bool(x.get()));
280 canvas_interface()->get_instance()->perform_action(action);
281 return;
283 else
285 CanvasTreeStore::set_value_impl(iter,column, value);
287 catch(std::exception x)
289 g_warning(x.what());
302 void
303 LayerParamTreeStore::rebuild()
305 // Profiler profiler("LayerParamTreeStore::rebuild()");
306 if(queued)queued=false;
307 clear();
308 layer_list=layer_tree->get_selected_layers();
310 if(layer_list.size()<=0)
311 return;
313 // Get rid of all the connections,
314 // and clear the connection map.
315 //while(!connection_map.empty())connection_map.begin()->second.disconnect(),connection_map.erase(connection_map.begin());
316 while(!changed_connection_list.empty())
318 changed_connection_list.back().disconnect();
319 changed_connection_list.pop_back();
322 struct REBUILD_HELPER
324 ParamVocab vocab;
325 Layer::Handle layer_0;
327 static ParamVocab::iterator find_param_desc(ParamVocab& vocab, const synfig::String& x)
329 ParamVocab::iterator iter;
331 for(iter=vocab.begin();iter!=vocab.end();++iter)
332 if(iter->get_name()==x)
333 break;
334 return iter;
337 void process_vocab(synfig::Layer::Handle layer_n)
339 ParamVocab x = layer_n->get_param_vocab();
340 ParamVocab::iterator iter;
342 for(iter=vocab.begin();iter!=vocab.end();++iter)
344 String name(iter->get_name());
345 ParamVocab::iterator iter2(find_param_desc(x,name));
346 if(iter2==x.end() ||
347 layer_0->get_param(name).get_type() != layer_n->get_param(name).get_type())
349 // remove it and start over
350 vocab.erase(iter);
351 iter=vocab.begin();
352 iter--;
353 continue;
358 } rebuild_helper;
362 LayerList::iterator iter(layer_list.begin());
363 rebuild_helper.vocab=(*iter)->get_param_vocab();
364 rebuild_helper.layer_0=*iter;
366 for(++iter;iter!=layer_list.end();++iter)
368 rebuild_helper.process_vocab(*iter);
369 changed_connection_list.push_back(
370 (*iter)->signal_changed().connect(
371 sigc::mem_fun(
372 *this,
373 &LayerParamTreeStore::changed
380 ParamVocab::iterator iter;
381 for(iter=rebuild_helper.vocab.begin();iter!=rebuild_helper.vocab.end();++iter)
383 if(iter->get_hidden())
384 continue;
387 if(iter->get_animation_only())
389 int length(layer_list.front()->get_canvas()->rend_desc().get_frame_end()-layer_list.front()->get_canvas()->rend_desc().get_frame_start());
390 if(!length)
391 continue;
394 Gtk::TreeRow row(*(append()));
395 synfigapp::ValueDesc value_desc(layer_list.front(),iter->get_name());
396 CanvasTreeStore::set_row(row,value_desc);
397 if(value_desc.is_value_node())
399 changed_connection_list.push_back(
400 value_desc.get_value_node()->signal_changed().connect(
401 sigc::mem_fun(
402 this,
403 &LayerParamTreeStore::changed
408 if(value_desc.get_value_type()==ValueBase::TYPE_CANVAS)
410 Canvas::Handle canvas_handle = value_desc.get_value().get(Canvas::Handle());
411 if(canvas_handle) changed_connection_list.push_back(
412 canvas_handle->signal_changed().connect(
413 sigc::mem_fun(
414 this,
415 &LayerParamTreeStore::changed
420 //row[model.label] = iter->get_local_name();
421 row[model.param_desc] = *iter;
422 row[model.canvas] = layer_list.front()->get_canvas();
423 row[model.is_inconsistent] = false;
424 //row[model.is_toplevel] = true;
427 LayerList::iterator iter2(layer_list.begin());
428 ValueBase value((*iter2)->get_param(iter->get_name()));
429 for(++iter2;iter2!=layer_list.end();++iter2)
431 if(value!=((*iter2)->get_param(iter->get_name())))
433 row[model.is_inconsistent] = true;
434 while(!row.children().empty() && erase(row.children().begin()))
436 break;
442 void
443 LayerParamTreeStore::queue_refresh()
445 if(queued)
446 return;
447 queued=1;
448 queue_connection.disconnect();
449 queue_connection=Glib::signal_timeout().connect(
450 sigc::bind_return(
451 sigc::mem_fun(*this,&LayerParamTreeStore::refresh),
452 false
454 ,150);
458 void
459 LayerParamTreeStore::queue_rebuild()
461 if(queued==2)
462 return;
463 queued=2;
464 queue_connection.disconnect();
465 queue_connection=Glib::signal_timeout().connect(
466 sigc::bind_return(
467 sigc::mem_fun(*this,&LayerParamTreeStore::rebuild),
468 false
470 ,150);
474 void
475 LayerParamTreeStore::refresh()
477 if(queued)queued=false;
479 Gtk::TreeModel::Children children_(children());
481 Gtk::TreeModel::Children::iterator iter;
483 if(!children_.empty())
484 for(iter = children_.begin(); iter && iter != children_.end(); ++iter)
486 Gtk::TreeRow row=*iter;
487 refresh_row(row);
491 void
492 LayerParamTreeStore::refresh_row(Gtk::TreeModel::Row &row)
494 if(row[model.is_toplevel])
496 row[model.is_inconsistent] = false;
497 ParamDesc param_desc(row[model.param_desc]);
499 LayerList::iterator iter2(layer_list.begin());
500 ValueBase value((*iter2)->get_param(param_desc.get_name()));
501 for(++iter2;iter2!=layer_list.end();++iter2)
503 if(value!=((*iter2)->get_param(param_desc.get_name())))
505 row[model.is_inconsistent] = true;
506 while(!row.children().empty() && erase(row.children().begin()))
508 return;
513 //handle<ValueNode> value_node=row[model.value_node];
514 //if(value_node)
516 CanvasTreeStore::refresh_row(row);
517 return;
521 void
522 LayerParamTreeStore::set_row(Gtk::TreeRow row,synfigapp::ValueDesc value_desc)
524 Gtk::TreeModel::Children children = row.children();
525 while(!children.empty() && erase(children.begin()))
528 CanvasTreeStore::set_row(row,value_desc);
531 void
532 LayerParamTreeStore::on_value_node_added(synfig::ValueNode::Handle /*value_node*/)
534 // queue_refresh();
537 void
538 LayerParamTreeStore::on_value_node_deleted(synfig::ValueNode::Handle /*value_node*/)
540 // queue_refresh();
543 void
544 LayerParamTreeStore::on_value_node_child_added(synfig::ValueNode::Handle /*value_node*/,synfig::ValueNode::Handle /*child*/)
546 queue_rebuild();
549 void
550 LayerParamTreeStore::on_value_node_child_removed(synfig::ValueNode::Handle /*value_node*/,synfig::ValueNode::Handle /*child*/)
552 rebuild();
555 void
556 LayerParamTreeStore::on_value_node_changed(synfig::ValueNode::Handle /*value_node*/)
558 queue_refresh();
561 void
562 LayerParamTreeStore::on_value_node_renamed(synfig::ValueNode::Handle /*value_node*/)
564 rebuild();
567 void
568 LayerParamTreeStore::on_value_node_replaced(synfig::ValueNode::Handle /*replaced_value_node*/,synfig::ValueNode::Handle /*new_value_node*/)
570 queue_rebuild();
573 void
574 LayerParamTreeStore::on_layer_param_changed(synfig::Layer::Handle /*handle*/,synfig::String /*param_name*/)
576 queue_refresh();