From 063bb27bebc4a01eefa879017c819a0058548955 Mon Sep 17 00:00:00 2001 From: mental Date: Wed, 4 Jul 2007 19:07:46 +0000 Subject: [PATCH] First stab at a connection UI from Nick --- src/display/nr-filter-types.h | 2 +- src/ui/dialog/filter-effects-dialog.cpp | 656 +++++++++++++++++------- src/ui/dialog/filter-effects-dialog.h | 102 ++-- src/ui/widget/filter-effect-chooser.cpp | 1 + 4 files changed, 533 insertions(+), 228 deletions(-) diff --git a/src/display/nr-filter-types.h b/src/display/nr-filter-types.h index 6f28c6257..0997d36f4 100644 --- a/src/display/nr-filter-types.h +++ b/src/display/nr-filter-types.h @@ -24,7 +24,7 @@ enum FilterPrimitiveType { }; //const int Filter::_filter_primitive_type_count = 16; -enum { +enum FilterSlotType { NR_FILTER_SLOT_NOT_SET = -1, NR_FILTER_SOURCEGRAPHIC = -2, NR_FILTER_SOURCEALPHA = -3, diff --git a/src/ui/dialog/filter-effects-dialog.cpp b/src/ui/dialog/filter-effects-dialog.cpp index 1d14d69f4..f6c61791b 100644 --- a/src/ui/dialog/filter-effects-dialog.cpp +++ b/src/ui/dialog/filter-effects-dialog.cpp @@ -31,6 +31,9 @@ #include "filter-chemistry.h" #include "filter-effects-dialog.h" #include "inkscape.h" +#include "sp-feblend.h" +#include "sp-fecomposite.h" +#include "sp-fedisplacementmap.h" #include "sp-filter-primitive.h" #include "sp-gaussian-blur.h" #include "sp-feoffset.h" @@ -89,8 +92,8 @@ FilterEffectsDialog::FilterModifier::FilterModifier() sw->set_shadow_type(Gtk::SHADOW_IN); show_all_children(); _add.signal_clicked().connect(sigc::mem_fun(*this, &FilterModifier::add_filter)); - _list.signal_button_press_event().connect_notify( - sigc::mem_fun(*this, &FilterModifier::filter_list_button_press)); + _list.signal_button_release_event().connect_notify( + sigc::mem_fun(*this, &FilterModifier::filter_list_button_release)); _menu = create_popup_menu(*this, sigc::mem_fun(*this, &FilterModifier::duplicate_filter), sigc::mem_fun(*this, &FilterModifier::remove_filter)); @@ -127,9 +130,9 @@ void FilterEffectsDialog::FilterModifier::select_filter(const SPFilter* filter) } } -void FilterEffectsDialog::FilterModifier::filter_list_button_press(GdkEventButton* event) +void FilterEffectsDialog::FilterModifier::filter_list_button_release(GdkEventButton* event) { - if((event->type == GDK_BUTTON_PRESS) && (event->button == 3)) { + if((event->type == GDK_BUTTON_RELEASE) && (event->button == 3)) { const bool sensitive = get_selected_filter() != NULL; _menu->items()[0].set_sensitive(sensitive); _menu->items()[1].set_sensitive(sensitive); @@ -184,38 +187,368 @@ void FilterEffectsDialog::FilterModifier::filter_name_edited(const Glib::ustring try_id_change((SPObject*)(*i)[_columns.filter], text); } -/*** SettingsFrame ***/ -FilterEffectsDialog::SettingsFrame::SettingsFrame() - : _where(0) +/*** PrimitiveList ***/ +class CellRendererConnection : public Gtk::CellRenderer { - set_col_spacings(12); - show(); +public: + CellRendererConnection() + { + + } + + Glib::PropertyProxy property_connection(); + + static int input_count(const SPFilterPrimitive* prim) + { + /*TODO*/ + + if(!prim) + return 0; + /*else if(SP_IS_FEBLEND(prim) || SP_IS_FECOMPOSITE(prim) || SP_IS_FEDISPLACEMENTMAP(prim)) + return 2;*/ + else + return 1; + } + + static const int size = 32; +protected: + virtual void get_size_vfunc(Gtk::Widget& widget, const Gdk::Rectangle* cell_area, + int* x_offset, int* y_offset, int* width, int* height) const + { + if(x_offset) + (*x_offset) = 0; + if(y_offset) + (*y_offset) = 0; + if(width) + (*width) = size; + if(height) + (*height) = size; + } +}; + +FilterEffectsDialog::PrimitiveList::PrimitiveList(FilterEffectsDialog& d) + : _dialog(d), _in_drag(0) +{ + add_events(Gdk::POINTER_MOTION_MASK | Gdk::BUTTON_PRESS_MASK | Gdk::BUTTON_RELEASE_MASK); + + _primitive_model = Gtk::ListStore::create(_primitive_columns); + + set_reorderable(true); + set_model(_primitive_model); + append_column(_("_Type"), _primitive_columns.type); + + signal_selection_changed().connect(sigc::mem_fun(*this, &PrimitiveList::queue_draw)); + + CellRendererConnection* cell = new CellRendererConnection; + int cols_count = append_column("Connections", *cell);/* + Gtk::TreeViewColumn* pColumn = get_column(cols_count - 1); + if(pColumn) + pColumn->add_attribute(cell->property_connection(), _columns.con);*/ +} + +Glib::SignalProxy0 FilterEffectsDialog::PrimitiveList::signal_selection_changed() +{ + return get_selection()->signal_changed(); +} + +/* Add all filter primitives in the current to the list. + Keeps the same selection if possible, otherwise selects the first element */ +void FilterEffectsDialog::PrimitiveList::update() +{ + SPFilter* f = _dialog._filter_modifier.get_selected_filter(); + const SPFilterPrimitive* active_prim = get_selected(); + bool active_found = false; + + _primitive_model->clear(); + + if(f) { + _dialog._primitive_box.set_sensitive(true); + + for(SPObject *prim_obj = f->children; + prim_obj && SP_IS_FILTER_PRIMITIVE(prim_obj); + prim_obj = prim_obj->next) { + SPFilterPrimitive *prim = SP_FILTER_PRIMITIVE(prim_obj); + if(prim) { + Gtk::TreeModel::Row row = *_primitive_model->append(); + row[_primitive_columns.primitive] = prim; + row[_primitive_columns.type_id] = FPConverter.get_id_from_name(prim->repr->name()); + row[_primitive_columns.type] = FPConverter.get_label(row[_primitive_columns.type_id]); + row[_primitive_columns.id] = SP_OBJECT_ID(prim); + + if(prim == active_prim) { + get_selection()->select(row); + active_found = true; + } + } + } + + if(!active_found && _primitive_model->children().begin()) + get_selection()->select(_primitive_model->children().begin()); + } + else { + _dialog._primitive_box.set_sensitive(false); + } +} + +void FilterEffectsDialog::PrimitiveList::set_menu(Glib::RefPtr menu) +{ + _primitive_menu = menu; } -void FilterEffectsDialog::SettingsFrame::init(Gtk::VBox& box) +SPFilterPrimitive* FilterEffectsDialog::PrimitiveList::get_selected() +{ + if(_dialog._filter_modifier.get_selected_filter()) { + Gtk::TreeModel::iterator i = get_selection()->get_selected(); + if(i) + return (*i)[_primitive_columns.primitive]; + } + + return 0; +} + +void FilterEffectsDialog::PrimitiveList::select(SPFilterPrimitive* prim) +{ + for(Gtk::TreeIter i = _primitive_model->children().begin(); + i != _primitive_model->children().end(); ++i) { + if((*i)[_primitive_columns.primitive] == prim) + get_selection()->select(i); + } +} + +bool FilterEffectsDialog::PrimitiveList::on_expose_event(GdkEventExpose* e) +{ + Gtk::TreeView::on_expose_event(e); + + const int sz = CellRendererConnection::size; + SPFilterPrimitive* prim = get_selected(); + + if(prim) { + int row_index = 0; + for(Gtk::TreeIter row = get_model()->children().begin(); + row != get_model()->children().end(); ++row, ++row_index) { + const int inputs = CellRendererConnection::input_count(prim); + for(int i = 0; i < inputs; ++i) { + Gdk::Rectangle rct, clip(&e->area); + get_cell_area(get_model()->get_path(row), *get_column(1), rct); + const int x = rct.get_x() + sz / 4 + sz * i; + const int y = rct.get_y() + sz / 4; + const bool on_sel_row = (*row)[_primitive_columns.primitive] == prim; + + // Check mouse state + int mx, my; + Gdk::ModifierType mask; + get_bin_window()->get_pointer(mx, my, mask); + //const bool inside = mx >= x && my >= y && mx <= x + sz / 2 && my <= y + sz / 2; + + get_bin_window()->draw_rectangle(get_style()->get_black_gc(), on_sel_row, x, y, sz / 2, sz / 2); + + // draw input connection(s) + if(on_sel_row) { + if(i == 0 && _in_drag != 1) + draw_connection(find_result(row), x + sz / 4, y + sz / 4); + else if(i == 1 && _in_drag != 2) { + /*if(SP_IS_FEBLEND(prim)) + \ draw_connection(SP_FEBLEND(prim)->in2, x + sz / 4, y + sz / 4);*/ + } + else if(_in_drag > 0) { + draw_connection(row, mx, my); + } + } + } + } + } + + return true; +} + +const Gtk::TreeIter FilterEffectsDialog::PrimitiveList::find_result(const Gtk::TreeIter& start) +{ + const int image = ((SPFilterPrimitive*)(*start)[_primitive_columns.primitive])->image_in; + Gtk::TreeIter target = _primitive_model->children().end(); + + if(image >= 0) { + for(Gtk::TreeIter i = _primitive_model->children().begin(); + i != start; ++i) { + if(((SPFilterPrimitive*)(*i)[_primitive_columns.primitive])->image_out == image) + target = i; + } + } + + return target; +} + +void FilterEffectsDialog::PrimitiveList::draw_connection(const Gtk::TreeIter& input, const int x, const int y) +{ + if(input != _primitive_model->children().end()) { + Gdk::Rectangle rct; + const int sz = CellRendererConnection::size; + + get_cell_area(get_model()->get_path(input), *get_column(1), rct); + + get_bin_window()->draw_line(get_style()->get_black_gc(), x, y, + rct.get_x() + sz / 2, rct.get_y() + sz / 2); + } +} + +// Gets (row, col) of the filter primitive input located at (x,y) +bool FilterEffectsDialog::PrimitiveList::get_coords_at_pos(const int x, const int y, int& row, + int& col, SPFilterPrimitive **prim) +{ + Gtk::TreePath path; + Gtk::TreeViewColumn* treecol; + Gdk::Rectangle rct; + int cx, cy; + + if(get_path_at_pos(x, y, path, treecol, cx, cy)) { + get_cell_area(path, *treecol, rct); + + if(x >= rct.get_x() && y >= rct.get_y() && + x <= rct.get_x() + rct.get_width() && y <= rct.get_y() + rct.get_height()) { + if(treecol == get_column(1)) { + col = (x - rct.get_x()) / CellRendererConnection::size + 1; + if(col > 0 && col <= 2) { + row = 0; + Gtk::TreeIter key = _primitive_model->get_iter(path); + for(Gtk::TreeIter i = _primitive_model->children().begin(); + i != _primitive_model->children().end(); ++i, ++row) { + if(key == i) + break; + } + if(prim) + (*prim) = (*key)[_primitive_columns.primitive]; + return true; + } + } + } + } + + return false; +} + +bool FilterEffectsDialog::PrimitiveList::on_button_press_event(GdkEventButton* e) +{ + int row, col; + + if(get_coords_at_pos((int)e->x, (int)e->y, row, col, 0)) { + _in_drag = col; + + queue_draw(); + } + + if(_in_drag) + return true; + else + return Gtk::TreeView::on_button_press_event(e); +} + +bool FilterEffectsDialog::PrimitiveList::on_motion_notify_event(GdkEventMotion* e) +{ + if(_in_drag) + queue_draw(); + + return Gtk::TreeView::on_motion_notify_event(e); +} + +bool FilterEffectsDialog::PrimitiveList::on_button_release_event(GdkEventButton* e) +{ + SPFilterPrimitive *prim = get_selected(), *target; + + if(_in_drag && prim) { + int row, col; + + if(get_coords_at_pos((int)e->x, (int)e->y, row, col, &target) && target != prim) { + Inkscape::XML::Node *repr = SP_OBJECT_REPR(target); + // Make sure the target has a result + const gchar *gres = repr->attribute("result"); + Glib::ustring result = gres ? gres : ""; + if(!gres) { + result = "result" + Glib::Ascii::dtostr(SP_FILTER(prim->parent)->_image_number_next); + repr->setAttribute("result", result.c_str()); + } + + SP_OBJECT_REPR(prim)->setAttribute("in", result.c_str()); + } + + _in_drag = 0; + queue_draw(); + + _dialog.update_settings_view(); + } + + if((e->type == GDK_BUTTON_RELEASE) && (e->button == 3)) { + const bool sensitive = get_selected() != NULL; + _primitive_menu->items()[0].set_sensitive(sensitive); + _primitive_menu->items()[1].set_sensitive(sensitive); + _primitive_menu->popup(e->button, e->time); + + return true; + } + else + return Gtk::TreeView::on_button_release_event(e); +} + +// Reorder the filter primitives to match the list order +void FilterEffectsDialog::PrimitiveList::on_drag_end(const Glib::RefPtr&) +{ + int ndx = 0; + SPFilter* filter = _dialog._filter_modifier.get_selected_filter(); + + for(Gtk::TreeModel::iterator iter = _primitive_model->children().begin(); + iter != _primitive_model->children().end(); ++iter) { + SPFilterPrimitive* prim = (*iter)[_primitive_columns.primitive]; + if(prim) + ;//reorder_primitive(filter, prim->repr->position(), ndx); /* FIXME */ + } + + sp_document_done(filter->document, SP_VERB_DIALOG_FILTER_EFFECTS, _("Reorder filter primitive")); +} + +/*** SettingsGroup ***/ +FilterEffectsDialog::SettingsGroup::SettingsGroup() +{ + show(); +} + +void FilterEffectsDialog::SettingsGroup::init(Gtk::VBox& box, Glib::RefPtr sg) { box.pack_start(*this, false, false); + _sizegroup = sg; } -void FilterEffectsDialog::SettingsFrame::add_setting(Gtk::Widget& w, const Glib::ustring& label) +void FilterEffectsDialog::SettingsGroup::add_setting(Gtk::Widget& w, const Glib::ustring& label) { - Gtk::Label *lbl = new Gtk::Label(label + ":", Gtk::ALIGN_LEFT); + Gtk::Label *lbl = Gtk::manage(new Gtk::Label(label + (label == "" ? "" : ":"), Gtk::ALIGN_LEFT)); + Gtk::HBox *hb = Gtk::manage(new Gtk::HBox); + hb->set_spacing(12); + hb->pack_start(*lbl, false, false); + hb->pack_start(w); + pack_start(*hb); - attach(*Gtk::manage(lbl), 0, 1, _where, _where + 1, Gtk::FILL, Gtk::FILL); - attach(w, 1, 2, _where, _where + 1, Gtk::FILL|Gtk::EXPAND, Gtk::FILL); + _sizegroup->add_widget(*lbl); + hb->show(); lbl->show(); + w.show(); +} - ++_where; +void FilterEffectsDialog::SettingsGroup::add_setting(std::vector& w, const Glib::ustring& label) +{ + Gtk::HBox *hb = Gtk::manage(new Gtk::HBox); + for(unsigned int i = 0; i < w.size(); ++i) + hb->pack_start(*w[i]); + hb->set_spacing(12); + add_setting(*hb, label); } /*** FilterEffectsDialog ***/ FilterEffectsDialog::FilterEffectsDialog() : Dialog ("dialogs.filtereffects", SP_VERB_DIALOG_FILTER_EFFECTS), + _primitive_list(*this), _add_primitive_type(FPConverter), _add_primitive(Gtk::Stock::ADD), + _settings_labels(Gtk::SizeGroup::create(Gtk::SIZE_GROUP_HORIZONTAL)), _empty_settings("No primitive selected", Gtk::ALIGN_LEFT), _blend_mode(BlendModeConverter), _gaussianblur_stddeviation(1, 0, 100, 1, 0.01, 1), @@ -223,21 +556,23 @@ FilterEffectsDialog::FilterEffectsDialog() _offset_dx(0, -100, 100, 1, 0.01, 1), _offset_dy(0, -100, 100, 1, 0.01, 1), _turbulence_basefrequency(1, 0, 100, 1, 0.01, 1), - _turbulence_numoctaves(1, 0, 100, 1, 0.01, 1), - _turbulence_seed(1, 0, 100, 1, 0.01, 1) + _turbulence_numoctaves(1, 1, 10, 1, 1, 0), + _turbulence_seed(1, 0, 100, 1, 0.01, 1), + _turbulence_stitchtiles(_("Stitch Tiles")), + _turbulence_fractalnoise(_turbulence_type, _("Fractal Noise")), + _turbulence_turbulence(_turbulence_type, _("Turbulence")) { // Initialize widget hierarchy Gtk::HPaned* hpaned = Gtk::manage(new Gtk::HPaned); - Gtk::VBox* vb_prims = Gtk::manage(new Gtk::VBox); Gtk::ScrolledWindow* sw_prims = Gtk::manage(new Gtk::ScrolledWindow); Gtk::HBox* hb_prims = Gtk::manage(new Gtk::HBox); Gtk::Frame* fr_settings = Gtk::manage(new Gtk::Frame("Settings")); Gtk::Alignment* al_settings = Gtk::manage(new Gtk::Alignment); get_vbox()->add(*hpaned); hpaned->pack1(_filter_modifier); - hpaned->pack2(*vb_prims); - vb_prims->pack_start(*sw_prims); - vb_prims->pack_start(*hb_prims, false, false); + hpaned->pack2(_primitive_box); + _primitive_box.pack_start(*sw_prims); + _primitive_box.pack_start(*hb_prims, false, false); sw_prims->add(_primitive_list); hb_prims->pack_end(_add_primitive, false, false); hb_prims->pack_end(_add_primitive_type, false, false); @@ -245,36 +580,24 @@ FilterEffectsDialog::FilterEffectsDialog() fr_settings->add(*al_settings); al_settings->add(_settings); - // Primitive list - _primitive_model = Gtk::ListStore::create(_primitive_columns); - _primitive_list.set_reorderable(true); - _primitive_list.set_model(_primitive_model); - //_primitive_list.append_column_editable(_("_Primitive"), _primitive_columns.id); - _primitive_list.append_column("Type", _primitive_columns.type); - ((Gtk::CellRendererText*)_primitive_list.get_column(0)->get_first_cell_renderer())-> - signal_edited().connect(sigc::mem_fun(*this, &FilterEffectsDialog::primitive_name_edited)); - _filter_modifier.signal_selection_changed().connect( - sigc::mem_fun(*this, &FilterEffectsDialog::update_primitive_list)); - _primitive_list.get_selection()->signal_changed().connect( + _primitive_list.signal_selection_changed().connect( sigc::mem_fun(*this, &FilterEffectsDialog::update_settings_view)); - _primitive_list.signal_button_press_event().connect_notify( - sigc::mem_fun(*this, &FilterEffectsDialog::primitive_list_button_press)); - _primitive_list.signal_drag_end().connect( - sigc::mem_fun(*this, &FilterEffectsDialog::primitive_list_drag_end)); + _filter_modifier.signal_selection_changed().connect( + sigc::mem_fun(_primitive_list, &PrimitiveList::update)); - // Other widgets sw_prims->set_policy(Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC); sw_prims->set_shadow_type(Gtk::SHADOW_IN); al_settings->set_padding(0, 0, 12, 0); fr_settings->set_shadow_type(Gtk::SHADOW_NONE); ((Gtk::Label*)fr_settings->get_label_widget())->set_use_markup(); _add_primitive.signal_clicked().connect(sigc::mem_fun(*this, &FilterEffectsDialog::add_primitive)); - _primitive_menu = create_popup_menu(*this, sigc::mem_fun(*this, &FilterEffectsDialog::duplicate_primitive), - sigc::mem_fun(*this, &FilterEffectsDialog::remove_primitive)); + _primitive_list.set_menu(create_popup_menu(*this, sigc::mem_fun(*this, &FilterEffectsDialog::duplicate_primitive), + sigc::mem_fun(*this, &FilterEffectsDialog::remove_primitive))); + _settings_labels->set_ignore_hidden(true); show_all_children(); init_settings_widgets(); - update_primitive_list(); + _primitive_list.update(); update_settings_view(); } @@ -282,72 +605,58 @@ FilterEffectsDialog::~FilterEffectsDialog() { } -void FilterEffectsDialog::primitive_list_button_press(GdkEventButton* event) -{ - if((event->type == GDK_BUTTON_PRESS) && (event->button == 3)) { - const bool sensitive = get_selected_primitive() != NULL; - _primitive_menu->items()[0].set_sensitive(sensitive); - _primitive_menu->items()[1].set_sensitive(sensitive); - _primitive_menu->popup(event->button, event->time); - } -} - -// Reorder the filter primitives to match the list order -void FilterEffectsDialog::primitive_list_drag_end(const Glib::RefPtr&) -{ - int ndx = 0; - SPFilter* filter = _filter_modifier.get_selected_filter(); - - for(Gtk::TreeModel::iterator iter = _primitive_model->children().begin(); - iter != _primitive_model->children().end(); ++iter) { - SPFilterPrimitive* prim = (*iter)[_primitive_columns.primitive]; - if(prim) - ;//reorder_primitive(filter, prim->repr->position(), ndx); /* FIXME */ - std::cout << prim->repr->position(); - } - - sp_document_done(filter->document, SP_VERB_DIALOG_FILTER_EFFECTS, _("Reorder filter primitive")); -} - void FilterEffectsDialog::init_settings_widgets() { _empty_settings.set_sensitive(false); _settings.pack_start(_empty_settings); - _blend.init(_settings); + _generic_settings.init(_settings, _settings_labels); + _generic_settings.add_setting(_primitive_input1, "Input"); + _primitive_input1.signal_changed().connect( + sigc::bind(sigc::mem_fun(*this, &FilterEffectsDialog::set_attr), SP_ATTR_IN)); + _primitive_input1.append_text("Default"); + _primitive_input1.append_text("Source Graphic"); + _primitive_input1.append_text("Source Alpha"); + _primitive_input1.append_text("Background Image"); + _primitive_input1.append_text("Background Alpha"); + _primitive_input1.append_text("Fill Paint"); + _primitive_input1.append_text("Stroke Paint"); + _primitive_input1.append_text("Connection"); + + _blend.init(_settings, _settings_labels); _blend.add_setting(_blend_mode, "Mode"); _blend_mode.signal_changed().connect( sigc::bind(sigc::mem_fun(*this, &FilterEffectsDialog::set_attr), SP_ATTR_MODE)); - _colormatrix.init(_settings); + _colormatrix.init(_settings, _settings_labels); _colormatrix.add_setting(_colormatrix_type, "Type"); - _componenttransfer.init(_settings); + _componenttransfer.init(_settings, _settings_labels); - _composite.init(_settings); + _composite.init(_settings, _settings_labels); - _convolvematrix.init(_settings); + _convolvematrix.init(_settings, _settings_labels); - _diffuselighting.init(_settings); + _diffuselighting.init(_settings, _settings_labels); - _displacementmap.init(_settings); + _displacementmap.init(_settings, _settings_labels); - _flood.init(_settings); + _flood.init(_settings, _settings_labels); - _gaussianblur.init(_settings); + _gaussianblur.init(_settings, _settings_labels); _gaussianblur.add_setting(_gaussianblur_stddeviation, "Standard Deviation"); _gaussianblur_stddeviation.signal_value_changed().connect( sigc::bind(sigc::mem_fun(*this, &FilterEffectsDialog::set_attr), SP_ATTR_STDDEVIATION)); - _image.init(_settings); + _image.init(_settings, _settings_labels); - _merge.init(_settings); + _merge.init(_settings, _settings_labels); - _morphology.init(_settings); + _morphology.init(_settings, _settings_labels); _morphology.add_setting(_morphology_operator, "Operator"); _morphology.add_setting(_morphology_radius, "Radius"); - _offset.init(_settings); + _offset.init(_settings, _settings_labels); _offset.add_setting(_offset_dx, "Delta X"); _offset_dx.signal_value_changed().connect( sigc::bind(sigc::mem_fun(*this, &FilterEffectsDialog::set_attr), SP_ATTR_DX)); @@ -355,16 +664,19 @@ void FilterEffectsDialog::init_settings_widgets() _offset_dy.signal_value_changed().connect( sigc::bind(sigc::mem_fun(*this, &FilterEffectsDialog::set_attr), SP_ATTR_DY)); - _specularlighting.init(_settings); + _specularlighting.init(_settings, _settings_labels); - _tile.init(_settings); + _tile.init(_settings, _settings_labels); - _turbulence.init(_settings); - _turbulence.add_setting(_turbulence_basefrequency, "Base Frequency"); + _turbulence.init(_settings, _settings_labels); + std::vector trb_grp; + trb_grp.push_back(&_turbulence_fractalnoise); + trb_grp.push_back(&_turbulence_turbulence); + _turbulence.add_setting(trb_grp); _turbulence.add_setting(_turbulence_numoctaves, "Octaves"); + _turbulence.add_setting(_turbulence_basefrequency, "Base Frequency"); _turbulence.add_setting(_turbulence_seed, "Seed"); - _turbulence.add_setting(_turbulence_stitchtiles, "Stitch Tiles"); - _turbulence.add_setting(_turbulence_type, "Type"); + _turbulence.add_setting(_turbulence_stitchtiles); } void FilterEffectsDialog::add_primitive() @@ -417,8 +729,8 @@ void FilterEffectsDialog::add_primitive() break; } - update_primitive_list(); - select_primitive(prim); + _primitive_list.update(); + _primitive_list.select(prim); sp_document_done(filter->document, SP_VERB_DIALOG_FILTER_EFFECTS, _("Add filter primitive")); } @@ -426,24 +738,22 @@ void FilterEffectsDialog::add_primitive() void FilterEffectsDialog::remove_primitive() { - Gtk::TreeModel::iterator i = _primitive_list.get_selection()->get_selected(); + SPFilterPrimitive* prim = _primitive_list.get_selected(); - if(i) { - SPFilterPrimitive* prim = (*i)[_primitive_columns.primitive]; - + if(prim) { sp_repr_unparent(prim->repr); sp_document_done(sp_desktop_document(SP_ACTIVE_DESKTOP), SP_VERB_DIALOG_FILTER_EFFECTS, _("Remove filter primitive")); - update_primitive_list(); + _primitive_list.update(); } } void FilterEffectsDialog::duplicate_primitive() { SPFilter* filter = _filter_modifier.get_selected_filter(); - SPFilterPrimitive* origprim = get_selected_primitive(); + SPFilterPrimitive* origprim = _primitive_list.get_selected(); if(filter && origprim) { Inkscape::XML::Node *repr; @@ -452,29 +762,37 @@ void FilterEffectsDialog::duplicate_primitive() sp_document_done(filter->document, SP_VERB_DIALOG_FILTER_EFFECTS, _("Duplicate filter primitive")); - update_primitive_list(); + _primitive_list.update(); } } -// Edits the id of the primitive at path -void FilterEffectsDialog::primitive_name_edited(const Glib::ustring& path, const Glib::ustring& text) -{ - Gtk::TreeModel::iterator i = _primitive_model->get_iter(path); - - if(i) - try_id_change((*i)[_primitive_columns.primitive], text); -} - void FilterEffectsDialog::set_attr(const SPAttributeEnum attr) { - Gtk::TreeModel::iterator i = _primitive_list.get_selection()->get_selected(); + SPFilterPrimitive* prim = _primitive_list.get_selected(); - if(i) { + if(prim) { SPFilter *filter = _filter_modifier.get_selected_filter(); - SPFilterPrimitive* prim = (*i)[_primitive_columns.primitive]; std::ostringstream os; Glib::ustring val; + if(attr == SP_ATTR_IN) { + val = _primitive_input1.get_active_text(); + if(val == "Default") { + val = ""; + } + else if(val == "Connection") { + return; + } + else { + val.erase(val.find(" "), 1); + for(Glib::ustring::size_type i = 0; i < val.size(); ++i) { + if(val[i] == ' ') { + val.erase(i, i + 1); + break; + } + } + } + } if(attr == SP_ATTR_MODE) { val = _blend_mode.get_active_data()->name; } @@ -491,6 +809,7 @@ void FilterEffectsDialog::set_attr(const SPAttributeEnum attr) val = os.str(); } + SP_OBJECT_REPR(prim)->setAttribute((gchar*)sp_attribute_name(attr), val.c_str()); sp_object_set(prim, attr, val.c_str()); filter->requestModified(SP_OBJECT_MODIFIED_FLAG); @@ -498,128 +817,87 @@ void FilterEffectsDialog::set_attr(const SPAttributeEnum attr) } } -/* Add all filter primitives in the current to the list. - Keeps the same selection if possible, otherwise selects the first element */ -void FilterEffectsDialog::update_primitive_list() -{ - SPFilter* f = _filter_modifier.get_selected_filter(); - const SPFilterPrimitive* active_prim = get_selected_primitive(); - bool active_found = false; - - _primitive_model->clear(); - - if(f) { - _primitive_box.set_sensitive(true); - - for(SPObject *prim_obj = f->children; - prim_obj && SP_IS_FILTER_PRIMITIVE(prim_obj); - prim_obj = prim_obj->next) { - SPFilterPrimitive *prim = SP_FILTER_PRIMITIVE(prim_obj); - if(prim) { - Gtk::TreeModel::Row row = *_primitive_model->append(); - row[_primitive_columns.primitive] = prim; - row[_primitive_columns.type_id] = FPConverter.get_id_from_name(prim->repr->name()); - row[_primitive_columns.type] = FPConverter.get_label(row[_primitive_columns.type_id]); - row[_primitive_columns.id] = SP_OBJECT_ID(prim); - - if(prim == active_prim) { - _primitive_list.get_selection()->select(row); - active_found = true; - } - } - } - - if(!active_found && _primitive_model->children().begin()) - _primitive_list.get_selection()->select(_primitive_model->children().begin()); - } - else { - _primitive_box.set_sensitive(false); - } -} - void FilterEffectsDialog::update_settings_view() { - SPFilterPrimitive* prim = get_selected_primitive(); + SPFilterPrimitive* prim = _primitive_list.get_selected(); - // Hide all the settings except for common - Glib::ListHandle c = _settings.get_children(); - for(Glib::ListHandle::iterator iter = c.begin(); - iter != c.end(); ++iter) { - (*iter)->hide(); - } + // Hide all the settings + _settings.hide_all(); + _settings.show(); _settings.set_sensitive(false); _empty_settings.show(); if(prim) { const NR::FilterPrimitiveType tid = FPConverter.get_id_from_name(prim->repr->name()); + + _generic_settings.show_all(); + const gchar *attr_in_g = SP_OBJECT_REPR(prim)->attribute("in"); + const Glib::ustring attr_in = attr_in_g ? attr_in_g : ""; + if(attr_in == "") + _primitive_input1.set_active(0); + else if(attr_in == "SourceGraphic") + _primitive_input1.set_active(1); + else if(attr_in == "SourceAlpha") + _primitive_input1.set_active(2); + else if(attr_in == "BackgroundImage") + _primitive_input1.set_active(3); + else if(attr_in == "BackgroundAlpha") + _primitive_input1.set_active(4); + else if(attr_in == "Fill Paint") + _primitive_input1.set_active(5); + else if(attr_in == "Stroke Paint") + _primitive_input1.set_active(6); + else + _primitive_input1.set_active(7); + if(tid == NR::NR_FILTER_BLEND) { - _blend.show(); + _blend.show_all(); const gchar* val = prim->repr->attribute("mode"); if(val) _blend_mode.set_active(BlendModeConverter.get_id_from_name(val)); } else if(tid == NR::NR_FILTER_COLORMATRIX) - _colormatrix.show(); + _colormatrix.show_all(); else if(tid == NR::NR_FILTER_COMPONENTTRANSFER) - _componenttransfer.show(); + _componenttransfer.show_all(); else if(tid == NR::NR_FILTER_COMPOSITE) - _composite.show(); + _composite.show_all(); else if(tid == NR::NR_FILTER_CONVOLVEMATRIX) - _convolvematrix.show(); + _convolvematrix.show_all(); else if(tid == NR::NR_FILTER_DIFFUSELIGHTING) - _diffuselighting.show(); + _diffuselighting.show_all(); else if(tid == NR::NR_FILTER_DISPLACEMENTMAP) - _displacementmap.show(); + _displacementmap.show_all(); else if(tid == NR::NR_FILTER_FLOOD) - _flood.show(); + _flood.show_all(); else if(tid == NR::NR_FILTER_GAUSSIANBLUR) { - _gaussianblur.show(); + _gaussianblur.show_all(); _gaussianblur_stddeviation.set_value(((SPGaussianBlur*)prim)->stdDeviation.getNumber()); } else if(tid == NR::NR_FILTER_IMAGE) - _image.show(); + _image.show_all(); else if(tid == NR::NR_FILTER_MERGE) - _merge.show(); + _merge.show_all(); else if(tid == NR::NR_FILTER_MORPHOLOGY) - _morphology.show(); + _morphology.show_all(); else if(tid == NR::NR_FILTER_OFFSET) { - _offset.show(); + _offset.show_all(); _offset_dx.set_value(((SPFeOffset*)prim)->dx); _offset_dy.set_value(((SPFeOffset*)prim)->dy); } else if(tid == NR::NR_FILTER_SPECULARLIGHTING) - _specularlighting.show(); + _specularlighting.show_all(); else if(tid == NR::NR_FILTER_TILE) - _tile.show(); + _tile.show_all(); else if(tid == NR::NR_FILTER_TURBULENCE) - _turbulence.show(); + _turbulence.show_all(); _settings.set_sensitive(true); _empty_settings.hide(); } } -SPFilterPrimitive* FilterEffectsDialog::get_selected_primitive() -{ - if(_filter_modifier.get_selected_filter()) { - Gtk::TreeModel::iterator i = _primitive_list.get_selection()->get_selected(); - if(i) - return (*i)[_primitive_columns.primitive]; - } - - return 0; -} - -void FilterEffectsDialog::select_primitive(SPFilterPrimitive* prim) -{ - for(Gtk::TreeIter i = _primitive_model->children().begin(); - i != _primitive_model->children().end(); ++i) { - if((*i)[_primitive_columns.primitive] == prim) - _primitive_list.get_selection()->select(i); - } -} - } // namespace Dialog } // namespace UI } // namespace Inkscape diff --git a/src/ui/dialog/filter-effects-dialog.h b/src/ui/dialog/filter-effects-dialog.h index 3438348d5..6b1f48895 100644 --- a/src/ui/dialog/filter-effects-dialog.h +++ b/src/ui/dialog/filter-effects-dialog.h @@ -21,6 +21,7 @@ #include #include #include +#include #include #include "attributes.h" @@ -52,7 +53,7 @@ private: virtual void select_filter(const SPFilter*); virtual Glib::SignalProxy0 signal_selection_changed(); private: - void filter_list_button_press(GdkEventButton*); + void filter_list_button_release(GdkEventButton*); void add_filter(); void remove_filter(); void duplicate_filter(); @@ -80,17 +81,46 @@ private: Gtk::TreeModelColumn id; }; - class SettingsFrame : public Gtk::Table + class PrimitiveList : public Gtk::TreeView { public: - SettingsFrame(); + PrimitiveList(FilterEffectsDialog&); - void init(Gtk::VBox& box); - void add_setting(Gtk::Widget& w, const Glib::ustring& label); + Glib::SignalProxy0 signal_selection_changed(); + + void update(); + void set_menu(Glib::RefPtr); + + SPFilterPrimitive* get_selected(); + void select(SPFilterPrimitive *prim); + protected: + bool on_expose_event(GdkEventExpose*); + bool on_button_press_event(GdkEventButton*); + bool on_motion_notify_event(GdkEventMotion*); + bool on_button_release_event(GdkEventButton*); + void on_drag_end(const Glib::RefPtr&); private: - Gtk::Alignment _alignment; - Gtk::Table _table; - int _where; + bool get_coords_at_pos(const int x, const int y, int& row, int& col, SPFilterPrimitive **prim); + const Gtk::TreeIter find_result(const Gtk::TreeIter& start); + void draw_connection(const Gtk::TreeIter&, const int x, const int y); + + FilterEffectsDialog& _dialog; + Glib::RefPtr _primitive_model; + PrimitiveColumns _primitive_columns; + Glib::RefPtr _primitive_menu; + int _in_drag; + }; + + class SettingsGroup : public Gtk::VBox + { + public: + SettingsGroup(); + + void init(Gtk::VBox& box, Glib::RefPtr sg); + void add_setting(Gtk::Widget& w, const Glib::ustring& label = ""); + void add_setting(std::vector& w, const Glib::ustring& label = ""); + private: + Glib::RefPtr _sizegroup; }; void init_settings_widgets(); @@ -99,77 +129,73 @@ private: void add_primitive(); void remove_primitive(); void duplicate_primitive(); - void primitive_name_edited(const Glib::ustring& path, const Glib::ustring& text); - void primitive_list_button_press(GdkEventButton* event); - void primitive_list_drag_end(const Glib::RefPtr&); void set_attr(const SPAttributeEnum); void update_settings_view(); - void update_primitive_list(); - - SPFilterPrimitive* get_selected_primitive(); - void select_primitive(SPFilterPrimitive *prim); // Filter effect selection FilterModifier _filter_modifier; // View/add primitives Gtk::VBox _primitive_box; - Gtk::TreeView _primitive_list; - Glib::RefPtr _primitive_model; - PrimitiveColumns _primitive_columns; - Glib::RefPtr _primitive_menu; + PrimitiveList _primitive_list; UI::Widget::ComboBoxEnum _add_primitive_type; Gtk::Button _add_primitive; // Right pane (filter effect primitive settings) Gtk::VBox _settings; + Glib::RefPtr _settings_labels; Gtk::Label _empty_settings; - SettingsFrame _blend; + // Generic settings + SettingsGroup _generic_settings; + Gtk::ComboBoxText _primitive_input1; + + SettingsGroup _blend; UI::Widget::ComboBoxEnum _blend_mode; - SettingsFrame _colormatrix; + SettingsGroup _colormatrix; Gtk::ComboBoxText _colormatrix_type; - SettingsFrame _componenttransfer; + SettingsGroup _componenttransfer; - SettingsFrame _composite; + SettingsGroup _composite; - SettingsFrame _convolvematrix; + SettingsGroup _convolvematrix; - SettingsFrame _diffuselighting; + SettingsGroup _diffuselighting; - SettingsFrame _displacementmap; + SettingsGroup _displacementmap; - SettingsFrame _flood; + SettingsGroup _flood; - SettingsFrame _gaussianblur; + SettingsGroup _gaussianblur; SpinSlider _gaussianblur_stddeviation; - SettingsFrame _image; + SettingsGroup _image; - SettingsFrame _merge; + SettingsGroup _merge; - SettingsFrame _morphology; + SettingsGroup _morphology; Gtk::ComboBoxText _morphology_operator; SpinSlider _morphology_radius; - SettingsFrame _offset; + SettingsGroup _offset; SpinSlider _offset_dx; SpinSlider _offset_dy; - SettingsFrame _specularlighting; + SettingsGroup _specularlighting; - SettingsFrame _tile; + SettingsGroup _tile; - SettingsFrame _turbulence; + SettingsGroup _turbulence; SpinSlider _turbulence_basefrequency; SpinSlider _turbulence_numoctaves; SpinSlider _turbulence_seed; - Gtk::ComboBoxText _turbulence_stitchtiles; - Gtk::ComboBoxText _turbulence_type; - + Gtk::CheckButton _turbulence_stitchtiles; + Gtk::RadioButton::Group _turbulence_type; + Gtk::RadioButton _turbulence_fractalnoise; + Gtk::RadioButton _turbulence_turbulence; FilterEffectsDialog(FilterEffectsDialog const &d); FilterEffectsDialog& operator=(FilterEffectsDialog const &d); diff --git a/src/ui/widget/filter-effect-chooser.cpp b/src/ui/widget/filter-effect-chooser.cpp index 06a6e833e..1303d6393 100644 --- a/src/ui/widget/filter-effect-chooser.cpp +++ b/src/ui/widget/filter-effect-chooser.cpp @@ -235,6 +235,7 @@ const EnumData FPData[NR::NR_FILTER_ENDPRIMITIVETYPE] = {NR::NR_FILTER_TURBULENCE, _("Turbulence"), "svg:feTurbulence"} }; const Converter FPConverter(FPData, NR::NR_FILTER_ENDPRIMITIVETYPE); + const EnumData BlendModeData[NR::BLEND_ENDMODE] = { {NR::BLEND_NORMAL, _("Normal"), "normal"}, {NR::BLEND_MULTIPLY, _("Multiply"), "multiply"}, -- 2.30.2