//$Id: string-list.cc,v 1.22 2006/10/06 22:35:47 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 */ #include "string-list.h" #include #include "ui.h" #include #include #include using namespace Guikachu::GUI::PropertyEditors; StringList::StringList (property_t &property_, op_factory_t *op_factory_): Gtk::HBox (false, 5), property (property_), op_factory (op_factory_), btnAdd (Gtk::StockID (Gtk::Stock::ADD)), btnUp (Gtk::StockID (Gtk::Stock::GO_UP)), btnDown (Gtk::StockID (Gtk::Stock::GO_DOWN)), btnRemove (Gtk::StockID (Gtk::Stock::REMOVE)), update_block (false) { set_border_width (5); // The ScrolledWindow around the TreeView Gtk::ScrolledWindow *scrollwin = new Gtk::ScrolledWindow; scrollwin->add (treeview); scrollwin->set_policy (Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC); scrollwin->set_shadow_type (Gtk::SHADOW_IN); scrollwin->show_all (); add (*manage (scrollwin)); // Right pane: the modifier buttons btnAdd.signal_clicked ().connect (sigc::mem_fun (*this, &StringList::button_add_cb)); btnRemove.signal_clicked ().connect (sigc::mem_fun (*this, &StringList::button_remove_cb)); btnUp.signal_clicked ().connect (sigc::mem_fun (*this, &StringList::button_up_cb)); btnDown.signal_clicked ().connect (sigc::mem_fun (*this, &StringList::button_down_cb)); buttons.set_spacing (5); buttons.add (btnUp); buttons.add (btnDown); buttons.add (btnRemove); buttons.add (btnAdd); buttons.show_all (); pack_start (buttons, false, false); property.changed.connect (sigc::mem_fun (*this, &StringList::update)); // We call setup() from and idle handler because it needs to call // virtual member functions Glib::signal_idle ().connect (sigc::bind_return ( sigc::mem_fun (*this, &StringList::setup), false)); } void StringList::setup () { // Set up ListStore Gtk::TreeModel::ColumnRecord cols; create_columns (cols); treestore = Gtk::ListStore::create (cols); treestore->signal_row_changed ().connect (sigc::mem_fun (*this, &StringList::store_changed_cb)); // Set up TreeView treeview.set_model (treestore); create_view_columns (col_text_num); treeview.set_headers_visible (false); treeview.get_selection ()->set_mode (Gtk::SELECTION_BROWSE); treeview.get_selection ()->signal_changed ().connect (sigc::mem_fun (*this, &StringList::selection_cb)); update (); selection_cb (); } void StringList::create_columns (Gtk::TreeModel::ColumnRecord &columns) { columns.add (col_text); } void StringList::create_view_columns (int &col_text_num) { treeview.append_column_editable ("", col_text); col_text_num = 0; } std::string StringList::new_item () { return _("New Item"); } void StringList::add_button (Gtk::Widget &button) { Gtk::Box::BoxList &box_list = buttons.children (); box_list.insert (box_list.find (btnRemove), button); } unsigned int StringList::get_selected_row () { Gtk::TreeModel::iterator selected_i = treeview.get_selection ()->get_selected (); g_return_val_if_fail (selected_i, 0); Gtk::TreeModel::Path selected_path = treestore->get_path (selected_i); return selected_path[0]; } void StringList::selection_cb () { Gtk::TreeModel::iterator selected_i = treeview.get_selection ()->get_selected (); if (!selected_i) { btnUp.set_sensitive (false); btnDown.set_sensitive (false); Gtk::Box::BoxList::iterator begin = ++buttons.children ().find (btnDown); Gtk::Box::BoxList::iterator end = buttons.children ().find (btnAdd); for (Gtk::Box::BoxList::iterator i = begin; i != end; i++) i->get_widget ()->set_sensitive (false); return; } unsigned int index = get_selected_row (); const value_t &curr_val = property; btnUp.set_sensitive ((index > 0)); btnDown.set_sensitive ((index < (curr_val.size () - 1))); Gtk::Box::BoxList::iterator begin = ++buttons.children ().find (btnDown); Gtk::Box::BoxList::iterator end = buttons.children ().find (btnAdd); for (Gtk::Box::BoxList::iterator i = begin; i != end; i++) i->get_widget ()->set_sensitive (true); } void StringList::button_remove_cb () { Gtk::TreeModel::iterator selection_i = treeview.get_selection ()->get_selected (); g_return_if_fail (selection_i); Gtk::TreeModel::Path selection_path = treestore->get_path (selection_i); unsigned int index = selection_path[0]; value_t val = property; val.erase (val.begin () + index); property = val; item_removed.emit (index); } void StringList::button_up_cb () { Gtk::TreeModel::iterator iter = treeview.get_selection ()->get_selected (); g_return_if_fail (iter); Gtk::TreeModel::Path path = treestore->get_path (iter); unsigned int index = path[0]; g_return_if_fail (index > 0); op_factory->push_move (index, index - 1); up.emit (index); UI::flush_events (); --path[0]; treeview.get_selection ()->select (path); } void StringList::button_down_cb () { Gtk::TreeModel::iterator iter = treeview.get_selection ()->get_selected (); g_return_if_fail (iter); Gtk::TreeModel::Path path = treestore->get_path (iter); unsigned int index = path[0]; op_factory->push_move (index, index + 1); down.emit (index); UI::flush_events (); ++path[0]; treeview.get_selection ()->select (path); } void StringList::button_add_cb () { value_t val = property; Gtk::TreeModel::iterator iter = treeview.get_selection ()->get_selected (); Gtk::TreeModel::Path path ("0"); int index; if (iter) { path = treestore->get_path (iter); index = path[0] + 1; } else { index = val.size (); } op_factory->push_add (index, new_item ()); item_added.emit (index); path[0] = index; UI::flush_events (); treeview.get_selection ()->select (path); Gtk::TreeViewColumn *col = treeview.get_column (col_text_num); g_return_if_fail (col); treeview.set_cursor (path, *col, true); } void StringList::store_changed_cb (const Gtk::TreeModel::Path &path, const Gtk::TreeModel::iterator &iter) { if (update_block) return; Glib::ustring new_text = (*iter)[col_text]; std::string new_text_val = convert_to_ascii (new_text); int index = path[0]; op_factory->push_change (index, new_text_val); } void StringList::update_row (Gtk::TreeRow &row, value_t::size_type i) { const value_t &curr_val = property; row[col_text] = curr_val[i]; } void StringList::update () { update_block = true; const value_t &curr_val = property; Gtk::TreeModel::Path store_path ("0"); for (value_t::size_type i = 0; i != curr_val.size (); ++i, ++store_path[0]) { Gtk::TreeModel::iterator store_iter = treestore->get_iter (store_path); if (!store_iter) store_iter = treestore->append (); Gtk::TreeRow row (*store_iter); update_row (row, i); } // Remove excessive treestore rows for (Gtk::TreeModel::iterator store_iter = treestore->get_iter (store_path); store_iter; store_iter = treestore->get_iter (store_path)) treestore->erase (store_iter); update_block = false; }