//$Id: element-combobox-base.h,v 1.4 2006/10/06 22:35:46 cactus Exp $ -*- c++ -*- /* Guikachu Copyright (C) 2001-2006 ÉRDI Gergõ * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 * as published by the Free Software Foundation. * * This program 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. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef GUIKACHU_WIDGETS_ELEMENT_COMBOBOX_BASE_H #define GUIKACHU_WIDGETS_ELEMENT_COMBOBOX_BASE_H #include #include #include #include "id-manager.h" namespace Guikachu { namespace GUI { template class ElementComboBoxBase: public Gtk::ComboBox { protected: typedef Element element_t; typedef typename element_t::type_t element_type_t; typedef std::set element_typeset_t; private: Gtk::TreeModelColumn col; Glib::RefPtr store; typedef std::map row_map_t; row_map_t row_map; element_typeset_t types; protected: ElementComboBoxBase (const element_typeset_t &types); public: element_t * get_value () const; void set_value (element_t *res); private: void cell_cb (const Gtk::TreeModel::iterator &iter, Gtk::CellRendererText *cell); Gtk::ListStore::iterator get_place (element_t *res) const; protected: void element_created_cb (element_t *res); void element_changed_cb (element_t *res); void element_removed_cb (element_t *res); }; namespace ElementComboBoxBase_Helpers { Glib::ustring get_empty_label (); } /**** Template implementations **********************************************/ template ElementComboBoxBase::ElementComboBoxBase (const element_typeset_t &types_): types (types_) { Gtk::TreeModel::ColumnRecord cols; cols.add (col); store = Gtk::ListStore::create (cols); set_model (store); Gtk::CellRendererText *cell_text = new Gtk::CellRendererText; pack_start (*manage (cell_text), true); set_cell_data_func (*cell_text, sigc::bind (sigc::mem_fun (*this, &ElementComboBoxBase::cell_cb), cell_text)); Gtk::TreeRow row = *(store->append ()); row[col] = 0; row_map[0] = row; } template void ElementComboBoxBase::cell_cb (const Gtk::TreeModel::iterator &iter, Gtk::CellRendererText *cell) { g_return_if_fail (cell); element_t *element = (*iter)[col]; Glib::ustring label = ElementComboBoxBase_Helpers::get_empty_label (); if (element) label = element->id; cell->property_text () = label; } template Element * ElementComboBoxBase::get_value () const { Gtk::TreeModel::iterator iter = get_active (); if (!iter) return 0; return (*iter)[col]; } template void ElementComboBoxBase::set_value (element_t *element) { typename row_map_t::iterator row_found = row_map.find (element); g_return_if_fail (row_found != row_map.end ()); set_active (row_found->second); } namespace { template class ElementRowCompare { typedef Element element_t; Gtk::TreeModelColumn col; public: ElementRowCompare (Gtk::TreeModelColumn col_): col (col_) {} bool operator() (const Gtk::TreeRow &row, element_t *element) const { element_t *curr_element = row[col]; if (!curr_element) return true; return IDManager::NoCase () (curr_element->id, element->id); } }; } // anonymous namespace template Gtk::ListStore::iterator ElementComboBoxBase::get_place (element_t *element) const { return std::lower_bound (store->children ().begin (), store->children ().end (), element, ElementRowCompare (col)); } template void ElementComboBoxBase::element_created_cb (element_t *element) { if (types.find (element->get_type ()) == types.end ()) return; Gtk::TreeRow row = *(store->insert (get_place (element))); row[col] = element; row_map[element] = row; element->changed.connect (sigc::bind (sigc::mem_fun (*this, &ElementComboBoxBase::element_changed_cb), element)); } template void ElementComboBoxBase::element_changed_cb (element_t *element) { Gtk::TreeRow selected_row = *get_active (); bool selected = (selected_row[col] == element); typename row_map_t::iterator row_found = row_map.find (element); g_return_if_fail (row_found != row_map.end ()); store->erase (row_found->second); Gtk::TreeRow row = *(store->insert (get_place (element))); row[col] = element; row_map[element] = row; if (selected) set_active (row); } template void ElementComboBoxBase::element_removed_cb (element_t *element) { if (types.find (element->get_type ()) == types.end ()) return; typename row_map_t::iterator row_found = row_map.find (element); g_return_if_fail (row_found != row_map.end ()); store->erase (row_found->second); row_map.erase (row_found); } } } #endif /* !GUIKACHU_WIDGETS_ELEMENT_COMBOBOX_BASE_H */