X-Git-Url: https://git.pterodactylus.net/?a=blobdiff_plain;f=synfig-studio%2Fsrc%2Fgui%2Ftrees%2Flayerparamtreestore.cpp;fp=synfig-studio%2Fsrc%2Fgui%2Ftrees%2Flayerparamtreestore.cpp;h=8fe850af01bda1c277cb4366b2fd3127dc9927ed;hb=27b5a5e825ecd199f7ef353e1ed45eb678991087;hp=0000000000000000000000000000000000000000;hpb=5fe12ee93aaca62d4d1e4007a5e94b97c1135d2c;p=synfig.git diff --git a/synfig-studio/src/gui/trees/layerparamtreestore.cpp b/synfig-studio/src/gui/trees/layerparamtreestore.cpp new file mode 100644 index 0000000..8fe850a --- /dev/null +++ b/synfig-studio/src/gui/trees/layerparamtreestore.cpp @@ -0,0 +1,577 @@ +/* === S Y N F I G ========================================================= */ +/*! \file layerparamtreestore.cpp +** \brief Template File +** +** $Id$ +** +** \legal +** Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley +** Copyright (c) 2007, 2008 Chris Moore +** +** This package is free software; you can redistribute it and/or +** modify it under the terms of the GNU General Public License as +** published by the Free Software Foundation; either version 2 of +** the License, or (at your option) any later version. +** +** This package is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +** General Public License for more details. +** \endlegal +*/ +/* ========================================================================= */ + +/* === H E A D E R S ======================================================= */ + +#ifdef USING_PCH +# include "pch.h" +#else +#ifdef HAVE_CONFIG_H +# include +#endif + +#include "layerparamtreestore.h" +#include "iconcontroller.h" +#include +#include +#include "layertree.h" +#include +#include +#include "app.h" +#include + +#include "general.h" + +#endif + +/* === U S I N G =========================================================== */ + +using namespace std; +using namespace etl; +using namespace synfig; +using namespace studio; + +/* === M A C R O S ========================================================= */ + +class Profiler : private etl::clock +{ + const std::string name; +public: + Profiler(const std::string& name):name(name) { reset(); } + ~Profiler() { float time(operator()()); synfig::info("%s: took %f msec",name.c_str(),time*1000); } +}; + +/* === G L O B A L S ======================================================= */ + +/* === P R O C E D U R E S ================================================= */ + +/* === M E T H O D S ======================================================= */ + +static LayerParamTreeStore::Model& ModelHack() +{ + static LayerParamTreeStore::Model* model(0); + if(!model)model=new LayerParamTreeStore::Model; + return *model; +} + +LayerParamTreeStore::LayerParamTreeStore(etl::loose_handle canvas_interface_,LayerTree* layer_tree): + Gtk::TreeStore (ModelHack()), + CanvasTreeStore (canvas_interface_), + layer_tree (layer_tree) +{ + queued=0; + // Connect all the signals + canvas_interface()->signal_value_node_changed().connect(sigc::mem_fun(*this,&studio::LayerParamTreeStore::on_value_node_changed)); + canvas_interface()->signal_value_node_renamed().connect(sigc::mem_fun(*this,&studio::LayerParamTreeStore::on_value_node_renamed)); + canvas_interface()->signal_value_node_added().connect(sigc::mem_fun(*this,&studio::LayerParamTreeStore::on_value_node_added)); + canvas_interface()->signal_value_node_deleted().connect(sigc::mem_fun(*this,&studio::LayerParamTreeStore::on_value_node_deleted)); + canvas_interface()->signal_value_node_replaced().connect(sigc::mem_fun(*this,&studio::LayerParamTreeStore::on_value_node_replaced)); + canvas_interface()->signal_layer_param_changed().connect(sigc::mem_fun(*this,&studio::LayerParamTreeStore::on_layer_param_changed)); + + canvas_interface()->signal_value_node_child_added().connect(sigc::mem_fun(*this,&studio::LayerParamTreeStore::on_value_node_child_added)); + canvas_interface()->signal_value_node_child_removed().connect(sigc::mem_fun(*this,&studio::LayerParamTreeStore::on_value_node_child_removed)); + + + layer_tree->get_selection()->signal_changed().connect(sigc::mem_fun(*this,&LayerParamTreeStore::queue_rebuild)); + + signal_changed().connect(sigc::mem_fun(*this,&LayerParamTreeStore::queue_refresh)); + rebuild(); +} + +LayerParamTreeStore::~LayerParamTreeStore() +{ + while(!changed_connection_list.empty()) + { + changed_connection_list.back().disconnect(); + changed_connection_list.pop_back(); + } + + if (getenv("SYNFIG_DEBUG_DESTRUCTORS")) + synfig::info("LayerParamTreeStore::~LayerParamTreeStore(): Deleted"); +} + +Glib::RefPtr +LayerParamTreeStore::create(etl::loose_handle canvas_interface_, LayerTree*layer_tree) +{ + return Glib::RefPtr(new LayerParamTreeStore(canvas_interface_,layer_tree)); +} + + + +void +LayerParamTreeStore::get_value_vfunc (const Gtk::TreeModel::iterator& iter, int column, Glib::ValueBase& value)const +{ + if(column<0) + { + synfig::error("LayerParamTreeStore::get_value_vfunc(): Bad column!"); + return; + } + +/* if(column==model.label.index()) + { + synfig::Layer::Handle layer((*iter)[model.layer]); + + if(!layer)return; + + Glib::Value x; + g_value_init(x.gobj(),x.value_type()); + + x.set(layer->get_non_empty_description()); + + g_value_init(value.gobj(),x.value_type()); + g_value_copy(x.gobj(),value.gobj()); + } + else +*/ + if(column==model.label.index()) + { + synfigapp::ValueDesc value_desc((*iter)[model.value_desc]); + Glib::ustring label; + + if(!(*iter)[model.is_toplevel]) + return CanvasTreeStore::get_value_vfunc(iter,column,value); + synfig::ParamDesc param_desc((*iter)[model.param_desc]); + label=param_desc.get_local_name(); + + if(!(*iter)[model.is_inconsistent]) + if(value_desc.is_value_node() && value_desc.get_value_node()->is_exported()) + { + label+=strprintf(" (%s)",value_desc.get_value_node()->get_id().c_str()); + } + + Glib::Value x; + g_value_init(x.gobj(),x.value_type()); + + x.set(label); + + g_value_init(value.gobj(),x.value_type()); + g_value_copy(x.gobj(),value.gobj()); + } + else + if(column==model.is_toplevel.index()) + { + Glib::Value x; + g_value_init(x.gobj(),x.value_type()); + + TreeModel::Path path(get_path(iter)); + + x.set(path.get_depth()<=1); + + g_value_init(value.gobj(),x.value_type()); + g_value_copy(x.gobj(),value.gobj()); + } + else + if(column==model.is_inconsistent.index()) + { + if((*iter)[model.is_toplevel]) + { + CanvasTreeStore::get_value_vfunc(iter,column,value); + return; + } + + Glib::Value x; + g_value_init(x.gobj(),x.value_type()); + + x.set(false); + + g_value_init(value.gobj(),x.value_type()); + g_value_copy(x.gobj(),value.gobj()); + } + else + CanvasTreeStore::get_value_vfunc(iter,column,value); +} + + + +void +LayerParamTreeStore::set_value_impl(const Gtk::TreeModel::iterator& iter, int column, const Glib::ValueBase& value) +{ + //if(!iterator_sane(row)) + // return; + + if(column>=get_n_columns_vfunc()) + { + g_warning("LayerTreeStore::set_value_impl: Bad column (%d)",column); + return; + } + + if(!g_value_type_compatible(G_VALUE_TYPE(value.gobj()),get_column_type_vfunc(column))) + { + g_warning("LayerTreeStore::set_value_impl: Bad value type"); + return; + } + + try + { + if(column==model.value.index()) + { + Glib::Value x; + g_value_init(x.gobj(),model.value.type()); + g_value_copy(value.gobj(),x.gobj()); + + if((bool)(*iter)[model.is_toplevel]) + { + synfigapp::Action::PassiveGrouper group(canvas_interface()->get_instance().get(),_("Set Layer Params")); + + synfig::ParamDesc param_desc((*iter)[model.param_desc]); + + LayerList::iterator iter2(layer_list.begin()); + + for(;iter2!=layer_list.end();++iter2) + { + if(!canvas_interface()->change_value(synfigapp::ValueDesc(*iter2,param_desc.get_name()),x.get())) + { + // ERROR! + group.cancel(); + App::dialog_error_blocking(_("Error"),_("Unable to set all layer parameters.")); + + return; + } + } + } + else + { + canvas_interface()->change_value((*iter)[model.value_desc],x.get()); + } + return; + } + else +/* + if(column==model.active.index()) + { + synfig::Layer::Handle layer((*iter)[model.layer]); + + if(!layer)return; + + Glib::Value x; + g_value_init(x.gobj(),model.active.type()); + g_value_copy(value.gobj(),x.gobj()); + + synfigapp::Action::Handle action(synfigapp::Action::create("LayerActivate")); + + if(!action) + return; + + action->set_param("canvas",canvas_interface()->get_canvas()); + action->set_param("canvas_interface",canvas_interface()); + action->set_param("layer",layer); + action->set_param("new_status",bool(x.get())); + + canvas_interface()->get_instance()->perform_action(action); + return; + } + else +*/ + CanvasTreeStore::set_value_impl(iter,column, value); + } + catch(std::exception x) + { + g_warning("%s", x.what()); + } +} + + + + + + + + + + +void +LayerParamTreeStore::rebuild() +{ + // Profiler profiler("LayerParamTreeStore::rebuild()"); + if(queued)queued=0; + clear(); + layer_list=layer_tree->get_selected_layers(); + + if(layer_list.size()<=0) + return; + + // Get rid of all the connections, + // and clear the connection map. + //while(!connection_map.empty())connection_map.begin()->second.disconnect(),connection_map.erase(connection_map.begin()); + while(!changed_connection_list.empty()) + { + changed_connection_list.back().disconnect(); + changed_connection_list.pop_back(); + } + + struct REBUILD_HELPER + { + ParamVocab vocab; + Layer::Handle layer_0; + + static ParamVocab::iterator find_param_desc(ParamVocab& vocab, const synfig::String& x) + { + ParamVocab::iterator iter; + + for(iter=vocab.begin();iter!=vocab.end();++iter) + if(iter->get_name()==x) + break; + return iter; + } + + void process_vocab(synfig::Layer::Handle layer_n) + { + ParamVocab x = layer_n->get_param_vocab(); + ParamVocab::iterator iter; + + for(iter=vocab.begin();iter!=vocab.end();++iter) + { + String name(iter->get_name()); + ParamVocab::iterator iter2(find_param_desc(x,name)); + if(iter2==x.end() || + layer_0->get_param(name).get_type() != layer_n->get_param(name).get_type()) + { + // remove it and start over + vocab.erase(iter); + iter=vocab.begin(); + iter--; + continue; + } + } + } + + } rebuild_helper; + + + { + LayerList::iterator iter(layer_list.begin()); + rebuild_helper.vocab=(*iter)->get_param_vocab(); + rebuild_helper.layer_0=*iter; + + for(++iter;iter!=layer_list.end();++iter) + { + rebuild_helper.process_vocab(*iter); + changed_connection_list.push_back( + (*iter)->signal_changed().connect( + sigc::mem_fun( + *this, + &LayerParamTreeStore::changed + ) + ) + ); + } + } + + ParamVocab::iterator iter; + for(iter=rebuild_helper.vocab.begin();iter!=rebuild_helper.vocab.end();++iter) + { + if(iter->get_hidden()) + continue; + + /* + if(iter->get_animation_only()) + { + int length(layer_list.front()->get_canvas()->rend_desc().get_frame_end()-layer_list.front()->get_canvas()->rend_desc().get_frame_start()); + if(!length) + continue; + } + */ + Gtk::TreeRow row(*(append())); + synfigapp::ValueDesc value_desc(layer_list.front(),iter->get_name()); + CanvasTreeStore::set_row(row,value_desc); + if(value_desc.is_value_node()) + { + changed_connection_list.push_back( + value_desc.get_value_node()->signal_changed().connect( + sigc::mem_fun( + this, + &LayerParamTreeStore::changed + ) + ) + ); + } + if(value_desc.get_value_type()==ValueBase::TYPE_CANVAS) + { + Canvas::Handle canvas_handle = value_desc.get_value().get(Canvas::Handle()); + if(canvas_handle) changed_connection_list.push_back( + canvas_handle->signal_changed().connect( + sigc::mem_fun( + this, + &LayerParamTreeStore::changed + ) + ) + ); + } + //row[model.label] = iter->get_local_name(); + row[model.param_desc] = *iter; + row[model.canvas] = layer_list.front()->get_canvas(); + row[model.is_inconsistent] = false; + //row[model.is_toplevel] = true; + + + LayerList::iterator iter2(layer_list.begin()); + ValueBase value((*iter2)->get_param(iter->get_name())); + for(++iter2;iter2!=layer_list.end();++iter2) + { + if(value!=((*iter2)->get_param(iter->get_name()))) + { + row[model.is_inconsistent] = true; + while(!row.children().empty() && erase(row.children().begin())) + ; + break; + } + } + } +} + +void +LayerParamTreeStore::queue_refresh() +{ + if(queued) + return; + queued=1; + queue_connection.disconnect(); + queue_connection=Glib::signal_timeout().connect( + sigc::bind_return( + sigc::mem_fun(*this,&LayerParamTreeStore::refresh), + false + ) + ,150); + +} + +void +LayerParamTreeStore::queue_rebuild() +{ + if(queued==2) + return; + queued=2; + queue_connection.disconnect(); + queue_connection=Glib::signal_timeout().connect( + sigc::bind_return( + sigc::mem_fun(*this,&LayerParamTreeStore::rebuild), + false + ) + ,150); + +} + +void +LayerParamTreeStore::refresh() +{ + if(queued)queued=0; + + Gtk::TreeModel::Children children_(children()); + + Gtk::TreeModel::Children::iterator iter; + + if(!children_.empty()) + for(iter = children_.begin(); iter && iter != children_.end(); ++iter) + { + Gtk::TreeRow row=*iter; + refresh_row(row); + } +} + +void +LayerParamTreeStore::refresh_row(Gtk::TreeModel::Row &row) +{ + if(row[model.is_toplevel]) + { + row[model.is_inconsistent] = false; + ParamDesc param_desc(row[model.param_desc]); + + LayerList::iterator iter2(layer_list.begin()); + ValueBase value((*iter2)->get_param(param_desc.get_name())); + for(++iter2;iter2!=layer_list.end();++iter2) + { + if(value!=((*iter2)->get_param(param_desc.get_name()))) + { + row[model.is_inconsistent] = true; + while(!row.children().empty() && erase(row.children().begin())) + ; + return; + } + } + } + + //handle value_node=row[model.value_node]; + //if(value_node) + { + CanvasTreeStore::refresh_row(row); + return; + } +} + +void +LayerParamTreeStore::set_row(Gtk::TreeRow row,synfigapp::ValueDesc value_desc) +{ + Gtk::TreeModel::Children children = row.children(); + while(!children.empty() && erase(children.begin())) + ; + + CanvasTreeStore::set_row(row,value_desc); +} + +void +LayerParamTreeStore::on_value_node_added(synfig::ValueNode::Handle /*value_node*/) +{ +// queue_refresh(); +} + +void +LayerParamTreeStore::on_value_node_deleted(synfig::ValueNode::Handle /*value_node*/) +{ +// queue_refresh(); +} + +void +LayerParamTreeStore::on_value_node_child_added(synfig::ValueNode::Handle /*value_node*/,synfig::ValueNode::Handle /*child*/) +{ + queue_rebuild(); +} + +void +LayerParamTreeStore::on_value_node_child_removed(synfig::ValueNode::Handle /*value_node*/,synfig::ValueNode::Handle /*child*/) +{ + rebuild(); +} + +void +LayerParamTreeStore::on_value_node_changed(synfig::ValueNode::Handle /*value_node*/) +{ + queue_refresh(); +} + +void +LayerParamTreeStore::on_value_node_renamed(synfig::ValueNode::Handle /*value_node*/) +{ + rebuild(); +} + +void +LayerParamTreeStore::on_value_node_replaced(synfig::ValueNode::Handle /*replaced_value_node*/,synfig::ValueNode::Handle /*new_value_node*/) +{ + queue_rebuild(); +} + +void +LayerParamTreeStore::on_layer_param_changed(synfig::Layer::Handle /*handle*/,synfig::String /*param_name*/) +{ + queue_refresh(); +}