/* This file is part of FlowCanvas. * Copyright (C) 2007-2009 David Robillard * * FlowCanvas 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 2 of the License, or (at your option) any later * version. * * FlowCanvas 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 details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ #ifndef FLOWCANVAS_ITEM_HPP #define FLOWCANVAS_ITEM_HPP #include #include #include #include #include #include #include #include "Port.hpp" namespace FlowCanvas { class Canvas; /** An item on a Canvas. * * \ingroup FlowCanvas */ class Item : public Gnome::Canvas::Group , public boost::enable_shared_from_this { public: Item(boost::shared_ptr canvas, const std::string& name, double x, double y, uint32_t color); virtual ~Item() {} bool selected() const { return _selected; } virtual void set_selected(bool s); virtual void set_minimum_width(double w) { _minimum_width = w; } virtual void select_tick() = 0; virtual void move(double dx, double dy) = 0; virtual void zoom(double z) {} boost::weak_ptr canvas() const { return _canvas; } bool popup_menu(guint button, guint32 activate_time) { if ( ! _menu) create_menu(); if (_menu) { _menu->popup(button, activate_time); return true; } else { return false; } } virtual void create_menu() {} Gtk::Menu* menu() const { return _menu; } void set_menu(Gtk::Menu* m) { delete _menu; _menu = m; } double width() const { return _width; } double height() const { return _height; } virtual void resize() = 0; virtual void load_location() {} virtual void store_location() {} bool is_within(const Gnome::Canvas::Rect& rect) const; inline bool point_is_within(double x, double y) const; const std::string& name() const { return _name; } virtual void set_name(const std::string& n) { _name = n; } uint32_t base_color() const { return _color; } virtual void set_border_color(uint32_t c) { _border_color = c; } virtual void set_base_color(uint32_t c) { _color = c; } virtual void set_default_base_color() = 0; /** Set the partner of this node. * Partner nodes are nodes that should be visually aligned to correspond to * each other, even if they are not necessarily connected (e.g. for separate * modules representing the inputs and outputs of a single interface). * The partner is invisibly connected as if it had an input that is connected * to this item, e.g. foo.set_partner(bar) will arrange like: * [foo] [bar] with a left-to-right flow direction. */ void set_partner(boost::shared_ptr partner) { _partner = partner; } boost::weak_ptr partner() { return _partner; } sigc::signal signal_pointer_entered; sigc::signal signal_pointer_exited; sigc::signal signal_selected; sigc::signal signal_unselected; sigc::signal signal_clicked; sigc::signal signal_double_clicked; sigc::signal signal_dragged; sigc::signal signal_dropped; protected: virtual void on_drag(double dx, double dy); virtual void on_drop(); virtual void on_click(GdkEventButton* ev); virtual void on_double_click(GdkEventButton* ev); virtual void set_height(double h) = 0; virtual void set_width(double w) = 0; bool on_event(GdkEvent* event); const boost::weak_ptr _canvas; boost::weak_ptr _partner; Gtk::Menu* _menu; std::string _name; double _minimum_width; double _width; double _height; uint32_t _border_color; uint32_t _color; bool _selected :1; }; typedef std::list > ItemList; /** Returns whether or not the point @a x, @a y (world units) is within the item. */ inline bool Item::point_is_within(double x, double y) const { return (x > property_x() && x < property_x() + _width && y > property_y() && y < property_y() + _height); } inline bool Item::is_within(const Gnome::Canvas::Rect& rect) const { const double x1 = rect.property_x1(); const double y1 = rect.property_y1(); const double x2 = rect.property_x2(); const double y2 = rect.property_y2(); if (x1 < x2 && y1 < y2) { return (property_x() > x1 && property_y() > y1 && property_x() + width() < x2 && property_y() + height() < y2); } else if (x2 < x1 && y2 < y1) { return (property_x() > x2 && property_y() > y2 && property_x() + width() < x1 && property_y() + height() < y1); } else if (x1 < x2 && y2 < y1) { return (property_x() > x1 && property_y() > y2 && property_x() + width() < x2 && property_y() + height() < y1); } else if (x2 < x1 && y1 < y2) { return (property_x() > x2 && property_y() > y1 && property_x() + width() < x1 && property_y() + height() < y2); } else { return false; } } } // namespace FlowCanvas #endif // FLOWCANVAS_ITEM_HPP