mirror of https://github.com/KLayout/klayout.git
800 lines
22 KiB
C++
800 lines
22 KiB
C++
|
|
/*
|
|
|
|
KLayout Layout Viewer
|
|
Copyright (C) 2006-2022 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 "layNavigator.h"
|
|
#include "layMainWindow.h"
|
|
#include "layConfig.h"
|
|
#include "layMarker.h"
|
|
#include "layAbstractMenu.h"
|
|
#include "layRubberBox.h"
|
|
#include "imgService.h"
|
|
|
|
#include <QVBoxLayout>
|
|
#include <QFrame>
|
|
#include <QLabel>
|
|
|
|
namespace lay
|
|
{
|
|
|
|
// ---------------------------------------------------------------------------------------------
|
|
// Navigator service definition and implementation
|
|
|
|
class NavigatorService
|
|
: public ViewService,
|
|
public tl::Object
|
|
{
|
|
public:
|
|
enum drag_mode_type {
|
|
DM_none, DM_move,
|
|
DM_l, DM_r, DM_t, DM_b
|
|
};
|
|
|
|
NavigatorService (LayoutView *view)
|
|
: ViewService (view->view_object_widget ()),
|
|
mp_view (view), mp_source_view (0),
|
|
mp_viewport_marker (0),
|
|
m_drag_mode (DM_none),
|
|
m_dragging (false),
|
|
mp_box (0),
|
|
m_color (0)
|
|
{
|
|
// .. nothing yet ..
|
|
}
|
|
|
|
~NavigatorService ()
|
|
{
|
|
if (mp_viewport_marker) {
|
|
delete mp_viewport_marker;
|
|
mp_viewport_marker = 0;
|
|
}
|
|
drag_cancel ();
|
|
}
|
|
|
|
void background_color_changed ()
|
|
{
|
|
lay::Color c = mp_view->background_color ();
|
|
|
|
// replace by "real" background color if required
|
|
if (! c.is_valid ()) {
|
|
c = lay::Color (mp_view->palette ().color (QPalette::Normal, QPalette::Base).rgb ());
|
|
}
|
|
|
|
lay::Color contrast;
|
|
if (c.green () > 128) {
|
|
contrast = lay::Color (0, 0, 0);
|
|
} else {
|
|
contrast = lay::Color (255, 255, 255);
|
|
}
|
|
|
|
set_colors (c, contrast);
|
|
}
|
|
|
|
bool mouse_release_event (const db::DPoint & /*p*/, unsigned int /*buttons*/, bool /*prio*/)
|
|
{
|
|
if (mp_box) {
|
|
|
|
// finish zoom box selection
|
|
delete mp_box;
|
|
mp_box = 0;
|
|
|
|
widget ()->ungrab_mouse (this);
|
|
|
|
if (mp_source_view) {
|
|
mp_source_view->zoom_box (db::DBox (m_p1, m_p2));
|
|
}
|
|
|
|
return true;
|
|
|
|
} else if (m_dragging) {
|
|
|
|
m_dragging = false;
|
|
widget ()->ungrab_mouse (this);
|
|
return true;
|
|
|
|
} else {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
bool 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_source_view && vp.contains (p)) {
|
|
db::DVector d = (vp.p2 () - vp.p1 ()) * 0.5;
|
|
mp_source_view->zoom_box (db::DBox (p - d, p + d));
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool mouse_press_event (const db::DPoint &p, unsigned int buttons, bool prio)
|
|
{
|
|
if (! prio && (buttons & lay::RightButton) != 0) {
|
|
|
|
mp_source_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_source_view->stop_redraw (); // TODO: how to restart if zoom is aborted?
|
|
begin_pan (p);
|
|
return true;
|
|
|
|
} else if (prio && (buttons & lay::LeftButton) != 0 && m_drag_mode != DM_none && mp_source_view) {
|
|
|
|
m_dragging = true;
|
|
m_p0 = p;
|
|
m_b0 = m_box;
|
|
widget ()->grab_mouse (this, true);
|
|
return true;
|
|
|
|
} else {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
// Taken from ZoomBox service
|
|
bool wheel_event (int delta, bool /*horizontal*/, const db::DPoint &p, unsigned int buttons, bool prio)
|
|
{
|
|
// Only act without the mouse being grabbed.
|
|
if (! prio) {
|
|
|
|
if (mp_source_view) {
|
|
|
|
enum { horizontal, vertical, zoom } direction = zoom;
|
|
if (mp_source_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_source_view->pan_up ();
|
|
} else {
|
|
mp_source_view->pan_down ();
|
|
}
|
|
|
|
} else if (direction == horizontal) {
|
|
|
|
if (delta > 0) {
|
|
mp_source_view->pan_left ();
|
|
} else {
|
|
mp_source_view->pan_right ();
|
|
}
|
|
|
|
} else if (m_drag_mode == DM_move) {
|
|
|
|
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_source_view->zoom_box (db::DBox (p.x () - (p.x () - m_box.left ()) * f,
|
|
p.y () - (p.y () - m_box.bottom ()) * f,
|
|
p.x () - (p.x () - m_box.right ()) * f,
|
|
p.y () - (p.y () - m_box.top ()) * f));
|
|
|
|
update_marker ();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
bool mouse_move_event (const db::DPoint &p, unsigned int /*buttons*/, bool prio)
|
|
{
|
|
bool ret_value = false;
|
|
|
|
if (mp_box) {
|
|
|
|
// drag zoom box
|
|
if (prio) {
|
|
|
|
m_p2 = p;
|
|
mp_box->set_points (m_p1, m_p2);
|
|
|
|
mp_source_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;
|
|
}
|
|
|
|
} else if (! m_dragging) {
|
|
|
|
m_drag_mode = DM_none;
|
|
|
|
if (! m_box.empty ()) {
|
|
|
|
double mw = 5.0/*pixel*/ / mp_view->viewport ().trans ().ctrans (1.0/*micron*/);
|
|
db::DVector d = db::DVector (std::max (mw, m_box.width () * 0.5 - mw), std::max (mw, m_box.height () * 0.5 - mw));
|
|
db::DBox move_box = db::DBox (m_box.center () - d, m_box.center () + d);
|
|
db::DBox l_box = db::DBox (m_box.left () - mw, m_box.bottom () , m_box.left () + mw, m_box.top () );
|
|
db::DBox r_box = db::DBox (m_box.right () - mw, m_box.bottom () , m_box.right () + mw, m_box.top () );
|
|
db::DBox t_box = db::DBox (m_box.left () , m_box.top () - mw, m_box.right () , m_box.top () + mw);
|
|
db::DBox b_box = db::DBox (m_box.left () , m_box.bottom () - mw, m_box.right () , m_box.bottom () + mw);
|
|
|
|
if (move_box.contains (p)) {
|
|
m_drag_mode = DM_move;
|
|
} else if (l_box.contains (p)) {
|
|
m_drag_mode = DM_l;
|
|
} else if (r_box.contains (p)) {
|
|
m_drag_mode = DM_r;
|
|
} else if (t_box.contains (p)) {
|
|
m_drag_mode = DM_t;
|
|
} else if (b_box.contains (p)) {
|
|
m_drag_mode = DM_b;
|
|
}
|
|
|
|
}
|
|
|
|
} else if (prio) {
|
|
|
|
db::DBox new_box;
|
|
db::DVector dp = p - m_p0;
|
|
|
|
if (m_drag_mode == DM_move) {
|
|
new_box = m_b0.moved (dp);
|
|
} else if (m_drag_mode == DM_l) {
|
|
double new_h = m_b0.height () / m_b0.width () * (m_b0.width () - dp.x ());
|
|
double dy = (new_h - m_b0.height ()) * 0.5;
|
|
new_box = db::DBox (m_b0.left () + dp.x (), m_b0.bottom () - dy, m_b0.right (), m_b0.top () + dy);
|
|
} else if (m_drag_mode == DM_r) {
|
|
double new_h = m_b0.height () / m_b0.width () * (m_b0.width () + dp.x ());
|
|
double dy = (new_h - m_b0.height ()) * 0.5;
|
|
new_box = db::DBox (m_b0.left (), m_b0.bottom () - dy, m_b0.right () + dp.x (), m_b0.top () + dy);
|
|
} else if (m_drag_mode == DM_t) {
|
|
double new_w = m_b0.width () / m_b0.height () * (m_b0.height () + dp.y ());
|
|
double dx = (new_w - m_b0.width ()) * 0.5;
|
|
new_box = db::DBox (m_b0.left () - dx, m_b0.bottom (), m_b0.right () + dx, m_b0.top () + dp.y ());
|
|
} else if (m_drag_mode == DM_b) {
|
|
double new_w = m_b0.width () / m_b0.height () * (m_b0.height () - dp.y ());
|
|
double dx = (new_w - m_b0.width ()) * 0.5;
|
|
new_box = db::DBox (m_b0.left () - dx, m_b0.bottom () + dp.y (), m_b0.right () + dx, m_b0.top ());
|
|
}
|
|
|
|
if (! new_box.empty () && mp_source_view) {
|
|
mp_source_view->zoom_box (new_box);
|
|
}
|
|
|
|
update_marker ();
|
|
|
|
ret_value = true;
|
|
|
|
}
|
|
|
|
if (m_drag_mode == DM_move) {
|
|
set_cursor (Cursor::size_all);
|
|
} else if (m_drag_mode == DM_l) {
|
|
set_cursor (Cursor::size_hor);
|
|
} else if (m_drag_mode == DM_r) {
|
|
set_cursor (Cursor::size_hor);
|
|
} else if (m_drag_mode == DM_t) {
|
|
set_cursor (Cursor::size_ver);
|
|
} else if (m_drag_mode == DM_b) {
|
|
set_cursor (Cursor::size_ver);
|
|
}
|
|
|
|
return ret_value;
|
|
|
|
}
|
|
|
|
void update_marker ()
|
|
{
|
|
if (mp_viewport_marker) {
|
|
delete mp_viewport_marker;
|
|
mp_viewport_marker = 0;
|
|
m_box = db::DBox ();
|
|
}
|
|
|
|
if (mp_source_view) {
|
|
|
|
m_box = mp_source_view->viewport ().box ();
|
|
// correct the box by a few pixels so it is more precisely reflecting the actual dimensions
|
|
double d = 1.0 / mp_view->viewport ().trans ().ctrans (1.0);
|
|
m_box.set_right (m_box.right () - 2.0 * d);
|
|
m_box.set_bottom (m_box.bottom () + d);
|
|
|
|
mp_viewport_marker = new DMarker (mp_view);
|
|
mp_viewport_marker->set_halo (true);
|
|
mp_viewport_marker->set_color (m_color);
|
|
mp_viewport_marker->set_line_width (2);
|
|
mp_viewport_marker->set_vertex_size (2);
|
|
mp_viewport_marker->set_dither_pattern (1);
|
|
mp_viewport_marker->set_frame_pattern (0);
|
|
mp_viewport_marker->set (m_box);
|
|
|
|
}
|
|
}
|
|
|
|
void attach_view (LayoutView *source_view)
|
|
{
|
|
if (mp_source_view != source_view) {
|
|
|
|
tl::Object::detach_from_all_events ();
|
|
|
|
mp_source_view = source_view;
|
|
mp_source_view->viewport_changed_event.add (this, &NavigatorService::update_marker);
|
|
|
|
mp_view->background_color_changed_event.add (this, &NavigatorService::background_color_changed);
|
|
background_color_changed ();
|
|
|
|
update_marker ();
|
|
|
|
}
|
|
}
|
|
|
|
void drag_cancel ()
|
|
{
|
|
// cancel zoom box dragging
|
|
if (mp_box) {
|
|
delete mp_box;
|
|
mp_box = 0;
|
|
}
|
|
widget ()->ungrab_mouse (this);
|
|
}
|
|
|
|
void set_colors (lay::Color /*background*/, lay::Color color)
|
|
{
|
|
// set zoom box color
|
|
m_color = color.rgb ();
|
|
if (mp_box) {
|
|
mp_box->set_color (m_color);
|
|
}
|
|
if (mp_viewport_marker) {
|
|
mp_viewport_marker->set_color (m_color);
|
|
}
|
|
}
|
|
|
|
private:
|
|
LayoutView *mp_view;
|
|
LayoutView *mp_source_view;
|
|
DMarker *mp_viewport_marker;
|
|
db::DBox m_box;
|
|
db::DPoint m_p0;
|
|
db::DBox m_b0;
|
|
drag_mode_type m_drag_mode;
|
|
bool m_dragging;
|
|
db::DPoint m_p1, m_p2;
|
|
db::DBox m_vp;
|
|
lay::RubberBox *mp_box;
|
|
unsigned int m_color;
|
|
|
|
void 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 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);
|
|
}
|
|
};
|
|
|
|
// ---------------------------------------------------------------------------------------------
|
|
// Navigator implementation
|
|
|
|
const std::string freeze_action_path ("@@navigator_menu.navigator_main_menu.navigator_freeze");
|
|
|
|
Navigator::Navigator (MainWindow *main_window)
|
|
: QFrame (main_window),
|
|
m_show_all_hier_levels (false),
|
|
m_show_images (true),
|
|
m_update_layers_needed (true),
|
|
m_update_needed (true),
|
|
mp_main_window (main_window),
|
|
mp_source_view (0),
|
|
mp_service (0),
|
|
m_do_view_changed (this, &Navigator::attach_view),
|
|
m_do_layers_changed (this, &Navigator::update_layers),
|
|
m_do_content_changed (this, &Navigator::update),
|
|
m_do_update_menu_dm (this, &Navigator::do_update_menu)
|
|
{
|
|
setObjectName (QString::fromUtf8 ("navigator"));
|
|
|
|
mp_menu_bar = new QFrame (this);
|
|
mp_menu_bar->setFrameShape (QFrame::NoFrame);
|
|
mp_menu_bar->setSizePolicy (QSizePolicy::Expanding, QSizePolicy::Preferred);
|
|
|
|
mp_view = 0;
|
|
mp_service = 0;
|
|
|
|
mp_placeholder_label = new QLabel (this);
|
|
mp_placeholder_label->setSizePolicy (QSizePolicy::Expanding, QSizePolicy::Expanding);
|
|
mp_placeholder_label->setMinimumWidth (100);
|
|
mp_placeholder_label->setMinimumHeight (100);
|
|
mp_placeholder_label->show ();
|
|
|
|
QVBoxLayout *layout = new QVBoxLayout (this);
|
|
layout->addWidget (mp_menu_bar);
|
|
layout->addWidget (mp_placeholder_label);
|
|
layout->setStretchFactor (mp_placeholder_label, 1);
|
|
layout->setContentsMargins (0, 0, 0, 0);
|
|
layout->setSpacing (0);
|
|
setLayout (layout);
|
|
|
|
mp_main_window->current_view_changed_event.add (this, &Navigator::view_changed);
|
|
mp_main_window->view_closed_event.add (this, &Navigator::view_closed);
|
|
|
|
do_update_menu ();
|
|
connect (mp_main_window->menu (), SIGNAL (changed ()), this, SLOT (menu_changed ()));
|
|
}
|
|
|
|
Navigator::~Navigator ()
|
|
{
|
|
if (mp_service) {
|
|
delete mp_service;
|
|
mp_service = 0;
|
|
}
|
|
|
|
if (mp_view) {
|
|
delete mp_view;
|
|
mp_view = 0;
|
|
}
|
|
}
|
|
|
|
void
|
|
Navigator::menu_changed ()
|
|
{
|
|
// delay actual rebuilding of the menu to collect multiple change events.
|
|
m_do_update_menu_dm ();
|
|
}
|
|
|
|
void
|
|
Navigator::do_update_menu ()
|
|
{
|
|
mp_main_window->menu ()->build_detached ("navigator_menu", mp_menu_bar);
|
|
}
|
|
|
|
void
|
|
Navigator::show_images (bool f)
|
|
{
|
|
if (f != m_show_images) {
|
|
m_show_images = f;
|
|
if (isVisible ()) {
|
|
update ();
|
|
}
|
|
}
|
|
}
|
|
|
|
void
|
|
Navigator::all_hier_levels (bool f)
|
|
{
|
|
if (f != m_show_all_hier_levels) {
|
|
m_show_all_hier_levels = f;
|
|
if (isVisible ()) {
|
|
update ();
|
|
}
|
|
}
|
|
}
|
|
|
|
void
|
|
Navigator::freeze_clicked ()
|
|
{
|
|
Action *freeze_action = mp_main_window->menu ()->action (freeze_action_path);
|
|
|
|
m_frozen_list.erase (mp_source_view);
|
|
|
|
if (freeze_action->is_checked () && mp_source_view) {
|
|
NavigatorFrozenViewInfo &info = m_frozen_list.insert (std::make_pair (mp_source_view, NavigatorFrozenViewInfo ())).first->second;
|
|
info.layer_properties = mp_source_view->get_properties ();
|
|
info.hierarchy_levels = mp_source_view->get_hier_levels ();
|
|
} else {
|
|
update ();
|
|
}
|
|
}
|
|
|
|
void
|
|
Navigator::showEvent (QShowEvent *)
|
|
{
|
|
if (mp_main_window->current_view () != mp_source_view) {
|
|
attach_view ();
|
|
} else if (m_update_needed) {
|
|
update ();
|
|
} else if (m_update_layers_needed) {
|
|
update_layers ();
|
|
}
|
|
|
|
m_update_layers_needed = false;
|
|
m_update_needed = false;
|
|
}
|
|
|
|
void
|
|
Navigator::closeEvent (QCloseEvent *)
|
|
{
|
|
mp_main_window->dispatcher ()->config_set (cfg_show_navigator, "false");
|
|
mp_main_window->dispatcher ()->config_end ();
|
|
}
|
|
|
|
void
|
|
Navigator::view_changed ()
|
|
{
|
|
if (isVisible ()) {
|
|
m_do_view_changed ();
|
|
} else {
|
|
// force attach view, when the window is opened again
|
|
attach_view (0);
|
|
}
|
|
}
|
|
|
|
void
|
|
Navigator::layers_changed (int)
|
|
{
|
|
if (isVisible ()) {
|
|
m_do_layers_changed ();
|
|
} else {
|
|
m_update_layers_needed = true;
|
|
}
|
|
}
|
|
|
|
void
|
|
Navigator::content_changed ()
|
|
{
|
|
if (isVisible ()) {
|
|
m_do_content_changed ();
|
|
} else {
|
|
m_update_needed = true;
|
|
}
|
|
}
|
|
|
|
void
|
|
Navigator::attach_view ()
|
|
{
|
|
attach_view (mp_main_window->current_view ());
|
|
}
|
|
|
|
void
|
|
Navigator::view_closed (int index)
|
|
{
|
|
LayoutView *view = mp_main_window->view ((unsigned int) index);
|
|
|
|
if (view == mp_source_view) {
|
|
attach_view (0);
|
|
}
|
|
}
|
|
|
|
void
|
|
Navigator::resizeEvent (QResizeEvent *)
|
|
{
|
|
if (mp_view) {
|
|
mp_view->setGeometry (mp_placeholder_label->geometry ());
|
|
}
|
|
}
|
|
|
|
void
|
|
Navigator::attach_view (LayoutView *view)
|
|
{
|
|
if (view != mp_source_view) {
|
|
|
|
tl::Object::detach_from_all_events ();
|
|
|
|
mp_main_window->current_view_changed_event.add (this, &Navigator::view_changed);
|
|
mp_main_window->view_closed_event.add (this, &Navigator::view_closed);
|
|
|
|
mp_source_view = view;
|
|
|
|
delete mp_service;
|
|
mp_service = 0;
|
|
|
|
LayoutView *old_view = mp_view;
|
|
mp_view = 0;
|
|
|
|
if (mp_source_view) {
|
|
|
|
mp_view = new LayoutView (0, false, mp_source_view, this, "navigator", LayoutView::LV_Naked + LayoutView::LV_NoZoom + LayoutView::LV_NoServices + LayoutView::LV_NoGrid);
|
|
mp_view->setSizePolicy (QSizePolicy::Expanding, QSizePolicy::Expanding);
|
|
mp_view->setMinimumWidth (100);
|
|
mp_view->setMinimumHeight (100);
|
|
mp_view->setGeometry (mp_placeholder_label->geometry ());
|
|
mp_view->show ();
|
|
|
|
mp_service = new NavigatorService (mp_view);
|
|
mp_view->view_object_widget ()->activate (mp_service);
|
|
|
|
mp_source_view->cellviews_changed_event.add (this, &Navigator::content_changed);
|
|
mp_source_view->cellview_changed_event.add (this, &Navigator::content_changed_with_int);
|
|
mp_source_view->geom_changed_event.add (this, &Navigator::content_changed);
|
|
mp_source_view->layer_list_changed_event.add (this, &Navigator::layers_changed),
|
|
mp_source_view->hier_levels_changed_event.add (this, &Navigator::hier_levels_changed);
|
|
|
|
img::Service *image_plugin = mp_source_view->get_plugin<img::Service> ();
|
|
if (image_plugin) {
|
|
image_plugin->images_changed_event.add (this, &Navigator::content_changed);
|
|
}
|
|
|
|
// update the list of frozen flags per view
|
|
std::set <lay::LayoutView *> all_views;
|
|
|
|
for (std::map <lay::LayoutView *, NavigatorFrozenViewInfo>::const_iterator f = m_frozen_list.begin (); f != m_frozen_list.end (); ++f) {
|
|
all_views.insert (f->first);
|
|
}
|
|
|
|
for (unsigned int i = 0; i < mp_main_window->views (); ++i) {
|
|
lay::LayoutView *view = mp_main_window->view (i);
|
|
if (m_frozen_list.find (view) != m_frozen_list.end ()) {
|
|
all_views.erase (view);
|
|
}
|
|
}
|
|
|
|
for (std::set <lay::LayoutView *>::const_iterator v = all_views.begin (); v != all_views.end (); ++v) {
|
|
all_views.erase (*v);
|
|
}
|
|
|
|
Action *freeze_action = mp_main_window->menu ()->action (freeze_action_path);
|
|
freeze_action->set_checked (m_frozen_list.find (mp_source_view) != m_frozen_list.end ());
|
|
|
|
// Hint: this must happen before update ()
|
|
mp_service->attach_view (mp_source_view);
|
|
|
|
update ();
|
|
|
|
}
|
|
|
|
delete old_view;
|
|
|
|
}
|
|
}
|
|
|
|
void
|
|
Navigator::hier_levels_changed ()
|
|
{
|
|
if (m_show_all_hier_levels && mp_source_view && m_frozen_list.find (mp_source_view) == m_frozen_list.end ()) {
|
|
mp_view->set_hier_levels (mp_source_view->get_hier_levels ());
|
|
}
|
|
}
|
|
|
|
void
|
|
Navigator::update_layers ()
|
|
{
|
|
if (! mp_source_view || m_frozen_list.find (mp_source_view) == m_frozen_list.end ()) {
|
|
update ();
|
|
}
|
|
}
|
|
|
|
void
|
|
Navigator::update ()
|
|
{
|
|
if (! mp_view || ! mp_source_view) {
|
|
return;
|
|
}
|
|
|
|
if (m_frozen_list.find (mp_source_view) == m_frozen_list.end ()) {
|
|
mp_view->select_cellviews (mp_source_view->cellview_list ());
|
|
mp_view->set_properties (mp_source_view->get_properties ());
|
|
} else {
|
|
mp_view->select_cellviews (mp_source_view->cellview_list ());
|
|
mp_view->set_properties (m_frozen_list [mp_source_view].layer_properties);
|
|
}
|
|
|
|
img::Service *img_target = mp_view->get_plugin<img::Service> ();
|
|
if (img_target) {
|
|
|
|
img_target->clear_images ();
|
|
|
|
if (m_show_images) {
|
|
img::Service *img_source = (mp_source_view->get_plugin<img::Service> ());
|
|
if (img_source) {
|
|
for (img::ImageIterator i = img_source->begin_images (); ! i.at_end (); ++i) {
|
|
img_target->insert_image (*i);
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
if (m_show_all_hier_levels && mp_source_view) {
|
|
if (m_frozen_list.find (mp_source_view) == m_frozen_list.end ()) {
|
|
mp_view->set_hier_levels (mp_source_view->get_hier_levels ());
|
|
} else {
|
|
mp_view->set_hier_levels (m_frozen_list [mp_source_view].hierarchy_levels);
|
|
}
|
|
} else {
|
|
mp_view->set_hier_levels (std::make_pair (0, 0));
|
|
}
|
|
|
|
mp_view->zoom_fit ();
|
|
mp_view->update_content ();
|
|
mp_service->update_marker ();
|
|
}
|
|
|
|
// ------------------------------------------------------------
|
|
// Declaration of the "plugin" for the menu entries
|
|
|
|
class NavigatorPluginDeclaration
|
|
: public lay::PluginDeclaration
|
|
{
|
|
public:
|
|
virtual void get_menu_entries (std::vector<lay::MenuEntry> &menu_entries) const
|
|
{
|
|
std::string at;
|
|
|
|
at = ".end";
|
|
menu_entries.push_back (lay::submenu ("@@navigator_menu", at, std::string ()));
|
|
|
|
at = "@@navigator_menu.end";
|
|
menu_entries.push_back (lay::submenu ("navigator_main_menu", at, tl::to_string (QObject::tr ("Options"))));
|
|
|
|
at = "@@navigator_menu.navigator_main_menu.end";
|
|
menu_entries.push_back (lay::config_menu_item ("navigator_show_images", at, tl::to_string (QObject::tr ("Show Images")), cfg_navigator_show_images, "?"));
|
|
menu_entries.push_back (lay::config_menu_item ("navigator_all_hier_levels", at, tl::to_string (QObject::tr ("Show All Hierarchy Levels")), cfg_navigator_all_hier_levels, "?"));
|
|
menu_entries.push_back (lay::separator ("navigator_options_group", at));
|
|
menu_entries.push_back (lay::menu_item ("cm_navigator_freeze", "navigator_freeze", at, tl::to_string (QObject::tr ("Freeze"))));
|
|
menu_entries.back ().checkable = true;
|
|
}
|
|
};
|
|
|
|
static tl::RegisteredClass<lay::PluginDeclaration> config_decl (new NavigatorPluginDeclaration (), -1, "NavigatorPlugin");
|
|
|
|
}
|
|
|