/* This file is part of Machina. * Copyright 2007-2011 David Robillard * * Machina is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Machina is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Machina. If not, see . */ #include #include "raul/TimeStamp.hpp" #include "client/ClientModel.hpp" #include "client/ClientObject.hpp" #include "machina/Controller.hpp" #include "machina/Engine.hpp" #include "machina/types.hpp" #include "EdgeView.hpp" #include "MachinaCanvas.hpp" #include "MachinaGUI.hpp" #include "NodeView.hpp" using namespace Raul; using namespace Ganv; namespace machina { namespace gui { MachinaCanvas::MachinaCanvas(MachinaGUI* app, int width, int height) : Canvas(width, height) , _app(app) { widget().grab_focus(); signal_event.connect( sigc::mem_fun(this, &MachinaCanvas::on_event)); } bool MachinaCanvas::node_clicked(WPtr item, GdkEventButton* event) { SPtr node = dynamic_ptr_cast(item.lock()); if (!node) { return false; } if (event->state & GDK_CONTROL_MASK) { return false; } 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 SPtr last = _last_clicked.lock(); if (last) { if (node != last) { if (get_edge(last.get(), node.get())) { action_disconnect(last, node); } else { action_connect(last, node); } } last->set_default_colors(); _last_clicked.reset(); } else { _last_clicked = node; } return true; } return false; } bool MachinaCanvas::on_event(GdkEvent* event) { if (( event->type == GDK_BUTTON_RELEASE) && ( event->button.button == 3) && !(event->button.state & (GDK_CONTROL_MASK))) { action_create_node(event->button.x, event->button.y); return true; } return false; } void MachinaCanvas::on_new_object(SPtr object) { const machina::URIs& uris = URIs::instance(); const Raul::Atom& type = object->get(uris.rdf_type); if (!type.is_valid()) { return; } if (type.get() == uris.machina_Node) { SPtr view( new NodeView(_app->window(), *this, object, object->get(uris.machina_canvas_x).get_float(), object->get(uris.machina_canvas_y).get_float())); //if ( ! node->enter_action() && ! node->exit_action() ) // view->set_base_color(0x101010FF); view->signal_clicked().connect( sigc::bind<0>(sigc::mem_fun(this, &MachinaCanvas::node_clicked), WPtr(view))); object->set_view(view); } else if (type.get() == uris.machina_Edge) { SPtr tail = _app->client_model()->find( object->get(uris.machina_tail_id).get_int32()); SPtr head = _app->client_model()->find( object->get(uris.machina_head_id).get_int32()); if (!tail || !head) { std::cerr << "Invalid arc" << std::endl; return; } SPtr tail_view = dynamic_ptr_cast(tail->view()); SPtr head_view = dynamic_ptr_cast(head->view()); SPtr view(new EdgeView(*this, tail_view, head_view, object)); object->set_view(view); } else { std::cerr << "Unknown object type " << type.get() << std::endl; } } void MachinaCanvas::on_erase_object(SPtr object) { const Raul::Atom& type = object->get(URIs::instance().rdf_type); if (type.get() == URIs::instance().machina_Node) { // Destruction of the view will remove from the canvas } else if (type.get() == URIs::instance().machina_Edge) { object->set_view(SPtr()); } else { std::cerr << "Unknown object type" << std::endl; } } void MachinaCanvas::action_create_node(double x, double y) { machina::client::ClientObject obj(0); obj.set(URIs::instance().rdf_type, _app->forge().make_urid(URIs::instance().machina_Node)); obj.set(URIs::instance().machina_canvas_x, _app->forge().make((float)x)); obj.set(URIs::instance().machina_canvas_y, _app->forge().make((float)y)); obj.set(URIs::instance().machina_duration, _app->forge().make(1.0f)); _app->controller()->create(obj); } void MachinaCanvas::action_connect(SPtr src, SPtr head) { _app->controller()->connect(src->node()->id(), head->node()->id()); } void MachinaCanvas::action_disconnect(SPtr src, SPtr head) { _app->controller()->disconnect(src->node()->id(), head->node()->id()); } } // namespace machina } // namespace gui