// SPDX-License-Identifier: GPL-2.0-or-later /* * Authors: * Nicholas Bishop * Johan Engelen * * Copyright (C) 2007 Authors * * Released under GNU GPL v2+, read the file 'COPYING' for more information. */ #ifndef INKSCAPE_UI_WIDGET_COMBO_ENUMS_H #define INKSCAPE_UI_WIDGET_COMBO_ENUMS_H #include "ui/widget/labelled.h" #include #include #include "attr-widget.h" #include "util/enums.h" #include namespace Inkscape { namespace UI { namespace Widget { /** * Simplified management of enumerations in the UI as combobox. */ template class ComboBoxEnum : public Gtk::ComboBox, public AttrWidget { private: int on_sort_compare( const Gtk::TreeModel::iterator & a, const Gtk::TreeModel::iterator & b) { Glib::ustring an=(*a)[_columns.label]; Glib::ustring bn=(*b)[_columns.label]; return an.compare(bn); } bool _sort; public: ComboBoxEnum(E default_value, const Util::EnumDataConverter& c, const SPAttr a = SPAttr::INVALID, bool sort = true) : AttrWidget(a, (unsigned int)default_value), setProgrammatically(false), _converter(c) { _sort = sort; signal_changed().connect(signal_attr_changed().make_slot()); gtk_widget_add_events(GTK_WIDGET(gobj()), GDK_SCROLL_MASK | GDK_SMOOTH_SCROLL_MASK); signal_scroll_event().connect(sigc::mem_fun(*this, &ComboBoxEnum::on_scroll_event)); _model = Gtk::ListStore::create(_columns); set_model(_model); pack_start(_columns.label); // Initialize list for(int i = 0; i < static_cast(_converter._length); ++i) { Gtk::TreeModel::Row row = *_model->append(); const Util::EnumData* data = &_converter.data(i); row[_columns.data] = data; row[_columns.label] = _( _converter.get_label(data->id).c_str() ); } set_active_by_id(default_value); // Sort the list if (sort) { _model->set_default_sort_func(sigc::mem_fun(*this, &ComboBoxEnum::on_sort_compare)); _model->set_sort_column(_columns.label, Gtk::SORT_ASCENDING); } } ComboBoxEnum(const Util::EnumDataConverter& c, const SPAttr a = SPAttr::INVALID, bool sort = true) : AttrWidget(a, (unsigned int) 0), setProgrammatically(false), _converter(c) { _sort = sort; signal_changed().connect(signal_attr_changed().make_slot()); gtk_widget_add_events(GTK_WIDGET(gobj()), GDK_SCROLL_MASK | GDK_SMOOTH_SCROLL_MASK); signal_scroll_event().connect(sigc::mem_fun(*this, &ComboBoxEnum::on_scroll_event)); _model = Gtk::ListStore::create(_columns); set_model(_model); pack_start(_columns.label); // Initialize list for(unsigned int i = 0; i < _converter._length; ++i) { Gtk::TreeModel::Row row = *_model->append(); const Util::EnumData* data = &_converter.data(i); row[_columns.data] = data; row[_columns.label] = _( _converter.get_label(data->id).c_str() ); } set_active(0); // Sort the list if (_sort) { _model->set_default_sort_func(sigc::mem_fun(*this, &ComboBoxEnum::on_sort_compare)); _model->set_sort_column(_columns.label, Gtk::SORT_ASCENDING); } } Glib::ustring get_as_attribute() const override { return get_active_data()->key; } void set_from_attribute(SPObject* o) override { setProgrammatically = true; const gchar* val = attribute_value(o); if(val) set_active_by_id(_converter.get_id_from_key(val)); else set_active(get_default()->as_uint()); } const Util::EnumData* get_active_data() const { Gtk::TreeModel::iterator i = this->get_active(); if(i) return (*i)[_columns.data]; return nullptr; } void add_row(const Glib::ustring& s) { Gtk::TreeModel::Row row = *_model->append(); row[_columns.data] = 0; row[_columns.label] = s; } void remove_row(E id) { Gtk::TreeModel::iterator i; for(i = _model->children().begin(); i != _model->children().end(); ++i) { const Util::EnumData* data = (*i)[_columns.data]; if(data->id == id) break; } if(i != _model->children().end()) _model->erase(i); } void set_active_by_id(E id) { setProgrammatically = true; for(Gtk::TreeModel::iterator i = _model->children().begin(); i != _model->children().end(); ++i) { const Util::EnumData* data = (*i)[_columns.data]; if(data->id == id) { set_active(i); break; } } }; bool on_scroll_event(GdkEventScroll *event) override { return false; } void set_active_by_key(const Glib::ustring& key) { setProgrammatically = true; set_active_by_id( _converter.get_id_from_key(key) ); }; bool setProgrammatically; private: class Columns : public Gtk::TreeModel::ColumnRecord { public: Columns() { add(data); add(label); } Gtk::TreeModelColumn*> data; Gtk::TreeModelColumn label; }; Columns _columns; Glib::RefPtr _model; const Util::EnumDataConverter& _converter; }; /** * Simplified management of enumerations in the UI as combobox. */ template class LabelledComboBoxEnum : public Labelled { public: LabelledComboBoxEnum( Glib::ustring const &label, Glib::ustring const &tooltip, const Util::EnumDataConverter& c, Glib::ustring const &suffix = "", Glib::ustring const &icon = "", bool mnemonic = true, bool sorted = true) : Labelled(label, tooltip, new ComboBoxEnum(c, SPAttr::INVALID, sorted), suffix, icon, mnemonic) { } ComboBoxEnum* getCombobox() { return static_cast< ComboBoxEnum* > (_widget); } }; } } } #endif /* Local Variables: mode:c++ c-file-style:"stroustrup" c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) indent-tabs-mode:nil fill-column:99 End: */ // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :