klayout/src/laybasic/layZoomBox.cc

279 lines
6.2 KiB
C++
Raw Normal View History

/*
KLayout Layout Viewer
2017-02-12 15:28:14 +01:00
Copyright (C) 2006-2017 Matthias Koefferlein
This program 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.
This program 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 more 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
*/
#include "layZoomBox.h"
#include "layRubberBox.h"
#include "layLayoutView.h"
namespace lay
{
// -------------------------------------------------------------
// ZoomService implementation
ZoomService::ZoomService (lay::LayoutView *view)
: lay::ViewService (view->view_object_widget ()),
mp_view (view),
mp_box (0),
m_color (0)
{ }
ZoomService::~ZoomService ()
{
drag_cancel ();
}
void
ZoomService::drag_cancel ()
{
if (mp_box) {
delete mp_box;
mp_box = 0;
}
widget ()->ungrab_mouse (this);
}
void
ZoomService::set_colors (QColor /*background*/, QColor color)
{
m_color = color.rgb ();
if (mp_box) {
mp_box->set_color (m_color);
}
}
bool
ZoomService::mouse_move_event (const db::DPoint &p, unsigned int /*buttons*/, bool prio)
{
if (prio) {
if (mp_box) {
m_p2 = p;
mp_box->set_points (m_p1, m_p2);
} else if (mp_view) {
m_vp.move (m_p1 - p);
mp_view->zoom_box (m_vp);
}
mp_view->message ("w: " + tl::micron_to_string (fabs (m_p2.x () - m_p1.x ())) + " h: " + tl::micron_to_string (fabs (m_p2.y () - m_p1.y ())));
return true;
} else {
return false;
}
}
bool
ZoomService::mouse_press_event (const db::DPoint &p, unsigned int buttons, bool prio)
{
if (! prio && (buttons & lay::RightButton) != 0) {
mp_view->stop_redraw (); // TODO: how to restart if zoom is aborted?
if ((buttons & lay::ShiftButton) != 0) {
begin_pan (p);
} else {
begin (p);
}
return true;
} else if (! prio && (buttons & lay::MidButton) != 0) {
mp_view->stop_redraw (); // TODO: how to restart if zoom is aborted?
begin_pan (p);
return true;
}
return false;
}
bool
ZoomService::mouse_click_event (const db::DPoint &p, unsigned int buttons, bool prio)
{
if (! prio && (buttons & lay::RightButton) != 0) {
db::DBox vp = widget ()->mouse_event_viewport ();
if (mp_view && vp.contains (p)) {
db::DVector d = (vp.p2 () - vp.p1 ()) * 0.5;
mp_view->zoom_box (db::DBox (p - d, p + d));
}
}
return false;
}
bool
ZoomService::mouse_release_event (const db::DPoint & /*p*/, unsigned int /*buttons*/, bool prio)
{
if (prio) {
widget ()->ungrab_mouse (this);
if (mp_box) {
delete mp_box;
mp_box = 0;
db::DBox vp = widget ()->mouse_event_viewport ();
db::DVector d = (vp.p2 () - vp.p1 ()) * 0.5;
if (mp_view) {
// we need to use the original screen coordinate to find the move direction
db::DPoint p1s = widget ()->mouse_event_trans ().trans (m_p1);
db::DPoint p2s = widget ()->mouse_event_trans ().trans (m_p2);
if (p2s.x () > p1s.x () && p1s.y () < p2s.y ()) {
// upward right: zoom fit
mp_view->zoom_fit ();
} else {
double fx = fabs (m_p2.x () - m_p1.x ()) / vp.width ();
double fy = fabs (m_p2.y () - m_p1.y ()) / vp.height ();
double f = std::max (0.001, std::max (fx, fy));
if (p1s.x () > p2s.x () || p1s.y () < p2s.y ()) {
// zoom out
f = 1.0 / f;
}
db::DPoint c = m_p1 + (m_p2 - m_p1) * 0.5;
db::DBox b (c - d * f, c + d * f);
mp_view->zoom_box (b);
}
}
}
}
return false;
}
bool
ZoomService::wheel_event (int delta, bool /*horizontal*/, const db::DPoint &p, unsigned int buttons, bool prio)
{
// Only act without the mouse being grabbed.
if (! prio) {
db::DBox vp = widget ()->mouse_event_viewport ();
if (mp_view && vp.contains (p) && vp.width () > 0 && vp.height () > 0) {
enum { horizontal, vertical, zoom } direction = zoom;
if (mp_view->mouse_wheel_mode () == 0) {
if ((buttons & lay::ShiftButton) != 0) {
direction = vertical;
} else if ((buttons & lay::ControlButton) != 0) {
direction = horizontal;
} else {
direction = zoom;
}
} else {
if ((buttons & lay::ShiftButton) != 0) {
direction = horizontal;
} else if ((buttons & lay::ControlButton) != 0) {
direction = zoom;
} else {
direction = vertical;
}
}
if (direction == vertical) {
if (delta > 0) {
mp_view->pan_up ();
} else {
mp_view->pan_down ();
}
} else if (direction == horizontal) {
if (delta > 0) {
mp_view->pan_left ();
} else {
mp_view->pan_right ();
}
} else {
double zoom_step = 0.25; // TODO: make variable?
double f;
if (delta > 0) {
f = 1.0 / (1.0 + zoom_step * (delta / 120.0));
} else {
f = 1.0 + zoom_step * (-delta / 120.0);
}
mp_view->zoom_box (db::DBox (p.x () - (p.x () - vp.left ()) * f,
p.y () - (p.y () - vp.bottom ()) * f,
p.x () - (p.x () - vp.right ()) * f,
p.y () - (p.y () - vp.top ()) * f));
}
}
}
return false;
}
void
ZoomService::begin_pan (const db::DPoint &pos)
{
if (mp_box) {
delete mp_box;
}
mp_box = 0;
m_p1 = pos;
m_vp = widget ()->mouse_event_viewport ();
widget ()->grab_mouse (this, true);
}
void
ZoomService::begin (const db::DPoint &pos)
{
if (mp_box) {
delete mp_box;
}
m_p1 = pos;
m_p2 = pos;
mp_box = new lay::RubberBox (widget (), m_color, pos, pos);
widget ()->grab_mouse (this, true);
}
}