diff options
-rw-r--r-- | src/gui/MachinaCanvas.cpp | 52 | ||||
-rw-r--r-- | src/gui/MachinaCanvas.hpp | 8 | ||||
-rw-r--r-- | src/gui/MachinaGUI.cpp | 30 | ||||
-rw-r--r-- | src/gui/MachinaGUI.hpp | 14 | ||||
-rw-r--r-- | src/gui/NodeView.cpp | 2 | ||||
-rw-r--r-- | src/gui/machina.ui | 61 |
6 files changed, 136 insertions, 31 deletions
diff --git a/src/gui/MachinaCanvas.cpp b/src/gui/MachinaCanvas.cpp index 1a95b1c..15aaf57 100644 --- a/src/gui/MachinaCanvas.cpp +++ b/src/gui/MachinaCanvas.cpp @@ -38,45 +38,55 @@ namespace gui { MachinaCanvas::MachinaCanvas(MachinaGUI* app, int width, int height) : Canvas(width, height) , _app(app) - , _last_clicked(NULL) + , _connect_node(NULL) + , _did_connect(false) { widget().grab_focus(); - signal_event.connect( - sigc::mem_fun(this, &MachinaCanvas::on_event)); + signal_event.connect(sigc::mem_fun(this, &MachinaCanvas::on_event)); +} + +void +MachinaCanvas::connect_nodes(GanvNode* node, void* data) +{ + NodeView* view = dynamic_cast<NodeView*>(Glib::wrap(node)); + if (!view) { + std::cerr << "error: Connect of node with no view" << std::endl; + return; + } + MachinaCanvas* canvas = (MachinaCanvas*)data; + if (canvas->get_edge(view, canvas->_connect_node)) { + canvas->action_disconnect(view, canvas->_connect_node); + canvas->_did_connect = true; + } else if (!canvas->get_edge(canvas->_connect_node, view)) { + canvas->action_connect(view, canvas->_connect_node); + canvas->_did_connect = true; + } } bool MachinaCanvas::node_clicked(NodeView* node, GdkEventButton* event) { - if (event->state & GDK_CONTROL_MASK) { + if (event->state & (GDK_CONTROL_MASK|GDK_SHIFT_MASK)) { return false; - } - if (event->button == 2) { + } else if (event->button == 2) { // Middle click: learn _app->controller()->learn(_app->maid(), node->node()->id()); return false; } else if (event->button == 1) { // Left click: connect/disconnect - if (_last_clicked) { - if (node != _last_clicked) { - if (get_edge(_last_clicked, node)) { - action_disconnect(_last_clicked, node); - } else { - action_connect(_last_clicked, node); - } - } - - _last_clicked->set_default_colors(); - _last_clicked = NULL; - + _connect_node = node; + for_each_selected_node(connect_nodes, this); + const bool handled = _did_connect; + _connect_node = NULL; + _did_connect = false; + if (_app->chain_mode()) { + return false; // Cause Ganv to select as usual } else { - _last_clicked = node; + return handled; // If we did something, stop event here } - - return true; } return false; diff --git a/src/gui/MachinaCanvas.hpp b/src/gui/MachinaCanvas.hpp index 155bdfc..f32e6cb 100644 --- a/src/gui/MachinaCanvas.hpp +++ b/src/gui/MachinaCanvas.hpp @@ -33,8 +33,7 @@ namespace gui { class MachinaGUI; class NodeView; -class MachinaCanvas - : public Canvas +class MachinaCanvas : public Canvas { public: MachinaCanvas(MachinaGUI* app, int width, int height); @@ -54,8 +53,11 @@ private: void action_connect(NodeView* tail, NodeView* head); void action_disconnect(NodeView* tail, NodeView* head); + static void connect_nodes(GanvNode* node, void* data); + MachinaGUI* _app; - NodeView* _last_clicked; + NodeView* _connect_node; + bool _did_connect; }; } // namespace machina diff --git a/src/gui/MachinaGUI.cpp b/src/gui/MachinaGUI.cpp index e283530..cc22cf8 100644 --- a/src/gui/MachinaGUI.cpp +++ b/src/gui/MachinaGUI.cpp @@ -41,13 +41,14 @@ namespace machina { namespace gui { MachinaGUI::MachinaGUI(SPtr<machina::Engine> engine) - : _refresh(false) - , _evolve(false) - , _unit(TimeUnit::BEATS, 19200) + : _unit(TimeUnit::BEATS, 19200) , _engine(engine) , _client_model(new machina::client::ClientModel()) , _controller(new machina::Controller(_engine, *_client_model.get())) , _maid(new Raul::Maid()) + , _refresh(false) + , _evolve(false) + , _chain_mode(true) { _canvas = SPtr<MachinaCanvas>(new MachinaCanvas(this, 1600*2, 1200*2)); @@ -80,6 +81,8 @@ MachinaGUI::MachinaGUI(SPtr<machina::Engine> engine) xml->get_widget("zoom_normal_but", _zoom_normal_button); xml->get_widget("zoom_full_but", _zoom_full_button); xml->get_widget("arrange_but", _arrange_button); + xml->get_widget("chain_but", _chain_button); + xml->get_widget("fan_but", _fan_button); xml->get_widget("load_target_but", _load_target_button); xml->get_widget("evolve_toolbar", _evolve_toolbar); xml->get_widget("evolve_but", _evolve_button); @@ -115,6 +118,11 @@ MachinaGUI::MachinaGUI(SPtr<machina::Engine> engine) _arrange_button->signal_clicked().connect( sigc::mem_fun(this, &MachinaGUI::arrange)); + _chain_button->signal_toggled().connect( + sigc::mem_fun(this, &MachinaGUI::chain_toggled)); + _fan_button->signal_toggled().connect( + sigc::mem_fun(this, &MachinaGUI::fan_toggled)); + _menu_file_open->signal_activate().connect( sigc::mem_fun(this, &MachinaGUI::menu_file_open)); _menu_file_save->signal_activate().connect( @@ -687,6 +695,22 @@ MachinaGUI::record_toggled() } void +MachinaGUI::chain_toggled() +{ + if (_chain_button->get_active()) { + _chain_mode = true; + } +} + +void +MachinaGUI::fan_toggled() +{ + if (_fan_button->get_active()) { + _chain_mode = false; + } +} + +void MachinaGUI::on_new_object(SPtr<client::ClientObject> object) { _canvas->on_new_object(object); diff --git a/src/gui/MachinaGUI.hpp b/src/gui/MachinaGUI.hpp index d71c556..3ebbd04 100644 --- a/src/gui/MachinaGUI.hpp +++ b/src/gui/MachinaGUI.hpp @@ -62,6 +62,8 @@ public: void attach(); void quit() { _main_window->hide(); } + bool chain_mode() const { return _chain_mode; } + SPtr<machina::Controller> controller() { return _controller; } inline void queue_refresh() { _refresh = true; } @@ -108,12 +110,12 @@ protected: void play_toggled(); void record_toggled(); + void chain_toggled(); + void fan_toggled(); + void quantize_changed(); void tempo_changed(); - bool _refresh; - bool _evolve; - string _save_uri; string _target_filename; @@ -160,6 +162,8 @@ protected: Gtk::ToolButton* _zoom_normal_button; Gtk::ToolButton* _zoom_full_button; Gtk::ToolButton* _arrange_button; + Gtk::RadioButton* _chain_button; + Gtk::RadioButton* _fan_button; Gtk::ToolButton* _load_target_button; Gtk::Toolbar* _evolve_toolbar; Gtk::ToggleToolButton* _evolve_button; @@ -171,6 +175,10 @@ protected: Gtk::ToolButton* _add_edge_button; Gtk::ToolButton* _remove_edge_button; Gtk::ToolButton* _adjust_edge_button; + + bool _refresh; + bool _evolve; + bool _chain_mode; }; } // namespace machina diff --git a/src/gui/NodeView.cpp b/src/gui/NodeView.cpp index 6132f8c..38e5ea7 100644 --- a/src/gui/NodeView.cpp +++ b/src/gui/NodeView.cpp @@ -92,7 +92,7 @@ NodeView::on_event(GdkEvent* event) return true; } } else { - _signal_clicked.emit(&event->button); + return _signal_clicked.emit(&event->button); } } else if (event->type == GDK_2BUTTON_PRESS) { return on_double_click(&event->button); diff --git a/src/gui/machina.ui b/src/gui/machina.ui index 88c1c0b..75c4c1f 100644 --- a/src/gui/machina.ui +++ b/src/gui/machina.ui @@ -619,6 +619,67 @@ press stop or play and the new nodes will be added to the machine. <property name="homogeneous">True</property> </packing> </child> + <child> + <object class="GtkSeparatorToolItem" id="separatortoolitem5"> + <property name="visible">True</property> + <property name="can_focus">False</property> + </object> + <packing> + <property name="expand">False</property> + </packing> + </child> + <child> + <object class="GtkToolItem" id="toolitem2"> + <property name="use_action_appearance">False</property> + <property name="visible">True</property> + <property name="can_focus">False</property> + <child> + <object class="GtkHBox" id="hbox1"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="border_width">4</property> + <child> + <object class="GtkRadioButton" id="chain_but"> + <property name="label" translatable="yes">Chain</property> + <property name="use_action_appearance">False</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">False</property> + <property name="tooltip_text" translatable="yes">Move selection to head node after connection</property> + <property name="active">True</property> + <property name="draw_indicator">True</property> + </object> + <packing> + <property name="expand">True</property> + <property name="fill">True</property> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkRadioButton" id="fan_but"> + <property name="label" translatable="yes">Fan</property> + <property name="use_action_appearance">False</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">False</property> + <property name="tooltip_text" translatable="yes">Keep selection on tail node after connection</property> + <property name="active">True</property> + <property name="draw_indicator">True</property> + <property name="group">chain_but</property> + </object> + <packing> + <property name="expand">True</property> + <property name="fill">True</property> + <property name="position">1</property> + </packing> + </child> + </object> + </child> + </object> + <packing> + <property name="expand">False</property> + </packing> + </child> </object> <packing> <property name="expand">True</property> |