ladish/gui/flowcanvas/Item.hpp

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