/* 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/SharedPtr.hpp" #include "raul/TimeStamp.hpp" #include "machina/Engine.hpp" #include "machina/Controller.hpp" #include "client/ClientObject.hpp" #include "client/ClientModel.hpp" #include "EdgeView.hpp" #include "MachinaCanvas.hpp" #include "MachinaGUI.hpp" #include "NodeView.hpp" using namespace Raul; using namespace Ganv; using namespace Machina; 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(WeakPtr item, GdkEventButton* event) { SharedPtr node = PtrCast(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 SharedPtr 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(SharedPtr 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) { SharedPtr 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), WeakPtr(view))); object->set_view(view); } else if (type.get() == uris.machina_Edge) { SharedPtr tail = _app->client_model()->find( object->get(uris.machina_tail_id).get_int32()); SharedPtr head = _app->client_model()->find( object->get(uris.machina_head_id).get_int32()); if (!tail || !head) { std::cerr << "Invalid arc" << std::endl; return; } SharedPtr tail_view = PtrCast(tail->view()); SharedPtr head_view = PtrCast(head->view()); SharedPtr view( new EdgeView(*this, tail_view, head_view, object)); object->set_view(view); } else { std::cerr << "Unknown object type" << std::endl; } } void MachinaCanvas::on_erase_object(SharedPtr 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(SharedPtr()); } 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(boost::shared_ptr src, boost::shared_ptr head) { _app->controller()->connect(src->node()->id(), head->node()->id()); } void MachinaCanvas::action_disconnect(boost::shared_ptr src, boost::shared_ptr head) { _app->controller()->disconnect(src->node()->id(), head->node()->id()); }