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