Blame c++/perspective/src/view.cpp

fdabb2
#include "view.h"
fdabb2
fdabb2
#include <gtkmm container.h=""></gtkmm>
fdabb2
fdabb2
fdabb2
void
fdabb2
View::Point::draw(
fdabb2
	const Cairo::RefPtr<cairo::context>& context,</cairo::context>
fdabb2
	View &view )
fdabb2
{
538bb7
	const Real ps = view.get_pixel_size();
fdabb2
	context->save();
538bb7
	context->arc(position.x, position.y, radius*ps, 0.0, 2.0*M_PI);
fdabb2
	context->set_source_rgba(color.r, color.g, color.b, color.a);
fdabb2
	context->fill_preserve();
fdabb2
	context->set_source_rgba(0.0, 0.0, 0.0, color.a);
538bb7
	context->set_line_width(selected ? 2.0*ps : ps);
fdabb2
	context->stroke();
fdabb2
	context->restore();
fdabb2
}
fdabb2
fdabb2
fdabb2
View::View():
fdabb2
	dragging()
fdabb2
{
fdabb2
	set_events(
fdabb2
		Gdk::POINTER_MOTION_MASK
fdabb2
	  | Gdk::BUTTON_PRESS_MASK
fdabb2
	  | Gdk::BUTTON_RELEASE_MASK );
0662a2
0662a2
	signal_draw_view.connect(sigc::mem_fun(*this, &View::on_draw_view));
0662a2
	signal_point_motion.connect(sigc::mem_fun(*this, &View::on_point_motion));
0662a2
	signal_point_changed.connect(sigc::mem_fun(*this, &View::on_point_changed));
0662a2
	signal_transform_changed.connect(sigc::mem_fun(*this, &View::on_transform_changed));
fdabb2
}
fdabb2
fdabb2
View::~View() { }
fdabb2
538bb7
Real
4dc49c
View::get_pixel_size() const
538bb7
	{ return 1.0/sqrt(fabs(transform.m00 * transform.m11)); }
538bb7
4dc49c
Pair2
4dc49c
View::get_bounds() const {
4dc49c
	Matrix m = transform_from_pixels();
4dc49c
	return Pair2(
4dc49c
		(m*Vector4(0          , 0           , 0, 1)).vec2(),
4dc49c
		(m*Vector4(get_width(), get_height(), 0, 1)).vec2() );
4dc49c
}
4dc49c
0662a2
Matrix
0662a2
View::transform_to_pixels() const {
0662a2
	Matrix matrix = transform;
0662a2
	matrix.row_w().vec2() += Vector2(get_width(), get_height())*0.5;
0662a2
	return matrix;
a1942e
}
a1942e
0662a2
Matrix
0662a2
View::transform_from_pixels() const
0662a2
	{ return transform_to_pixels().inverted(); }
0662a2
fdabb2
bool
fdabb2
View::on_draw(const Cairo::RefPtr<cairo::context>& context) {</cairo::context>
fdabb2
	context->save();
fdabb2
fdabb2
	const Real border_size = 1.0;
fdabb2
	const Real border_margin = 2.0;
fdabb2
	
fdabb2
	context->save();
fdabb2
	context->rectangle(0, 0, get_width(), get_height());
fdabb2
	context->set_source_rgba(0, 0, 0, 1);	
fdabb2
	context->fill();
fdabb2
	context->rectangle(
fdabb2
		border_margin, border_margin,
fdabb2
		get_width() - 2*border_margin,
fdabb2
		get_height() - 2*border_margin );
fdabb2
	context->set_line_width(border_size);
fdabb2
	context->set_source_rgba(1, 1, 0, 1);
fdabb2
	context->stroke();
fdabb2
	context->restore();
fdabb2
0662a2
	context->transform( transform_to_pixels().to_cairo() );
538bb7
	signal_draw_view(context);
538bb7
	for(PointList::const_iterator i = points.begin(); i != points.end(); ++i)
fdabb2
		(*i)->draw(context, *this);
fdabb2
	context->restore();
fdabb2
	return true;
fdabb2
}
fdabb2
fdabb2
bool
fdabb2
View::on_motion_notify_event(GdkEventMotion *event) {
a1942e
	Vector2 prev_mouse_position = mouse_position;
0662a2
	mouse_position = Vector2(event->x, event->y);
0662a2
0662a2
	Matrix to_pixels = transform_to_pixels();
0662a2
	Matrix from_pixels = transform_from_pixels();
0662a2
	
fdabb2
	if (dragging) {
fdabb2
		if (selected_point) {
0662a2
			selected_point->position = (from_pixels*Vector4(mouse_position + selected_point_offset, 0, 1)).vec2();
538bb7
			point_motion(selected_point);
fdabb2
			queue_draw();
fdabb2
		}
a1942e
		return true;
a1942e
	}
a1942e
a1942e
	PointPtr point;
a1942e
	for(PointList::iterator i = points.begin(); i != points.end(); ++i) {
a1942e
		(*i)->selected = false;
0662a2
		Vector2 point_position = (to_pixels*Vector4((*i)->position, 0, 1)).vec2();
a1942e
		Vector2 offset = point_position - mouse_position;
a1942e
		if (offset.square() <= (*i)->radius * (*i)->radius) {
a1942e
			point = *i;
a1942e
			selected_point_offset = offset;
fdabb2
		}
fdabb2
	}
a1942e
	if (point)
a1942e
		point->selected = true;
a1942e
	if (selected_point != point) {
a1942e
		selected_point = point;
a1942e
		queue_draw();
a1942e
	}
a1942e
a1942e
	if (event->state & Gdk::BUTTON2_MASK) {
a1942e
		// translate
a1942e
		transform.row_w() += Vector4(mouse_position - prev_mouse_position);
a1942e
		queue_draw();
a1942e
	}
0662a2
a1942e
	if (event->state & Gdk::BUTTON3_MASK) {
a1942e
		// zoom
a1942e
		Real scale = pow(2.0, (prev_mouse_position.y - mouse_position.y)/50.0); // zoom x2 by motion to 50 pixels
a1942e
		Vector2 center = Vector2(transform.inverted() * Vector4(0, 0, 0, 1));
a1942e
		transform.scale(scale, scale);
a1942e
		transform.row_w() = Vector4(0, 0, 0, 1);
a1942e
		transform.row_w() = transform * Vector4(-center, 0, 1);
a1942e
		queue_draw();
a1942e
	}
a1942e
	
fdabb2
	return true;
fdabb2
}
fdabb2
fdabb2
bool
fdabb2
View::on_button_press_event(GdkEventButton *event) {
fdabb2
	if (event->button == 1)
fdabb2
		dragging = true;
fdabb2
	return true;
fdabb2
}
fdabb2
fdabb2
bool
fdabb2
View::on_button_release_event(GdkEventButton *event) {
fdabb2
	if (event->button == 1) {
fdabb2
		dragging = false;
538bb7
		if (selected_point)
538bb7
			point_changed(selected_point);
fdabb2
	}
a1942e
	if (event->button == 2 || event->button == 3)
a1942e
		signal_transform_changed();
fdabb2
	return true;
fdabb2
}
0662a2
0662a2
0662a2
void
0662a2
View::on_draw_view(const Cairo::RefPtr<cairo::context>&)</cairo::context>
0662a2
	{ }
0662a2
0662a2
void
0662a2
View::on_point_motion(const PointPtr&)
0662a2
	{ }
0662a2
0662a2
void
0662a2
View::on_point_changed(const PointPtr&)
0662a2
	{ }
0662a2
0662a2
void
0662a2
View::on_transform_changed()
0662a2
	{ }