#include "activearea.h"
ActiveArea::ActiveArea() {
add_events( Gdk::BUTTON_PRESS_MASK
| Gdk::BUTTON_RELEASE_MASK
| Gdk::POINTER_MOTION_MASK );
}
bool ActiveArea::is_point_added(const ActivePoint::Handle &point) const {
for(PointList::const_iterator i = points.begin(); i != points.end(); ++i)
if (*i == point) return true;
return false;
}
void ActiveArea::add_point(const ActivePoint::Handle &point) {
if (point && !is_point_added(point)) {
points.push_back(point);
queue_draw();
}
}
void ActiveArea::remove_point(const ActivePoint::Handle &point) {
ActivePoint::Handle p = point;
for(PointList::iterator i = points.begin(); i != points.end();)
if (*i == p) { i = points.erase(i); queue_draw(); } else ++i;
if (drag_point == p)
hover_point.reset();
if (hover_point == p)
{ hover_point->active = false; hover_point.reset(); }
}
void ActiveArea::bring_to_front(const ActivePoint::Handle &point) {
ActivePoint::Handle p = point;
for(PointList::iterator i = points.begin(); i != points.end(); ++i)
if (*i == p)
{ i = points.erase(i); points.push_back(p); break; }
}
ActivePoint::Handle ActiveArea::get_point_at(const Vector &position) const {
for(PointList::const_reverse_iterator ri = points.rbegin(); ri != points.rend(); ++ri)
if ((*ri)->enabled && (*ri)->visible && (*ri)->is_inside(position))
return *ri;
return nohandle;
}
bool ActiveArea::on_button_press_event(GdkEventButton* event) {
if (event->button == 1) {
Vector position(event->x, event->y);
ActivePoint::Handle old_point = drag_point;
drag_point = get_point_at(position);
if (drag_point) {
if (hover_point) hover_point->active = false;
hover_point = drag_point;
hover_point->active = true;
bring_to_front(drag_point);
drag_offset = drag_point->position - position;
}
if (old_point != drag_point) queue_draw();
return true;
}
return false;
}
bool ActiveArea::on_button_release_event(GdkEventButton* event) {
if (event->button == 1) {
if (drag_point) {
drag_point.reset();
if (hover_point) hover_point->active = false;
hover_point = get_point_at(Vector(event->x, event->y));
if (hover_point) hover_point->active = true;
queue_draw();
}
return true;
}
return false;
}
bool ActiveArea::on_motion_notify_event(GdkEventMotion* event) {
Vector position(event->x, event->y);
if (drag_point) {
Vector oldposition = drag_point->position;
Vector newposition = position + drag_offset;
if (newposition != oldposition) {
drag_point->position = newposition;
on_point_move(drag_point, oldposition, newposition);
queue_draw();
}
} else {
ActivePoint::Handle old_point = hover_point;
if (hover_point) hover_point->active = false;
hover_point = get_point_at(position);
if (hover_point) hover_point->active = true;
if (old_point != hover_point) queue_draw();
}
return true;
}
bool ActiveArea::on_draw(const Cairo::RefPtr<Cairo::Context> &context) {
on_draw(Context(context));
return true;
}
void ActiveArea::on_draw(const Context &context) {
// fill background
context->save();
context->rectangle(0, 0, get_width(), get_height());
context->set_source_rgba(1, 1, 1, 1);
context->fill();
context->restore();
on_draw_content(context);
// draw points
for(PointList::const_iterator i = points.begin(); i != points.end(); ++i)
context.point(**i);
}
void ActiveArea::on_point_move(const ActivePoint::Handle &/*point*/, const Vector &/*oldposition*/, const Vector &/*newposition*/)
{ }
void ActiveArea::on_draw_content(const Context &/*context*/)
{ }