X-Git-Url: https://git.pterodactylus.net/?a=blobdiff_plain;f=synfig-studio%2Fsrc%2Fgtkmm%2Fcanvastreestore.cpp;fp=synfig-studio%2Fsrc%2Fgtkmm%2Fcanvastreestore.cpp;h=f49d7a3e4c8f04856d5634c02e40ef36df71d5be;hb=a095981e18cc37a8ecc7cd237cc22b9c10329264;hp=0000000000000000000000000000000000000000;hpb=9459638ad6797b8139f1e9f0715c96076dbf0890;p=synfig.git diff --git a/synfig-studio/src/gtkmm/canvastreestore.cpp b/synfig-studio/src/gtkmm/canvastreestore.cpp new file mode 100644 index 0000000..f49d7a3 --- /dev/null +++ b/synfig-studio/src/gtkmm/canvastreestore.cpp @@ -0,0 +1,622 @@ +/* === S Y N F I G ========================================================= */ +/*! \file canvastreestore.cpp +** \brief Template File +** +** $Id$ +** +** \legal +** Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley +** Copyright (c) 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 "canvastreestore.h" +#include +#include "iconcontroller.h" +#include +#include +#include +#include +#include "cellrenderer_value.h" +#include "cellrenderer_timetrack.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 ========================================================= */ + +/* === 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 CanvasTreeStore::Model& ModelHack() +{ + static CanvasTreeStore::Model* model(0); + if(!model)model=new CanvasTreeStore::Model; + return *model; +} + +CanvasTreeStore::CanvasTreeStore(etl::loose_handle canvas_interface_): + Gtk::TreeStore(ModelHack()), + canvas_interface_ (canvas_interface_) +{ +} + +CanvasTreeStore::~CanvasTreeStore() +{ +} + +void +CanvasTreeStore::get_value_vfunc(const Gtk::TreeModel::iterator& iter, int column, Glib::ValueBase& value)const +{ + if(column==model.value.index()) + { + synfigapp::ValueDesc value_desc((*iter)[model.value_desc]); + + Glib::Value x; + g_value_init(x.gobj(),x.value_type()); + + if(!value_desc) + { + x.set(ValueBase()); + } + else + if(value_desc.is_const()) + x.set(value_desc.get_value()); + else + if(value_desc.is_value_node()) + x.set((*value_desc.get_value_node())(canvas_interface()->get_time())); + else + { + synfig::error(__FILE__":%d: Unable to figure out value",__LINE__); + return; + } + + g_value_init(value.gobj(),x.value_type()); + g_value_copy(x.gobj(),value.gobj()); + } + else + if(column==model.is_value_node.index()) + { + synfigapp::ValueDesc value_desc((*iter)[model.value_desc]); + + Glib::Value x; + g_value_init(x.gobj(),x.value_type()); + + x.set(value_desc && value_desc.is_value_node()); + + g_value_init(value.gobj(),x.value_type()); + g_value_copy(x.gobj(),value.gobj()); + } + else + if(column==model.is_shared.index()) + { + synfigapp::ValueDesc value_desc((*iter)[model.value_desc]); + + Glib::Value x; + g_value_init(x.gobj(),x.value_type()); + + x.set(value_desc.is_value_node() && value_desc.get_value_node()->rcount()>1); + + g_value_init(value.gobj(),x.value_type()); + g_value_copy(x.gobj(),value.gobj()); + } + else + if(column==model.is_exported.index()) + { + synfigapp::ValueDesc value_desc((*iter)[model.value_desc]); + + Glib::Value x; + g_value_init(x.gobj(),x.value_type()); + + x.set(value_desc.is_value_node() && value_desc.get_value_node()->is_exported()); + + g_value_init(value.gobj(),x.value_type()); + g_value_copy(x.gobj(),value.gobj()); + } + else + if(column==model.is_canvas.index()) + { + synfigapp::ValueDesc value_desc((*iter)[model.value_desc]); + + Glib::Value x; + g_value_init(x.gobj(),x.value_type()); + + x.set(!value_desc && (Canvas::Handle)(*iter)[model.canvas]); + + g_value_init(value.gobj(),x.value_type()); + g_value_copy(x.gobj(),value.gobj()); + } + else + if(column==model.id.index()) + { + synfigapp::ValueDesc value_desc((*iter)[model.value_desc]); + + Glib::Value x; + g_value_init(x.gobj(),x.value_type()); + + if(value_desc && value_desc.is_value_node()) + x.set(value_desc.get_value_node()->get_id()); + else if(!value_desc && Canvas::Handle((*iter)[model.canvas])) + x.set(Canvas::Handle((*iter)[model.canvas])->get_id()); + else + return Gtk::TreeStore::get_value_vfunc(iter,column,value); + + g_value_init(value.gobj(),x.value_type()); + g_value_copy(x.gobj(),value.gobj()); + } + else + if(column==model.is_editable.index()) + { + synfigapp::ValueDesc value_desc((*iter)[model.value_desc]); + + Glib::Value x; + g_value_init(x.gobj(),x.value_type()); + + x.set(!value_desc.is_value_node() || synfigapp::is_editable(value_desc.get_value_node())); + + g_value_init(value.gobj(),x.value_type()); + g_value_copy(x.gobj(),value.gobj()); + } + else + if(column==model.type.index()) + { + synfigapp::ValueDesc value_desc((*iter)[model.value_desc]); + + Glib::Value x; + g_value_init(x.gobj(),x.value_type()); + + // Set the type + if(!value_desc) + { + if((*iter)[model.is_canvas]) + x.set(_("Canvas")); + } + else + { + if(!value_desc.is_value_node() || value_desc.get_value_node()->get_name()=="constant") + { + x.set(ValueBase::type_local_name(value_desc.get_value_type())); + } + else + { + x.set(value_desc.get_value_node()->get_local_name()); + } + } + + 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::Value x; + g_value_init(x.gobj(),x.value_type()); + + // Set the type + if(!value_desc) + { + Canvas::Handle canvas((*iter)[model.canvas]); + if(canvas) + { + if(!canvas->get_id().empty()) + x.set(canvas->get_id()); + else + if(!canvas->get_name().empty()) + x.set(canvas->get_name()); + else + x.set(_("[Unnamed]")); + x.set(_("Canvas")); + } + return Gtk::TreeStore::get_value_vfunc(iter,column,value); + } + else + { + ValueNode::Handle value_node=value_desc.get_value_node(); + + // Setup the row's label + if(value_node->get_id().empty()) + x.set(Glib::ustring((*iter)[model.name])); + else if(Glib::ustring((*iter)[model.name]).empty()) + x.set(value_node->get_id()); + else + x.set(Glib::ustring((*iter)[model.name])+" ("+value_node->get_id()+')'); + } + + g_value_init(value.gobj(),x.value_type()); + g_value_copy(x.gobj(),value.gobj()); + } + else + if(column==model.icon.index()) + { + synfigapp::ValueDesc value_desc((*iter)[model.value_desc]); + if(!value_desc) + return Gtk::TreeStore::get_value_vfunc(iter,column,value); + + Glib::Value > x; + g_value_init(x.gobj(),x.value_type()); + + x.set(get_tree_pixbuf(value_desc.get_value_type())); + + g_value_init(value.gobj(),x.value_type()); + g_value_copy(x.gobj(),value.gobj()); + } + else + Gtk::TreeStore::get_value_vfunc(iter,column,value); +} + +bool +CanvasTreeStore::find_first_value_desc(const synfigapp::ValueDesc& value_desc, Gtk::TreeIter& iter) +{ + iter=children().begin(); + while(iter && value_desc!=(*iter)[model.value_desc]) + { + if(!iter->children().empty()) + { + Gtk::TreeIter iter2(iter->children().begin()); + //! \todo confirm that the && should be done before the || + if((iter2 && value_desc==(*iter2)[model.value_desc]) || find_next_value_desc(value_desc, iter2)) + { + iter=iter2; + return true; + } + } + Gtk::TreeIter iter2(++iter); + if(!iter2) + iter==iter->parent(); + else + iter=iter2; + } + return (bool)iter && value_desc==(*iter)[model.value_desc]; +} + +bool +CanvasTreeStore::find_next_value_desc(const synfigapp::ValueDesc& value_desc, Gtk::TreeIter& iter) +{ + if(!iter) return find_first_value_desc(value_desc,iter); + + if(iter) do { + if(!iter->children().empty()) + { + Gtk::TreeIter iter2(iter->children().begin()); + //! \todo confirm that the && should be done before the || + if((iter2 && value_desc==(*iter2)[model.value_desc]) || find_next_value_desc(value_desc, iter2)) + { + iter=iter2; + return true; + } + } + Gtk::TreeIter iter2(++iter); + if(!iter2) + { + iter==iter->parent(); + if(iter)++iter; + } + else + iter=iter2; + } while(iter && value_desc!=(*iter)[model.value_desc]); + return (bool)iter && value_desc==(*iter)[model.value_desc]; +} + +bool +CanvasTreeStore::find_first_value_node(const synfig::ValueNode::Handle& value_node, Gtk::TreeIter& iter) +{ + iter=children().begin(); + while(iter && value_node!=(ValueNode::Handle)(*iter)[model.value_node]) + { + if(!iter->children().empty()) + { + Gtk::TreeIter iter2(iter->children().begin()); + //! \todo confirm that the && should be done before the || + if((iter2 && value_node==(ValueNode::Handle)(*iter2)[model.value_node]) || find_next_value_node(value_node, iter2)) + { + iter=iter2; + return true; + } + } + Gtk::TreeIter iter2(++iter); + if(!iter2) + iter==iter->parent(); + else + iter=iter2; + } + return (bool)iter && value_node==(ValueNode::Handle)(*iter)[model.value_node]; +} + +bool +CanvasTreeStore::find_next_value_node(const synfig::ValueNode::Handle& value_node, Gtk::TreeIter& iter) +{ + if(!iter) return find_first_value_node(value_node,iter); + + if(iter) do { + if(!iter->children().empty()) + { + Gtk::TreeIter iter2(iter->children().begin()); + //! \todo confirm that the && should be done before the || + if((iter2 && value_node==(ValueNode::Handle)(*iter2)[model.value_node]) || find_next_value_node(value_node, iter2)) + { + iter=iter2; + return true; + } + } + Gtk::TreeIter iter2(++iter); + if(!iter2) + { + iter==iter->parent(); + if(iter)++iter; + } + else + iter=iter2; + } while(iter && value_node!=(ValueNode::Handle)(*iter)[model.value_node]); + return (bool)iter && value_node==(ValueNode::Handle)(*iter)[model.value_node]; +} + +void +CanvasTreeStore::set_row(Gtk::TreeRow row,synfigapp::ValueDesc value_desc, bool do_children) +{ + Gtk::TreeModel::Children children = row.children(); + while(!children.empty() && erase(children.begin())) + ; + + row[model.value_desc]=value_desc; + try + { + //row[model.icon] = get_tree_pixbuf(value_desc.get_value_type()); + + if(value_desc.is_value_node()) + { + ValueNode::Handle value_node=value_desc.get_value_node(); + + assert(value_node); + + row[model.value_node] = value_node; + //row[model.is_canvas] = false; + //row[model.is_value_node] = true; + //row[model.is_editable] = synfigapp::is_editable(value_node); + //row[model.id]=value_node->get_id(); + + // Set the canvas + if(value_desc.parent_is_canvas()) + row[model.canvas]=value_desc.get_canvas(); + else + row[model.canvas]=canvas_interface()->get_canvas(); + + LinkableValueNode::Handle linkable; + linkable=LinkableValueNode::Handle::cast_dynamic(value_node); + + if(linkable && do_children) + { + row[model.link_count] = linkable->link_count(); + for(int i=0;ilink_count();i++) + { + Gtk::TreeRow child_row=*(append(row.children())); + child_row[model.link_id] = i; + child_row[model.canvas] = static_cast(row[model.canvas]); + child_row[model.name] = linkable->link_local_name(i); + set_row(child_row,synfigapp::ValueDesc(linkable,i)); + } + } + return; + } + else + { + //row[model.is_value_node] = false; + //row[model.is_editable] = true; + //row[model.label] = Glib::ustring(row[model.name]); + return; + } + } + catch(synfig::Exception::IDNotFound x) + { + synfig::error(__FILE__":%d: IDNotFound thrown",__LINE__); + erase(row); + return; + } + + // We should never get to this point + assert(0); +} + +void +CanvasTreeStore::refresh_row(Gtk::TreeModel::Row &row, bool do_children) +{ + synfigapp::ValueDesc value_desc=row[model.value_desc]; + + if(value_desc) + { + if((bool)row[model.is_value_node] != value_desc.is_value_node() || + (!bool(row[model.is_value_node]) && row[model.link_count]!=0)) + { + set_row(row,value_desc,do_children); + return; + } + + if(row[model.is_value_node]) + { + ValueNode::Handle value_node(value_desc.get_value_node()); + + if(ValueNode::Handle(row[model.value_node])!=value_node) + { + rebuild_row(row,do_children); + return; + } + + //row[model.id]=value_node->get_id(); + + // Setup the row's label + /* + if(value_node->get_id().empty()) + row[model.label] = Glib::ustring(row[model.name]); + else if(Glib::ustring(row[model.name]).empty()) + row[model.label] = value_node->get_id(); + else + row[model.label] = Glib::ustring(row[model.name])+" ("+value_node->get_id()+')'; + */ + + LinkableValueNode::Handle linkable; + linkable=LinkableValueNode::Handle::cast_dynamic(value_node); + if(do_children && linkable && ((int)row[model.link_count] != linkable->link_count())) + { + // Gtk::TreeModel::Children children = row.children(); + // while(!children.empty() && erase(children.begin())); + + set_row(row,value_desc); + return; + } + } + else + { + //row[model.label] = Glib::ustring(row[model.name]); + //row[model.is_value_node] = false; + //row[model.is_editable] = true; + } + } + if(!do_children) + return; + + Gtk::TreeModel::Children children = row.children(); + Gtk::TreeModel::Children::iterator iter; + + if(!children.empty()) + for(iter = children.begin(); iter != children.end(); ++iter) + { + Gtk::TreeRow row=*iter; + refresh_row(row); + } +} + +void +CanvasTreeStore::rebuild_row(Gtk::TreeModel::Row &row, bool do_children) +{ + synfigapp::ValueDesc value_desc=(synfigapp::ValueDesc)row[model.value_desc]; + + if(value_desc && value_desc.get_value_node()) + { + ValueNode::Handle value_node; + value_node=value_desc.get_value_node(); + + assert(value_node);if(!value_node)return; + + if(value_node && value_node!=(ValueNode::Handle)row[model.value_node]) + { +// Gtk::TreeModel::Children children = row.children(); +// while(!children.empty() && erase(children.begin())); + + set_row(row,value_desc,do_children); + return; + } + + LinkableValueNode::Handle linkable; + linkable=LinkableValueNode::Handle::cast_dynamic(value_node); + + if( do_children && linkable && (int)row[model.link_count] != linkable->link_count()) + { +// Gtk::TreeModel::Children children = row.children(); +// while(!children.empty() && erase(children.begin())); + + set_row(row,value_desc); + return; + } + + //if(!value_node) + // value_node=row[model.value_node]; + + row[model.id]=value_node->get_id(); + + // Setup the row's label + if(value_node->get_id().empty()) + row[model.label] = Glib::ustring(row[model.name]); + else if(Glib::ustring(row[model.name]).empty()) + row[model.label] = value_node->get_id(); + else + row[model.label] = Glib::ustring(row[model.name])+" ("+value_node->get_id()+')'; + } + else + { + row[model.label] = Glib::ustring(row[model.name]); + row[model.is_value_node] = false; + row[model.is_editable] = true; + Gtk::TreeModel::Children children = row.children(); + while(!children.empty() && erase(children.begin())) + ; + } + if(!do_children) + return; + + Gtk::TreeModel::Children children = row.children(); + Gtk::TreeModel::Children::iterator iter; + if(!children.empty()) + for(iter = children.begin(); iter != children.end(); ++iter) + { + Gtk::TreeRow row=*iter; + rebuild_row(row); + } +} + +CellRenderer_ValueBase* +CanvasTreeStore::add_cell_renderer_value(Gtk::TreeView::Column* column) +{ + const CanvasTreeStore::Model model; + + CellRenderer_ValueBase* ret; + + ret=Gtk::manage( new CellRenderer_ValueBase() ); + + column->pack_start(*ret,true); + column->add_attribute(ret->property_value(), model.value); + column->add_attribute(ret->property_editable(), model.is_editable); + column->add_attribute(ret->property_canvas(), model.canvas); + + return ret; +} + +CellRenderer_TimeTrack* +CanvasTreeStore::add_cell_renderer_value_node(Gtk::TreeView::Column* column) +{ + const CanvasTreeStore::Model model; + + CellRenderer_TimeTrack* ret; + + ret = Gtk::manage( new CellRenderer_TimeTrack() ); + + column->pack_start(*ret,true); + //column->add_attribute(ret->property_visible(), model.is_value_node); + column->add_attribute(ret->property_value_desc(), model.value_desc); + column->add_attribute(ret->property_canvas(), model.canvas); + + + return ret; +}