Blob Blame Raw


#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);
			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*/)
	{ }

void ActiveArea::on_draw_content(const Context &/*context*/)
	{ }