1/* Copyright(C) 2002 The gtkmm Development Team 2 * 3 * This library is free software; you can redistribute it and/or 4 * modify it under the terms of the GNU Lesser General Public 5 * License as published by the Free Software Foundation; either 6 * version 2.1 of the License, or(at your option) any later version. 7 * 8 * This library is distributed in the hope that it will be useful, 9 * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 11 * Lesser General Public License for more details. 12 * 13 * You should have received a copy of the GNU Lesser General Public 14 * License along with this library; if not, write to the Free Software 15 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 16 */ 17 18// This is for including the config header before any code (such as 19// the #ifndef GTKMM_DISABLE_DEPRECATED in deprecated classes) is generated: 20_CONFIGINCLUDE(gtkmmconfig.h) 21 22#include <vector> 23 24#include <gtkmm/container.h> 25#include <gtkmm/treeviewcolumn.h> 26#include <gtkmm/treeselection.h> 27#include <gtkmm/treemodelcolumn.h> 28#include <gtkmm/cellrenderer.h> 29#include <gtkmm/scrollable.h> 30#include <gtkmm/targetentry.h> 31#include <gtkmm/entry.h> 32#include <gtkmm/tooltip.h> 33 34_DEFS(gtkmm,gtk) 35_PINCLUDE(gtkmm/private/container_p.h) 36 37namespace Gtk 38{ 39 40_CC_INCLUDE(gtk/gtk.h) 41_WRAP_ENUM(TreeViewDropPosition, GtkTreeViewDropPosition) 42_WRAP_ENUM(TreeViewGridLines, GtkTreeViewGridLines) 43 44 45#ifndef DOXYGEN_SHOULD_SKIP_THIS 46 47class TreeView; 48 49namespace TreeView_Private 50{ 51/* This helper function is not a member of TreeView just for the reason that 52 * there are compilers that have problems compiling it otherwise. E.g. in gcc 53 * 2.95.3 a compiler bug prevents member functions from refering to specialized 54 * member function templates and that's what we do here: In function 55 * _connect_auto_store_editable_signal_handler we build a slot from 56 * TreeView::_auto_store_on_cellrenderer_*_edited. (The latter must be member 57 * functions of TreeView since we connect them to signals and we want the 58 * connections to vanish when the TreeView dies, of course.) 59 */ 60 template <class ColumnType> inline 61 void _connect_auto_store_editable_signal_handler(Gtk::TreeView* this_p, Gtk::CellRenderer* pCellRenderer, const Gtk::TreeModelColumn<ColumnType>& model_column); 62 63 template <class ColumnType> inline 64 void _connect_auto_store_numeric_editable_signal_handler(Gtk::TreeView* this_p, Gtk::CellRenderer* pCellRenderer, const Gtk::TreeModelColumn<ColumnType>& model_column); 65 66 template<class ColumnType> inline 67 void _auto_store_on_cellrenderer_text_edited_string(const Glib::ustring& path_string, const Glib::ustring& new_text, int model_column, const Glib::RefPtr<Gtk::TreeModel>& model); 68 69 template <class ColumnType> inline 70 void _auto_store_on_cellrenderer_text_edited_numerical(const Glib::ustring& path_string, const Glib::ustring& new_text, int model_column, const Glib::RefPtr<Gtk::TreeModel>& model); 71 72 template <class ColumnType> inline 73 void _auto_cell_data_func(Gtk::CellRenderer* cell, const Gtk::TreeModel::iterator& iter, int model_column, const Glib::ustring& format); 74} 75 76#endif //DOXYGEN_SHOULD_SKIP_THIS 77 78 79//class TreeViewColumn; 80class TreeModel; 81 82/** @defgroup TreeView TreeView Classes 83 * These classes are used with the Gtk::TreeView widget. 84 */ 85 86/** The TreeView widget displays the model (Gtk::TreeModel) data and allows the user to interact with it. 87 * The View can show all of the model's columns, or just some, and it can show them in various ways. 88 * You must provide the TreeModel in the constructor, or with set_model(). 89 * 90 * Add View columns with append_column(), append_column_editable(), append_column_numeric(), 91 * append_column_numeric_editable(), insert_column(), or insert_column_editable(). 92 * 93 * You can manipulate the selection by obtaining the @link Gtk::TreeSelection Gtk::TreeView::Selection@endlink from get_selection(). 94 * 95 * @ingroup Widgets 96 * @ingroup Containers 97 * @ingroup TreeView 98 */ 99class TreeView 100 : public Container, 101 public Scrollable 102{ 103 _CLASS_GTKOBJECT(TreeView, GtkTreeView, GTK_TREE_VIEW, Gtk::Container, GtkContainer) 104 _IMPLEMENTS_INTERFACE(Scrollable) 105 _IGNORE(gtk_tree_view_get_path_at_pos, gtk_tree_view_set_destroy_count_func, gtk_tree_view_get_cursor 106 gtk_tree_view_insert_column_with_data_func, gtk_tree_view_get_drag_dest_row, gtk_tree_view_get_dest_row_at_pos) 107public: 108 /** A visible column in a Gtk::TreeView widget. 109 */ 110 typedef TreeViewColumn Column; 111 112 /** A selection object for Gtk::TreeView. 113 */ 114 typedef TreeSelection Selection; 115 116 /** Default constructor. 117 */ 118 _CTOR_DEFAULT() 119 120 /** 121 Constructor that binds to a TreeModel. 122 */ 123 _WRAP_CTOR(TreeView(const Glib::RefPtr<TreeModel>& model), gtk_tree_view_new_with_model) 124 125 _WRAP_METHOD(Glib::RefPtr<TreeModel> get_model(), gtk_tree_view_get_model, refreturn) 126 _WRAP_METHOD(Glib::RefPtr<const TreeModel> get_model() const, gtk_tree_view_get_model, refreturn) 127 _WRAP_METHOD(void set_model(const Glib::RefPtr<TreeModel>& model), gtk_tree_view_set_model) 128 129 /** Remove the model from the TreeView. 130 * 131 * @see set_model(). 132 * 133 * @newin{2,8} 134 */ 135 void unset_model(); 136 137 _WRAP_METHOD(Glib::RefPtr<TreeSelection> get_selection(), gtk_tree_view_get_selection, refreturn) 138 _WRAP_METHOD(Glib::RefPtr<const TreeSelection> get_selection() const, gtk_tree_view_get_selection, refreturn, constversion) 139 _IGNORE(gtk_tree_view_get_hadjustment, gtk_tree_view_get_vadjustment, 140 gtk_tree_view_set_hadjustment, gtk_tree_view_set_vadjustment) //deprecated 141 142 _WRAP_METHOD(bool get_headers_visible() const, gtk_tree_view_get_headers_visible) 143 _WRAP_METHOD(void set_headers_visible(bool headers_visible = true), gtk_tree_view_set_headers_visible) 144 _WRAP_METHOD(void columns_autosize(), gtk_tree_view_columns_autosize) 145 _WRAP_METHOD(bool get_headers_clickable() const, gtk_tree_view_get_headers_clickable) 146 _WRAP_METHOD(void set_headers_clickable(bool setting = true), gtk_tree_view_set_headers_clickable) 147 _WRAP_METHOD(void set_rules_hint(bool setting = true), gtk_tree_view_set_rules_hint, deprecated "Don't use this API. There is no replacement.") 148 _WRAP_METHOD(bool get_rules_hint() const, gtk_tree_view_get_rules_hint, deprecated "Don't use this API. There is no replacement.") 149 150 _WRAP_METHOD(void set_activate_on_single_click(bool single = true), gtk_tree_view_set_activate_on_single_click) 151 _WRAP_METHOD(bool get_activate_on_single_click() const, gtk_tree_view_get_activate_on_single_click) 152 153 _WRAP_METHOD(int append_column(TreeViewColumn& column), gtk_tree_view_append_column) 154 155 /** Appends a View column with the appropriate CellRenderer for the Model column. 156 * 157 * The CellRenderer can only be created automatically for some basic 158 * column types, such as Glib::ustring, int, double, bool, and Gdk::Pixbuf. 159 * If the type is not supported then the following warning will be shown: 160 * GLib-GObject-WARNING **: unable to set property `text' of type 161 * `gchararray' from value of type `glibmm__CustomBoxed_t'. 162 * 163 * If the default formatting is not sufficient, or the numeric type is 164 * not supported, then you could use append_column_numeric(). Or you 165 * could create the TreeView::Column and/or CellRenderer 166 * manually and use TreeViewColumn::set_cell_data_func() to provide a callback 167 * that converts the model value into a string representation with . 168 * 169 * @param title The text to be used in the title header of this column. 170 * @param model_column The column in the TreeModel that will be rendered by this View column. 171 * @result The number of columns in the View after appending. 172 */ 173 template <class ColumnType> inline 174 int append_column(const Glib::ustring& title, const TreeModelColumn<ColumnType>& model_column); 175 176 /** Like append_column(), but only for numeric types, which will be displayed in the specified format. 177 * This convenience template uses TreeView::Column::set_cell_data_func(), so the numeric formatting will 178 * be deactivated if you specify your own cell_data callback by calling set_cell_data_func() again. 179 * 180 * @param title The text to be used in the title header of this column. 181 * @param model_column The column in the TreeModel that will be rendered by this View column. 182 * @param format A printf-style format, such as "%d", used to create a text representation of the number. 183 * @result The number of columns in the View after appending. 184 */ 185 template <class ColumnType> inline 186 int append_column_numeric(const Glib::ustring& title, const TreeModelColumn<ColumnType>& model_column, const Glib::ustring& format); 187 188 //TODO: danielk suggested use of Glib::Value to simplify/improve this. 189 /** Appends a View column with the appropriate CellRenderer for the Model 190 * column. The compiler will attempt to instantiate appropriate template 191 * code to automatically store user changes in the model. To intercept the 192 * user's change and implement non-default logic, or if the compiler can't 193 * instantiate appropriate code for your model type, you could use 194 * append_column() and connect a signal handler to the CellRenderer. 195 * 196 * @see append_column_numeric_editable(). 197 * 198 * @param title The text to be used in the title header of this column. 199 * @param model_column The column in the TreeModel that will be rendered by this View column. 200 * @result The number of columns in the View after appending. 201 */ 202 template <class ColumnType> inline 203 int append_column_editable(const Glib::ustring& title, const TreeModelColumn<ColumnType>& model_column); 204 205 /** Like append_column_editable(), but only for numeric types, which will be displayed in the specified format. 206 * This convenience template uses TreeView::Column::set_cell_data_func(), so the numeric formatting will 207 * be deactivated if you specify your own cell_data callback by calling set_cell_data_func() again. 208 * 209 * Note that the user's input will be interpreted as decimal (base 10), regardless of the @a format. 210 * 211 * @param title The text to be used in the title header of this column. 212 * @param model_column The column in the TreeModel that will be rendered by this View column. 213 * @param format A printf-style format, such as "%d", used to create a text representation of the number. 214 * @result The number of columns in the View after appending. 215 */ 216 template <class ColumnType> inline 217 int append_column_numeric_editable(const Glib::ustring& title, const TreeModelColumn<ColumnType>& model_column, const Glib::ustring& format); 218 219 220 /// Creates a View column containing the CellRenderer, and appends it. 221 int append_column(const Glib::ustring& title, CellRenderer& cell); 222 223 _WRAP_METHOD(int remove_column(TreeViewColumn& column), gtk_tree_view_remove_column) 224 225 /// Removes all View columns. 226 void remove_all_columns(); 227 228 _WRAP_METHOD(int insert_column(TreeViewColumn& column, int position), gtk_tree_view_insert_column) 229 230 /** Creates a View column containing the CellRenderer, and inserts it. 231 * 232 * @param title The text to be used in the title header of this column. 233 * @param cell The CellRenderer. 234 * @param position The position at which the CellRenderer should be inserted. 235 * @result The number of columns in the View after inserting. 236 */ 237 int insert_column(const Glib::ustring& title, CellRenderer& cell, int position); 238 239 _IGNORE(gtk_tree_view_insert_column_with_attributes) 240 241 /** Inserts a View column with the appropriate CellRenderer for the Model column. 242 * 243 * @param title The text to be used in the title header of this column. 244 * @param model_column The column in the TreeModel that will be rendered by this View column. 245 * @param position The position at which the CellRenderer should be inserted. 246 * @result The number of columns in the View after inserting. 247 */ 248 template <class ColumnType> inline 249 int insert_column(const Glib::ustring& title, const TreeModelColumn<ColumnType>& model_column, int position); 250 251 /** Inserts a View column with the appropriate CellRenderer for the Model 252 * column. The compiler will attempt to instantiate appropriate template 253 * code to automatically store user changes in the model. To intercept the 254 * user's change and implement non-default logic, or if the compiler can't 255 * instantiate appropriate code for your model type, you should use 256 * insert_column() and connect a signal handler to the CellRenderer. 257 * 258 * @param title The text to be used in the title header of this column. 259 * @param model_column The column in the TreeModel that will be rendered by this View column. 260 * @param position The position at which the CellRenderer should be inserted. 261 * @result The number of columns in the View after inserting. 262 */ 263 template <class ColumnType> inline 264 int insert_column_editable(const Glib::ustring& title, const TreeModelColumn<ColumnType>& model_column, int position); 265 266_DEPRECATE_IFDEF_START 267 /** @deprecated Use SlotTreeCellData instead. 268 */ 269 typedef TreeViewColumn::SlotCellData SlotCellData; 270_DEPRECATE_IFDEF_END 271 272 typedef TreeViewColumn::SlotTreeCellData SlotTreeCellData; 273 274 /** 275 * Inserts a new column into the TreeView with the given cell 276 * renderer and a SlotTreeCellData to set cell renderer attributes 277 * (normally using data from the model). 278 * 279 * @param position Position to insert, -1 for append 280 * @param title column title 281 * @param cell cell renderer for column 282 * @param slot function to set attributes of cell renderer 283 * @return number of columns in the TreeView after the insert 284 */ 285 int insert_column_with_data_func(int position, const Glib::ustring& title, CellRenderer& cell, const SlotTreeCellData& slot); 286 287 _WRAP_METHOD(guint get_n_columns() const, gtk_tree_view_get_n_columns) 288 289 _WRAP_METHOD(TreeViewColumn* get_column(int n), gtk_tree_view_get_column) 290 _WRAP_METHOD(const TreeViewColumn* get_column(int n) const, gtk_tree_view_get_column, constversion) 291 292 //The column index is of the view, not the model, so we do not need TreeViewColumn* get_column(TreeViewColumn& base_column). 293 294 /** Gets the CellRenderer for that column. 295 * You should dynamic_cast<> to the expected derived CellRenderer type. 296 * This assumes that the TreeViewColumn contains only one CellRenderer. 297 * 298 * @param n The position of the view column. 299 * @result The CellRenderer. 300 */ 301 CellRenderer* get_column_cell_renderer(int n); 302 303 //TODO: Add TreeViewColumn* get_column_cell_renderer(TreeViewColumn& base_column); and a const one. 304 305 306 /** Gets the CellRenderer for that column. 307 * You should dynamic_cast<> to the expected derived CellRenderer type. 308 * This assumes that the TreeViewColumn contains only one CellRenderer. 309 * 310 * @param n The position of the view column. 311 * @result The CellRenderer. 312 */ 313 const CellRenderer* get_column_cell_renderer(int n) const; 314 315#m4 _CONVERSION(`GList*',`std::vector<TreeViewColumn*>',`Glib::ListHandler<TreeViewColumn*>::list_to_vector($3, Glib::OWNERSHIP_SHALLOW)') 316 _WRAP_METHOD(std::vector<TreeViewColumn*> get_columns(), gtk_tree_view_get_columns) 317#m4 _CONVERSION(`GList*',`std::vector<const TreeViewColumn*>',`Glib::ListHandler<const TreeViewColumn*>::list_to_vector($3, Glib::OWNERSHIP_SHALLOW)') 318 _WRAP_METHOD(std::vector<const TreeViewColumn*> get_columns() const, gtk_tree_view_get_columns) 319 320 _WRAP_METHOD(void move_column_after(TreeViewColumn& column, TreeViewColumn& base_column), gtk_tree_view_move_column_after) 321 322 /** This method moves column to the first position in the view. 323 * 324 * @param column The view column that will be moved 325 */ 326 void move_column_to_start(TreeViewColumn& column); 327 328 _WRAP_METHOD(void set_expander_column(TreeViewColumn& column), gtk_tree_view_set_expander_column) 329 330 /** This method resets the expander arrow to the default - the first visible column. 331 * @see set_expander_column(). 332 */ 333 void reset_expander_column(); 334 335 _WRAP_METHOD(TreeViewColumn* get_expander_column(), gtk_tree_view_get_expander_column) 336 _WRAP_METHOD(const TreeViewColumn* get_expander_column() const, gtk_tree_view_get_expander_column, constversion) 337 338 /** For instance, 339 * bool on_column_drop(TreeView*, tree_view, TreeViewColumn* column, TreeViewColumn* prev_column, TreeViewColumn* next_column) 340 * 341 * This function is called on every column pair in turn at the beginning of a column drag to determine where a 342 * drop can take place. The arguments passed to the function are: the tree_view, the view Column being dragged, 343 * and the two view Columns determining the drop spot. If either of the view Column arguments for the drop spot 344 * are 0, then they indicate an edge. 345 */ 346 typedef sigc::slot<bool, TreeView*, TreeViewColumn*, TreeViewColumn*, TreeViewColumn*> SlotColumnDrop; 347 348 /** Sets a callback slot for determining where a column may be dropped when dragged. 349 * This function is called on every column pair in turn at the beginning of a column drag to determine where a 350 * drop can take place. The arguments passed to the function are: the tree_view, the view Column being dragged, 351 * and the two view Columns determining the drop spot. If either of the view Column arguments for the drop spot 352 * are 0, then they indicate an edge. 353 * 354 * See unset_column_drag_function(). 355 * 356 * @param slot A callback function to determine which columns are reorderable. 357 */ 358 void set_column_drag_function(const SlotColumnDrop& slot); 359 _IGNORE(gtk_tree_view_set_column_drag_function) 360 361 /** See set_column_drag_function(). After this method has been called, the TreeView reverts to the default behavior of 362 * allowing all columns to be dropped everywhere. 363 */ 364 void unset_column_drag_function(); 365 366 _WRAP_METHOD(void scroll_to_point(int tree_x, int tree_y), gtk_tree_view_scroll_to_point) 367 368 /** Moves the alignments of tree view to the position specified by @a column and @a path. 369 * @a row_align determines where the row is placed, and @a col_align determines where 370 * column is placed. Both are expected to be between 0.0 and 1.0. 0.0 means left/top 371 * alignment, 1.0 means right/bottom alignment, 0.5 means center. 372 * 373 * This function only works if the model is set, and @a path is a valid row on the model. 374 * If the model changes before the tree view is realized, the centered path will be 375 * modified to reflect this change. 376 * 377 * @param path The path of the row to move to. 378 * @param column The Gtk::TreeViewColumn to move horizontally to. 379 * @param row_align The vertical alignment of the row specified by @a path. 380 * @param col_align The horizontal alignment of the column specified by @a column. 381 */ 382 void scroll_to_cell(const TreeModel::Path& path, TreeViewColumn& column, float row_align, float col_align); 383 _IGNORE(gtk_tree_view_scroll_to_cell) 384 385 /** Moves the alignments of tree view to the position specified by @a column and @a path. 386 * The tree does the minimum amount of work to scroll the cell onto the screen. This means 387 * that the cell will be scrolled to the edge closest to it's current position. If the cell 388 * is currently visible on the screen, nothing is done. 389 * 390 * This function only works if the model is set, and @a path is a valid row on the model. 391 * If the model changes before the tree_view is realized, the centered path will be modified 392 * to reflect this change. 393 * 394 * @param path The path of the row to move to. 395 * @param column The Gtk::TreeViewColumn to move horizontally to. 396 */ 397 void scroll_to_cell(const TreeModel::Path& path, TreeViewColumn& column); 398 399 /** Moves the alignments of tree view to the position specified by @a path. 400 * @a row_align determines where the row is placed, and is expected to be between 0.0 401 * and 1.0. 0.0 means top alignment, 1.0 means bottom alignment, 0.5 means center. 402 * 403 * This function only works if the model is set, and @a path is a valid row on the model. 404 * If the model changes before the tree view is realized, the centered path will be 405 * modified to reflect this change. 406 * 407 * @param path The path of the row to move to. 408 * @param row_align The vertical alignment of the row specified by @a path. 409 */ 410 void scroll_to_row(const TreeModel::Path& path, float row_align); 411 412 /** Moves the alignments of tree view to the position specified by @a path. 413 * The tree does the minimum amount of work to scroll the row onto the screen. This means 414 * that the row will be scrolled to the edge closest to it's current position. If the row 415 * is currently visible on the screen, nothing is done. 416 * 417 * This function only works if the model is set, and @a path is a valid row on the model. 418 * If the model changes before the tree view is realized, the centered path will be 419 * modified to reflect this change. 420 * 421 * @param path The path of the row to move to. 422 */ 423 void scroll_to_row(const TreeModel::Path& path); 424 425 /** Moves the alignments of tree view to the position specified by @a column. 426 * @a col_align determines where the column is placed, and is expected to be between 0.0 427 * and 1.0. 0.0 means left alignment, 1.0 means right alignment, 0.5 means center. 428 * 429 * This function only works if the model is set. If the model changes before the tree 430 * view is realized, the centered path will be modified to reflect this change. 431 * 432 * @param column The Gtk::TreeViewColumn to move horizontally to. 433 * @param col_align The horizontal alignment of the column specified by @a column. 434 */ 435 void scroll_to_column(TreeViewColumn& column, float col_align); 436 437 /** Moves the alignments of tree view to the position specified by @a column. 438 * The tree does the minimum amount of work to scroll the column onto the screen. This means 439 * that the column will be scrolled to the edge closest to it's current position. If the column 440 * is currently visible on the screen, nothing is done. 441 * 442 * This function only works if the model is set. If the model changes before the 443 * tree view is realized, the centered path will be modified to reflect this change. 444 * 445 * @param column The Gtk::TreeViewColumn to move horizontally to. 446 */ 447 void scroll_to_column(TreeViewColumn& column); 448 449 _WRAP_METHOD(void row_activated(const TreeModel::Path& path,TreeViewColumn& column), gtk_tree_view_row_activated) 450 _WRAP_METHOD(void expand_all(), gtk_tree_view_expand_all) 451 _WRAP_METHOD(void collapse_all(), gtk_tree_view_collapse_all) 452 _WRAP_METHOD(void expand_to_path(const TreeModel::Path& path), gtk_tree_view_expand_to_path) 453 _WRAP_METHOD(bool expand_row(const TreeModel::Path& path, bool open_all), gtk_tree_view_expand_row) 454 _WRAP_METHOD(bool collapse_row(const TreeModel::Path& path), gtk_tree_view_collapse_row) 455 456 /** For example, 457 * void on_map_expanded_rows(TreeView* tree_view, const TreeModel::Path& path); 458 */ 459 typedef sigc::slot<void, TreeView*, const TreeModel::Path&> SlotMapping; 460 461 /** Calls the callback slot on all expanded rows. 462 * @param slot A callback function to be called. 463 */ 464 void map_expanded_rows(const SlotMapping& slot); 465 _IGNORE(gtk_tree_view_map_expanded_rows) 466 467 _WRAP_METHOD(bool row_expanded(const TreeModel::Path& path), gtk_tree_view_row_expanded) 468 _WRAP_METHOD(void set_reorderable(bool reorderable = true), gtk_tree_view_set_reorderable) 469 _WRAP_METHOD(bool get_reorderable() const, gtk_tree_view_get_reorderable) 470 471 //TODO: Add set_cursor(path, ModelColumnBase&, start_editing)? 472 _WRAP_METHOD(void set_cursor(const TreeModel::Path& path, TreeViewColumn& focus_column, bool start_editing = false), gtk_tree_view_set_cursor) 473 474 _WRAP_METHOD(void set_cursor(const TreeModel::Path& path, TreeViewColumn& focus_column, CellRenderer& focus_cell, bool start_editing = false), gtk_tree_view_set_cursor_on_cell) 475 476 477 /** Sets the current keyboard focus to be at path , and selects it. 478 * This is useful when you want to focus the user's attention on a particular row. 479 * This function is often followed by Gtk::widget::grab_focus(tree_view) 480 * in order to give keyboard focus to the widget. 481 * 482 * @param path A reference to cursor path. 483 */ 484 void set_cursor(const TreeModel::Path& path); 485 486 /** Fills in path and focus_column with the current path and focus column. 487 * 488 * @param path A reference to be filled with the current cursor path 489 * @param focus_column A reference to be filled with the current focus column 490 */ 491 void get_cursor(TreeModel::Path& path, TreeViewColumn*& focus_column); 492 493/* Layout information */ 494 _WRAP_METHOD(Glib::RefPtr<Gdk::Window> get_bin_window(), gtk_tree_view_get_bin_window, refreturn) 495 _WRAP_METHOD(Glib::RefPtr<const Gdk::Window> get_bin_window() const, gtk_tree_view_get_bin_window, refreturn, constversion) 496 497 /** Finds the path at the point (@a x, @a y), relative to bin_window coordinates 498 * (please see get_bin_window()). 499 * That is, @a x and @a y are relative to an events coordinates. @a x and @a y must 500 * come from an event on the TreeView only where event->window == 501 * get_bin_window(). It is primarily for 502 * things like popup menus. @a path will be filled 503 * with the TreeModel::Path at that point. @a column will be filled 504 * with the column at that point. @a cell_x and @a cell_y return the coordinates 505 * relative to the cell background (i.e. the background_area passed to 506 * Gtk::CellRenderer::render()). This method is only meaningful if 507 * the TreeView is realized. 508 * 509 * For converting widget coordinates (eg. the ones you get from 510 * Widget::property_query_tooltip()), please see 511 * convert_widget_to_bin_window_coords(). 512 * 513 * @param x The x position to be identified (relative to bin_window). 514 * @param y The y position to be identified (relative to bin_window). 515 * @param path A reference to a TreeModel::Path to be filled in 516 * @param column A reference to a TreeViewColumn pointer to be filled in 517 * @param cell_x A reference where the X coordinate relative to the cell 518 * can be placed 519 * @param cell_y A reference where the Y coordinate relative to the cell 520 * can be placed 521 * @return true if a row exists at that coordinate. 522 * 523 * @newin{2,8} 524 */ 525 bool get_path_at_pos(int x, int y, TreeModel::Path& path, TreeViewColumn*& column, int& cell_x, int& cell_y) const; 526 527 /** Finds the path at the point (@a x, @a y), relative to bin_window coordinates 528 * (please see get_bin_window()). 529 * That is, @a x and @a y are relative to an events coordinates. @a x and @a y must 530 * come from an event on the TreeView only where event->window == 531 * get_bin_window(). It is primarily for 532 * things like popup menus. @a path will be filled 533 * with the TreeModel::Path at that point. 534 * This method is only meaningful if the TreeView is realized. 535 * 536 * For converting widget coordinates (eg. the ones you get from 537 * Widget::property_query_tooltip()), please see 538 * convert_widget_to_bin_window_coords(). 539 * 540 * @param x The x position to be identified (relative to bin_window). 541 * @param y The y position to be identified (relative to bin_window). 542 * @param path A reference to a TreeModel::Path to be filled in 543 * @return true if a row exists at that coordinate. 544 * 545 * newin{2,16} 546 */ 547 bool get_path_at_pos(int x, int y, TreeModel::Path& path) const; 548 549 //We ignore the fact that one of the arguments can be 0 - it does not seem useful. 550 _WRAP_METHOD(void get_cell_area(const TreeModel::Path& path, TreeViewColumn& column, Gdk::Rectangle& rect) const, gtk_tree_view_get_cell_area) 551 552 _WRAP_METHOD(void get_background_area(const TreeModel::Path& path, TreeViewColumn& column, Gdk::Rectangle& rect) const, gtk_tree_view_get_background_area) 553 //We ignore the fact that one of the arguments can be 0 - it does not seem useful. 554 555 _WRAP_METHOD(void get_visible_rect(Gdk::Rectangle& visible_rect) const, gtk_tree_view_get_visible_rect) 556 557 bool get_visible_range(TreeModel::Path& start_path, TreeModel::Path& end_path) const; 558 _IGNORE(gtk_tree_view_get_visible_range) 559 560 //TODO: Documentation 561 bool is_blank_at_pos(int x, int y, TreePath& path, TreeViewColumn*& column, int& cell_x, int& cell_y) const; 562 _IGNORE(gtk_tree_view_is_blank_at_pos) 563 564 //TODO: Documentation 565 bool is_blank_at_pos(int x, int y) const; 566 567 568/* Drag-and-Drop support */ 569 _IGNORE(gtk_tree_view_enable_model_drag_source) 570 571 /** 572 * Turns the TreeView into a drag source for automatic DND. 573 * 574 * @param targets Standard container of targets that the drag will support. 575 * @param start_button_mask Mask of allowed buttons to start drag. 576 * @param actions The bitmask of possible actions for a drag from this widget. 577 */ 578 void enable_model_drag_source(const std::vector<TargetEntry>& targets, 579 Gdk::ModifierType start_button_mask = Gdk::MODIFIER_MASK, 580 Gdk::DragAction actions = Gdk::ACTION_COPY | Gdk::ACTION_MOVE); 581 582 // Uses the default "GTK_TREE_MODEL_ROW" target, which the TreeView can handle automatically. 583 584 /** Turns the TreeView into a drag source for automatic DND. 585 * 586 * @param start_button_mask Mask of allowed buttons to start drag. 587 * @param actions The bitmask of possible actions for a drag from this widget. 588 */ 589 void enable_model_drag_source(Gdk::ModifierType start_button_mask = Gdk::MODIFIER_MASK, 590 Gdk::DragAction actions = Gdk::ACTION_COPY | Gdk::ACTION_MOVE); 591 592 _IGNORE(gtk_tree_view_enable_model_drag_dest) 593 594 /** Turns the TreeView into a drop destination for automatic DND. 595 * 596 * @param targets The table of targets that the drag will support. 597 * @param actions The bitmask of possible actions for a drag from this widget. 598 */ 599 void enable_model_drag_dest(const std::vector<TargetEntry>& targets, Gdk::DragAction actions = Gdk::ACTION_COPY | Gdk::ACTION_MOVE); 600 601 /** Turns the TreeView into a drop destination for automatic DND. This uses the default 602 * "GTK_TREE_MODEL_ROW" target, which the TreeView can handle automatically. 603 * 604 * @param actions The bitmask of possible actions for a drag from this widget. 605 */ 606 void enable_model_drag_dest(Gdk::DragAction actions = Gdk::ACTION_COPY | Gdk::ACTION_MOVE); 607 608 /** Undoes the effect of enable_model_drag_source() 609 */ 610 _WRAP_METHOD(void unset_rows_drag_source(), gtk_tree_view_unset_rows_drag_source) 611 612 /** Undoes the effect of enable_model_drag_dest() 613 */ 614 _WRAP_METHOD(void unset_rows_drag_dest(), gtk_tree_view_unset_rows_drag_dest) 615 616 617 /* These are useful to implement your own custom stuff. */ 618 619 /** Sets the row that is highlighted for feedback. 620 * See also unset_drag_dest_row(). 621 * 622 * @param path The path of the row to highlight 623 * @param pos Specifies whether to drop before, after or into the row 624 */ 625 _WRAP_METHOD(void set_drag_dest_row(const TreeModel::Path& path, TreeViewDropPosition pos), gtk_tree_view_set_drag_dest_row) 626 627 /** Remove an existing highlight. 628 * See set_drag_dest_row(). 629 * 630 * @newin{3,2} 631 */ 632 void unset_drag_dest_row(); 633 634 /** Gets information about the row that is highlighted for feedback. 635 * 636 * @param path Return location for the path of the highlighted row 637 * @param pos Return location for the drop position 638 */ 639 void get_drag_dest_row(TreeModel::Path& path, TreeViewDropPosition& pos) const; 640 641 /** Determines the destination row for a given position. 642 * 643 * @param drag_x The x position to determine the destination row for 644 * @param drag_y The y position to determine the destination row for 645 * @param path Return location for the path of the highlighted row 646 * @param pos Return location for the drop position 647 */ 648 bool get_dest_row_at_pos(int drag_x, int drag_y, TreeModel::Path& path, TreeViewDropPosition& pos) const; 649 650#m4 _CONVERSION(`cairo_surface_t*',`Cairo::RefPtr<Cairo::Surface>',`Cairo::RefPtr<Cairo::Surface>(new Cairo::Surface($3, true /* take reference */))') 651 _WRAP_METHOD(Cairo::RefPtr<Cairo::Surface> create_row_drag_icon(const TreeModel::Path& path) const, gtk_tree_view_create_row_drag_icon) 652 653/* Interactive search */ 654 _WRAP_METHOD(void set_enable_search(bool enable_search = true), gtk_tree_view_set_enable_search) 655 _WRAP_METHOD(bool get_enable_search() const, gtk_tree_view_get_enable_search) 656 _WRAP_METHOD(int get_search_column() const, gtk_tree_view_get_search_column) 657 _WRAP_METHOD(void set_search_column(const TreeModelColumnBase& column), gtk_tree_view_set_search_column) 658 _WRAP_METHOD(void set_search_column(int column), gtk_tree_view_set_search_column) 659 660 ///void on_search_equal(const Glib::RefPtr<TreeModel>& model, int column, const Glib::ustring& key, const TreeModel::iterator& iter) 661 typedef sigc::slot<bool, const Glib::RefPtr<TreeModel>&, int, const Glib::ustring&, const TreeModel::iterator&> SlotSearchEqual; 662 //SlotSearchEqual get_search_equal_func(); 663 _IGNORE(gtk_tree_view_get_search_equal_func) 664 665 /** Sets the compare function for the interactive search capabilities. 666 * 667 * @param slot The compare function to use during the search 668 */ 669 void set_search_equal_func(const SlotSearchEqual& slot); 670 _IGNORE(gtk_tree_view_set_search_equal_func) 671 672 _WRAP_METHOD(Entry* get_search_entry(), gtk_tree_view_get_search_entry) 673 _WRAP_METHOD(const Entry* get_search_entry() const, gtk_tree_view_get_search_entry, constversion) 674 _WRAP_METHOD(void set_search_entry(Entry& entry), gtk_tree_view_set_search_entry) 675 676 ///void on_search_position(Gtk::Widget* search_dialog) 677 typedef sigc::slot<void, Gtk::Widget* /* search_dialog */> SlotSearchPosition; 678 void set_search_position_func(const SlotSearchPosition& slot); 679 _IGNORE(gtk_tree_view_get_search_position_func, gtk_tree_view_set_search_position_func) 680 681 _WRAP_METHOD(void convert_widget_to_tree_coords(int wx, int wy, int& tx, int& ty) const, gtk_tree_view_convert_widget_to_tree_coords) 682 _WRAP_METHOD(void convert_tree_to_widget_coords(int tx, int ty, int& wx, int& wy) const, gtk_tree_view_convert_tree_to_widget_coords) 683 _WRAP_METHOD(void convert_widget_to_bin_window_coords(int wx, int wy, int& bx, int& by) const, gtk_tree_view_convert_widget_to_bin_window_coords) 684 _WRAP_METHOD(void convert_bin_window_to_widget_coords(int bx, int by, int& wx, int& wy) const, gtk_tree_view_convert_bin_window_to_widget_coords) 685 _WRAP_METHOD(void convert_tree_to_bin_window_coords(int tx, int ty, int& bx, int& by) const, gtk_tree_view_convert_tree_to_bin_window_coords) 686 _WRAP_METHOD(void convert_bin_window_to_tree_coords(int bx, int by, int& tx, int& ty) const, gtk_tree_view_convert_bin_window_to_tree_coords) 687 688 689 _WRAP_METHOD(void set_fixed_height_mode(bool enable = true), gtk_tree_view_set_fixed_height_mode) 690 _WRAP_METHOD(bool get_fixed_height_mode() const, gtk_tree_view_get_fixed_height_mode) 691 _WRAP_METHOD(void set_hover_selection(bool hover = true), gtk_tree_view_set_hover_selection) 692 _WRAP_METHOD(bool get_hover_selection() const, gtk_tree_view_get_hover_selection) 693 _WRAP_METHOD(void set_hover_expand(bool expand = true), gtk_tree_view_set_hover_expand) 694 _WRAP_METHOD(bool get_hover_expand() const, gtk_tree_view_get_hover_expand) 695 _WRAP_METHOD(void set_rubber_banding(bool enable = true), gtk_tree_view_set_rubber_banding) 696 _WRAP_METHOD(bool get_rubber_banding() const, gtk_tree_view_get_rubber_banding) 697 698 //TODO: Rename to get_is? 699 _WRAP_METHOD(bool is_rubber_banding_active() const, gtk_tree_view_is_rubber_banding_active) 700 701 /** The slot type for determining whether the row pointed to by the iterator should be rendered as a separator. 702 * Return true if the row is a separator. 703 * A common way to implement this is to have a boolean column in the model, whose values the slot returns. 704 * 705 * For instance, 706 * bool on_row_separator(const Glib::RefPtr<Gtk::TreeModel>& model, const Gtk::TreeModel::iterator& iter); 707 */ 708 typedef sigc::slot<bool, const Glib::RefPtr<TreeModel>&, const TreeModel::iterator&> SlotRowSeparator; 709 710 /** Sets the row separator function, which is used to determine whether a row should be drawn as a separator. 711 */ 712 void set_row_separator_func(const SlotRowSeparator& slot); 713 _IGNORE(gtk_tree_view_set_row_separator_func, gtk_tree_view_get_row_separator_func) 714 715 /** Removes the row separator function, so no separators are drawn. 716 * See set_row_separator_func(). 717 * 718 * @newin{3,2} 719 */ 720 void unset_row_separator_func(); 721 722 _WRAP_METHOD(void set_grid_lines(TreeViewGridLines grid_lines), gtk_tree_view_set_grid_lines) 723 _WRAP_METHOD(TreeViewGridLines get_grid_lines() const, gtk_tree_view_get_grid_lines) 724 725 _WRAP_METHOD(void set_enable_tree_lines(bool enable = true), gtk_tree_view_set_enable_tree_lines) 726 _WRAP_METHOD(bool get_enable_tree_lines() const, gtk_tree_view_get_enable_tree_lines) 727 728 _WRAP_METHOD(void set_show_expanders(bool enabled = true), gtk_tree_view_set_show_expanders) 729 _WRAP_METHOD(bool get_show_expanders() const, gtk_tree_view_get_show_expanders) 730 _WRAP_METHOD(void set_level_indentation(int indentation), gtk_tree_view_set_level_indentation) 731 _WRAP_METHOD(int get_level_indentation() const, gtk_tree_view_get_level_indentation) 732 733 _WRAP_METHOD(void set_tooltip_row(const Glib::RefPtr<Tooltip>& tooltip, const TreePath& path), gtk_tree_view_set_tooltip_row) 734 735 //Note that we use pointers instead of references because any one of the 3 arguments may be NULL, and we don't want that many method overloads: 736#m4 _CONVERSION(`const TreeModel::Path*',`GtkTreePath*',`(($3) ? const_cast<GtkTreePath*>(($3)->gobj()) : nullptr)') 737 _WRAP_METHOD(void set_tooltip_cell(const Glib::RefPtr<Tooltip>& tooltip, const TreeModel::Path* path, TreeViewColumn* column, CellRenderer* cell), gtk_tree_view_set_tooltip_cell) 738 739 _IGNORE(gtk_tree_view_get_tooltip_context) 740 741 /** 742 * @param x: the x coordinate (relative to widget coordinates) 743 * @param y: the y coordinate (relative to widget coordinates) 744 * @param keyboard_tip: whether this is a keyboard tooltip or not 745 * @param path: a reference to receive a Gtk::TreePath 746 * 747 * This function is supposed to be used in a Gtk::Widget::query-tooltip 748 * signal handler for Gtk::TreeView. The x, y and keyboard_tip values 749 * which are received in the signal handler, should be passed to this 750 * function without modification. 751 * 752 * The return value indicates whether there is an tree view row at the given 753 * coordinates (true) or not (false) for mouse tooltips. For keyboard 754 * tooltips the row returned will be the cursor item. When true, then the 755 * path which has been provided will be set to point to 756 * that row and the corresponding model. x and y will always be converted 757 * to be relative to Gtk::TreeView's bin_window if keyboard_tooltip is false. 758 * 759 * Return value: whether or not the given tooltip context points to a row. 760 * 761 * @newin{2,12} 762 */ 763 bool get_tooltip_context_path(int& x, int& y, 764 bool keyboard_tip, 765 TreeModel::Path& path); 766 767 /** 768 * @param x: the x coordinate (relative to widget coordinates) 769 * @param y: the y coordinate (relative to widget coordinates) 770 * @param keyboard_tip: whether this is a keyboard tooltip or not 771 * @param iter: a pointer to receive a Gtk::TreeIter 772 * 773 * This function is supposed to be used in a Gtk::Widget::query-tooltip 774 * signal handler for Gtk::TreeView. The x, y and keyboard_tip values 775 * which are received in the signal handler, should be passed to this 776 * function without modification. 777 * 778 * The return value indicates whether there is an tree view row at the given 779 * coordinates (true) or not (false) for mouse tooltips. For keyboard 780 * tooltips the row returned will be the cursor item. When true, then the 781 * iter which has been provided will be set to point to 782 * that row and the corresponding model. x and y will always be converted 783 * to be relative to Gtk::TreeView's bin_window if keyboard_tooltip is false. 784 * 785 * Return value: whether or not the given tooltip context points to a row. 786 * 787 * @newin{2,12} 788 */ 789 bool get_tooltip_context_iter(int& x, int& y, 790 bool keyboard_tip, 791 Gtk::TreeModel::iterator& iter); 792 793 _WRAP_METHOD(void set_tooltip_column(int column), gtk_tree_view_set_tooltip_column) 794 _WRAP_METHOD(int get_tooltip_column() const, gtk_tree_view_get_tooltip_column) 795 796#m4begin 797dnl // We need this special conversion here since the C++ Gtk::TreeIter carries 798dnl // a pointer to the Gtk::TreeModel, whereas the plain GtkTreeIter struct does 799dnl // not. Fortunately we can use the `self' parameter to get our hands on the 800dnl // GtkTreeModel*. 801_CONVERSION(`GtkTreeIter*',`const TreeModel::iterator&',`TreeModel::iterator(gtk_tree_view_get_model(self), $3)') 802#m4end 803 804 _WRAP_SIGNAL(void row_activated(const TreeModel::Path& path, TreeViewColumn* column) , "row-activated") 805 _WRAP_SIGNAL(bool test_expand_row(const TreeModel::iterator& iter, const TreeModel::Path& path), "test-expand-row") 806 _WRAP_SIGNAL(bool test_collapse_row(const TreeModel::iterator& iter, const TreeModel::Path& path), "test-collapse-row") 807 _WRAP_SIGNAL(void row_expanded(const TreeModel::iterator& iter, const TreeModel::Path& path), "row-expanded") 808 _WRAP_SIGNAL(void row_collapsed(const TreeModel::iterator& iter, const TreeModel::Path& path), "row-collapsed") 809 _WRAP_SIGNAL(void cursor_changed(), "cursor-changed") 810 _WRAP_SIGNAL(void columns_changed(), "columns-changed") 811 812 //Don't wrap these. They are keybinding signals, and their API broke for GTK+ 2.2. 813 _IGNORE_SIGNAL("move-cursor") 814 _IGNORE_SIGNAL("select-all") 815 _IGNORE_SIGNAL("unselect-all") 816 _IGNORE_SIGNAL("select-cursor-row") 817 _IGNORE_SIGNAL("toggle-cursor-row") 818 _IGNORE_SIGNAL("expand-collapse-cursor-row") 819 _IGNORE_SIGNAL("select-cursor-parent") 820 _IGNORE_SIGNAL("start-interactive-search") 821 822 823 _WRAP_PROPERTY("model", Glib::RefPtr<TreeModel>) 824 _WRAP_PROPERTY("headers-visible", bool) 825 _WRAP_PROPERTY("headers-clickable", bool) 826 _WRAP_PROPERTY("expander-column", TreeViewColumn*) 827 _WRAP_PROPERTY("reorderable", bool) 828 _WRAP_PROPERTY("rules-hint", bool, deprecated "Don't use this API. There is no replacement.") 829 _WRAP_PROPERTY("enable-search", bool) 830 _WRAP_PROPERTY("search-column", int) 831 _WRAP_PROPERTY("fixed-height-mode", bool) 832 _WRAP_PROPERTY("hover-selection", bool) 833 _WRAP_PROPERTY("hover-expand", bool) 834 _WRAP_PROPERTY("show-expanders", bool) 835 _WRAP_PROPERTY("level-indentation", bool) 836 _WRAP_PROPERTY("rubber-banding", bool) 837 _WRAP_PROPERTY("enable-grid-lines", bool) 838 _WRAP_PROPERTY("enable-tree-lines", bool) 839 _WRAP_PROPERTY("tooltip-column", int) 840 _WRAP_PROPERTY("activate-on-single-click", bool) 841 842protected: 843 844#ifndef DOXYGEN_SHOULD_SKIP_THIS 845 template<class ColumnType> friend 846 void _auto_store_on_cellrenderer_text_edited_string(const Glib::ustring& path_string, const Glib::ustring& new_text, int model_column, const Glib::RefPtr<Gtk::TreeModel>& model); 847 848 template <class ColumnType> friend 849 void _auto_store_on_cellrenderer_text_edited_numerical(const Glib::ustring& path_string, const Glib::ustring& new_text, int model_column, const Glib::RefPtr<Gtk::TreeModel>& model); 850 851 void _auto_store_on_cellrenderer_toggle_edited_with_model(const Glib::ustring& path_string, int model_column, const Glib::RefPtr<Gtk::TreeModel>& model); 852 853 // This is no longer used, but we must keep it to prevent linker errors with already-compiled applications, 854 // For instance, applications that were compiled with the older versions of the templates that did use this method. 855 // TODO: Remove this when we can break API. 856 void _auto_store_on_cellrenderer_toggle_edited(const Glib::ustring& path_string, int model_column); 857 858 template<class ColumnType> friend 859 void TreeView_Private::_connect_auto_store_editable_signal_handler(TreeView*, CellRenderer*, const TreeModelColumn<ColumnType>&); 860 861#endif //DOXYGEN_SHOULD_SKIP_THIS 862}; 863 864 865 866template <class ColumnType> inline 867int TreeView::append_column(const Glib::ustring& title, const TreeModelColumn<ColumnType>& model_column) 868{ 869 // compilation will fail if there is no appropriate TreeViewColumn 870 // constructor for this model column type. 871 TreeViewColumn *const pViewColumn = Gtk::manage( new TreeViewColumn(title, model_column) ); 872 873 return append_column(*pViewColumn); 874} 875 876//This is here because sigc::bind once did not work on all platforms, but now it does.. 877#define GTKMM_HAVE_SIGC_BIND 1 878 879#ifdef GTKMM_HAVE_SIGC_BIND 880 881template <class ColumnType> inline 882int TreeView::append_column_numeric(const Glib::ustring& title, const TreeModelColumn<ColumnType>& model_column, const Glib::ustring& format) 883{ 884 TreeViewColumn* const pViewColumn = Gtk::manage( new TreeViewColumn(title) ); 885 886 //Use a CellRendererText: 887 //We don't use TreeView::Column::append_column(model_column) to generate an appropriate CellRenderer, 888 //because that uses set_renderer(), which renders the model value using the automatic glib "transformations" (number-string conversions). As well as being unnecessary here, those automatic conversions can't handle all numeric types. 889 CellRenderer* pCellRenderer = manage( new CellRendererText() ); 890 pViewColumn->pack_start(*pCellRenderer); 891 892 893 //Some compilers don't like us to give the pointer to a template function directly to sigc::ptr_fun(): 894 typedef void (*type_fptr)(Gtk::CellRenderer* cell, const Gtk::TreeModel::iterator& iter, int model_column, const Glib::ustring& format); 895 type_fptr fptr = TreeView_Private::_auto_cell_data_func<ColumnType>; 896 897 //Connect a cell_data callback, to show the number's text representation in the specified format: 898 //We use sigc::bind<-1> twice here, instead of sigc::bind() once, because some compilers need the extra hint. 899 Gtk::TreeViewColumn::SlotTreeCellData slot = sigc::bind<-1>( 900 sigc::bind<-1>( sigc::ptr_fun(fptr), format), 901 model_column.index() 902 ); 903 904 pViewColumn->set_cell_data_func(*pCellRenderer, slot); 905 906 return append_column(*pViewColumn); 907} 908 909#endif //GTKMM_HAVE_SIGC_BIND 910 911template <class ColumnType> inline 912int TreeView::append_column_numeric_editable(const Glib::ustring& title, const TreeModelColumn<ColumnType>& model_column, const Glib::ustring& format) 913{ 914 int cols_count = append_column_numeric(title, model_column, format); 915 916 //connect signal handlers for auto-storing of edited cell data 917 //Note: This will only work for base-10 (decimal) formatted numbers: 918 CellRenderer *const cell = get_column_cell_renderer(cols_count - 1); 919 if(cell) 920 { 921 TreeView_Private::_connect_auto_store_numeric_editable_signal_handler<ColumnType>(this, cell, model_column); 922 } 923 924 return cols_count; 925} 926 927template <class ColumnType> inline 928int TreeView::append_column_editable(const Glib::ustring& title, const TreeModelColumn<ColumnType>& model_column) 929{ 930 //Don't use this in a header, because it gives warnings when disabled: g_assert(model_column.type() != 0); 931 932 // compilation will fail if there is no appropriate TreeViewColumn 933 // constructor for this model column type. 934 TreeViewColumn *const pViewColumn = Gtk::manage( new TreeViewColumn(title, model_column) ); 935 936 //connect signal handlers for auto-storing of edited cell data 937 CellRenderer* pCellRender = pViewColumn->get_first_cell(); 938 TreeView_Private::_connect_auto_store_editable_signal_handler<ColumnType>(this, pCellRender, model_column); 939 940 return append_column(*pViewColumn); 941} 942 943template <class ColumnType> inline 944int TreeView::insert_column(const Glib::ustring& title, const TreeModelColumn<ColumnType>& model_column, int position) 945{ 946 // compilation will fail if there is no appropriate TreeViewColumn 947 // constructor for this model column type. 948 TreeViewColumn *const pViewColumn = Gtk::manage( new TreeViewColumn(title, model_column) ); 949 950 return insert_column(*pViewColumn, position); 951} 952 953template <class ColumnType> inline 954int TreeView::insert_column_editable(const Glib::ustring& title, const TreeModelColumn<ColumnType>& model_column, int position) 955{ 956 // compilation will fail if there is no appropriate TreeViewColumn 957 // constructor for this model column type. 958 TreeViewColumn *const pViewColumn = Gtk::manage( new TreeViewColumn(title, model_column) ); 959 960 //connect signal handlers for auto-storing of edited cell data 961 CellRenderer* pCellRender = pViewColumn->get_first_cell(); 962 TreeView_Private::_connect_auto_store_editable_signal_handler(this, pCellRender, model_column); 963 964 return insert_column(*pViewColumn, position); 965} 966 967 968#ifndef DOXYGEN_SHOULD_SKIP_THIS 969namespace TreeView_Private 970{ 971 972//Template specializations, for different model column types: 973//TODO: Move these specializations into the .ccg file - I tried, but the int specialization was not used by the compiler. murrayc. 974 975// append_column_editable<>() and insert_column_editable<>() call template function 976// _connect_auto_store_editable_signal_handler<ColumnType>(). 977// There are 3 versions of _connect_auto_store_editable_signal_handler<>(): 978// 979// 1. The default version for string data. It connects 980// CellRendererText::signal_edited() to template function 981// _auto_store_on_cellrenderer_text_edited_string<ColumnType>(). 982// 983// 2. A bool specialization. It connects CellRendererToggle::signal_toggled() 984// to function _auto_store_on_cellrenderer_toggle_edited_with_model(). 985// 986// 3. Several identical (except for the type name) specializations for numeric data. 987// They call _connect_auto_store_numeric_editable_signal_handler<ColumnType>(), 988// which connects CellRendererText::signal_edited() to template function 989// _auto_store_on_cellrenderer_text_edited_numerical<ColumnType>(). 990// 991// We need all those specializations with identical implementations, because we 992// chose to avoid multiple specializations for the string types by dealing with 993// string types in the default implementation. 994// 995// With these numeric specializations append_column_editable<>() and 996// insert_column_editable<>() can be used for the same numeric types as 997// append_column<>() and insert_column<>(). Those are fundamental types in the 998// GType system, and Glib registers conversion functions from those types to 999// gchararray with g_value_register_transform_func(). 1000// 'short' is not one of those types. It can be handled only by 1001// append_column_numeric<>() and append_column_numeric_editable<>(). 1002 1003#ifdef GTKMM_HAVE_SIGC_BIND 1004 1005//bool specialization: 1006template<> inline 1007void _connect_auto_store_editable_signal_handler(Gtk::TreeView* this_p, Gtk::CellRenderer* pCellRenderer, const Gtk::TreeModelColumn<bool>& model_column) 1008{ 1009 Gtk::CellRendererToggle* pCellToggle = dynamic_cast<Gtk::CellRendererToggle*>(pCellRenderer); 1010 if(pCellToggle) 1011 { 1012 //Set the appropriate property, 1013 pCellToggle->property_activatable() = true; 1014 1015 //Connect to the appropriate signal, sending the model_column too 1016 1017 sigc::slot<void, const Glib::ustring&, int> slot_temp = 1018 sigc::bind<-1>( 1019 sigc::mem_fun(*this_p, &Gtk::TreeView::_auto_store_on_cellrenderer_toggle_edited_with_model), 1020 this_p->get_model() 1021 ); 1022 1023 pCellToggle->signal_toggled().connect( 1024 sigc::bind<-1>( 1025 slot_temp, 1026 model_column.index() 1027 ) 1028 ); 1029 1030 //We use bind<1> instead of bind because some compilers need the extra hint. 1031 } 1032} 1033 1034//int specialization: 1035template<> inline 1036void _connect_auto_store_editable_signal_handler(Gtk::TreeView* this_p, Gtk::CellRenderer* pCellRenderer, const Gtk::TreeModelColumn<int>& model_column) 1037{ 1038 _connect_auto_store_numeric_editable_signal_handler<int>(this_p, pCellRenderer, model_column); 1039} 1040 1041//unsigned int specialization: 1042template<> inline 1043void _connect_auto_store_editable_signal_handler(Gtk::TreeView* this_p, Gtk::CellRenderer* pCellRenderer, const Gtk::TreeModelColumn<unsigned int>& model_column) 1044{ 1045 _connect_auto_store_numeric_editable_signal_handler<unsigned int>(this_p, pCellRenderer, model_column); 1046} 1047 1048//long specialization: 1049template<> inline 1050void _connect_auto_store_editable_signal_handler(Gtk::TreeView* this_p, Gtk::CellRenderer* pCellRenderer, const Gtk::TreeModelColumn<long>& model_column) 1051{ 1052 _connect_auto_store_numeric_editable_signal_handler<long>(this_p, pCellRenderer, model_column); 1053} 1054 1055//unsigned long specialization: 1056template<> inline 1057void _connect_auto_store_editable_signal_handler(Gtk::TreeView* this_p, Gtk::CellRenderer* pCellRenderer, const Gtk::TreeModelColumn<unsigned long>& model_column) 1058{ 1059 _connect_auto_store_numeric_editable_signal_handler<unsigned long>(this_p, pCellRenderer, model_column); 1060} 1061 1062//float specialization: 1063template<> inline 1064void _connect_auto_store_editable_signal_handler(Gtk::TreeView* this_p, Gtk::CellRenderer* pCellRenderer, const Gtk::TreeModelColumn<float>& model_column) 1065{ 1066 _connect_auto_store_numeric_editable_signal_handler<float>(this_p, pCellRenderer, model_column); 1067} 1068 1069//double specialization: 1070template<> inline 1071void _connect_auto_store_editable_signal_handler(Gtk::TreeView* this_p, Gtk::CellRenderer* pCellRenderer, const Gtk::TreeModelColumn<double>& model_column) 1072{ 1073 _connect_auto_store_numeric_editable_signal_handler<double>(this_p, pCellRenderer, model_column); 1074} 1075 1076#endif //GTKMM_HAVE_SIGC_BIND 1077 1078} // namespace TreeView_Private 1079#endif //DOXYGEN_SHOULD_SKIP_THIS 1080 1081 1082#ifndef DOXYGEN_SHOULD_SKIP_THIS 1083namespace TreeView_Private 1084{ 1085 1086#ifdef GTKMM_HAVE_SIGC_BIND 1087 1088template <class ColumnType> inline 1089void _connect_auto_store_editable_signal_handler(Gtk::TreeView* this_p, Gtk::CellRenderer* pCellRenderer, const Gtk::TreeModelColumn<ColumnType>& model_column) 1090{ 1091 //Don't use this in a header, because it gives warnings when disabled: g_assert(model_column.type() != 0); 1092 1093 //The different CellRenderers have different "edited" signals, 1094 //and numerical values need to convert the text value to a number, 1095 //so there are specializations for this template. 1096 1097 Gtk::CellRendererText* pCellText = dynamic_cast<Gtk::CellRendererText*>(pCellRenderer); 1098 1099 //Set the appropriate property, 1100 //and connect to the appropriate signal, sending the model_column too, 1101 if(pCellText) 1102 { 1103 pCellText->property_editable() = true; 1104 1105 //Some compilers (IRIX MipsPro) don't like us to give the pointer to a template function directly to sigc::ptr_fun(): 1106 typedef void (*type_func)(const Glib::ustring&, const Glib::ustring&, int, const Glib::RefPtr<Gtk::TreeModel>&); 1107 type_func func = &(Gtk::TreeView_Private::_auto_store_on_cellrenderer_text_edited_string<ColumnType>); 1108 sigc::slot<void, const Glib::ustring&, const Glib::ustring&, int, const Glib::RefPtr<Gtk::TreeModel>&> theslot = 1109 sigc::ptr_fun(func); 1110 1111 //We use bind<-1> twice here, instead of using bind() once, because some compilers need the extra hint. 1112 pCellText->signal_edited().connect( 1113 sigc::bind<-1>( 1114 sigc::bind<-1>( theslot, this_p->get_model()), 1115 model_column.index() 1116 ) 1117 ); 1118 } 1119} 1120 1121template<class ColumnType> inline 1122void _connect_auto_store_numeric_editable_signal_handler(Gtk::TreeView* this_p, Gtk::CellRenderer* pCellRenderer, const Gtk::TreeModelColumn<ColumnType>& model_column) 1123{ 1124 //The different CellRenderers have different "edited" signals, 1125 //and numerical values need to convert the text value to a number. 1126 1127 Gtk::CellRendererText* pCellText = dynamic_cast<Gtk::CellRendererText*>(pCellRenderer); 1128 if(pCellText) 1129 { 1130 //Set the appropriate property. 1131 pCellText->property_editable() = true; 1132 1133 //Some compilers don't like us to give the pointer to a template function directly to sigc::ptr_fun(): 1134 typedef void (*type_fptr)(const Glib::ustring& path_string, const Glib::ustring& new_text, int model_column, const Glib::RefPtr<Gtk::TreeModel>& model); 1135 type_fptr fptr = _auto_store_on_cellrenderer_text_edited_numerical<ColumnType>; 1136 1137 //Connect to the appropriate signal, sending the model_column too. 1138 //We use bind<-1> twice here, instead of using bind() once, because some compilers need the extra hint. 1139 pCellText->signal_edited().connect( 1140 sigc::bind<-1>( 1141 sigc::bind<-1>( 1142 sigc::ptr_fun(fptr), 1143 this_p->get_model() ), 1144 model_column.index() 1145 ) 1146 ); 1147 } 1148} 1149 1150#endif //GTKMM_HAVE_SIGC_BIND 1151 1152template <class ColumnType> inline 1153void _auto_store_on_cellrenderer_text_edited_string(const Glib::ustring& path_string, const Glib::ustring& new_text, int model_column, const Glib::RefPtr<Gtk::TreeModel>& model) 1154{ 1155 Gtk::TreePath path(path_string); 1156 1157 //Get the row from the path: 1158 if(model) 1159 { 1160 Gtk::TreeModel::iterator iter = model->get_iter(path); 1161 if(iter) 1162 { 1163 //Store the user's new text in the model: 1164 Gtk::TreeRow row = *iter; 1165 row.set_value(model_column, (ColumnType)new_text); 1166 } 1167 } 1168} 1169 1170template <class ColumnType> inline 1171void _auto_store_on_cellrenderer_text_edited_numerical(const Glib::ustring& path_string, const Glib::ustring& new_text, int model_column, const Glib::RefPtr<Gtk::TreeModel>& model) 1172{ 1173 //This is used on numerical model columns: 1174 1175 Gtk::TreePath path(path_string); 1176 1177 //Get the row from the path: 1178 if(model) 1179 { 1180 Gtk::TreeModel::iterator iter = model->get_iter(path); 1181 if(iter) 1182 { 1183 //std::istringstream astream(new_text); //Put it in a stream. 1184 //ColumnType new_value = ColumnType(); 1185 //new_value << astream; //Get it out of the stream as the numerical type. 1186 1187 //Convert the text to a number, using the same logic used by GtkCellRendererText when it stores numbers. 1188 ColumnType new_value = ColumnType(); 1189 try 1190 { 1191 new_value = static_cast<ColumnType>( std::stod(new_text) ); 1192 } 1193 catch(const std::invalid_argument&) 1194 { 1195 //Intentionally ignored. 1196 //Applications can use their own logic if they want to handle invalid input differently. 1197 } 1198 1199 //Store the user's new text in the model: 1200 Gtk::TreeRow row = *iter; 1201 row.set_value(model_column, (ColumnType)new_value); 1202 } 1203 } 1204} 1205 1206template <class ColumnType> inline 1207void _auto_cell_data_func(Gtk::CellRenderer* cell, const Gtk::TreeModel::iterator& iter, int model_column, const Glib::ustring& format) 1208{ 1209 Gtk::CellRendererText* pTextRenderer = dynamic_cast<Gtk::CellRendererText*>(cell); 1210 if(!pTextRenderer) 1211 { 1212 g_warning("gtkmm: TextView: append_column_numeric() was used with a non-numeric type."); 1213 } 1214 else 1215 { 1216 if(iter) 1217 { 1218 //Get the value from the model. 1219 Gtk::TreeModel::Row row = *iter; 1220 ColumnType value = ColumnType(); 1221 row.get_value(model_column, value); 1222 1223 //Convert it to a string representation: 1224 char buff[20]; 1225 int used = g_snprintf(buff, sizeof(buff), format.c_str(), value); //value must be a numeric type. 1226 if(used > 0) 1227 { 1228 //Show the text representation in the view: 1229 pTextRenderer->property_text() = buff; 1230 } 1231 } 1232 } 1233} 1234 1235} // namespace TreeView_Private 1236#endif //DOXYGEN_SHOULD_SKIP_THIS 1237 1238} // namespace Gtk 1239