mirror of https://github.com/KLayout/klayout.git
1416 lines
36 KiB
C++
1416 lines
36 KiB
C++
|
|
/*
|
|
|
|
KLayout Layout Viewer
|
|
Copyright (C) 2006-2025 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
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifndef HDR_layViewObject
|
|
#define HDR_layViewObject
|
|
|
|
#include "laybasicCommon.h"
|
|
|
|
#include <list>
|
|
#include <string>
|
|
#include <vector>
|
|
#include <map>
|
|
|
|
#if defined(HAVE_QT)
|
|
# include <QPoint>
|
|
# include <QByteArray>
|
|
# include <QColor>
|
|
#endif
|
|
|
|
#include "tlObjectCollection.h"
|
|
#include "tlVariant.h"
|
|
#include "dbTrans.h"
|
|
#include "dbBox.h"
|
|
#include "layViewOp.h"
|
|
#include "layCursor.h"
|
|
#include "layBitmapRenderer.h"
|
|
|
|
#if defined(HAVE_QT)
|
|
class QWidget;
|
|
class QMouseEvent;
|
|
class QImage;
|
|
class QDragEnterEvent;
|
|
class QDragMoveEvent;
|
|
class QDragLeaveEvent;
|
|
class QDropEvent;
|
|
class QMimeData;
|
|
#endif
|
|
|
|
namespace db
|
|
{
|
|
class Library;
|
|
class Layout;
|
|
}
|
|
|
|
namespace tl
|
|
{
|
|
class PixelBuffer;
|
|
class BitmapBuffer;
|
|
}
|
|
|
|
namespace lay {
|
|
|
|
class Viewport;
|
|
class ViewObjectUI;
|
|
class ViewObjectCanvas;
|
|
class CanvasPlane;
|
|
class Bitmap;
|
|
|
|
#if defined(HAVE_QT)
|
|
class DragDropDataBase;
|
|
#endif
|
|
|
|
class ViewObjectQWidget;
|
|
|
|
/**
|
|
* @brief A view service
|
|
*
|
|
* A view service is providing editing or informational services
|
|
* on the canvas.
|
|
* A service can be "active" by requesting mouse
|
|
* events through a trigger by "select" or "activate" after
|
|
* which a "grab_mouse" redirects all mouse events to the
|
|
* view service.
|
|
* This is an interface that should/must be implemented
|
|
* by the super class.
|
|
*/
|
|
|
|
class LAYBASIC_PUBLIC ViewService
|
|
{
|
|
public:
|
|
/**
|
|
* @brief Constructor
|
|
*/
|
|
ViewService (ViewObjectUI *widget = 0);
|
|
|
|
/**
|
|
* @brief Initialization, can follow default constructor
|
|
*/
|
|
void init (ViewObjectUI *widget);
|
|
|
|
/**
|
|
* @brief Destructor
|
|
*/
|
|
virtual ~ViewService ();
|
|
|
|
/**
|
|
* @brief Key press event handler
|
|
*
|
|
* This method will be called by the ViewObjectWidget object to
|
|
* dispatch key press events.
|
|
*
|
|
* The active service will receive that call and should return true
|
|
* if the event is taken. Otherwise the event will be passed further.
|
|
*/
|
|
virtual bool key_event (unsigned int /*key*/, unsigned int /*buttons*/) { return false; }
|
|
|
|
#if defined(HAVE_QT)
|
|
/**
|
|
* @brief The drag enter event
|
|
*
|
|
* If something is dragged into the view, this event is triggered.
|
|
* p will be the position of the event.
|
|
*
|
|
* The implementation should return true, if the drop is accepted.
|
|
*/
|
|
virtual bool drag_enter_event (const db::DPoint & /*p*/, const DragDropDataBase * /*data*/) { return false; }
|
|
|
|
/**
|
|
* @brief The drag move event
|
|
*/
|
|
virtual bool drag_move_event (const db::DPoint & /*p*/, const DragDropDataBase * /*data*/) { return false; }
|
|
|
|
/**
|
|
* @brief The drag leave event
|
|
*/
|
|
virtual void drag_leave_event () { }
|
|
|
|
/**
|
|
* @brief The drop event
|
|
*/
|
|
virtual bool drop_event (const db::DPoint & /*p*/, const DragDropDataBase * /*data*/) { return false; }
|
|
#endif
|
|
|
|
/**
|
|
* @brief Hover reset request
|
|
*
|
|
* This event is issued for services providing some "hover" mode - i.e. capture
|
|
* mouse move events and start a timer on them.
|
|
*
|
|
* The implementation of this event should cancel this timer and
|
|
* not raise a hover condition.
|
|
*/
|
|
virtual void hover_reset () { }
|
|
|
|
/**
|
|
* @brief Mouse press event handler
|
|
*
|
|
* This method will be called by the ViewObjectWidget object to
|
|
* dispatch mouse press events. First, the objects that grabbed
|
|
* the mouse will receive the events with prio "true" in the reverse order they
|
|
* grabbed the mouse (last one first). This loop will terminate
|
|
* if one of the objects has returned "true".
|
|
* If no service has grabbed the mouse or none of them was taking the
|
|
* event, the active service receives the event with prio set to "true".
|
|
* If this is not the case, then all objects will receive
|
|
* the event with "prio" set to "false", unless one of the objects
|
|
* returns "true".
|
|
* This event is not sent immediately when the mouse button is pressed
|
|
* but when a signification movement for the mouse cursor away from the
|
|
* original position is detected. If the mouse button is released before
|
|
* that, a mouse_clicked_event is sent rather than a press-move-release
|
|
* sequence.
|
|
*
|
|
* @param p The point at which the button was pressed
|
|
* @param buttons A ored combination of ShiftButton etc.
|
|
* @return True to terminate dispatcher
|
|
*/
|
|
virtual bool mouse_press_event (const db::DPoint & /*p*/, unsigned int /*buttons*/, bool /*prio*/) { return false; }
|
|
|
|
/**
|
|
* @brief Mouse single-click event handler
|
|
*
|
|
* Analogous to mouse_press_event (see above), but sent if the mouse was not moved.
|
|
* The click event is coincident with the release of the mouse button.
|
|
*/
|
|
virtual bool mouse_click_event (const db::DPoint & /*p*/, unsigned int /*buttons*/, bool /*prio*/) { return false; }
|
|
|
|
/**
|
|
* @brief Mouse double-click event handler
|
|
*
|
|
* Analogous to mouse_press_event (see above), but sent if a double-click was detected.
|
|
*/
|
|
virtual bool mouse_double_click_event (const db::DPoint & /*p*/, unsigned int /*buttons*/, bool /*prio*/) { return false; }
|
|
|
|
/**
|
|
* @brief Mouse leave event handler
|
|
*/
|
|
virtual bool leave_event (bool /*prio*/) { return false; }
|
|
|
|
/**
|
|
* @brief Mouse enter event handler
|
|
*/
|
|
virtual bool enter_event (bool /*prio*/) { return false; }
|
|
|
|
/**
|
|
* @brief Mouse move event handler
|
|
*
|
|
* Analogous to mouse_press_event (see above).
|
|
*/
|
|
virtual bool mouse_move_event (const db::DPoint & /*p*/, unsigned int /*buttons*/, bool /*prio*/) { return false; }
|
|
|
|
/**
|
|
* @brief Mouse release event handler
|
|
*
|
|
* Analogous to mouse_press_event (see above).
|
|
*/
|
|
virtual bool mouse_release_event (const db::DPoint & /*p*/, unsigned int /*buttons*/, bool /*prio*/) { return false; }
|
|
|
|
/**
|
|
* @brief Wheel event handler
|
|
*
|
|
* Analogous to mouse_press_event (see above).
|
|
*
|
|
* @param delta The rotation angle in eights of a degree
|
|
* @param horizontal True, if the horizontal wheel was turned
|
|
* @param p The position where the mouse currently is at (in micron units)
|
|
*/
|
|
virtual bool wheel_event (int /*delta*/, bool /*horizontal*/, const db::DPoint & /*p*/, unsigned int /*buttons*/, bool /*prio*/) { return false; }
|
|
|
|
/**
|
|
* @brief Set the mouse cursor
|
|
*
|
|
* This method can be called from a mouse event handler to set the cursor for the view.
|
|
* It is only effective if called from a mouse event handler.
|
|
*/
|
|
void set_cursor (lay::Cursor::cursor_shape cursor);
|
|
|
|
/**
|
|
* @brief Do an update
|
|
*
|
|
* This method is supposed to update the internals,
|
|
* specifically upon changing of the coordinate system
|
|
*/
|
|
virtual void update ()
|
|
{
|
|
// The default implementation does nothing
|
|
}
|
|
|
|
/**
|
|
* @brief Accessor to the widget pointer
|
|
*/
|
|
ViewObjectUI *ui () const
|
|
{
|
|
return mp_widget;
|
|
}
|
|
|
|
/**
|
|
* @brief This method is called on the service that got activated
|
|
*/
|
|
virtual void activated () { }
|
|
|
|
/**
|
|
* @brief This method is called on the service that got deactivated
|
|
*/
|
|
virtual void deactivated () { }
|
|
|
|
/**
|
|
* @brief This method is called to set the background and text (foreground) color
|
|
*/
|
|
virtual void set_colors (tl::Color /*background*/, tl::Color /*text*/) { }
|
|
|
|
/**
|
|
* @brief This method is called when a mouse tracking operation should be cancelled
|
|
*/
|
|
virtual void drag_cancel () { }
|
|
|
|
/**
|
|
* @brief Gets a value indicating whether the mouse receiver claims the view message bar
|
|
*
|
|
* If this method returns true, other services are not supposed to emit transient
|
|
* messages.
|
|
*/
|
|
virtual bool claims_message_bar () const { return false; }
|
|
|
|
/**
|
|
* @brief Gets a value indicating whether a cursor position it set
|
|
*/
|
|
virtual bool has_tracking_position () const { return false; }
|
|
|
|
/**
|
|
* @brief Gets the cursor position if one is set
|
|
*/
|
|
virtual db::DPoint tracking_position () const { return db::DPoint (); }
|
|
|
|
/**
|
|
* @brief Enable or disable a service
|
|
*
|
|
* If a service is disabled, it will not receive mouse events
|
|
*/
|
|
void enable (bool en);
|
|
|
|
/**
|
|
* @brief Returns true, if the service is enabled
|
|
*/
|
|
bool enabled () const
|
|
{
|
|
return m_enabled;
|
|
}
|
|
|
|
private:
|
|
friend class ViewObjectUI;
|
|
|
|
ViewObjectUI *mp_widget;
|
|
bool m_abs_grab;
|
|
bool m_enabled;
|
|
};
|
|
|
|
/**
|
|
* @brief The background view object
|
|
*
|
|
* A background view object is an object that is painted onto the
|
|
* canvas background and is contained by the view object widget.
|
|
* This is an interface that should/must be implemented
|
|
* by the super class.
|
|
*/
|
|
|
|
class LAYBASIC_PUBLIC BackgroundViewObject
|
|
: virtual public tl::Object
|
|
{
|
|
public:
|
|
/**
|
|
* @brief The constructor
|
|
*
|
|
* @param widget The widget object that the object is shown on.
|
|
* @param _static True, if the object is in frozen mode initially
|
|
*/
|
|
BackgroundViewObject (ViewObjectUI *widget = 0);
|
|
|
|
/**
|
|
* @brief The destructor
|
|
*/
|
|
virtual ~BackgroundViewObject ();
|
|
|
|
/**
|
|
* @brief Render the object on the background
|
|
*
|
|
* This method is supposed to repaint the background part of the object
|
|
* on the QImage provided in the canvas.
|
|
*/
|
|
virtual void render_bg (const Viewport &vp, ViewObjectCanvas &canvas) = 0;
|
|
|
|
/**
|
|
* @brief Accessor to the widget object pointer
|
|
*/
|
|
ViewObjectUI *widget () const
|
|
{
|
|
return const_cast<ViewObjectUI *> (mp_widget.get());
|
|
}
|
|
|
|
/**
|
|
* @brief Set the visibility state of the view object
|
|
*
|
|
* Invisible objects are not drawn
|
|
*/
|
|
void visible (bool vis);
|
|
|
|
/**
|
|
* @brief Tell the visibility state of the view object
|
|
*/
|
|
bool is_visible () const
|
|
{
|
|
return m_visible;
|
|
}
|
|
|
|
/**
|
|
* @brief This method tells the widget to update the object on next repaint
|
|
*
|
|
* If the object is static, a "touch" is issued on the widget. Otherwise
|
|
* just a update is issued, resulting in a repaint
|
|
* This is the preferred method to tell that an object needs repainting.
|
|
* It can be called multiple times without performance penalty.
|
|
*/
|
|
void redraw ();
|
|
|
|
/**
|
|
* @brief Z-Order property
|
|
*
|
|
* This property controls in which order the background objects are drawn:
|
|
* those with a lower z-order value are drawn first. Thus, ones with the
|
|
* higher value overwrite them.
|
|
*/
|
|
int z_order () const
|
|
{
|
|
return m_z_order;
|
|
}
|
|
|
|
/**
|
|
* @brief Z-Order write accessor
|
|
*/
|
|
void z_order (int z);
|
|
|
|
private:
|
|
friend class ViewObjectUI;
|
|
|
|
BackgroundViewObject (const BackgroundViewObject &d);
|
|
BackgroundViewObject &operator= (const BackgroundViewObject &d);
|
|
|
|
tl::weak_ptr<ViewObjectUI> mp_widget;
|
|
bool m_visible;
|
|
int m_z_order;
|
|
};
|
|
|
|
/**
|
|
* @brief The view object
|
|
*
|
|
* A view object is an object that is painted onto the
|
|
* canvas and is contained by the view object widget.
|
|
* View objects can be static or non-static. Changing a
|
|
* view object in the non-static case is somewhat more
|
|
* efficient and is recommended for dynamic objects.
|
|
* Static mode is entered with "freeze", non-static mode
|
|
* with "thaw".
|
|
* This is an interface that should/must be implemented
|
|
* by the super class.
|
|
*/
|
|
|
|
class LAYBASIC_PUBLIC ViewObject
|
|
: public tl::Object
|
|
{
|
|
public:
|
|
/**
|
|
* @brief The constructor
|
|
*
|
|
* @param widget The widget object that the object is shown on.
|
|
* @param _static True, if the object is in frozen mode initially
|
|
*/
|
|
ViewObject (ViewObjectUI *widget = 0, bool _static = true);
|
|
|
|
/**
|
|
* @brief The destructor
|
|
*/
|
|
virtual ~ViewObject ();
|
|
|
|
/**
|
|
* @brief Attaches a view object to a widget
|
|
*
|
|
* This will register the object at the widget, but not transfer ownership.
|
|
*/
|
|
void set_widget (ViewObjectUI *widget);
|
|
|
|
/**
|
|
* @brief Render the object on the planes provided by the canvas.
|
|
*
|
|
* This method is supposed to repaint the object on the plane
|
|
* objects that the canvas can provide upon request with the plane
|
|
* method.
|
|
*/
|
|
virtual void render (const Viewport &vp, ViewObjectCanvas &canvas) = 0;
|
|
|
|
/**
|
|
* @brief Accessor to the widget object pointer
|
|
*/
|
|
ViewObjectUI *widget () const
|
|
{
|
|
return const_cast<ViewObjectUI *> (mp_widget.get());
|
|
}
|
|
|
|
/**
|
|
* @brief Gets a value indicating whether the marker can be dismissed (made invisible)
|
|
*
|
|
* Markers with this flag set to true can be hidden by using ViewObjectCanvas::show_markers.
|
|
*/
|
|
bool get_dismissable () const
|
|
{
|
|
return m_dismissable;
|
|
}
|
|
|
|
/**
|
|
* @brief Sets a value indicating whether the marker can be dismissed (made invisible)
|
|
*
|
|
* See \\get_dismissable for details.
|
|
*/
|
|
void set_dismissable (bool f);
|
|
|
|
/**
|
|
* @brief Set the visibility state of the view object
|
|
*
|
|
* Invisible objects are not drawn
|
|
*/
|
|
void visible (bool vis);
|
|
|
|
/**
|
|
* @brief Tell the visibility state of the view object
|
|
*/
|
|
bool is_visible () const
|
|
{
|
|
return m_visible;
|
|
}
|
|
|
|
/**
|
|
* @brief This method tells the widget to update the object on next repaint
|
|
*
|
|
* If the object is static, a "touch" is issued on the widget. Otherwise
|
|
* just a update is issued, resulting in a repaint
|
|
* This is the preferred method to tell that an object needs repainting.
|
|
* It can be called multiple times without performance penalty.
|
|
*/
|
|
void redraw ();
|
|
|
|
/**
|
|
* @brief thaw this object
|
|
*
|
|
* This is a convenience function that avoids having to store a widget pointer
|
|
*/
|
|
void thaw ();
|
|
|
|
/**
|
|
* @brief freeze this object
|
|
*
|
|
* This is a convenience function that avoids having to store a widget pointer
|
|
*/
|
|
void freeze ();
|
|
|
|
private:
|
|
friend class ViewObjectUI;
|
|
|
|
ViewObject (const ViewObject &d);
|
|
ViewObject &operator= (const ViewObject &d);
|
|
|
|
tl::weak_ptr<ViewObjectUI> mp_widget;
|
|
bool m_static;
|
|
bool m_visible;
|
|
bool m_dismissable;
|
|
};
|
|
|
|
/**
|
|
* @brief Describes the button state (supposed to be ored)
|
|
*/
|
|
enum ButtonState {
|
|
ShiftButton = 1,
|
|
ControlButton = 2,
|
|
AltButton = 4,
|
|
LeftButton = 8,
|
|
MidButton = 16,
|
|
RightButton = 32
|
|
};
|
|
|
|
/**
|
|
* @brief Key codes for keys understood by the standard components
|
|
*/
|
|
enum KeyCodes {
|
|
#if defined(HAVE_QT)
|
|
KeyEscape = int(Qt::Key_Escape),
|
|
KeyTab = int(Qt::Key_Tab),
|
|
KeyBacktab = int(Qt::Key_Backtab),
|
|
KeyBackspace = int(Qt::Key_Backspace),
|
|
KeyReturn = int(Qt::Key_Return),
|
|
KeyEnter = int(Qt::Key_Enter),
|
|
KeyInsert = int(Qt::Key_Insert),
|
|
KeyDelete = int(Qt::Key_Delete),
|
|
KeyHome = int(Qt::Key_Home),
|
|
KeyEnd = int(Qt::Key_End),
|
|
KeyDown = int(Qt::Key_Down),
|
|
KeyUp = int(Qt::Key_Up),
|
|
KeyLeft = int(Qt::Key_Left),
|
|
KeyRight = int(Qt::Key_Right),
|
|
KeyPageUp = int(Qt::Key_PageUp),
|
|
KeyPageDown = int(Qt::Key_PageDown)
|
|
#else
|
|
KeyEscape = 0x01000000,
|
|
KeyTab = 0x01000001,
|
|
KeyBacktab = 0x01000002,
|
|
KeyBackspace = 0x01000003,
|
|
KeyReturn = 0x01000004,
|
|
KeyEnter = 0x01000005,
|
|
KeyInsert = 0x01000006,
|
|
KeyDelete = 0x01000007,
|
|
KeyHome = 0x01000010,
|
|
KeyEnd = 0x01000011,
|
|
KeyLeft = 0x01000012,
|
|
KeyUp = 0x01000013,
|
|
KeyRight = 0x01000014,
|
|
KeyDown = 0x01000015,
|
|
KeyPageUp = 0x01000016,
|
|
KeyPageDown = 0x01000017
|
|
#endif
|
|
};
|
|
|
|
/**
|
|
* @brief The view object container
|
|
*
|
|
* The container holds the view objects and
|
|
* manages the the mouse event distribution and
|
|
* painting.
|
|
*/
|
|
|
|
class LAYBASIC_PUBLIC ViewObjectUI :
|
|
public tl::Object
|
|
{
|
|
public:
|
|
typedef tl::weak_collection<ViewObject>::iterator object_iterator;
|
|
typedef tl::weak_collection<BackgroundViewObject>::iterator background_object_iterator;
|
|
typedef std::list<ViewService *>::const_iterator service_iterator;
|
|
typedef std::list<ViewService *>::const_iterator mouse_receivers_iterator;
|
|
|
|
/**
|
|
* @brief ctor
|
|
*/
|
|
ViewObjectUI ();
|
|
|
|
/**
|
|
* @brief dtor
|
|
*/
|
|
~ViewObjectUI ();
|
|
|
|
#if defined(HAVE_QT)
|
|
/**
|
|
* @brief Initializes the UI components
|
|
*/
|
|
virtual void init_ui (QWidget *parent);
|
|
#endif
|
|
|
|
/**
|
|
* @brief Cancel all drag operations
|
|
*/
|
|
void drag_cancel ();
|
|
|
|
/**
|
|
* @brief Calls hover_reset on all services
|
|
*/
|
|
void hover_reset ();
|
|
|
|
/**
|
|
* @brief CanvasPlane rendering
|
|
*
|
|
* This method is supposed to render the object on the planes provided
|
|
* by the planes() method.
|
|
*
|
|
* @param vp The viewport
|
|
* @param st True, if only static (frozen) objects are to be redrawn
|
|
*/
|
|
void do_render (const Viewport &vp, ViewObjectCanvas &canvas, bool st);
|
|
|
|
/**
|
|
* @brief Background rendering
|
|
*
|
|
* Objects on the background must provide a paint method that paints
|
|
* them on the canvas directly.
|
|
*
|
|
* @param vp The viewport
|
|
* @param canvas The canvas where to paint on
|
|
*/
|
|
void do_render_bg (const Viewport &vp, ViewObjectCanvas &canvas);
|
|
|
|
/**
|
|
* @brief Query if any "static" object needs to be redrawn
|
|
*
|
|
* To reset this flag, call do_render with "st" set to true.
|
|
*/
|
|
bool needs_update_static () const
|
|
{
|
|
return m_needs_update_static;
|
|
}
|
|
|
|
/**
|
|
* @brief Query if the background needs to be redrawn
|
|
*
|
|
* To reset this flag, call do_render_bg
|
|
*/
|
|
bool needs_update_bg () const
|
|
{
|
|
return m_needs_update_bg;
|
|
}
|
|
|
|
/**
|
|
* @brief Puts the object into "static" mode
|
|
*/
|
|
void freeze (ViewObject *obj);
|
|
|
|
/**
|
|
* @brief Puts the object into "non-static" mode
|
|
*/
|
|
void thaw (ViewObject *obj);
|
|
|
|
/**
|
|
* @brief Marks the widget for update
|
|
*
|
|
* Beside issuing an "update" request, the widget is also
|
|
* marked for "static-update", which shall redraw all static
|
|
* objects also.
|
|
*/
|
|
void touch ();
|
|
|
|
/**
|
|
* @brief Marks the widget background for update
|
|
*
|
|
* Beside issuing an "update" request, the widget is also
|
|
* marked for "bg-update", which shall redraw including the background.
|
|
*/
|
|
void touch_bg ();
|
|
|
|
/**
|
|
* @brief Grab the mouse for the object
|
|
*
|
|
* This will put the object into the list of objects interested
|
|
* into mouse events with high priority (prio = true on mouse_* events).
|
|
* Objects with dragging semantics (press-drag-release) may request
|
|
* "absolute" mouse grab. This way, all mouse events are passed to the
|
|
* object. The grab should then in any case be released on mouse button
|
|
* release.
|
|
*/
|
|
void grab_mouse (ViewService *obj, bool abs);
|
|
|
|
/**
|
|
* @brief Remove the object from the list of objects that grabbed the mouse
|
|
*
|
|
* This will also remove any absolute grabs if there is no other object
|
|
* that needs this.
|
|
*/
|
|
void ungrab_mouse (ViewService *obj);
|
|
|
|
/**
|
|
* @brief Set the mouse cursor
|
|
*
|
|
* This method can be called from a mouse event handler to set the cursor for the view.
|
|
* It is only effective if called from a mouse event handler.
|
|
*/
|
|
void set_cursor (lay::Cursor::cursor_shape cursor);
|
|
|
|
/**
|
|
* @brief Determine the active service
|
|
*/
|
|
lay::ViewService *active_service () const
|
|
{
|
|
return const_cast<lay::ViewService *> (mp_active_service);
|
|
}
|
|
|
|
/**
|
|
* @brief Activate a service
|
|
*
|
|
* The active service will be the first to receive mouse events
|
|
* with prio==true, unless the mouse is grabbed and the event is
|
|
* taken by the grabber.
|
|
* Passing 0 deactivates all services. The service currently active
|
|
* will get a "deactivated" signal.
|
|
*/
|
|
void activate (lay::ViewService *service);
|
|
|
|
/**
|
|
* @brief Services iterator: begin
|
|
*/
|
|
service_iterator begin_services ()
|
|
{
|
|
return m_services.begin ();
|
|
}
|
|
|
|
/**
|
|
* @brief Services iterator: end
|
|
*/
|
|
service_iterator end_services ()
|
|
{
|
|
return m_services.end ();
|
|
}
|
|
|
|
/**
|
|
* @brief Background objects iterator: begin
|
|
*/
|
|
background_object_iterator begin_background_objects ()
|
|
{
|
|
return m_background_objects.begin ();
|
|
}
|
|
|
|
/**
|
|
* @brief Background objects iterator: end
|
|
*/
|
|
background_object_iterator end_background_objects ()
|
|
{
|
|
return m_background_objects.end ();
|
|
}
|
|
|
|
/**
|
|
* @brief Objects iterator: begin
|
|
*/
|
|
object_iterator begin_objects ()
|
|
{
|
|
return m_objects.begin ();
|
|
}
|
|
|
|
/**
|
|
* @brief Objects iterator: end
|
|
*/
|
|
object_iterator end_objects ()
|
|
{
|
|
return m_objects.end ();
|
|
}
|
|
|
|
/**
|
|
* @brief Adds an object, transferring ownership to the view
|
|
*/
|
|
void add_object (lay::ViewObject *object);
|
|
|
|
/**
|
|
* @brief Clears all objects owned by the view
|
|
*/
|
|
void clear_objects ();
|
|
|
|
/**
|
|
* @brief Remaining leave event handler
|
|
*
|
|
* This event handler is called if no ViewObject requested handling
|
|
* of this event.
|
|
*/
|
|
virtual void leave_event () { }
|
|
|
|
/**
|
|
* @brief Remaining enter event handler
|
|
*
|
|
* This event handler is called if no ViewObject requested handling
|
|
* of this event.
|
|
*/
|
|
virtual void enter_event () { }
|
|
|
|
/**
|
|
* @brief Remaining key event handler
|
|
*
|
|
* This event handler is called if no ViewObject requested handling
|
|
* of this event.
|
|
*/
|
|
virtual void key_event (unsigned int /*key*/, unsigned int /*buttons*/) { }
|
|
|
|
#if defined(HAVE_QT)
|
|
/**
|
|
* @brief The drag enter event
|
|
*
|
|
* If something is dragged into the view, this event is triggered.
|
|
* p will be the position of the event.
|
|
*
|
|
* The implementation should return true, if the drop is accepted.
|
|
*/
|
|
virtual bool drag_enter_event (const db::DPoint & /*p*/, const DragDropDataBase * /*data*/) { return false; }
|
|
|
|
/**
|
|
* @brief The drag move event
|
|
*/
|
|
virtual bool drag_move_event (const db::DPoint & /*p*/, const DragDropDataBase * /*data*/) { return false; }
|
|
|
|
/**
|
|
* @brief The drag leave event
|
|
*/
|
|
virtual void drag_leave_event () { }
|
|
|
|
/**
|
|
* @brief The drop event
|
|
*/
|
|
virtual bool drop_event (const db::DPoint & /*p*/, const DragDropDataBase * /*data*/) { return false; }
|
|
#endif
|
|
|
|
/**
|
|
* @brief Remaining mouse double click event handler
|
|
*
|
|
* This event handler is called if no ViewObject requested handling
|
|
* of this event.
|
|
*/
|
|
virtual void mouse_double_click_event (const db::DPoint & /*p*/, unsigned int /*buttons*/) { }
|
|
|
|
/**
|
|
* @brief Remaining single mouse click event handler
|
|
*
|
|
* This event handler is called if no ViewObject requested handling
|
|
* of this event.
|
|
*/
|
|
virtual void mouse_click_event (const db::DPoint & /*p*/, unsigned int /*buttons*/) { }
|
|
|
|
/**
|
|
* @brief Remaining mouse press event handler
|
|
*
|
|
* This event handler is called if no ViewObject requested handling
|
|
* of this event.
|
|
*/
|
|
virtual void mouse_press_event (const db::DPoint & /*p*/, unsigned int /*buttons*/) { }
|
|
|
|
/**
|
|
* @brief Remaining mouse release event handler
|
|
*
|
|
* This event handler is called if no ViewObject requested handling
|
|
* of this event.
|
|
*/
|
|
virtual void mouse_release_event (const db::DPoint & /*p*/, unsigned int /*buttons*/) { }
|
|
|
|
/**
|
|
* @brief Remaining mouse move event handler
|
|
*
|
|
* This event handler is called if no ViewObject requested handling
|
|
* of this event.
|
|
*/
|
|
virtual void mouse_move_event (const db::DPoint & /*p*/, unsigned int /*buttons*/) { }
|
|
|
|
/**
|
|
* @brief Remaining wheel event handler
|
|
*
|
|
* This event handler is called if no ViewObject requested handling
|
|
* of this event.
|
|
*/
|
|
virtual void wheel_event (int /*delta*/, bool /*horizontal*/, const db::DPoint & /*p*/, unsigned int /*buttons*/) { }
|
|
|
|
/**
|
|
* @brief Get the transformation for mouse events
|
|
*/
|
|
const db::DCplxTrans &mouse_event_trans () const
|
|
{
|
|
return m_trans;
|
|
}
|
|
|
|
/**
|
|
* @brief Deliver an iterator for the mouse receivers (begin)
|
|
*/
|
|
mouse_receivers_iterator begin_mouse_receivers () const
|
|
{
|
|
return m_grabbed.begin ();
|
|
}
|
|
|
|
/**
|
|
* @brief Deliver an iterator for the mouse receivers (end)
|
|
*/
|
|
mouse_receivers_iterator end_mouse_receivers () const
|
|
{
|
|
return m_grabbed.end ();
|
|
}
|
|
|
|
/**
|
|
* @brief Get the viewport for mouse events
|
|
*/
|
|
db::DBox mouse_event_viewport () const;
|
|
|
|
/**
|
|
* @brief Set the default cursor
|
|
*
|
|
* The default cursor is shown when no mouse event sets the cursor.
|
|
*/
|
|
void set_default_cursor (lay::Cursor::cursor_shape cursor);
|
|
|
|
/**
|
|
* @brief Sets a value indicating whether dismissable view objects shall be drawn or not
|
|
*
|
|
* Markers with dismissable = false are always drawn. The default value is "false".
|
|
*/
|
|
void set_dismiss_view_objects (bool dismissed);
|
|
|
|
/**
|
|
* @brief Gets a value indicating whether dismissable markers shall be drawn or not
|
|
*/
|
|
bool dismiss_view_objects () const
|
|
{
|
|
return m_view_objects_dismissed;
|
|
}
|
|
|
|
/**
|
|
* @brief Gets the current mouse position
|
|
*/
|
|
db::DPoint mouse_position () const
|
|
{
|
|
return m_mouse_pos;
|
|
}
|
|
|
|
/**
|
|
* @brief Gets the current mouse position in micrometer units
|
|
*/
|
|
db::DPoint mouse_position_um () const
|
|
{
|
|
return pixel_to_um (m_mouse_pos);
|
|
}
|
|
|
|
/**
|
|
* @brief Translates a screen coordinate in micrometer coordinates
|
|
*/
|
|
db::DPoint pixel_to_um (const db::Point &pt) const;
|
|
|
|
/**
|
|
* @brief Translates a screen coordinate in micrometer coordinates
|
|
*/
|
|
db::DPoint pixel_to_um (const db::DPoint &pt) const;
|
|
|
|
/**
|
|
* @brief Gets a flag indicating whether the mouse is inside the window
|
|
*/
|
|
bool mouse_in_window () const
|
|
{
|
|
return m_mouse_inside;
|
|
}
|
|
|
|
#if !defined(HAVE_QT)
|
|
/**
|
|
* @brief Gets a value indicating that the image data has been updated
|
|
*
|
|
* This method will return true once after "update" was called.
|
|
*/
|
|
bool image_updated ();
|
|
#endif
|
|
|
|
#if defined(HAVE_QT)
|
|
/**
|
|
* @brief Gets the QWidget representing this canvas visually in Qt
|
|
*/
|
|
QWidget *widget () const
|
|
{
|
|
return mp_widget;
|
|
}
|
|
#endif
|
|
|
|
/**
|
|
* @brief External entry point for key press event generation
|
|
*/
|
|
void send_key_press_event (unsigned int key, unsigned int buttons);
|
|
|
|
/**
|
|
* @brief External entry point for mouse move event generation
|
|
*/
|
|
void send_mouse_move_event (const db::DPoint &pt, unsigned int buttons);
|
|
|
|
/**
|
|
* @brief External entry point for leave event generation
|
|
*/
|
|
void send_leave_event ();
|
|
|
|
/**
|
|
* @brief External entry point for enter event generation
|
|
*/
|
|
void send_enter_event ();
|
|
|
|
/**
|
|
* @brief External entry point for mouse button press event generation
|
|
*/
|
|
void send_mouse_press_event (const db::DPoint &pt, unsigned int buttons);
|
|
|
|
/**
|
|
* @brief External entry point for mouse button double-click event generation
|
|
*/
|
|
void send_mouse_double_clicked_event (const db::DPoint &pt, unsigned int buttons);
|
|
|
|
/**
|
|
* @brief External entry point for mouse button release event generation
|
|
*/
|
|
void send_mouse_release_event (const db::DPoint &pt, unsigned int buttons);
|
|
|
|
/**
|
|
* @brief External entry point for mouse wheel event generation
|
|
*/
|
|
void send_wheel_event (int delta, bool horizontal, const db::DPoint &pt, unsigned int buttons);
|
|
|
|
/**
|
|
* @brief Resizes the widget
|
|
*/
|
|
void resize (unsigned int w, unsigned int h);
|
|
|
|
protected:
|
|
friend class ViewObjectQWidget;
|
|
|
|
/**
|
|
* @brief Emulates the update() method in the non-Qt case
|
|
*
|
|
* After calling this method, the next image_updated() call will return true while also resetting the
|
|
* update needed flag.
|
|
*/
|
|
void update ();
|
|
|
|
/**
|
|
* @brief Set the transformation for mouse events
|
|
*/
|
|
void mouse_event_trans (const db::DCplxTrans &trans);
|
|
|
|
/**
|
|
* @brief Gets called when the view is resized
|
|
*/
|
|
virtual void resize_event (unsigned int w, unsigned int h);
|
|
|
|
/**
|
|
* @brief Receives the paint event from Qt
|
|
*/
|
|
virtual void paint_event ();
|
|
|
|
/**
|
|
* @brief GTF probe event
|
|
*/
|
|
virtual void gtf_probe ();
|
|
|
|
private:
|
|
friend class lay::ViewObject;
|
|
friend class lay::ViewService;
|
|
friend class lay::BackgroundViewObject;
|
|
|
|
#if defined(HAVE_QT)
|
|
QWidget *mp_widget;
|
|
#endif
|
|
tl::weak_collection<lay::ViewObject> m_objects;
|
|
tl::shared_collection<lay::ViewObject> m_owned_objects;
|
|
tl::weak_collection<lay::BackgroundViewObject> m_background_objects;
|
|
std::list<lay::ViewService *> m_services;
|
|
std::list<ViewService *> m_grabbed;
|
|
bool m_view_objects_dismissed;
|
|
bool m_needs_update_static;
|
|
bool m_needs_update_bg;
|
|
lay::ViewService *mp_active_service;
|
|
db::DCplxTrans m_trans;
|
|
db::DPoint m_mouse_pos;
|
|
db::DPoint m_mouse_pressed;
|
|
bool m_mouse_pressed_state;
|
|
unsigned int m_mouse_buttons;
|
|
bool m_in_mouse_move;
|
|
bool m_mouse_inside;
|
|
lay::Cursor::cursor_shape m_cursor, m_default_cursor;
|
|
unsigned int m_widget_width, m_widget_height;
|
|
bool m_image_updated;
|
|
|
|
void ensure_entered ();
|
|
void do_mouse_move ();
|
|
void begin_mouse_event (lay::Cursor::cursor_shape cursor = lay::Cursor::keep);
|
|
void end_mouse_event ();
|
|
void objects_changed ();
|
|
int widget_height () const;
|
|
int widget_width () const;
|
|
void realize_cursor ();
|
|
|
|
/**
|
|
* @brief Register a service
|
|
*
|
|
* This method is called by the service constructor and registers the service in the widget.
|
|
*/
|
|
void register_service (lay::ViewService *);
|
|
|
|
/**
|
|
* @brief Register a service
|
|
*
|
|
* This method is called by the service destructor and unregisters the service in the widget.
|
|
*/
|
|
void unregister_service (lay::ViewService *svc);
|
|
};
|
|
|
|
/**
|
|
* @brief The canvas interface
|
|
*
|
|
* The canvas provides ways and attributes that allow the view objects to render
|
|
* themselves. The basic functionality of this interface is to provide planes
|
|
* for painting.
|
|
*/
|
|
class LAYBASIC_PUBLIC ViewObjectCanvas
|
|
{
|
|
public:
|
|
/**
|
|
* The destructor
|
|
*/
|
|
virtual ~ViewObjectCanvas ()
|
|
{ }
|
|
|
|
/**
|
|
* @brief Background color property: background color of the canvas
|
|
*/
|
|
virtual tl::Color background_color () const = 0;
|
|
|
|
/**
|
|
* @brief Foreground color property: foreground color of the canvas (some "contrast" color to background)
|
|
*/
|
|
virtual tl::Color foreground_color () const = 0;
|
|
|
|
/**
|
|
* @brief Active color property: color of active elements on the canvas (some "contrast" color to background and different from foreground)
|
|
*/
|
|
virtual tl::Color active_color () const = 0;
|
|
|
|
/**
|
|
* @brief Get the resolution
|
|
*
|
|
* The resolution describes the size of one pixel in relation to "one line width". "One line width" is the unit
|
|
* of the drawing and describes the width of a "one unit" wide line. In that sense, the resolution is the reciprocal
|
|
* of a "one unit" line's width in pixels.
|
|
*/
|
|
virtual double resolution () const = 0;
|
|
|
|
/**
|
|
* @brief Get the font resolution
|
|
*
|
|
* The resolution describes the size of one pixel for the rendering of the "Default" font.
|
|
*/
|
|
virtual double font_resolution () const = 0;
|
|
|
|
/**
|
|
* @brief CanvasPlane provider
|
|
*
|
|
* This method is used by the view objects to obtain the planes
|
|
* they should paint themselves on.
|
|
* A style can be specified that determines how the plane will
|
|
* be displayed. CanvasPlanes may be shared if the style is identical.
|
|
* The plane index of the ViewOp is not used.
|
|
*/
|
|
virtual lay::CanvasPlane *plane (const lay::ViewOp &style) = 0;
|
|
|
|
/**
|
|
* @brief CanvasPlane provider for a sequence of operations on the same plane
|
|
*
|
|
* This method is used by the view objects to obtain the planes
|
|
* they should paint themselves on.
|
|
* A operator vector can be specified that determines how the plane will
|
|
* be displayed. The operators are executed in the order given on the same plane.
|
|
* CanvasPlanes may be shared if the styles are identical.
|
|
* The plane index of the ViewOp is not used.
|
|
*/
|
|
virtual lay::CanvasPlane *plane (const std::vector<lay::ViewOp> &style) = 0;
|
|
|
|
/**
|
|
* @brief Provide the renderer
|
|
*/
|
|
virtual lay::Renderer &renderer () = 0;
|
|
|
|
/**
|
|
* @brief Sort the planes in the painting order
|
|
*/
|
|
virtual void sort_planes () = 0;
|
|
};
|
|
|
|
/**
|
|
* @brief The canvas interface
|
|
*
|
|
* The canvas provides ways and attributes that allow the view objects to render
|
|
* themselves. The basic functionality of this interface is to provide planes
|
|
* for painting.
|
|
*/
|
|
class LAYBASIC_PUBLIC BitmapViewObjectCanvas
|
|
: public ViewObjectCanvas
|
|
{
|
|
public:
|
|
/**
|
|
* @brief Constructor
|
|
*/
|
|
BitmapViewObjectCanvas ();
|
|
|
|
/**
|
|
* @brief Constructor
|
|
*/
|
|
BitmapViewObjectCanvas (unsigned int width, unsigned int height, double resolution, double font_resolution);
|
|
|
|
/**
|
|
* @brief The destructor
|
|
*/
|
|
virtual ~BitmapViewObjectCanvas ();
|
|
|
|
/**
|
|
* @brief CanvasPlane provider
|
|
*
|
|
* This method is used by the view objects to obtain the planes
|
|
* they should paint themselves on.
|
|
* A style can be specified that determines how the plane will
|
|
* be displayed. CanvasPlanes may be shared if the style is identical.
|
|
* The plane index of the ViewOp is not used.
|
|
*/
|
|
virtual lay::CanvasPlane *plane (const lay::ViewOp &style);
|
|
|
|
/**
|
|
* @brief CanvasPlane provider for a sequence of operations on the same plane
|
|
*
|
|
* This method is used by the view objects to obtain the planes
|
|
* they should paint themselves on.
|
|
* A operator vector can be specified that determines how the plane will
|
|
* be displayed. The operators are executed in the order given on the same plane.
|
|
* CanvasPlanes may be shared if the styles are identical.
|
|
* The plane index of the ViewOp is not used.
|
|
*/
|
|
virtual lay::CanvasPlane *plane (const std::vector<lay::ViewOp> &style);
|
|
|
|
/**
|
|
* @brief Sort the planes in the painting order
|
|
*/
|
|
virtual void sort_planes ();
|
|
|
|
/**
|
|
* @brief Provide the renderer
|
|
*/
|
|
virtual lay::Renderer &renderer ()
|
|
{
|
|
return m_renderer;
|
|
}
|
|
|
|
/**
|
|
* @brief Get the resolution
|
|
*/
|
|
virtual double resolution () const
|
|
{
|
|
return m_resolution;
|
|
}
|
|
|
|
/**
|
|
* @brief Get the font resolution
|
|
*/
|
|
virtual double font_resolution () const
|
|
{
|
|
return m_font_resolution;
|
|
}
|
|
|
|
/**
|
|
* @brief Return the number of bitmaps stored so far
|
|
*/
|
|
size_t fg_bitmaps () const
|
|
{
|
|
return mp_fg_bitmaps.size ();
|
|
}
|
|
|
|
/**
|
|
* @brief Return the foreground bitmap with the given index
|
|
*
|
|
* The returned pointer may be 0. The index must be less than the one returned
|
|
* by fg_bitmaps ().
|
|
*/
|
|
const lay::Bitmap *fg_bitmap (unsigned int i) const
|
|
{
|
|
return mp_fg_bitmaps [i];
|
|
}
|
|
|
|
/**
|
|
* @brief Direct access to the bitmap pointers
|
|
*/
|
|
|
|
const std::vector <lay::Bitmap *> &fg_bitmap_vector () const
|
|
{
|
|
return mp_fg_bitmaps;
|
|
}
|
|
|
|
/**
|
|
* @brief Return the foreground plane style with the given index
|
|
*
|
|
* The index must be less than the one returned by fg_planes ().
|
|
*/
|
|
const lay::ViewOp &fg_style (unsigned int i) const
|
|
{
|
|
return m_fg_view_ops [i];
|
|
}
|
|
|
|
/**
|
|
* @brief Direct access to the styles vector
|
|
*/
|
|
const std::vector <lay::ViewOp> &fg_view_op_vector () const
|
|
{
|
|
return m_fg_view_ops;
|
|
}
|
|
|
|
/**
|
|
* @brief Clear the foreground bitmaps and all associated information
|
|
*/
|
|
void clear_fg_bitmaps ();
|
|
|
|
/**
|
|
* @brief Set the width and height and resolution
|
|
*/
|
|
void set_size (unsigned int width, unsigned int height, double resolution, double font_resolution);
|
|
|
|
/**
|
|
* @brief Set the width and height
|
|
*/
|
|
void set_size (unsigned int width, unsigned int height);
|
|
|
|
/**
|
|
* @brief Set the resolution
|
|
*/
|
|
void set_size (double resolution, double font_resolution);
|
|
|
|
/**
|
|
* @brief Get the width
|
|
*/
|
|
unsigned int canvas_width () const
|
|
{
|
|
return m_width;
|
|
}
|
|
|
|
/**
|
|
* @brief Get the height
|
|
*/
|
|
unsigned int canvas_height () const
|
|
{
|
|
return m_height;
|
|
}
|
|
|
|
/**
|
|
* @brief Gets the pixel buffer that background objects render to
|
|
*/
|
|
virtual tl::PixelBuffer *bg_image ();
|
|
|
|
/**
|
|
* @brief Gets the monochrome pixel buffer that background objects render to
|
|
*/
|
|
virtual tl::BitmapBuffer *bg_bitmap ();
|
|
|
|
private:
|
|
std::map <lay::ViewOp, unsigned int> m_fg_bitmap_table;
|
|
std::map <std::vector <lay::ViewOp>, unsigned int> m_fgv_bitmap_table;
|
|
std::vector <lay::Bitmap *> mp_fg_bitmaps;
|
|
std::vector <lay::Bitmap *> mp_alloc_bitmaps;
|
|
std::vector <lay::ViewOp> m_fg_view_ops;
|
|
lay::BitmapRenderer m_renderer;
|
|
unsigned int m_width, m_height;
|
|
double m_resolution;
|
|
double m_font_resolution;
|
|
};
|
|
|
|
} // namespace lay
|
|
|
|
#endif
|
|
|