199 lines
5.5 KiB
C++
199 lines
5.5 KiB
C++
/* This file is part of FlowCanvas.
|
|
* Copyright (C) 2007-2009 David Robillard <http://drobilla.net>
|
|
*
|
|
* 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 <algorithm>
|
|
#include <list>
|
|
#include <map>
|
|
#include <string>
|
|
|
|
#include <boost/enable_shared_from_this.hpp>
|
|
#include <boost/shared_ptr.hpp>
|
|
|
|
#include <libgnomecanvasmm.h>
|
|
|
|
#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<Item>
|
|
{
|
|
public:
|
|
Item(boost::shared_ptr<Canvas> 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> 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<Item> partner) { _partner = partner; }
|
|
boost::weak_ptr<Item> partner() { return _partner; }
|
|
|
|
sigc::signal<void> signal_pointer_entered;
|
|
sigc::signal<void> signal_pointer_exited;
|
|
sigc::signal<void> signal_selected;
|
|
sigc::signal<void> signal_unselected;
|
|
|
|
sigc::signal<void, GdkEventButton*> signal_clicked;
|
|
sigc::signal<void, GdkEventButton*> signal_double_clicked;
|
|
|
|
sigc::signal<void, double, double> signal_dragged;
|
|
sigc::signal<void, double, double> 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> _canvas;
|
|
|
|
boost::weak_ptr<Item> _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<boost::shared_ptr<Item> > 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
|
|
|