From 2298a9a5c8322f0ba153e567d8d05748e49d074d Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Fri, 29 Apr 2022 23:40:07 +0200 Subject: [PATCH] WIP --- src/laybasic/laybasic/layCellView.h | 10 +- src/laybasic/laybasic/layDispatcher.cc | 27 +- src/laybasic/laybasic/layDispatcher.h | 26 +- src/laybasic/laybasic/layLayerProperties.cc | 30 +- src/laybasic/laybasic/layLayerProperties.h | 22 +- src/laybasic/laybasic/layLayoutCanvas.h | 30 +- src/laybasic/laybasic/layLayoutView.h | 2935 ++------- src/laybasic/laybasic/layLayoutViewBase.cc | 5487 +++++++++++++++++ src/laybasic/laybasic/layLayoutViewBase.h | 2566 ++++++++ src/laybasic/laybasic/layMouseTracker.h | 6 +- src/laybasic/laybasic/layMove.h | 16 +- src/laybasic/laybasic/layParsedLayerSource.cc | 4 +- src/laybasic/laybasic/layParsedLayerSource.h | 4 +- src/laybasic/laybasic/layPlugin.h | 10 +- src/laybasic/laybasic/laySelector.h | 24 +- src/laybasic/laybasic/layZoomBox.h | 6 +- src/laybasic/laybasic/laybasic.pro | 2 + 17 files changed, 8501 insertions(+), 2704 deletions(-) create mode 100644 src/laybasic/laybasic/layLayoutViewBase.cc create mode 100644 src/laybasic/laybasic/layLayoutViewBase.h diff --git a/src/laybasic/laybasic/layCellView.h b/src/laybasic/laybasic/layCellView.h index 99c6c18d3..4fc1e98b4 100644 --- a/src/laybasic/laybasic/layCellView.h +++ b/src/laybasic/laybasic/layCellView.h @@ -46,7 +46,7 @@ namespace lay { -class LayoutView; +class LayoutViewBase; /** * @brief A layout handle @@ -581,7 +581,7 @@ public: * @param cv The reference to the target cellview * @param view The reference to the layout view */ - CellViewRef (lay::CellView *cv, lay::LayoutView *view); + CellViewRef (lay::CellView *cv, lay::LayoutViewBase *view); /** * @brief Gets the cellview index of this reference @@ -590,9 +590,9 @@ public: int index () const; /** - * @brief Gets the LayoutView the reference is pointing to + * @brief Gets the LayoutViewBase the reference is pointing to */ - lay::LayoutView *view (); + lay::LayoutViewBase *view (); /** * @brief Equality: Gives true, if the cellviews are identical @@ -749,7 +749,7 @@ public: private: tl::weak_ptr mp_cv; - tl::weak_ptr mp_view; + tl::weak_ptr mp_view; }; } diff --git a/src/laybasic/laybasic/layDispatcher.cc b/src/laybasic/laybasic/layDispatcher.cc index dce1ec93b..809d25a56 100644 --- a/src/laybasic/laybasic/layDispatcher.cc +++ b/src/laybasic/laybasic/layDispatcher.cc @@ -73,21 +73,6 @@ Dispatcher::Dispatcher (DispatcherDelegate *delegate, Plugin *parent, bool stand } } -#if defined(HAVE_QT) -Dispatcher::Dispatcher (QWidget *menu_parent_widget, DispatcherDelegate *delegate, Plugin *parent, bool standalone) - : Plugin (parent, standalone), - mp_menu_parent_widget (menu_parent_widget), - mp_delegate (delegate) -{ - if (mp_menu_parent_widget) { - mp_menu.reset (new lay::AbstractMenu (this)); - } - if (! parent && ! ms_dispatcher_instance) { - ms_dispatcher_instance = this; - } -} -#endif - Dispatcher::~Dispatcher () { if (ms_dispatcher_instance == this) { @@ -95,6 +80,18 @@ Dispatcher::~Dispatcher () } } +#if defined(HAVE_QT) +void Dispatcher::set_menu_parent_widget (QWidget *menu_parent_widget) +{ + mp_menu_parent_widget = menu_parent_widget; + if (mp_menu_parent_widget) { + mp_menu.reset (new lay::AbstractMenu (this)); + } else { + mp_menu.reset (0); + } +} +#endif + bool Dispatcher::configure (const std::string &name, const std::string &value) { diff --git a/src/laybasic/laybasic/layDispatcher.h b/src/laybasic/laybasic/layDispatcher.h index 703b4eec0..05acda580 100644 --- a/src/laybasic/laybasic/layDispatcher.h +++ b/src/laybasic/laybasic/layDispatcher.h @@ -121,17 +121,6 @@ public: */ Dispatcher (Plugin *parent = 0, bool standalone = false); -#if defined(HAVE_QT) - /** - * @brief The constructor - * - * @param menu_parent_widget If not 0, indicates that this is a GUI mode dispatcher providing an abstract menu - * @param parent Usually 0, but a dispatcher may have parents. In this case, the dispatcher is not the actual dispatcher, but the real plugin chain's root is. - * @param standalone The standalone flag passed to the plugin constructor. - */ - Dispatcher (QWidget *menu_parent_widget, Plugin *parent = 0, bool standalone = false); -#endif - /** * @brief The root constructor * @@ -139,16 +128,6 @@ public: */ Dispatcher (DispatcherDelegate *delegate, Plugin *parent = 0, bool standalone = false); -#if defined(HAVE_QT) - /** - * @brief The root constructor - * - * @param menu_parent_widget If not 0, indicates that this is a GUI mode dispatcher providing an abstract menu - * @param delegate The notification receiver for dispatcher events - */ - Dispatcher (QWidget *menu_parent_widget, DispatcherDelegate *delegate, Plugin *parent = 0, bool standalone = false); -#endif - /** * @brief Destructor */ @@ -233,6 +212,11 @@ public: return mp_menu_parent_widget; } + /** + * @brief Sets the parent widget + */ + void set_menu_parent_widget (QWidget *pw); + /** * @brief Returns true, if the dispatcher supplies a user interface */ diff --git a/src/laybasic/laybasic/layLayerProperties.cc b/src/laybasic/laybasic/layLayerProperties.cc index d24c08a62..a6cdd3726 100644 --- a/src/laybasic/laybasic/layLayerProperties.cc +++ b/src/laybasic/laybasic/layLayerProperties.cc @@ -22,7 +22,7 @@ #include "layLayerProperties.h" -#include "layLayoutView.h" +#include "layLayoutViewBase.h" #include "layConverters.h" #include "tlXMLParser.h" #include "tlException.h" @@ -404,7 +404,7 @@ class LayerSourceEval : public tl::Eval { public: - LayerSourceEval (const lay::LayerProperties &lp, const lay::LayoutView *view, bool real) + LayerSourceEval (const lay::LayerProperties &lp, const lay::LayoutViewBase *view, bool real) : m_lp (lp), mp_view (view), m_real (real) { // .. nothing yet .. @@ -415,14 +415,14 @@ public: return m_lp.source (m_real); } - const lay::LayoutView *view () const + const lay::LayoutViewBase *view () const { return mp_view; } private: const lay::LayerProperties &m_lp; - const lay::LayoutView *mp_view; + const lay::LayoutViewBase *mp_view; bool m_real; }; @@ -480,7 +480,7 @@ private: }; std::string -LayerProperties::display_string (const lay::LayoutView *view, bool real, bool always_show_source) const +LayerProperties::display_string (const lay::LayoutViewBase *view, bool real, bool always_show_source) const { refresh (); @@ -592,7 +592,7 @@ LayerProperties::need_realize (unsigned int flags, bool /*force*/) } void -LayerProperties::do_realize (const LayoutView *view) const +LayerProperties::do_realize (const LayoutViewBase *view) const { m_layer_index = -1; m_cellview_index = -1; @@ -712,10 +712,10 @@ LayerPropertiesNode::operator== (const LayerPropertiesNode &d) const return m_children == d.m_children; } -LayoutView * +LayoutViewBase * LayerPropertiesNode::view () const { - return const_cast (mp_view.get ()); + return const_cast (mp_view.get ()); } unsigned int @@ -804,7 +804,7 @@ LayerPropertiesNode::bbox () const } void -LayerPropertiesNode::attach_view (LayoutView *view, unsigned int list_index) +LayerPropertiesNode::attach_view (LayoutViewBase *view, unsigned int list_index) { mp_view.reset (view); m_list_index = list_index; @@ -1335,7 +1335,7 @@ static LayerPropertiesNode expand_wildcard_layout (const LayerPropertiesNode &so } static std::vector -expand_wildcard_layers (const LayerPropertiesNode &lp, const LayerPropertiesList ¤t_props, lay::LayoutView *view, unsigned int list_index) +expand_wildcard_layers (const LayerPropertiesNode &lp, const LayerPropertiesList ¤t_props, lay::LayoutViewBase *view, unsigned int list_index) { std::vector new_props; @@ -1651,7 +1651,7 @@ struct UIntColorConverter if (c == 0) { return ""; } else { - return ColorConverter::to_string (QColor (c & 0xffffff)); + return ColorConverter::to_string (lay::Color (c | 0xff000000)); } } @@ -1660,7 +1660,7 @@ struct UIntColorConverter if (s.empty ()) { c = 0; } else { - QColor qc; + lay::Color qc; ColorConverter::from_string (s, qc); c = qc.rgb () | 0xff000000; } @@ -1858,7 +1858,7 @@ LayerPropertiesList::save (tl::OutputStream &os, const std::vector (mp_view.get ()); + return const_cast (mp_view.get ()); } unsigned int diff --git a/src/laybasic/laybasic/layLayerProperties.h b/src/laybasic/laybasic/layLayerProperties.h index 6f9c6d760..3df52ade7 100644 --- a/src/laybasic/laybasic/layLayerProperties.h +++ b/src/laybasic/laybasic/layLayerProperties.h @@ -48,7 +48,7 @@ namespace tl { namespace lay { -class LayoutView; +class LayoutViewBase; class LayerPropertiesList; class LayerPropertiesNode; @@ -700,7 +700,7 @@ public: * If it is set to false, the view's always_show_source attribute with determine whether the source is * shown. */ - std::string display_string (const lay::LayoutView *view, bool real, bool always_with_source = false) const; + std::string display_string (const lay::LayoutViewBase *view, bool real, bool always_with_source = false) const; /** * @brief The source specification @@ -717,7 +717,7 @@ public: * * This method may throw an exception if the specification * is not valid. In order to make the layer usable, the properties - * object must be "realized" with respect to a LayoutView object. + * object must be "realized" with respect to a LayoutViewBase object. */ void set_source (const std::string &s); @@ -725,7 +725,7 @@ public: * @brief Load the source specification * * In order to make the layer usable, the properties - * object must be "realized" with respect to a LayoutView object. + * object must be "realized" with respect to a LayoutViewBase object. */ void set_source (const lay::ParsedLayerSource &s); @@ -887,7 +887,7 @@ protected: * * @param view The view the properties refer to or 0 if there is no view. */ - void do_realize (const LayoutView *view) const; + void do_realize (const LayoutViewBase *view) const; /** * @brief Tell, if a realize of the visual properties is needed @@ -1172,12 +1172,12 @@ public: * compute the actual property selection set. * This method is supposed to be */ - void attach_view (LayoutView *view, unsigned int list_index); + void attach_view (LayoutViewBase *view, unsigned int list_index); /** * @brief Gets the layout view the node lives in */ - LayoutView *view () const; + LayoutViewBase *view () const; /** * @brief Gets the index of the layer properties list that node lives in @@ -1214,7 +1214,7 @@ protected: private: // A reference to the view - tl::weak_ptr mp_view; + tl::weak_ptr mp_view; unsigned int m_list_index; // the parent node tl::weak_ptr mp_parent; @@ -1912,12 +1912,12 @@ public: * "load" automatically attaches the view. * This method has the side effect of recomputing the layer source parameters. */ - void attach_view (lay::LayoutView *view, unsigned int list_index); + void attach_view (lay::LayoutViewBase *view, unsigned int list_index); /** * @brief Gets the layout view this list is attached to */ - lay::LayoutView *view () const; + lay::LayoutViewBase *view () const; /** * @brief Gets the layout list @@ -1925,7 +1925,7 @@ public: unsigned int list_index () const; private: - tl::weak_ptr mp_view; + tl::weak_ptr mp_view; unsigned int m_list_index; layer_list m_layer_properties; lay::DitherPattern m_dither_pattern; diff --git a/src/laybasic/laybasic/layLayoutCanvas.h b/src/laybasic/laybasic/layLayoutCanvas.h index aa4d9e624..de403bc88 100644 --- a/src/laybasic/laybasic/layLayoutCanvas.h +++ b/src/laybasic/laybasic/layLayoutCanvas.h @@ -47,7 +47,7 @@ namespace lay { -class LayoutView; +class LayoutViewBase; class RedrawThread; /** @@ -138,10 +138,16 @@ class LayoutCanvas public lay::BitmapRedrawThreadCanvas, public lay::Drawings { +#if defined(HAVE_QT) Q_OBJECT +#endif public: - LayoutCanvas (QWidget *parent, lay::LayoutView *view, const char *name = "canvas"); +#if defined(HAVE_QT) + LayoutCanvas (QWidget *parent, lay::LayoutViewBase *view, const char *name = "canvas"); +#else + LayoutCanvas (lay::LayoutViewBase *view, const char *name = "canvas"); +#endif ~LayoutCanvas (); void set_colors (lay::Color background, lay::Color foreground, lay::Color active); @@ -341,18 +347,18 @@ public: */ tl::Event viewport_changed_event; -signals: - void left_arrow_key_pressed (); - void up_arrow_key_pressed (); - void right_arrow_key_pressed (); - void down_arrow_key_pressed (); - void left_arrow_key_pressed_with_shift (); - void up_arrow_key_pressed_with_shift (); - void right_arrow_key_pressed_with_shift (); - void down_arrow_key_pressed_with_shift (); + // key events + tl::Event left_arrow_key_pressed; + tl::Event up_arrow_key_pressed; + tl::Event right_arrow_key_pressed; + tl::Event down_arrow_key_pressed; + tl::Event left_arrow_key_pressed_with_shift; + tl::Event up_arrow_key_pressed_with_shift; + tl::Event right_arrow_key_pressed_with_shift; + tl::Event down_arrow_key_pressed_with_shift; private: - lay::LayoutView *mp_view; + lay::LayoutViewBase *mp_view; QImage *mp_image; QImage *mp_image_bg; QPixmap *mp_pixmap; diff --git a/src/laybasic/laybasic/layLayoutView.h b/src/laybasic/laybasic/layLayoutView.h index 17e4d20b5..a8ad43acf 100644 --- a/src/laybasic/laybasic/layLayoutView.h +++ b/src/laybasic/laybasic/layLayoutView.h @@ -36,6 +36,7 @@ #include #include +#include "layLayoutViewBase.h" #include "layLayerProperties.h" #include "layAbstractMenu.h" #include "layAnnotationShapes.h" @@ -85,71 +86,6 @@ class ColorButton; class ConfigureAction; class EditorOptionsPages; -/** - * @brief Stores a layer reference to create layers which have been added by some action - * - * This object is delivered by LayoutView::layer_snapshot and can be used in add_missing_layers - * to create new layer views for layers which have been created between layer_snapshot and - * add_missing_layers. - */ -struct LayerState -{ - /** - * @brief Constructor - */ - LayerState () { } - - std::set present; -}; - -/** - * @brief A layer display properties structure - * - * The layer properties encapsulate the settings relevant for - * the display of a layer. - * - * "brightness" is a index that indicates how much to make the - * color brighter to darker rendering the effective color - * (eff_frame_color (), eff_fill_color ()). It's value is roughly between - * -255 and 255. - */ -struct LAYBASIC_PUBLIC LayerDisplayProperties -{ - LayerDisplayProperties (); - - bool operator== (const LayerDisplayProperties &d); - bool operator!= (const LayerDisplayProperties &d); - - /** - * @brief render the effective frame color - * - * The effective frame color is computed from the frame color brightness and the - * frame color. - */ - color_t eff_frame_color () const; - - /** - * @brief render the effective frame color - * - * The effective frame color is computed from the frame color brightness and the - * frame color. - */ - color_t eff_fill_color () const; - - // display styles - color_t frame_color; - color_t fill_color; - int frame_brightness; - int fill_brightness; - unsigned int dither_pattern; - bool visible; - bool transparent; - int width; - bool marked; - int animation; - std::string name; -}; - /** * @brief The layout view object * @@ -158,39 +94,11 @@ struct LAYBASIC_PUBLIC LayerDisplayProperties * It manages the layer display list, bookmark list etc. */ class LAYBASIC_PUBLIC LayoutView - : public QFrame, - public lay::Editables, - public lay::Dispatcher + : public LayoutViewBase { Q_OBJECT public: - typedef lay::CellView::unspecific_cell_path_type cell_path_type; - typedef lay::CellView::cell_index_type cell_index_type; - typedef std::pair bookmark_type; - - /** - * @brief Define some options for the view - */ - enum options_type { - LV_Normal = 0, - LV_NoLayers = 1, - LV_NoHierarchyPanel = 2, - LV_NoLibrariesView = 4, - LV_NoEditorOptionsPanel = 8, - LV_NoBookmarksView = 16, - LV_Naked = 32, - LV_NoZoom = 64, - LV_NoGrid = 128, - LV_NoMove = 256, - LV_NoTracker = 512, - LV_NoSelection = 1024, - LV_NoPlugins = 2048, - LV_NoServices = LV_NoMove + LV_NoTracker + LV_NoSelection + LV_NoPlugins - }; - - enum drop_small_cells_cond_type { DSC_Max = 0, DSC_Min = 1, DSC_Sum = 2 }; - /** * @brief Constructor */ @@ -201,11 +109,6 @@ public: */ LayoutView (lay::LayoutView *source, db::Manager *mgr, bool editable, lay::Plugin *plugin_parent, QWidget *parent = 0, const char *name = "view", unsigned int options = (unsigned int) LV_Normal); - /** - * @brief Destructor - */ - ~LayoutView (); - /** * @brief Makes this view the current one */ @@ -216,20 +119,188 @@ public: * * The argument can be 0 which means there is no current view. */ - static void set_current (LayoutView *); + static void set_current (LayoutViewBase *); /** * @brief Gets the current view */ - static LayoutView *current (); + static LayoutViewBase *current (); /** - * @brief Determine if there is something to copy - * - * This reimplementation of the lay::Editables interface additionally - * looks for content providers in the tree views for example. + * @brief Gets the window title of the view */ - bool has_selection (); + std::string title () const; + + /** + * @brief Sets the window title to an explicit string + */ + void set_title (const std::string &t); + + /** + * @brief Resets the explicit title and enable the automatic naming + */ + void reset_title (); + + /** + * @brief Sets the currently active layer by layer properties and cell view index + * + * If the layer does not exist, the user will be asked whether to create the layer. + * Returns false if the layer is not a valid one and the user defined to create the layer. + */ + bool set_or_request_current_layer (unsigned int cv_index, const db::LayerProperties &properties); + + /** + * @brief Sets the currently active layer by layer properties and cell view index + * + * This method will look up that layer in the layer view tree and select that layer. + * This method will also select this layer. + * + * Returns false if the layer is not a valid one. + */ + bool set_current_layer (unsigned int cv_index, const db::LayerProperties &properties); + + /** + * @brief Sets the currently active layer + * + * The active layer is the one that is active in the layer + * browser panel. This method will also select this layer. + */ + void set_current_layer (const lay::LayerPropertiesConstIterator &l); + + /** + * @brief Retrieve the index of the currently active layer + * + * The active layer is the one that is active in the layer + * browser panel. + * This method returns a null iterator, if no layer is active. + */ + lay::LayerPropertiesConstIterator current_layer () const; + + /** + * @brief Return the layers that are selected in the layer browser + * + * Returns an empty list if no layer is selected. + */ + std::vector selected_layers () const; + + /** + * @brief Sets the layers that are selected in the layer browser + */ + void set_selected_layers (const std::vector &sel); + + /** + * @brief Get the index of the active cellview (shown in hierarchy browser) + */ + int active_cellview_index () const; + + /** + * @brief Get the index of the active cellview (shown in hierarchy browser) + */ + const lay::CellView &active_cellview () const; + + /** + * @brief Gets a cellview reference to the active cellview + */ + lay::CellViewRef active_cellview_ref (); + + /** + * @brief Select a certain cellview for the active one + */ + void set_active_cellview_index (int index); + + /** + * @brief Cell paths of the selected cells + * + * The current cell is the one highlighted in the browser with the focus rectangle. The + * current path is returned for the cellview given by cv_index. + */ + void selected_cells_paths (int cv_index, std::vector &paths) const; + + /** + * @brief Cell path of the current cell + * + * The current cell is the one highlighted in the browser with the focus rectangle. The + * current path is returned for the cellview given by cv_index. + */ + void current_cell_path (int cv_index, cell_path_type &path) const; + + /** + * @brief Cell path of the current cell + * + * This method version is provided for automation purposes mainly. + */ + cell_path_type get_current_cell_path (int cv_index) const + { + cell_path_type r; + current_cell_path (cv_index, r); + return r; + } + + /** + * @brief Cell path of the current cell in the active cellview + * + * This is a convenience function returning the path for the active cellview. + */ + void current_cell_path (cell_path_type &path) const + { + current_cell_path (active_cellview_index (), path); + } + + /** + * @brief Set the path to the current cell + * + * The current cell is the one highlighted in the browser with the focus rectangle. The + * cell given by the path is highlighted and scrolled into view. + */ + void set_current_cell_path (int cv_index, const cell_path_type &path); + + /** + * @brief Set the path to the current cell is the current cellview + * + * This is a convenience function setting the path for the active cellview. + */ + void set_current_cell_path (const cell_path_type &path) + { + set_current_cell_path (active_cellview_index (), path); + } + + /** + * @brief Bookmark the current view under the given name + */ + void bookmark_view (const std::string &name); + + /** + * @brief Asks for a bookmark name and bookmark the current view under this name + */ + void bookmark_current_view (); + + /** + * @brief Show the bookmark management form + */ + void manage_bookmarks (); + + /** + * @brief Obtain the bookmarks list + */ + const BookmarkList &bookmarks () const + { + return m_bookmarks; + } + + /** + * @brief Set the bookmarks list + */ + void bookmarks (const BookmarkList &b); + + /** + * @brief Open the RDB browser for a given database and associated cv index + */ + void open_rdb_browser (int rdb_index, int cv_index); + + /** + * @brief Open the L2NDB browser for a given database and associated cv index + */ + void open_l2ndb_browser (int l2ndb_index, int cv_index); /** * @brief Gets the container with the layer control panel @@ -288,407 +359,9 @@ public: } /** - * @brief Gets the editor options pages widget + * @brief Deliver a size hint (reimplementation of QWidget) */ - lay::EditorOptionsPages *editor_options_pages (); - - /** - * @brief Pastes from clipboard - * - * This reimplementation of the lay::Editables interface additionally - * looks for paste receivers in the tree views for example. - */ - void paste (); - - /** - * @brief Pastes from clipboard and initiates a move - */ - void paste_interactive (); - - /** - * @brief Copies to clipboard - * - * This reimplementation of the lay::Editables interface additionally - * looks for copy providers in the tree views for example. - */ - void copy (); - - /** - * @brief Cuts to clipboard - * - * This reimplementation of the lay::Editables interface additionally - * looks for cut & copy providers in the tree views for example. - */ - void cut (); - - /** - * @brief Gets the explicit title string of the view - * - * This is the one explicitly set, not the one displayed. The displayed text is composed of internal information - * if no title string is set. - */ - const std::string &title_string () const - { - return m_title; - } - - /** - * @brief Gets the window title of the view - */ - std::string title () const; - - /** - * @brief Sets the window title to an explicit string - */ - void set_title (const std::string &t); - - /** - * @brief Resets the explicit title and enable the automatic naming - */ - void reset_title (); - - /** - * @brief The "dirty" flag indicates that one of the layout has been modified - * - * A signal is provided on a change of this flag (dirty_changed). - */ - bool is_dirty () const; - - /** - * @brief Fill the layer properties for a new layer - * - * The layer's source must be set already to allow computing of the initial color. - * It is assumed that the layer is appended at the end of the layer list. This - * is important to set the dither pattern index accordingly. - */ - void init_layer_properties (LayerProperties &props) const; - - /** - * @brief Create a set of new layers for the given layers of the given cellview - */ - void add_new_layers (const std::vector &layer_ids, int cv_index); - - /** - * @brief Set the layer properties of a layer with the given position (by iterator) for the current layer list - * - * @param iter Points to the layer to be replaced - * @param props The properties to replace the current properties - */ - void set_properties (const LayerPropertiesConstIterator &iter, const LayerProperties &props) - { - set_properties (current_layer_list (), iter, props); - } - - /** - * @brief Set the layer properties of a layer with the given position (by iterator) for the layer list with the given index - * - * @param index The layer list's index - * @param iter Points to the layer to be replaced - * @param props The properties to replace the current properties - */ - void set_properties (unsigned int index, const LayerPropertiesConstIterator &iter, const LayerProperties &props); - - /** - * @brief Expand the layer properties of all tabs - * - * This method will replace the wildcard specifications in the layer properties of all - * tabs. All unspecific cv index specifications will be expanded to all cellviews, all - * layer and datatype specs will be expanded into all available (remaining) specs. - */ - void expand_properties (); - - /** - * @brief Expand the layer properties for the given tab - * - * @param index The index of the tab to which to apply the expansion to. - */ - void expand_properties (unsigned int index); - - /** - * @brief Expand the layer properties of all tabs with some options - * - * @param map_cv_index Maps a specified cv index to the one to use. Use -1 for the first entry to map any present cv index. Map to -1 to specify expansion to all available cv indices. - * @param add_default Set this parameter to true to implicitly add an entry for all "missing" layers. - */ - void expand_properties (const std::map &map_cv_index, bool add_default); - - /** - * @brief Expand the layer properties of the specified tab with some options - * - * @param index The index of the tab to which to apply the expansion to. - * @param map_cv_index Maps a specified cv index to the one to use. Use -1 for the first entry to map any present cv index. Map to -1 to specify expansion to all available cv indices. - * @param add_default Set this parameter to true to implicitly add an entry for all "missing" layers. - */ - void expand_properties (unsigned int index, const std::map &map_cv_index, bool add_default); - - /** - * @brief Replace the layer node with a new one for the current layer list - */ - void replace_layer_node (const LayerPropertiesConstIterator &iter, const LayerPropertiesNode &props) - { - replace_layer_node (current_layer_list (), iter, props); - } - - /** - * @brief Replace the layer node with a new one for the layer list with the given index - */ - void replace_layer_node (unsigned int index, const LayerPropertiesConstIterator &iter, const LayerPropertiesNode &props); - - /** - * @brief Insert the given layer properties node into the list for the current layer list - * - * This method returns a reference to the element created. - */ - const LayerPropertiesNode &insert_layer (const LayerPropertiesConstIterator &iter, const LayerPropertiesNode &props) - { - return insert_layer (current_layer_list (), iter, props); - } - - /** - * @brief Insert the given layer properties node into the list before the given index - * - * This method returns a reference to the element created. - */ - const LayerPropertiesNode &insert_layer (unsigned int index, const LayerPropertiesConstIterator &iter, const LayerPropertiesNode &props); - - /** - * @brief Delete the layer properties node for the current layer list - * - * This method deletes the object that the iterator points to and invalidates - * the iterator since the object that the iterator points to is no longer valid. - */ - void delete_layer (LayerPropertiesConstIterator &iter) - { - delete_layer (current_layer_list (), iter); - } - - /** - * @brief Delete the layer properties node for the layer list with the given index - * - * This method deletes the object that the iterator points to and invalidates - * the iterator since the object that the iterator points to is no longer valid. - */ - void delete_layer (unsigned int index, LayerPropertiesConstIterator &iter); - - /** - * @brief Begin iterator for the layers - * - * This iterator delivers recursively the layers of this view - */ - LayerPropertiesConstIterator begin_layers () const - { - return get_properties ().begin_const_recursive (); - } - - /** - * @brief End iterator for the layers - */ - LayerPropertiesConstIterator end_layers () const - { - return get_properties ().end_const_recursive (); - } - - /** - * @brief Begin iterator for the layers for a given list - * - * This iterator delivers recursively the layers of this view - */ - LayerPropertiesConstIterator begin_layers (unsigned int index) const - { - return get_properties (index).begin_const_recursive (); - } - - /** - * @brief End iterator for the layers for a given list - */ - LayerPropertiesConstIterator end_layers (unsigned int index) const - { - return get_properties (index).end_const_recursive (); - } - - /** - * @brief Replace the current layer properties list - */ - void set_properties (const LayerPropertiesList &list) - { - set_properties (current_layer_list (), list); - } - - /** - * @brief Rename a layer properties list - */ - void rename_properties (unsigned int index, const std::string &new_name); - - /** - * @brief Replace the specified layer properties list - */ - void set_properties (unsigned int index, const LayerPropertiesList &list); - - /** - * @brief Clear the given layer view list - */ - void clear_layers (unsigned int index) - { - set_properties (index, LayerPropertiesList ()); - } - - /** - * @brief Clear the current layer view list - */ - void clear_layers () - { - set_properties (LayerPropertiesList ()); - } - - /** - * @brief Access the current layer properties list - */ - const LayerPropertiesList &get_properties () const - { - return get_properties (current_layer_list ()); - } - - /** - * @brief Access the specified layer properties list - */ - const LayerPropertiesList &get_properties (unsigned int index) const; - - /** - * @brief Get the number of lists present in this view - */ - unsigned int layer_lists () const - { - return (unsigned int) m_layer_properties_lists.size (); - } - - /** - * @brief Get the index of the current properties list - */ - unsigned int current_layer_list () const - { - return m_current_layer_list; - } - - /** - * @brief Set the index of the current properties list - */ - void set_current_layer_list (unsigned int index); - - /** - * @brief Delete the specified layer properties list - */ - void delete_layer_list (unsigned int index); - - /** - * @brief Insert the layer properties list at the given index and make it the current list. - */ - void insert_layer_list (unsigned int index, const LayerPropertiesList &props); - - /** - * @brief Insert the layer properties list at the given index and make it the current list. - */ - void insert_layer_list (unsigned int index) - { - insert_layer_list (index, LayerPropertiesList ()); - } - - /** - * @brief Set the custom dither pattern - */ - void set_dither_pattern (const DitherPattern &pattern); - - /** - * @brief Obtain the custom dither pattern - */ - const DitherPattern &dither_pattern () const - { - return mp_canvas->dither_pattern (); - } - - /** - * @brief Set the custom line styles - */ - void set_line_styles (const LineStyles &styles); - - /** - * @brief Obtain the custom line styles - */ - const LineStyles &line_styles () const - { - return mp_canvas->line_styles (); - } - - /** - * @brief An event signalling the change in the number of hierarchy levels shown - */ - tl::Event hier_levels_changed_event; - - /** - * @brief An event signalling a change in the annotations shape list - * - * If annotation shapes are added or removed, this event is triggered. - */ - tl::Event annotations_changed_event; - - /** - * @brief An event signalling a change in the hierarchy of the layouts - * - * If the hierarchy of a layout is changed, this event is triggered. - * This may happen due to the removal or insertion of cells or instances. - */ - tl::Event hier_changed_event; - - /** - * @brief An event signalling a change in the geometries of the layouts - * - * If something on the geometries of a cell in one the layouts changes, this - * event is triggered. This may happed due to the removal or insertion of shapes or cell instances. - * In general, this indicates the need for redrawing of the layout for example. - */ - tl::Event geom_changed_event; - - /** - * @brief An event triggered before something on a cellview is changed - * - * This event is triggered before something on the cellview (i.e. the current cell of - * of set of the cellview) is changed. The argument is the index of the cell view to be - * changed. - * This event is followed by a corresponding cellview_changed event after the cellview - * has changed. - */ - tl::event cellview_about_to_change_event; - - /** - * @brief An event triggered before something on the cellviews is changed - * - * This event is triggered before something on the cellviews is changed, i.e. a cellview is deleted or inserted. - * Each of these events is followed by a cellviews_changed event after the change has been made. - */ - tl::Event cellviews_about_to_change_event; - - /** - * @brief An event signalling that the cell views have changed. - * - * When a cellview is added or removed, this event is triggered after the change has been made. - * The corresponding event that is triggered before the change is made is cellviews_about_to_change_event. - */ - tl::Event cellviews_changed_event; - - /** - * @brief An event signalling a change in a cellview. - * - * If a cellview is changed (i.e. the cell is changed) this event is triggered. - * The integer argument will receive the index of the cellview that has changed. - * The corresponding event that is triggered before the change is made is cellview_about_to_change_event. - */ - tl::event cellview_changed_event; - - /** - * @brief An event signalling that a file has been loaded. - * - * If a new file is loaded, this event is triggered. - */ - tl::Event file_open_event; + QSize sizeHint () const; /** * @brief An event signalling that the view is going to close @@ -705,1932 +378,86 @@ public: */ tl::Event hide_event; - /** - * @brief An event signalling that the viewport has changed. - * - * If the viewport (the rectangle that is shown) changes, this event - * is triggered. - */ - tl::Event viewport_changed_event; - - /** - * @brief This event is triggered if the background color changed - */ - tl::Event background_color_changed_event; - - /** - * @brief An event signalling that the layer list has changed. - * - * If the layer list changes, this event is triggered with an integer argument. - * The arguments's bit 0 is set, if the properties have changed. If the arguments bit 1 is - * set, the hierarchy has changed. If the name of layer properties is changed, bit 2 is - * set. - */ - tl::event layer_list_changed_event; - - /** - * @brief An event signalling that a layer list was deleted. - * - * If a layer list is deleted from the layer list set, the event is triggered with - * the index of the deleted list as an integer parameter. - */ - tl::event layer_list_deleted_event; - - /** - * @brief An event signalling that a layer list was inserted. - * - * If a layer list is inserted into the layer list set, the event is triggered with - * the index of the new list as an integer parameter. - */ - tl::event layer_list_inserted_event; - - /** - * @brief An event signalling that the current layer list has changed. - * - * If the current layer list is changed, this event is triggered. - */ - tl::event current_layer_list_changed_event; - - /** - * @brief An event signalling that the current layer has changed - */ - tl::event current_layer_changed_event; - - - /** - * @brief An event signalling that the visibility of some cells has changed - */ - tl::Event cell_visibility_changed_event; - - /** - * @brief An event triggered if the active cellview changes - * This event is triggered after the active cellview changed. - */ - tl::Event active_cellview_changed_event; - - /** - * @brief An event triggered if the active cellview changes - * This event is triggered after the active cellview changed. The integer parameter is the index of the - * new cellview. - */ - tl::event active_cellview_changed_with_index_event; - - /** - * @brief Sets the currently active layer by layer properties and cell view index - * - * This method will look up that layer in the layer view tree and select that layer. - * This method will also select this layer. - * - * Returns false if the layer is not a valid one. - */ - bool set_current_layer (unsigned int cv_index, const db::LayerProperties &properties); - - /** - * @brief Sets the currently active layer by layer properties and cell view index - * - * If the layer does not exist, the user will be asked whether to create the layer. - * Returns false if the layer is not a valid one and the user defined to create the layer. - */ - bool set_or_request_current_layer (unsigned int cv_index, const db::LayerProperties &properties); - - /** - * @brief Sets the currently active layer - * - * The active layer is the one that is active in the layer - * browser panel. This method will also select this layer. - */ - void set_current_layer (const lay::LayerPropertiesConstIterator &l); - - /** - * @brief Retrieve the index of the currently active layer - * - * The active layer is the one that is active in the layer - * browser panel. - * This method returns a null iterator, if no layer is active. - */ - lay::LayerPropertiesConstIterator current_layer () const; - - /** - * @brief Return the layers that are selected in the layer browser - * - * Returns an empty list if no layer is selected. - */ - std::vector selected_layers () const; - - /** - * @brief Sets the layers that are selected in the layer browser - */ - void set_selected_layers (const std::vector &sel); - - /** - * @brief Save the given cellview into the given file (with options) - * If "update" is true, the cell view's properties will be updated (options, filename etc.). - */ - void save_as (unsigned int index, const std::string &filename, tl::OutputStream::OutputStreamMode om, const db::SaveLayoutOptions &options, bool update, int keep_backups); - - /** - * @brief Implementation of the undo operations - */ - virtual void undo (db::Op *op); - - /** - * @brief Implementation of the redo operations - */ - virtual void redo (db::Op *op); - - /** - * @brief Set the cellview at the given index - * - * If cvindex is used as the cellview index to associate the - * layout with. As a side effect, this method will emit a - * title_changed signal, which means that the cellview passed - * should be correctly named before to reflect the correct - * title if no explicit title is set. - */ - void set_layout (const lay::CellView &cv, unsigned int cvindex); - - /** - * @brief clear the cellviews - */ - void clear_cellviews (); - - /** - * @brief erase one cellview with the given index - */ - void erase_cellview (unsigned int index); - - /** - * @brief Save the layer properties - */ - void save_layer_props (const std::string &fn); - - /** - * @brief Load the layer properties - * - * @param fn The file to load. - */ - void load_layer_props (const std::string &fn); - - /** - * @brief Load the layer properties - * - * @param fn The file to load - * - * This version allows one to specify whether defaults should be used for all other layers by - * setting add_default to true - */ - void load_layer_props (const std::string &fn, bool add_default); - - /** - * @brief Load the layer properties - * - * @param fn The file to load - * - * This version allows one to specify whether defaults should be used for all other layers by - * setting add_default to true. In addition, this version will apply the .lyp definitions - * to a specific cellview after removing all definitions for this one. If cv_index is set - * to -1, the .lyp file will be applied to each cellview. In any case, the cv index specs - * in the .lyp file will be overridden. - */ - void load_layer_props (const std::string &fn, int cv_index, bool add_default); - - /** - * @brief Save the screen content to a file - */ - void save_screenshot (const std::string &fn); - - /** - * @brief Get the screen content as a QImage object - */ - QImage get_screenshot (); - - /** - * @brief Save an image file with the given width and height - */ - void save_image (const std::string &fn, unsigned int width, unsigned int height); - - /** - * @brief Save an image file with some options - * - * @param fn The path of the file to write - * @param width The width of the image in pixels - * @param height The height of the image - * @param linewidth The width of a line in pixels (usually 1) or 0 for default - * @param oversampling The oversampling factor (1..3) or 0 for default - * @param resolution The resolution (pixel size compared to a screen pixel size, i.e 1/oversampling) or 0 for default - * @param background The background color or lay::Color() for default - * @param foreground The foreground color or lay::Color() for default - * @param active The active color or lay::Color() for default - * @param target_box The box to draw or db::DBox() for default - * @param monochrome If true, monochrome images will be produced - */ - void save_image_with_options (const std::string &fn, unsigned int width, unsigned int height, int linewidth, int oversampling, double resolution, Color background, Color foreground, Color active_color, const db::DBox &target_box, bool monochrome); - - /** - * @brief Get the screen content as a QImage object with the given width and height - */ - QImage get_image (unsigned int width, unsigned int height); - - /** - * @brief Get the screen content as a QImage object with the given width and height - * - * @param width The width of the image in pixels - * @param height The height of the image - * @param linewidth The width of a line in pixels (usually 1) or 0 for default - * @param oversampling The oversampling factor (1..3) or 0 for default - * @param resolution The resolution (pixel size compared to a screen pixel size, i.e 1/oversampling) or 0 for default - * @param background The background color or lay::Color() for default - * @param foreground The foreground color or lay::Color() for default - * @param active The active color or lay::Color() for default - * @param target_box The box to draw or db::DBox() for default - * @param monochrome If true, monochrome images will be produced - */ - QImage get_image_with_options (unsigned int width, unsigned int height, int linewidth, int oversampling, double resolution, lay::Color background, lay::Color foreground, lay::Color active_color, const db::DBox &target_box, bool monochrome); - - /** - * @brief Hierarchy level selection setter - */ - void set_hier_levels (std::pair l); - - /** - * @brief Hierarchy level selection setter - */ - void set_min_hier_levels (int l) - { - set_hier_levels (std::pair (l, get_max_hier_levels ())); - } - - /** - * @brief Hierarchy level selection setter - */ - void set_max_hier_levels (int l) - { - set_hier_levels (std::pair (get_min_hier_levels (), l)); - } - - /** - * @brief Hierarchy level selection getter - */ - std::pair get_hier_levels () const; - - /** - * @brief Hierarchy level selection getter - */ - int get_min_hier_levels () const - { - return get_hier_levels ().first; - } - - /** - * @brief Hierarchy level selection getter - */ - int get_max_hier_levels () const - { - return get_hier_levels ().second; - } - - /** - * @brief Return true, if there is a "last" display state - */ - bool has_prev_display_state (); - - /** - * @brief Return true, if there is a "next" display state - */ - bool has_next_display_state (); - - /** - * @brief Cell box/label color setter - */ - void cell_box_color (lay::Color c); - - /** - * @brief Cell box/label getter - */ - lay::Color cell_box_color () const - { - return m_box_color; - } - - /** - * @brief Transform label flag setter - */ - void cell_box_text_transform (bool xform); - - /** - * @brief Transform label flag getter - */ - bool cell_box_text_transform () const - { - return m_box_text_transform; - } - - /** - * @brief Label font setter - */ - void cell_box_text_font (unsigned int f); - - /** - * @brief Label font setter - */ - unsigned int cell_box_text_font () const - { - return m_box_font; - } - - /** - * @brief Visibility of cell boxes - */ - void cell_box_visible (bool vis); - - /** - * @brief Visibility of cell boxes - */ - bool cell_box_visible () const - { - return m_cell_box_visible; - } - - /** - * @brief Min instance label size setter - */ - void min_inst_label_size (int px); - - /** - * @brief Min instance label size getter - */ - int min_inst_label_size () const - { - return m_min_size_for_label; - } - - /** - * @brief Visibility of text objects - */ - void text_visible (bool vis); - - /** - * @brief Visibility of text objects - */ - bool text_visible () const - { - return m_text_visible; - } - - /** - * @brief Show properties - */ - void show_properties_as_text (bool sp); - - /** - * @brief Show properties - */ - bool show_properties_as_text () - { - return m_show_properties; - } - - /** - * @brief Enable or disable bitmap caching - * - * Bitmap caching is used to optimize drawing by storing bitmaps - * in a cache for each cell. Repeated cells will be drawn faster then. - */ - void bitmap_caching (bool en); - - /** - * @brief Lazy rendering of text objects - */ - bool bitmap_caching () - { - return m_bitmap_caching; - } - - /** - * @brief Lazy rendering of text objects - */ - void text_lazy_rendering (bool lzy); - - /** - * @brief Lazy rendering of text objects - */ - bool text_lazy_rendering () - { - return m_text_lazy_rendering; - } - - /** - * @brief Text object font setter - */ - void text_font (unsigned int f); - - /** - * @brief Text object font getter - */ - unsigned int text_font () const - { - return m_text_font; - } - - /** - * @brief The default text size property - */ - void default_text_size (double fs); - - /** - * @brief The default text size property - */ - double default_text_size () const - { - return m_default_text_size; - } - - /** - * @brief Show or hide markers - */ - void show_markers (bool f); - - /** - * @brief "show_markers" property getter - */ - bool show_markers () const - { - return m_show_markers; - } - - /** - * @brief Don't show stipples - */ - void no_stipples (bool f); - - /** - * @brief "Don't show stipples" property getter - */ - bool no_stipples () const - { - return m_no_stipples; - } - - /** - * @brief Offset stipples property - */ - void offset_stipples (bool f); - - /** - * @brief Offset stipples property getter - */ - bool offset_stipples () const - { - return m_stipple_offset; - } - - /** - * @brief Apply text transformation property - */ - void apply_text_trans (bool f); - - /** - * @brief Apply text transformation property - */ - bool apply_text_trans () const - { - return m_apply_text_trans; - } - - /** - * @brief Text object color - */ - void text_color (lay::Color c); - - /** - * @brief Text object color - */ - lay::Color text_color () const - { - return m_text_color; - } - - /** - * @brief Clear all rulers if a new cell is selected (setter) - * - * If this property is set to true, all rulers are cleared - * if the cell is changed. - */ - void clear_ruler_new_cell (bool f); - - /** - * @brief Clear all rulers if a new cell is selected (getter) - * - * If this property is set to true, all rulers are cleared - * if the cell is changed. - */ - bool clear_ruler_new_cell () const - { - return m_clear_ruler_new_cell; - } - - /** - * @brief Switch new cell to full hierarchy property - * - * If this property is set to true, all hierarchy levels are selected - * if the cell is changed. - */ - void full_hier_new_cell (bool f); - - /** - * @brief Switch new cell to full hierarchy property - * - * If this property is set to true, all hierarchy levels are selected - * if the cell is changed. - */ - bool full_hier_new_cell () const - { - return m_full_hier_new_cell; - } - - /** - * @brief Fit new cell property - * - * If this property is set to false, the coordinate window is not - * changed if the cell is changed. - */ - void fit_new_cell (bool f); - - /** - * @brief Fit new cell - * - * If this property is set to false, the coordinate window is not - * changed if the cell is changed. - */ - bool fit_new_cell () const - { - return m_fit_new_cell; - } - - /** - * @brief The pan distance - * - * The pan distance is given relative to the current width and height. - */ - void pan_distance (double d); - - /** - * @brief Gets the pan distance - */ - double pan_distance () const; - - /** - * @brief Get the mouse wheel mode - * - * The mouse wheel mode determines how the wheel behaves. Mode 0 is the - * default mode, mode 1 is the alternative mode (default is up/down, - * shift is left/right, ctrl is zoom). - */ - int mouse_wheel_mode () const - { - return m_wheel_mode; - } - - /** - * @brief Set the mouse wheel mode - * - * The mouse wheel mode determines how the wheel behaves. Mode 0 is the - * default mode, mode 1 is the alternative mode (default is up/down, - * shift is left/right, ctrl is zoom). - */ - void mouse_wheel_mode (int m) - { - m_wheel_mode = m; - } - - /** - * @brief Sets the color palette - * - * The color palette is used for coloring new layers and is shown in the - * layer toolbox. - */ - void set_palette (const lay::ColorPalette &); - - /** - * @brief Gets the color palette - */ - const lay::ColorPalette &get_palette () const - { - return m_palette; - } - - /** - * @brief Sets the stipple palette - * - * The stipple palette is used for selecting stipples for new layers and is shown in the - * layer toolbox. - */ - void set_palette (const lay::StipplePalette &); - - /** - * @brief Gets the stipple palette - */ - const lay::StipplePalette &get_stipple_palette () const - { - return m_stipple_palette; - } - - /** - * @brief Sets the line style palette - * - * The line style palette is used for selecting line styles and is shown in the - * layer toolbox. - */ - void set_palette (const lay::LineStylePalette &); - - /** - * @brief Gets the line style palette - */ - const lay::LineStylePalette &get_line_style_palette () const - { - return m_line_style_palette; - } - - /** - * @brief Reloads the given cellview into the current view - * - * The cellview is given by index in the current view's cellview list. - */ - void reload_layout (unsigned int cv_index); - - /** - * @brief Load a (new) file into the layout - * - * The add_cellview param controls whether to create a new cellview - * or clear all cellviews before. - * - * The new layout will use the default technology. - * - * @return The index of the cellview loaded. - */ - unsigned int load_layout (const std::string &filename, bool add_cellview) - { - return load_layout (filename, std::string (), add_cellview); - } - - /** - * @brief Load a (new) file into the layout associating it with the given technology - * - * The add_cellview param controls whether to create a new cellview - * or clear all cellviews before. - * - * @return The index of the cellview loaded. - */ - unsigned int load_layout (const std::string &filename, const std::string &technology, bool add_cellview); - - /** - * @brief Load a (new) file into the layout with the options - * - * The add_cellview param controls whether to create a new cellview - * or clear all cellviews before. - * - * The new layout will use the default technology. - * - * @param options The options to use when loading. - * @param add_cellview_param See above. - * @return The index of the cellview loaded. - */ - unsigned int load_layout (const std::string &filename, const db::LoadLayoutOptions &options, bool add_cellview) - { - return load_layout (filename, options, std::string (), add_cellview); - } - - /** - * @brief Load a (new) file into the layout with the options and using the specified technology - * - * The add_cellview param controls whether to create a new cellview - * or clear all cellviews before. - * - * @param options The options to use when loading. - * @param add_cellview_param See above. - * @return The index of the cellview loaded. - */ - unsigned int load_layout (const std::string &filename, const db::LoadLayoutOptions &options, const std::string &technology, bool add_cellview); - - /** - * @brief Create a new, empty layout - * - * The add_cellview param controls whether to create a new cellview - * or clear all cellviews before. - * - * The new layout will use the default technology. - * - * @return The index of the cellview loaded. - */ - unsigned int create_layout (bool add_cellview) - { - return create_layout (std::string (), add_cellview, true); - } - - /** - * @brief Create a new, empty layout using the specified technology - * - * The add_cellview param controls whether to create a new cellview - * or clear all cellviews before. - * - * @return The index of the cellview created. - */ - unsigned int create_layout (const std::string &technology, bool add_cellview) - { - return create_layout (technology, add_cellview, true); - } - - /** - * @brief Create a new, empty layout using the specified technology - * - * The add_cellview param controls whether to create a new cellview - * or clear all cellviews before. This version allows one to specify whether layer properties shall be created. - * - * @return The index of the cellview created. - */ - unsigned int create_layout (const std::string &technology, bool add_cellview, bool initialize_layers); - - /** - * @brief Add an existing layout or replace the current cellview by the given layout - * - * The add_cellview param controls whether to add the layout as a new cellview - * or clear all cellviews before. - * - * The "initialize_layers" parameter allows one to specify whether the layer properties shall be initialized. - * - * @return The index of the cellview loaded. - */ - unsigned int add_layout (lay::LayoutHandle *layout_handle, bool add_cellview, bool initialize_layers = true); - - /** - * @brief Pass the current position from the mouse tracker to the status bar - */ - void current_pos (double x, double y); - - /** - * @brief Get the index of the active cellview (shown in hierarchy browser) - */ - int active_cellview_index () const; - - /** - * @brief Get the index of the active cellview (shown in hierarchy browser) - */ - const lay::CellView &active_cellview () const; - - /** - * @brief Gets a cellview reference to the active cellview - */ - lay::CellViewRef active_cellview_ref (); - - /** - * @brief Select a certain cellview for the active one - */ - void set_active_cellview_index (int index); - - /** - * @brief Cell paths of the selected cells - * - * The current cell is the one highlighted in the browser with the focus rectangle. The - * current path is returned for the cellview given by cv_index. - */ - void selected_cells_paths (int cv_index, std::vector &paths) const; - - /** - * @brief Cell path of the current cell - * - * The current cell is the one highlighted in the browser with the focus rectangle. The - * current path is returned for the cellview given by cv_index. - */ - void current_cell_path (int cv_index, cell_path_type &path) const; - - /** - * @brief Cell path of the current cell - * - * This method version is provided for automation purposes mainly. - */ - cell_path_type get_current_cell_path (int cv_index) const - { - cell_path_type r; - current_cell_path (cv_index, r); - return r; - } - - /** - * @brief Cell path of the current cell in the active cellview - * - * This is a convenience function returning the path for the active cellview. - */ - void current_cell_path (cell_path_type &path) const - { - current_cell_path (active_cellview_index (), path); - } - - /** - * @brief Set the path to the current cell - * - * The current cell is the one highlighted in the browser with the focus rectangle. The - * cell given by the path is highlighted and scrolled into view. - */ - void set_current_cell_path (int cv_index, const cell_path_type &path); - - /** - * @brief Set the path to the current cell is the current cellview - * - * This is a convenience function setting the path for the active cellview. - */ - void set_current_cell_path (const cell_path_type &path) - { - set_current_cell_path (active_cellview_index (), path); - } - - /** - * @brief Obtain the number of cellviews - */ - unsigned int cellviews () const - { - return (unsigned int) m_cellviews.size (); - } - - /** - * @brief Obtain the cellviews as a vector - */ - const std::list &cellview_list () const - { - return m_cellviews; - } - - /** - * @brief Obtain the cell view reference for an index - * - * If the index is invalid, an empty cell view reference is returned - */ - const CellView &cellview (unsigned int index) const; - - /** - * @brief Gets a cellview reference to the active cellview - */ - lay::CellViewRef cellview_ref (unsigned int index); - - /** - * @brief Gets the index of the given cellview - * Based on the pointer passed to the function, the index of the respective cellview - * will be returned. If a null pointer is given or the pointer is not a valid cellview, - * -1 will be returned. - */ - int index_of_cellview (const lay::CellView *cv) const; - - /** - * @brief Obtain the list of annotation shapes - */ - const lay::AnnotationShapes &annotation_shapes () const - { - return m_annotation_shapes; - } - - /** - * @brief Obtain the list of annotation shapes (non-const version) - */ - lay::AnnotationShapes &annotation_shapes () - { - return m_annotation_shapes; - } - - /** - * @brief Select the list of cellviews for this window and fit cell - * - * Warning: use with care! - */ - void select_cellviews_fit (const std::list &cvs); - - /** - * @brief Select the list of cellviews for this window - * - * Warning: use with care! - */ - void select_cellviews (const std::list &cvs); - - /** - * @brief Configures the cellview with the given index - * @param index Index of the cellview to configure - * @param cv The cellview that provides the new configuration - */ - void select_cellview (int index, const CellView &cv); - - /** - * @brief Shift and scale the window - */ - void shift_window (double f, double dx, double dy); - - /** - * @brief Goto window - * - * Position the window to the new position x and y with a size of s (approximately). - * If s is negative or zero, the windows is just shifted. - */ - void goto_window (const db::DPoint &p, double s = -1.0); - - /** - * @brief Return the displayed window - */ - db::DBox box () const; - - /** - * @brief Display a status message - */ - void message (const std::string &s = "", int timeout = 10); - - /** - * @brief Create a new cell with the given in the given cellview - * - * @param cv_index The index of the cellview where to create the cell - * @param cell_name The name of the cell (an exception is thrown if a cell of that name already exists) - * @return The index of the new cell - */ - db::cell_index_type new_cell (int cv_index, const std::string &cell_name); - - /** - * @brief Bookmark the current view under the given name - */ - void bookmark_view (const std::string &name); - - /** - * @brief Asks for a bookmark name and bookmark the current view under this name - */ - void bookmark_current_view (); - - /** - * @brief Show the bookmark management form - */ - void manage_bookmarks (); - - /** - * @brief Obtain the bookmarks list - */ - const BookmarkList &bookmarks () const - { - return m_bookmarks; - } - - /** - * @brief Set the bookmarks list - */ - void bookmarks (const BookmarkList &b); - - std::pair redo_available (); - std::pair undo_available (); - - /** - * @brief Select a certain mode (by index) - */ - void mode (int m); - - /** - * @brief Switches the application's mode - * - * Switches the mode on application level. Use this method to initiate - * a mode switch from the view. - */ - void switch_mode (int m); - - /** - * @brief Test, if the view is currently in move mode. - */ - bool is_move_mode () const; - - /** - * @brief Test, if the view is currently in selection mode. - */ - bool is_selection_mode () const; - - /** - * @brief Query the intrinsic mouse modes available - */ - static unsigned int intrinsic_mouse_modes (std::vector *descriptions); - - /** - * @brief Updates the menu for the given view - * If the view is 0, the menu shall be updated to reflect "no view active" - */ - static void update_menu (lay::LayoutView *view, lay::AbstractMenu &menu); - - /** - * @brief Query the default mode - */ - static int default_mode (); - - /** - * @brief Get a list of cellview index and transform variants - */ - std::set< std::pair > cv_transform_variants () const; - - /** - * @brief Get the global transform variants for a given cellview index - */ - std::vector cv_transform_variants (int cv_index) const; - - /** - * @brief Get the global transform variants for a given cellview index and layer - */ - std::vector cv_transform_variants (int cv_index, unsigned int layer) const; - - /** - * @brief Get the transformation variants for a given cellview index ordered by layer - */ - std::map > cv_transform_variants_by_layer (int cv_index) const; - - /** - * @brief Access to the hidden cell list - */ - const std::vector > &hidden_cells () const - { - return m_hidden_cells; - } - - /** - * @brief Get the "dbu_coordinates" flag - * - * If this flag is true, the property dialogs and other display functions should use - * database units to display coordinates etc. - */ - bool dbu_coordinates () const - { - return m_dbu_coordinates; - } - - /** - * @brief Set the "dbu_coordinates" flag - * - * If this flag is true, the property dialogs and other display functions should use - * database units to display coordinates etc. - */ - void dbu_coordinates (bool f); - - /** - * @brief Get the "absolute_coordinates" flag - * - * If this flag is true, the property dialogs and other display functions should use - * absolute (on top level) coordinates for points etc. - * "absolute" may as well refer to orientation, not only to coordinates, - * if transformations are considered. - */ - bool absolute_coordinates () const - { - return m_absolute_coordinates; - } - - /** - * @brief Set the "absolute_coordinates" flag - * - * If this flag is true, the property dialogs and other display functions should use - * absolute (on top level) coordinates for points etc. - * "absolute" may as well refer to orientation, not only to coordinates, - * if transformations are considered. - */ - void absolute_coordinates (bool f); - - /** - * @brief Get the view object widget - * - * This method intentionally delivers the ViewObjectWidget, not the - * LayoutCanvas to emphasize that the LayoutCanvas object shall not - * be modified. - */ - lay::ViewObjectWidget *view_object_widget () - { - return mp_canvas; - } - - /** - * @brief Get the current viewport - */ - const lay::Viewport &viewport () const - { - return mp_canvas->viewport (); - } - - /** - * @brief Background color property - */ - lay::Color background_color () const - { - return mp_canvas->background_color (); - } - - /** - * @brief Foreground color property - */ - lay::Color foreground_color () const - { - return mp_canvas->foreground_color (); - } - - /** - * @brief Active color property - */ - lay::Color active_color () const - { - return mp_canvas->active_color (); - } - - /** - * @brief Write accessor to the "drop small cells" flag - */ - void drop_small_cells (bool m); - - /** - * @brief Read accessor to the "drop small cells" flag - */ - bool drop_small_cells () const - { - return m_drop_small_cells; - } - - /** - * @brief Write accessor to the "drop small cells" value - */ - void drop_small_cells_value (unsigned int s); - - /** - * @brief Read accessor to the "drop small cells" value - */ - unsigned int drop_small_cells_value () const - { - return m_drop_small_cells_value; - } - - /** - * @brief Write accessor to the "drop small cells" condition - */ - void drop_small_cells_cond (drop_small_cells_cond_type t); - - /** - * @brief Read accessor to the "drop small cells" condition - */ - drop_small_cells_cond_type drop_small_cells_cond () const - { - return m_drop_small_cells_cond; - } - - /** - * @brief Gets a value indicating whether guiding shapes are visible - */ - bool guiding_shapes_visible () const - { - return m_guiding_shape_visible; - } - - /** - * @brief Sets a value indicating whether guiding shapes are visible - */ - void guiding_shapes_visible (bool v); - - /** - * @brief Gets the guiding shapes color - */ - lay::Color guiding_shapes_color () const - { - return m_guiding_shape_color; - } - - /** - * @brief Sets the guiding shapes color - */ - void guiding_shapes_color (lay::Color c); - - /** - * @brief Gets the guiding shapes line width - */ - int guiding_shapes_line_width () const - { - return m_guiding_shape_line_width; - } - - /** - * @brief Sets the guiding shapes line width - */ - void guiding_shapes_line_width (int lw); - - /** - * @brief Gets the guiding shapes vertex size - */ - int guiding_shapes_vertex_size () const - { - return m_guiding_shape_vertex_size; - } - - /** - * @brief Sets the guiding shapes vertex size - */ - void guiding_shapes_vertex_size (int lw); - - /** - * @brief Read accessor to the "abstract mode width" property. - * - * The abstract mode width enables abstract mode (for values > 0) and - * specifies the border to search for touching shapes. - */ - double abstract_mode_width () const - { - return m_abstract_mode_enabled ? m_abstract_mode_width : 0.0; - } - - /** - * @brief Read accessor to the "child context enabled" property. - * - * If child context is enabled, a third set of bit planes must be created by the redraw thread - * containing the shapes for the below-top-level objects. - */ - bool child_context_enabled () const - { - return m_child_ctx_enabled; - } - - /** - * @brief Write accessor to the "draw array border instances" flag - */ - void draw_array_border_instances (bool m); - - /** - * @brief Read accessor to the "draw array border instances" flag - */ - bool draw_array_border_instances () const - { - return m_draw_array_border_instances; - } - - /** - * @brief Get the Drawings interface - * - * Although the Drawings interface is implemented by LayoutCanvas, - * it is a different interface from ViewObjectWidget. - */ - lay::Drawings *drawings () - { - return mp_canvas; - } - - /** - * @brief Select synchronous mode or deselect it - */ - void set_synchronous (bool sync_mode); - - /** - * @brief Tell the state of synchronous mode - */ - bool synchronous () const - { - return m_synchronous; - } - - /** - * @brief Set the number of drawing workers (if not synchronous) - */ - void set_drawing_workers (int workers); - - /** - * @brief Get the number of drawing workers - */ - int drawing_workers () const - { - return m_drawing_workers; - } - - /** - * @brief Gets a value indicating whether the view will accept a dropped file with the given URL or path - */ - virtual bool accepts_drop (const std::string &path_or_url) const; - - /** - * @brief Gets called when a file or URL is dropped on the view - */ - virtual void drop_url (const std::string &path_or_url); - - /** - * @brief Gets a list of all plugins - */ - const std::vector &plugins () - { - return mp_plugins; - } - - /** - * @brief Localize a plugin by name - * - * This method will return 0, if no such plugin is registered - */ - Plugin *get_plugin_by_name (const std::string &name) const; - - /** - * @brief Localize the plugin of the given Type - * - * This method will return 0, if no such plugin is registered - */ - template - PI *get_plugin () const - { - PI *pi = 0; - for (std::vector::const_iterator p = mp_plugins.begin (); p != mp_plugins.end () && !pi; ++p) { - pi = dynamic_cast (*p); - } - return pi; - } - - /** - * @brief Localize the plugins of the given Type - * - * This method will return 0, if no such plugin is registered - */ - template - std::vector get_plugins () const - { - std::vector pi; - for (std::vector::const_iterator p = mp_plugins.begin (); p != mp_plugins.end (); ++p) { - if (dynamic_cast (*p) != 0) { - pi.push_back (dynamic_cast (*p)); - } - } - return pi; - } - - /** - * @brief Create a plugin of the given type - * - * This method can be used to selectively create plugins when the NoPlugin option - * is used. If no such plugin is registered, no plugin is created. - * If a plugin with that name is already registered, it is not created again. - * PD is the type of the declaration. - */ - template - void create_plugin () - { - for (std::vector::const_iterator p = mp_plugins.begin (); p != mp_plugins.end (); ++p) { - if (dynamic_cast ((*p)->plugin_declaration ()) != 0) { - return; - } - } - for (tl::Registrar::iterator cls = tl::Registrar::begin (); cls != tl::Registrar::end (); ++cls) { - if (dynamic_cast (&*cls) != 0) { - create_plugin (&*cls); - break; - } - } - } - - - /** - * @brief Enable or disable the actions for edit functions - * - * This method is used by non-modal dialogs that want to suppress any editing - * activities (like browsers) while they are open. - * - * This method can be called multiple times and will count the enable/disable - * transitions. Each disable will cancel on enable call. - */ - void enable_edits (bool enable); - - /** - * @brief Gets a value indicating whether edits are enabled or not - * - * "enable_edits" will change this value. - */ - bool edits_enabled () const - { - return m_disabled_edits <= 0; - } - - /** - * @brief Rename the given cellview to the given name - * - * The name of the cell view is shown in the title - */ - void rename_cellview (const std::string &name, int cellview_index); - - /** - * @brief Descend into the hierarchy along the given specific path for the given cellview - */ - void descend (const std::vector &path, int cellview_index); - - /** - * @brief Ascend one level in the hierarchy for the given cellview - * - * @return The instance element removed by ascending the path - */ - db::InstElement ascend (int cellview_index); - - /** - * @brief Select a cell by path for a certain cell view and fit cell - */ - void select_cell_fit (const cell_path_type &path, int cellview_index); - - /** - * @brief Select a cell by index for a certain cell view and fit cell - */ - void select_cell_fit (cell_index_type index, int cellview_index); - - /** - * @brief Select a cell by path for a certain cell view - */ - void select_cell (const cell_path_type &path, int cellview_index); - - /** - * @brief Select a cell by index for a certain cell view - */ - void select_cell (cell_index_type index, int cellview_index); - - /** - * @brief Check if a cell is hidden - */ - bool is_cell_hidden (cell_index_type ci, int cellview_index) const; - - /** - * @brief Get the hidden cells for a certain cellview - */ - const std::set &hidden_cells (int cellview_index) const; - - /** - * @brief Add a cell to the hidden cell list - */ - void hide_cell (cell_index_type ci, int cellview_index); - - /** - * @brief Remove a cell from the hidden cell list - */ - void show_cell (cell_index_type ci, int cellview_index); - - /** - * @brief Clears the hidden cell list - */ - void show_all_cells (); - - /** - * @brief Clears the hidden cell list for the given cellview - */ - void show_all_cells (int cv_index); - - /** - * @brief Update the layout view to the current state - * - * This method must be called in order to trigger the update of - * the contents. It will be known, what needs to be updated. - */ - void update_content (); - - /** - * @brief Force an unconditional update - * - * This method is supposed to be used to ensure everything is updated. - * TODO: this method should become obsolete once there is a consistent - * signalling of states implemented. - */ - void force_update_content (); - - /** - * @brief Create a set of initial layer properties for the given cellview - * - * @param cv_index The cellview for which to produce a set of layer properties - * @param lyp_file The layer properties file to load or empty if no file should be loaded - * @param add_missing True, if missing layers should be added (ignored if lyp_file is empty) - */ - void create_initial_layer_props (int cv_index, const std::string &lyp_file, bool add_missing); - - /** - * @brief Merges the given properties into the cell properties of this view - */ - void merge_layer_props (const std::vector &props); - - /** - * @brief Internal method: check, if the layer tree is and an consistent state. - * - * This method is used by the layer tree model to check, if the tree has been brought into - * a consistent state. - * HINT: for the layout this is solved more consistently with the "under construction" attribute - * of the layout. There is no equivalent object for the layer tree currently. - */ - bool layer_model_updated (); - - /** - * @brief Get the "select inside PCells" selection mode - * - * @return true, objects inside PCells can be selected - */ - bool select_inside_pcells_mode () const - { - return m_sel_inside_pcells; - } - - /** - * @brief Get the transient selection mode - * - * @return true, if transient (hover) selection mode is enabled - */ - bool transient_selection_mode () const - { - return m_transient_selection_mode; - } - - /** - * @brief Get the default color for markers - */ - lay::Color default_marker_color () const - { - return m_marker_color; - } - - /** - * @brief Get the default line width for markers - */ - int default_marker_line_width () const - { - return m_marker_line_width; - } - - /** - * @brief Get the default marker dither pattern index - */ - int default_dither_pattern () const - { - return m_marker_dither_pattern; - } - - /** - * @brief Get the default marker line style index - */ - int default_line_style () const - { - return m_marker_line_style; - } - - /** - * @brief Get the default vertex size for markers - */ - int default_marker_vertex_size () const - { - return m_marker_vertex_size; - } - - /** - * @brief Get the default halo flag for markers - */ - int default_marker_halo () const - { - return m_marker_halo; - } - - /** - * @brief Gets the "search range" in pixels (for single click) - * The search range applies whenever some object is looked up in the vicinity of the - * mouse cursor. This value gives the search range in pixels. - */ - unsigned int search_range (); - - /** - * @brief Sets the "search range" in pixels (for single click) - */ - void set_search_range (unsigned int sr); - - /** - * @brief Gets the "search range" in pixels (for box) - * The search range applies whenever some object is looked up in the vicinity of the - * mouse cursor. This value gives the search range in pixels. - */ - unsigned int search_range_box (); - - /** - * @brief Sets the "search range" in pixels (for box) - */ - void set_search_range_box (unsigned int sr); - - /** - * @brief Return true, if any cellview is editable - */ - bool is_editable () const; - - /** - * @brief Get the view_op's for rendering the layers - */ - const std::vector &get_view_ops () const - { - return mp_canvas->get_view_ops (); - } - - /** - * @brief Get the redraw layer info vector - */ - const std::vector &get_redraw_layers () const - { - return mp_canvas->get_redraw_layers (); - } - - /** - * @brief Add missing layers - */ - void add_missing_layers (); - - /** - * @brief Add layers which are not part of the LayerState - */ - void add_new_layers (const LayerState &snapshot); - - /** - * @brief Gets a snapshot of the current layers (can be used for add_missing_layers later) - */ - LayerState layer_snapshot () const; - - /** - * @brief Remove unused layers - */ - void remove_unused_layers (); - - /** - * @brief Returns true, if the layer source shall be shown always in the layer properties tree - */ - bool always_show_source () const - { - return m_always_show_source; - } - - /** - * @brief Returns true, if the layer/datatype shall be shown always in the layer properties tree - */ - bool always_show_ld () const - { - return m_always_show_ld; - } - - /** - * @brief Returns true, if the layout index shall be shown always in the layer properties tree - */ - bool always_show_layout_index () const - { - return m_always_show_layout_index; - } - - /** - * @brief Add a marker database - * - * The layout view will become owner of the database. - * - * @param rdb The database to add - * @return The index of the database - */ - unsigned int add_rdb (rdb::Database *rdb); - - /** - * @brief Replaces a marker database - * - * The layout view will become owner of the database. - * If the index is not valid, the database will be added and the new index will be returned. - * - * @param db_index The index of the database to replace - * @param rdb The database to add - */ - unsigned int replace_rdb (unsigned int db_index, rdb::Database *rdb); - - /** - * @brief Get the marker database by index - * - * @param index The index of the database - * @return A pointer to the database or 0 if the index was not valid. - */ - rdb::Database *get_rdb (int index); - - /** - * @brief Get the marker database by index (const version) - * - * @param index The index of the database - * @return A pointer to the database or 0 if the index was not valid. - */ - const rdb::Database *get_rdb (int index) const; - - /** - * @brief Open the RDB browser for a given database and associated cv index - */ - void open_rdb_browser (int rdb_index, int cv_index); - - /** - * @brief Remove the marker database with the given index - * - * This will release the marker database at the given index. The list - * will be reduced by that element. This means, that the following elements - * will have different indicies. - */ - void remove_rdb (unsigned int index); - - /** - * @brief Get the number of marker databases - */ - unsigned int num_rdbs () const - { - return (unsigned int) m_rdbs.size (); - } - - /** - * @brief An event signalling a change in the marker database list - * - * If marker databases are added or removed, this event is triggered. - */ - tl::Event rdb_list_changed_event; - - /** - * @brief Add a Netlist database - * - * The layout view will become owner of the database. - * - * @param l2ndb The database to add - * @return The index of the database - */ - unsigned int add_l2ndb (db::LayoutToNetlist *l2ndb); - - /** - * @brief Replaces a Netlist database - * - * The layout view will become owner of the database. - * If the index is not valid, the database will be added and the new index will be returned. - * - * @param db_index The index of the database to replace - * @param l2ndb The database to add - */ - unsigned int replace_l2ndb (unsigned int db_index, db::LayoutToNetlist *l2ndb); - - /** - * @brief Get the netlist database by index - * - * @param index The index of the database - * @return A pointer to the database or 0 if the index was not valid. - */ - db::LayoutToNetlist *get_l2ndb (int index); - - /** - * @brief Get the netlist database by index (const version) - * - * @param index The index of the database - * @return A pointer to the database or 0 if the index was not valid. - */ - const db::LayoutToNetlist *get_l2ndb (int index) const; - - /** - * @brief Open the L2NDB browser for a given database and associated cv index - */ - void open_l2ndb_browser (int l2ndb_index, int cv_index); - - /** - * @brief Remove the netlist database with the given index - * - * This will release the netlist database at the given index. The list - * will be reduced by that element. This means, that the following elements - * will have different indicies. - */ - void remove_l2ndb (unsigned int index); - - /** - * @brief Get the number of netlist databases - */ - unsigned int num_l2ndbs () const - { - return (unsigned int) m_l2ndbs.size (); - } - - /** - * @brief An event signalling a change in the netlist database list - * - * If netlist databases are added or removed, this event is triggered. - */ - tl::Event l2ndb_list_changed_event; - - /** - * @brief Deliver a size hint (reimplementation of QWidget) - */ - QSize sizeHint () const; - - /** - * @brief Ensure the given box is visible - */ - void ensure_visible (const db::DBox &b); - - /** - * @brief Specify the global transformation - */ - void set_global_trans (const db::DCplxTrans &b); - - /** - * @brief Gets the global transformation - */ - const db::DCplxTrans &global_trans () const - { - return mp_canvas->global_trans (); - } - - /** - * @brief Removes the previous state from the stack - */ - void pop_state (); - - /** - * @brief Clears the state stack - */ - void clear_states (); - - /** - * @brief Zoom the given box into view - */ - void zoom_box (const db::DBox &b); - - /** - * @brief Zoom the given box into view and select hierarchy levels - */ - void zoom_box_and_set_hier_levels (const db::DBox &b, const std::pair &levels); - - /** - * @brief Specify the transformation explicitly - */ - void zoom_trans (const db::DCplxTrans &b); - - /** - * @brief Move the viewport such that the given point is at the center of the viewport - */ - void pan_center (const db::DPoint &p); - - /** - * @brief Goto a position/cell view that was saved with save_view - */ - void goto_view (const DisplayState &state); - - /** - * @brief Save a position/cell view that can be used for "goto_view" - */ - void save_view (DisplayState &state) const; - - // access to the basic services - lay::MouseTracker *mouse_tracker () const { return mp_tracker; } - lay::ZoomService *zoom_service () const { return mp_zoom_service; } - lay::SelectionService *selection_service () const { return mp_selection_service; } - lay::MoveService *move_service () const { return mp_move_service; } - - /** - * @brief Create all plugins - * - * If plugins already exist, they are deleted and created again - */ - void create_plugins (const lay::PluginDeclaration *except_this = 0); - - /** - * @brief Gets the full field box - * - * This is the box to which the view will zoom on zoom_fit(). - * This box is supposed to cover everything inside the view. - */ - db::DBox full_box () const; - public slots: /** * @brief Store the current state on the "previous states" stack */ - void store_state (); + void store_state () + { + LayoutViewBase::store_state (); + } /** * @brief Cancels all edit operations, clears the selection and resets the mode to "Select" */ - void cancel_esc (); + void cancel_esc () + { + LayoutViewBase::cancel_esc (); + } /** * @brief Cancels all edit operations and clears the selection */ - void cancel (); + void cancel () + { + LayoutViewBase::cancel (); + } /** * @brief Cancels all edit operations but maintains selection */ - void cancel_edits (); + void cancel_edits () + { + LayoutViewBase::cancel_edits (); + } /** * @brief Select all levels of hierarchy available */ - void max_hier (); + void max_hier () + { + LayoutViewBase::max_hier (); + } /** * @brief Stop activities like shape browser and redrawing thread */ - void stop (); + void stop () + { + LayoutViewBase::stop (); + } /** * @brief Stop redrawing thread */ - void stop_redraw (); + void stop_redraw () + { + LayoutViewBase::stop_redraw (); + } /** * @brief Select last display state */ - void prev_display_state (); + void prev_display_state () + { + LayoutViewBase::prev_display_state (); + } /** * @brief Select next display state */ - void next_display_state (); + void next_display_state () + { + LayoutViewBase::next_display_state (); + } /** * @brief Ensure the selection is visible */ - void ensure_selection_visible (); + void ensure_selection_visible () + { + LayoutViewBase::ensure_selection_visible (); + } /** * @brief Select a cell by index for a certain cell view @@ -2638,40 +465,127 @@ public slots: * This will be forwarded to select_cell or select_cell_fit depending * on the m_fit_new_cell flag. */ - void select_cell_dispatch (const cell_path_type &path, int cellview_index); + void select_cell_dispatch (const cell_path_type &path, int cellview_index) + { + LayoutViewBase::select_cell_dispatch (path, cellview_index); + } /** * @brief Called when the current layer changed */ - void current_layer_changed_slot (const lay::LayerPropertiesConstIterator &iter); + void current_layer_changed_slot (const lay::LayerPropertiesConstIterator &iter) + { + LayoutViewBase::current_layer_changed_slot (iter); + } // zoom slots - void zoom_fit (); - void zoom_fit_sel (); - void zoom_in (); - void zoom_out (); - void pan_left (); - void pan_up (); - void pan_right (); - void pan_down (); - void pan_left_fast (); - void pan_up_fast (); - void pan_right_fast (); - void pan_down_fast (); + void zoom_fit () + { + LayoutViewBase::zoom_fit (); + } + + void zoom_fit_sel () + { + LayoutViewBase::zoom_fit_sel (); + } + + void zoom_in () + { + LayoutViewBase::zoom_in (); + } + + void zoom_out () + { + LayoutViewBase::zoom_out (); + } + + void pan_left () + { + LayoutViewBase::pan_left (); + } + + void pan_up () + { + LayoutViewBase::pan_up (); + } + + void pan_right () + { + LayoutViewBase::pan_right (); + } + + void pan_down () + { + LayoutViewBase::pan_down (); + } + + void pan_left_fast () + { + LayoutViewBase::pan_left_fast (); + } + + void pan_up_fast () + { + LayoutViewBase::pan_up_fast (); + } + + void pan_right_fast () + { + LayoutViewBase::pan_right_fast (); + } + + void pan_down_fast () + { + LayoutViewBase::pan_down_fast (); + } // called by children and owner - void redraw (); - void redraw_layer (unsigned int index); - void redraw_deco_layer (); - void redraw_cell_boxes (); - void layer_tab_changed (); - void layer_order_changed (); - void timer (); - void menu_activated (const std::string &symbol); - static std::vector menu_symbols (); + void redraw () + { + LayoutViewBase::redraw (); + } + + void redraw_layer (unsigned int index) + { + LayoutViewBase::redraw_layer (index); + } + + void redraw_deco_layer () + { + LayoutViewBase::redraw_deco_layer (); + } + + void redraw_cell_boxes () + { + LayoutViewBase::redraw_cell_boxes (); + } + + void layer_tab_changed () + { + LayoutViewBase::layer_tab_changed (); + } + + void layer_order_changed () + { + LayoutViewBase::layer_order_changed (); + } + + void timer () + { + LayoutViewBase::timer (); + } + + void min_hier_changed (int i) + { + LayoutViewBase::min_hier_changed (i); + } + + void max_hier_changed (int i) + { + LayoutViewBase::max_hier_changed (i); + } + void deactivate_all_browsers (); - void min_hier_changed (int i); - void max_hier_changed (int i); private: // event handlers used to connect to the layout object's events @@ -2686,8 +600,16 @@ private: void signal_apply_technology (lay::LayoutHandle *layout_handle); private slots: - void active_cellview_changed (int index); - void active_library_changed (int index); + void active_cellview_changed (int index) + { + LayoutViewBase::active_cellview_changed (index); + } + + void active_library_changed (int index) + { + LayoutViewBase::active_library_changed (index); + } + void side_panel_destroyed (); signals: @@ -2736,33 +658,8 @@ signals: */ void current_layer_changed (const lay::LayerPropertiesConstIterator &l); -protected: - /** - * @brief Establish the view operations - */ - void set_view_ops (); - - /** - * @brief Deactivate the view - * - * A view gets "deactivated" if it is no longer the current one. - * This is the opposite operation than activation. - */ - void deactivate (); - - /** - * @brief Activate the view - * - * This method gets called when the view becomes the current one. - */ - void activate (); - private: - bool m_editable; - int m_disabled_edits; - unsigned int m_options; QTimer *mp_timer; - lay::LayoutCanvas *mp_canvas; QFrame *mp_left_frame; lay::LayerControlPanel *mp_control_panel; lay::HierarchyControlPanel *mp_hierarchy_panel; @@ -2772,165 +669,21 @@ private: lay::EditorOptionsFrame *mp_editor_options_frame; QSpinBox *mp_min_hier_spbx; QSpinBox *mp_max_hier_spbx; - std::list m_cellviews; - lay::AnnotationShapes m_annotation_shapes; - std::vector > m_hidden_cells; - std::string m_title; - tl::vector m_rdbs; - tl::vector m_l2ndbs; - std::string m_def_lyp_file; - bool m_add_other_layers; - bool m_always_show_source; - bool m_always_show_ld; - bool m_always_show_layout_index; - bool m_synchronous; - int m_drawing_workers; - - int m_from_level, m_to_level; - double m_pan_distance; - int m_paste_display_mode; - int m_wheel_mode; - bool m_guiding_shape_visible; - lay::Color m_guiding_shape_color; - int m_guiding_shape_line_width; - int m_guiding_shape_vertex_size; - - lay::Color m_ctx_color; - int m_ctx_dimming; - bool m_ctx_hollow; - - lay::Color m_child_ctx_color; - int m_child_ctx_dimming; - bool m_child_ctx_hollow; - bool m_child_ctx_enabled; - - double m_abstract_mode_width; - bool m_abstract_mode_enabled; - - lay::Color m_box_color; - bool m_box_text_transform; - unsigned int m_box_font; - int m_min_size_for_label; - bool m_cell_box_visible; - - lay::Color m_marker_color; - int m_marker_line_width; - int m_marker_vertex_size; - int m_marker_dither_pattern; - int m_marker_line_style; - bool m_marker_halo; - - unsigned int m_search_range; - unsigned int m_search_range_box; - - bool m_transient_selection_mode; - bool m_sel_inside_pcells; - - int m_default_font_size; - bool m_text_visible; - bool m_text_lazy_rendering; - bool m_bitmap_caching; - bool m_show_properties; - lay::Color m_text_color; - bool m_apply_text_trans; - double m_default_text_size; - unsigned int m_text_font; - bool m_show_markers; - bool m_no_stipples; - bool m_stipple_offset; - - bool m_drop_small_cells; - unsigned int m_drop_small_cells_value; - drop_small_cells_cond_type m_drop_small_cells_cond; - - bool m_draw_array_border_instances; - - bool m_fit_new_cell; - bool m_full_hier_new_cell; - bool m_clear_ruler_new_cell; - bool m_dbu_coordinates; - bool m_absolute_coordinates; - - bool m_dirty; - bool m_activated; - bool m_animated; - unsigned int m_phase; - - lay::ColorPalette m_palette; - lay::StipplePalette m_stipple_palette; - lay::LineStylePalette m_line_style_palette; - - std::vector m_display_states; - unsigned int m_display_state_ptr; - - std::vector m_layer_properties_lists; - unsigned int m_current_layer_list; - BookmarkList m_bookmarks; - - // service and editable management - int m_mode; - - // services & editables - lay::MouseTracker *mp_tracker; - lay::ZoomService *mp_zoom_service; - lay::SelectionService *mp_selection_service; - lay::MoveService *mp_move_service; - - std::vector mp_plugins; - - bool m_visibility_changed; bool m_active_cellview_changed_event_enabled; - tl::DeferredMethod dm_prop_changed; + tl::DeferredMethod dm_prop_changed; tl::DeferredMethod dm_setup_editor_option_pages; void init (db::Manager *mgr, QWidget *parent); void init_menu (); - - void do_prop_changed (); - void do_redraw (int layer); - void do_redraw (); - - void background_color (lay::Color c); - void ctx_color (lay::Color c); - void ctx_dimming (int percent); - void ctx_hollow (bool h); - void child_ctx_color (lay::Color c); - void child_ctx_dimming (int percent); - void child_ctx_hollow (bool h); - void child_ctx_enabled (bool e); - void abstract_mode_width (double w); - void abstract_mode_enabled (bool e); - bool has_max_hier () const; - int max_hier_level () const; - bool set_hier_levels_basic (std::pair l); - void do_setup_editor_options_pages (); - - void update_event_handlers (); - void viewport_changed (); - void cellview_changed (unsigned int index); - - bool configure (const std::string &name, const std::string &value); - void config_finalize (); - - void do_load_layer_props (const std::string &fn, bool map_cv, int cv_index, bool add_default); - void finish_cellviews_changed (); - void init_layer_properties (LayerProperties &props, const LayerPropertiesList &lp_list) const; - void merge_dither_pattern (lay::LayerPropertiesList &props); - - // overrides Editables method to display a message - void signal_selection_changed (); + void activate (); + void deactivate (); bool eventFilter(QObject *obj, QEvent *ev); void showEvent (QShowEvent *); void hideEvent (QHideEvent *); - - lay::Plugin *create_plugin (const lay::PluginDeclaration *cls); - - std::list::iterator cellview_iter (int cv_index); - std::list::const_iterator cellview_iter (int cv_index) const; }; } diff --git a/src/laybasic/laybasic/layLayoutViewBase.cc b/src/laybasic/laybasic/layLayoutViewBase.cc new file mode 100644 index 000000000..f5713323a --- /dev/null +++ b/src/laybasic/laybasic/layLayoutViewBase.cc @@ -0,0 +1,5487 @@ + +/* + + 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 +#include +#include + +#include "tlInternational.h" +#include "tlExpression.h" +#include "tlTimer.h" +#include "tlString.h" +#include "tlLog.h" +#include "tlAssert.h" +#include "tlExceptions.h" +#include "layLayoutViewBase.h" +#include "layViewOp.h" +#include "layViewObject.h" +#include "laybasicConfig.h" +#include "layConverters.h" +#include "layGridNet.h" +#include "layMove.h" +#include "layZoomBox.h" +#include "layMouseTracker.h" +#include "layEditable.h" +#include "layFixedFont.h" +#include "laySelector.h" +#include "layLayoutCanvas.h" +#include "layLayerControlPanel.h" +#include "layHierarchyControlPanel.h" +#include "layLibrariesView.h" +#include "layBrowser.h" +#include "layRedrawThread.h" +#include "layRedrawThreadWorker.h" +#include "layParsedLayerSource.h" +#include "layBookmarkManagementForm.h" +#include "layNetlistBrowserDialog.h" +#include "layBookmarksView.h" +#include "layEditorOptionsFrame.h" +#include "layEditorOptionsPages.h" +#include "dbClipboard.h" +#include "dbLayout.h" +#include "dbLayoutUtils.h" +#include "dbManager.h" +#include "dbLibrary.h" +#include "rdb.h" +#include "rdbMarkerBrowserDialog.h" +#include "dbLayoutToNetlist.h" +#include "dbTechnology.h" +#include "tlXMLParser.h" +#include "gsi.h" +#include "gtf.h" + +#include + +namespace lay +{ + +// factor for "zoom in & out" +const double zoom_factor = 0.7; + +// factor by which panning is faster in "fast" (+Shift) mode +const double fast_factor = 3.0; + +// ------------------------------------------------------------- + +struct OpHideShowCell + : public db::Op +{ + OpHideShowCell (lay::CellView::cell_index_type ci, int cv_index, bool show) + : m_cell_index (ci), m_cellview_index (cv_index), m_show (show) + { } + + lay::CellView::cell_index_type m_cell_index; + int m_cellview_index; + bool m_show; +}; + +struct OpSetDitherPattern + : public db::Op +{ + OpSetDitherPattern (const lay::DitherPattern &o, const lay::DitherPattern &n) + : db::Op (), m_old (o), m_new (n) + { + // nothing yet. + } + + lay::DitherPattern m_old, m_new; +}; + +struct OpSetLineStyles + : public db::Op +{ + OpSetLineStyles (const lay::LineStyles &o, const lay::LineStyles &n) + : db::Op (), m_old (o), m_new (n) + { + // nothing yet. + } + + lay::LineStyles m_old, m_new; +}; + +struct OpSetLayerProps + : public db::Op +{ + OpSetLayerProps (unsigned int li, unsigned int i, const lay::LayerProperties &o, const lay::LayerProperties &n) + : m_list_index (li), m_index (i), m_old (o), m_new (n) + { + // .. nothing yet .. + } + + unsigned int m_list_index; + size_t m_index; + lay::LayerProperties m_old, m_new; +}; + +struct OpSetLayerPropsNode + : public db::Op +{ + OpSetLayerPropsNode (unsigned int li, unsigned int i, const lay::LayerPropertiesNode &o, const lay::LayerPropertiesNode &n) + : m_list_index (li), m_index (i), m_old (o), m_new (n) + { + // .. nothing yet .. + } + + unsigned int m_list_index; + size_t m_index; + lay::LayerPropertiesNode m_old, m_new; +}; + +struct OpDeleteLayerList + : public db::Op +{ + OpDeleteLayerList (unsigned int li, const lay::LayerPropertiesList &o) + : m_list_index (li), m_old (o) + { + // .. nothing yet .. + } + + unsigned int m_list_index; + lay::LayerPropertiesList m_old; +}; + +struct OpInsertLayerList + : public db::Op +{ + OpInsertLayerList (unsigned int li, const lay::LayerPropertiesList &n) + : m_list_index (li), m_new (n) + { + // .. nothing yet .. + } + + unsigned int m_list_index; + lay::LayerPropertiesList m_new; +}; + +struct OpRenameProps + : public db::Op +{ + OpRenameProps (unsigned int li, const std::string &old_name, const std::string &new_name) + : m_list_index (li), m_old (old_name), m_new (new_name) + { + // .. nothing yet .. + } + + unsigned int m_list_index; + std::string m_old, m_new; +}; + +struct OpSetAllProps + : public db::Op +{ + OpSetAllProps (unsigned int li, const lay::LayerPropertiesList &o, const lay::LayerPropertiesList &n) + : m_list_index (li), m_old (o), m_new (n) + { + // .. nothing yet .. + } + + unsigned int m_list_index; + lay::LayerPropertiesList m_old, m_new; +}; + +struct OpLayerList + : public db::Op +{ + enum Mode { Delete, Insert }; + + OpLayerList (unsigned int li, unsigned int i, const lay::LayerPropertiesNode &n, Mode m) + : m_list_index (li), m_index (i), m_mode (m), m_node (n) + { } + + unsigned int m_list_index; + size_t m_index; + Mode m_mode; + lay::LayerPropertiesNode m_node; +}; + +struct OpInsertLayerProps + : public OpLayerList +{ + OpInsertLayerProps (unsigned int li, unsigned int i, const lay::LayerPropertiesNode &n) + : OpLayerList (li, i, n, Insert) + { + // .. nothing yet .. + } +}; + +struct OpDeleteLayerProps + : public OpLayerList +{ + OpDeleteLayerProps (unsigned int li, unsigned int i, const lay::LayerPropertiesNode &n) + : OpLayerList (li, i, n, Delete) + { + // .. nothing yet .. + } +}; + +// ------------------------------------------------------------- + +const int timer_interval = 500; + +static LayoutViewBase *ms_current = 0; + +LayoutViewBase::LayoutViewBase (db::Manager *manager, bool editable, lay::Plugin *plugin_parent, unsigned int options) + : lay::Dispatcher (plugin_parent, false /*not standalone*/), + m_editable (editable), + m_options (options), + m_annotation_shapes (manager), + dm_prop_changed (this, &LayoutViewBase::do_prop_changed) +{ + // either it's us or the parent has a dispatcher + tl_assert (dispatcher () != 0); + + // ensures the deferred method scheduler is present + tl::DeferredMethodScheduler::instance (); + + init (manager); +} + +LayoutViewBase::LayoutViewBase (lay::LayoutViewBase *source, db::Manager *manager, bool editable, lay::Plugin *plugin_parent, unsigned int options) + : lay::Dispatcher (plugin_parent, false /*not standalone*/), + m_editable (editable), + m_options (options), + m_annotation_shapes (manager), + dm_prop_changed (this, &LayoutViewBase::do_prop_changed) +{ + // either it's us or the parent has a dispatcher + tl_assert (dispatcher () != 0); + + // ensures the deferred method scheduler is present + tl::DeferredMethodScheduler::instance (); + + m_annotation_shapes = source->m_annotation_shapes; + + init (manager); + + // set the handle reference and clear all cell related stuff + m_cellviews = source->cellview_list (); + m_hidden_cells = source->m_hidden_cells; + + // clear the history, store path and zoom box + m_display_states.clear (); + m_display_state_ptr = 0; + m_synchronous = source->synchronous (); + m_drawing_workers = source->drawing_workers (); + + // duplicate the layer properties + for (size_t i = 0; i < source->m_layer_properties_lists.size (); ++i) { + if (i >= m_layer_properties_lists.size ()) { + m_layer_properties_lists.push_back (new lay::LayerPropertiesList (*source->m_layer_properties_lists [i])); + } else { + *m_layer_properties_lists [i] = *source->m_layer_properties_lists [i]; + } + m_layer_properties_lists [i]->attach_view (this, (unsigned int) i); + } + + if (! m_layer_properties_lists.empty ()) { + mp_canvas->set_dither_pattern (m_layer_properties_lists [0]->dither_pattern ()); + } + + bookmarks (source->bookmarks ()); + + set_active_cellview_index (source->active_cellview_index ()); + + // copy the title + m_title = source->m_title; + + layer_list_changed_event (3); + + finish_cellviews_changed (); +} + +void +LayoutViewBase::init (db::Manager *mgr) +{ + manager (mgr); + + m_annotation_shapes.manager (mgr); + + m_visibility_changed = false; + m_disabled_edits = 0; + m_synchronous = false; + m_drawing_workers = 1; + m_from_level = 0; + m_pan_distance = 0.15; + m_wheel_mode = 0; + m_paste_display_mode = 2; + m_guiding_shape_visible = true; + m_guiding_shape_line_width = 1; + m_guiding_shape_color = lay::Color (); + m_guiding_shape_vertex_size = 5; + m_to_level = 0; + m_ctx_dimming = 50; + m_ctx_hollow = false; + m_child_ctx_dimming = 50; + m_child_ctx_hollow = false; + m_child_ctx_enabled = false; + m_abstract_mode_width = 10.0; + m_abstract_mode_enabled = false; + m_box_text_transform = true; + m_box_font = 0; + m_min_size_for_label = 16; + m_cell_box_visible = true; + m_text_visible = true; + m_default_font_size = lay::FixedFont::default_font_size (); + m_text_lazy_rendering = true; + m_bitmap_caching = true; + m_show_properties = false; + m_apply_text_trans = true; + m_default_text_size = 0.1; + m_text_font = 0; + m_show_markers = true; + m_no_stipples = false; + m_stipple_offset = true; + m_fit_new_cell = true; + m_full_hier_new_cell = true; + m_clear_ruler_new_cell = false; + m_dbu_coordinates = false; + m_absolute_coordinates = false; + m_drop_small_cells = false; + m_drop_small_cells_value = 10; + m_drop_small_cells_cond = DSC_Max; + m_draw_array_border_instances = false; + m_dirty = false; + m_activated = true; + m_animated = false; + m_phase = 0; + m_palette = lay::ColorPalette::default_palette (); + m_stipple_palette = lay::StipplePalette::default_palette (); + m_display_state_ptr = 0; + m_mode = std::numeric_limits::min (); // nothing selected yet. + mp_tracker = 0; + mp_zoom_service = 0; + mp_selection_service = 0; + mp_move_service = 0; + m_marker_line_width = 0; + m_marker_vertex_size = 0; + m_marker_dither_pattern = 1; + m_marker_line_style = 0; + m_marker_halo = true; + m_transient_selection_mode = true; + m_sel_inside_pcells = false; + m_add_other_layers = false; + m_always_show_source = false; + m_always_show_ld = true; + m_always_show_layout_index = false; + m_search_range = 5; + m_search_range_box = 0; + + m_layer_properties_lists.push_back (new LayerPropertiesList ()); + m_layer_properties_lists.back ()->attach_view (this, (unsigned int) (m_layer_properties_lists.size () - 1)); + m_current_layer_list = 0; + + mp_canvas = new lay::LayoutCanvas (this); // @@@ Widget parent??? + + mp_canvas->left_arrow_key_pressed.add (this, &LayoutViewBase::pan_left); + mp_canvas->up_arrow_key_pressed.add (this, &LayoutViewBase::pan_up); + mp_canvas->right_arrow_key_pressed.add (this, &LayoutViewBase::pan_right); + mp_canvas->down_arrow_key_pressed.add (this, &LayoutViewBase::pan_down); + mp_canvas->left_arrow_key_pressed_with_shift.add (this, &LayoutViewBase::pan_left_fast); + mp_canvas->up_arrow_key_pressed_with_shift.add (this, &LayoutViewBase::pan_up_fast); + mp_canvas->right_arrow_key_pressed_with_shift.add (this, &LayoutViewBase::pan_right_fast); + mp_canvas->down_arrow_key_pressed_with_shift.add (this, &LayoutViewBase::pan_down_fast); + + // occupy services and editables: + // these services get deleted by the canvas destructor automatically: + if ((m_options & LV_NoTracker) == 0) { + mp_tracker = new lay::MouseTracker (this); + } + if ((m_options & LV_NoZoom) == 0) { + mp_zoom_service = new lay::ZoomService (this); + } + if ((m_options & LV_NoSelection) == 0) { + mp_selection_service = new lay::SelectionService (this); + } + if ((m_options & LV_NoMove) == 0) { + mp_move_service = new lay::MoveService (this); + } + + create_plugins (); + + config_setup (); +} + +LayoutViewBase::~LayoutViewBase () +{ + if (ms_current == this) { + ms_current = 0; + } + + // detach all observers + // This is to prevent signals to partially destroyed observers that own a LayoutViewBase + layer_list_changed_event.clear (); + layer_list_deleted_event.clear (); + layer_list_inserted_event.clear (); + current_layer_list_changed_event.clear (); + cell_visibility_changed_event.clear (); + cellviews_about_to_change_event.clear (); + cellview_about_to_change_event.clear (); + cellviews_changed_event.clear (); + cellview_changed_event.clear (); + rdb_list_changed_event.clear (); + l2ndb_list_changed_event.clear (); + file_open_event.clear (); + hier_changed_event.clear (); + geom_changed_event.clear (); + annotations_changed_event.clear (); + + // detach ourselves from any observed objects to prevent signals while destroying + tl::Object::detach_from_all_events (); + + // remove all rdb's + while (num_rdbs () > 0) { + remove_rdb (0); + } + + // remove all L2N DB's + while (num_l2ndbs () > 0) { + remove_l2ndb (0); + } + + // delete layer lists + std::vector layer_properties_lists; + layer_properties_lists.swap (m_layer_properties_lists); + for (std::vector::iterator l = layer_properties_lists.begin (); l != layer_properties_lists.end (); ++l) { + if (*l) { + delete *l; + } + } + + // delete all plugins + std::vector plugins; + plugins.swap (mp_plugins); + for (std::vector::iterator p = plugins.begin (); p != plugins.end (); ++p) { + delete *p; + } + + // detach from the manager, so we can safely delete the manager + manager (0); + + stop (); + + // because LayoutViewBase and LayoutCanvas both control lifetimes of + // ruler objects for example, it is safer to explicitly delete the + // LayoutCanvas object here: + delete mp_canvas; + mp_canvas = 0; +} + +void LayoutViewBase::update_event_handlers () +{ + tl::Object::detach_from_all_events (); + + for (std::vector::iterator p = mp_plugins.begin (); p != mp_plugins.end (); ++p) { + // TODO: get rid of the const_cast hack + const_cast ((*p)->plugin_declaration ())->editable_enabled_changed_event.add (this, &LayoutViewBase::signal_plugin_enabled_changed); + } + + for (unsigned int i = 0; i < cellviews (); ++i) { + cellview (i)->layout ().hier_changed_event.add (this, &LayoutViewBase::signal_hier_changed); + cellview (i)->layout ().bboxes_changed_event.add (this, &LayoutViewBase::signal_bboxes_from_layer_changed, i); + cellview (i)->layout ().dbu_changed_event.add (this, &LayoutViewBase::signal_bboxes_changed); + cellview (i)->layout ().prop_ids_changed_event.add (this, &LayoutViewBase::signal_prop_ids_changed); + cellview (i)->layout ().layer_properties_changed_event.add (this, &LayoutViewBase::signal_layer_properties_changed); + cellview (i)->layout ().cell_name_changed_event.add (this, &LayoutViewBase::signal_cell_name_changed); + cellview (i)->apply_technology_with_sender_event.add (this, &LayoutViewBase::signal_apply_technology); + } + + annotation_shapes ().bboxes_changed_any_event.add (this, &LayoutViewBase::signal_annotations_changed); + + mp_canvas->viewport_changed_event.add (this, &LayoutViewBase::viewport_changed); +} + +void LayoutViewBase::viewport_changed () +{ + viewport_changed_event (); +} + +bool LayoutViewBase::accepts_drop (const std::string &path_or_url) const +{ + for (std::vector::const_iterator p = mp_plugins.begin (); p != mp_plugins.end (); ++p) { + if ((*p)->accepts_drop (path_or_url)) { + return true; + } + } + return false; +} + +void LayoutViewBase::drop_url (const std::string &path_or_url) +{ + for (std::vector::const_iterator p = mp_plugins.begin (); p != mp_plugins.end (); ++p) { + if ((*p)->accepts_drop (path_or_url)) { + (*p)->drop_url (path_or_url); + break; + } + } +} + +lay::Plugin *LayoutViewBase::create_plugin (const lay::PluginDeclaration *cls) +{ + lay::Plugin *p = cls->create_plugin (manager (), dispatcher (), this); + if (p) { + + // unhook the plugin from the script side if created there (prevent GC from destroying it) + p->gsi::ObjectBase::keep (); + + mp_plugins.push_back (p); + p->set_plugin_declaration (cls); + + // enable editable functionality + if (p->editable_interface ()) { + enable (p->editable_interface (), cls->editable_enabled ()); + } + + update_event_handlers (); + + } + return p; +} + +void LayoutViewBase::create_plugins (const lay::PluginDeclaration *except_this) +{ + for (std::vector::iterator p = mp_plugins.begin (); p != mp_plugins.end (); ++p) { + delete *p; + } + mp_plugins.clear (); + + // create the plugins + for (tl::Registrar::iterator cls = tl::Registrar::begin (); cls != tl::Registrar::end (); ++cls) { + + if (&*cls != except_this) { + + // TODO: clean solution. The following is a HACK: + if (cls.current_name () == "ant::Plugin" || cls.current_name () == "img::Plugin") { + // ant and img are created always + create_plugin (&*cls); + } else if ((m_options & LV_NoPlugins) == 0) { + // others: only create unless LV_NoPlugins is set + create_plugin (&*cls); + } else if ((m_options & LV_NoGrid) == 0 && cls.current_name () == "GridNetPlugin") { + // except grid net plugin which is created on request + create_plugin (&*cls); + } + + } + + } + + dm_setup_editor_option_pages (); + + mode (default_mode ()); +} + +Plugin *LayoutViewBase::get_plugin_by_name (const std::string &name) const +{ + lay::PluginDeclaration *decl = 0; + for (tl::Registrar::iterator cls = tl::Registrar::begin (); !decl && cls != tl::Registrar::end (); ++cls) { + if (cls.current_name () == name) { + decl = cls.operator-> (); + } + } + + if (decl) { + for (std::vector::const_iterator p = mp_plugins.begin (); p != mp_plugins.end (); ++p) { + if ((*p)->plugin_declaration () == decl) { + return *p; + } + } + } + + return 0; +} + +void +LayoutViewBase::set_drawing_workers (int workers) +{ + m_drawing_workers = std::max (0, std::min (100, workers)); +} + +void +LayoutViewBase::set_synchronous (bool s) +{ + m_synchronous = s; +} + +bool +LayoutViewBase::is_dirty () const +{ + return m_dirty; +} + +bool +LayoutViewBase::configure (const std::string &name, const std::string &value) +{ + lay::Dispatcher::configure (name, value); + + if (mp_move_service && mp_move_service->configure (name, value)) { + return true; + } + + if (name == cfg_default_lyp_file) { + + m_def_lyp_file = value; + return false; // not taken - let others set it too. + + } else if (name == cfg_default_add_other_layers) { + + tl::from_string (value, m_add_other_layers); + return false; // not taken - let others set it too. + + } else if (name == cfg_layers_always_show_source) { + + bool a = false; + tl::from_string (value, a); + if (a != m_always_show_source) { + m_always_show_source = a; + layer_list_changed_event (4); + } + + return true; + + } else if (name == cfg_layers_always_show_ld) { + + tl::from_string (value, m_always_show_ld); + update_content (); + return true; + + } else if (name == cfg_layers_always_show_layout_index) { + + tl::from_string (value, m_always_show_layout_index); + update_content (); + return true; + +/*@@@ + } else if (name == cfg_flat_cell_list) { + + bool f; + tl::from_string (value, f); + if (mp_hierarchy_panel) { + mp_hierarchy_panel->set_flat (f); + } + return true; + + } else if (name == cfg_split_cell_list) { + + bool f; + tl::from_string (value, f); + if (mp_hierarchy_panel) { + mp_hierarchy_panel->set_split_mode (f); + } + return true; + + } else if (name == cfg_split_lib_views) { + + bool f; + tl::from_string (value, f); + if (mp_libraries_view) { + mp_libraries_view->set_split_mode (f); + } + return true; + + } else if (name == cfg_bookmarks_follow_selection) { + + bool f; + tl::from_string (value, f); + if (mp_bookmarks_view) { + mp_bookmarks_view->follow_selection (f); + } + return true; + + } else if (name == cfg_current_lib_view) { + + if (mp_libraries_view) { + mp_libraries_view->select_active_lib_by_name (value); + } + return true; + + } else if (name == cfg_cell_list_sorting) { + + if (mp_hierarchy_panel) { + if (value == "by-name") { + mp_hierarchy_panel->set_sorting (CellTreeModel::ByName); + } else if (value == "by-area") { + mp_hierarchy_panel->set_sorting (CellTreeModel::ByArea); + } else if (value == "by-area-reverse") { + mp_hierarchy_panel->set_sorting (CellTreeModel::ByAreaReverse); + } + } + return true; + + } else if (name == cfg_hide_empty_layers) { + + bool f; + tl::from_string (value, f); + if (mp_control_panel) { + mp_control_panel->set_hide_empty_layers (f); + } + return true; + + } else if (name == cfg_test_shapes_in_view) { + + bool f; + tl::from_string (value, f); + if (mp_control_panel) { + mp_control_panel->set_test_shapes_in_view (f); + } + return true; + +@@@*/ + } else if (name == cfg_background_color) { + + lay::Color color; + ColorConverter ().from_string (value, color); + background_color (color); + // do not take - let others receive the background color events as well + return false; + + } else if (name == cfg_default_font_size) { + + int df = 0; + tl::from_string (value, df); + if (m_default_font_size != df) { + // keep a shadow state to correctly issue the redraw call + m_default_font_size = df; + lay::FixedFont::set_default_font_size (df); + redraw (); + } + // do not take - let others have the event for the redraw call + return false; + + } else if (name == cfg_bitmap_oversampling) { + + int os = 1; + tl::from_string (value, os); + mp_canvas->set_oversampling (os); + return true; + + } else if (name == cfg_image_cache_size) { + + int sz = 0; + tl::from_string (value, sz); + mp_canvas->set_image_cache_size (size_t (sz)); + return true; + + } else if (name == cfg_global_trans) { + + tl::Extractor ex (value.c_str ()); + try { + db::DCplxTrans t; + ex.read (t); + set_global_trans (t); + } catch (...) { } + return true; + + } else if (name == cfg_ctx_color) { + + lay::Color color; + ColorConverter ().from_string (value, color); + ctx_color (color); + return true; + + } else if (name == cfg_ctx_dimming) { + + int n; + tl::from_string (value, n); + ctx_dimming (n); + return true; + + } else if (name == cfg_ctx_hollow) { + + bool h; + tl::from_string (value, h); + ctx_hollow (h); + return true; + + } else if (name == cfg_child_ctx_color) { + + lay::Color color; + ColorConverter ().from_string (value, color); + child_ctx_color (color); + return true; + + } else if (name == cfg_child_ctx_dimming) { + + int n; + tl::from_string (value, n); + child_ctx_dimming (n); + return true; + + } else if (name == cfg_child_ctx_hollow) { + + bool h; + tl::from_string (value, h); + child_ctx_hollow (h); + return true; + + } else if (name == cfg_child_ctx_enabled) { + + bool h; + tl::from_string (value, h); + child_ctx_enabled (h); + return true; + + } else if (name == cfg_search_range) { + + unsigned int n; + tl::from_string (value, n); + set_search_range (n); + return true; + + } else if (name == cfg_search_range_box) { + + unsigned int n; + tl::from_string (value, n); + set_search_range_box (n); + return true; + + } else if (name == cfg_abstract_mode_enabled) { + + bool e; + tl::from_string (value, e); + abstract_mode_enabled (e); + return true; + + } else if (name == cfg_abstract_mode_width) { + + double w; + tl::from_string (value, w); + abstract_mode_width (w); + return true; + + } else if (name == cfg_min_inst_label_size) { + + int n; + tl::from_string (value, n); + min_inst_label_size (n); + return true; + + } else if (name == cfg_cell_box_text_font) { + + int n; + tl::from_string (value, n); + cell_box_text_font (n); + return true; + + } else if (name == cfg_cell_box_text_transform) { + + bool flag; + tl::from_string (value, flag); + cell_box_text_transform (flag); + return true; + + } else if (name == cfg_cell_box_visible) { + + bool flag; + tl::from_string (value, flag); + cell_box_visible (flag); + return true; + + } else if (name == cfg_cell_box_color) { + + lay::Color color; + ColorConverter ().from_string (value, color); + cell_box_color (color); + return true; + + } else if (name == cfg_text_color) { + + lay::Color color; + ColorConverter ().from_string (value, color); + text_color (color); + return true; + + } else if (name == cfg_text_visible) { + + bool flag; + tl::from_string (value, flag); + text_visible (flag); + return true; + + } else if (name == cfg_bitmap_caching) { + + bool flag; + tl::from_string (value, flag); + bitmap_caching (flag); + return true; + + } else if (name == cfg_text_lazy_rendering) { + + bool flag; + tl::from_string (value, flag); + text_lazy_rendering (flag); + return true; + + } else if (name == cfg_show_properties) { + + bool flag; + tl::from_string (value, flag); + show_properties_as_text (flag); + return true; + + } else if (name == cfg_apply_text_trans) { + + bool flag; + tl::from_string (value, flag); + apply_text_trans (flag); + return true; + + } else if (name == cfg_markers_visible) { + + bool flag; + tl::from_string (value, flag); + mp_canvas->set_dismiss_view_objects (! flag); + return true; + + } else if (name == cfg_no_stipple) { + + bool flag; + tl::from_string (value, flag); + no_stipples (flag); + return true; + + } else if (name == cfg_stipple_offset) { + + bool flag; + tl::from_string (value, flag); + offset_stipples (flag); + return true; + + } else if (name == cfg_default_text_size) { + + double sz; + tl::from_string (value, sz); + default_text_size (sz); + return true; + + } else if (name == cfg_text_font) { + + int n; + tl::from_string (value, n); + text_font (n); + return true; + + } else if (name == cfg_full_hier_new_cell) { + + bool flag; + tl::from_string (value, flag); + full_hier_new_cell (flag); + return true; + + } else if (name == cfg_fit_new_cell) { + + bool flag; + tl::from_string (value, flag); + fit_new_cell (flag); + return true; + + } else if (name == cfg_clear_ruler_new_cell) { + + bool flag; + tl::from_string (value, flag); + clear_ruler_new_cell (flag); + return true; + + } else if (name == cfg_abs_units) { + + bool flag; + tl::from_string (value, flag); + absolute_coordinates (flag); + return true; + + } else if (name == cfg_guiding_shape_visible) { + + bool v = false; + tl::from_string (value, v); + guiding_shapes_visible (v); + return true; + + } else if (name == cfg_guiding_shape_line_width) { + + int v = 0; + tl::from_string (value, v); + guiding_shapes_line_width (v); + return true; + + } else if (name == cfg_guiding_shape_color) { + + lay::Color color; + ColorConverter ().from_string (value, color); + guiding_shapes_color (color); + return true; + + } else if (name == cfg_guiding_shape_color) { + + lay::Color color; + ColorConverter ().from_string (value, color); + guiding_shapes_color (color); + return true; + + } else if (name == cfg_guiding_shape_vertex_size) { + + int v = 0; + tl::from_string (value, v); + guiding_shapes_vertex_size (v); + return true; + + } else if (name == cfg_paste_display_mode) { + + tl::from_string (value, m_paste_display_mode); + return true; + + } else if (name == cfg_mouse_wheel_mode) { + + tl::from_string (value, m_wheel_mode); + return true; + + } else if (name == cfg_pan_distance) { + + double pd; + tl::from_string (value, pd); + pan_distance (pd); + return true; + + } else if (name == cfg_drawing_workers) { + + int workers; + tl::from_string (value, workers); + set_drawing_workers (workers); + return true; + + } else if (name == cfg_drop_small_cells) { + + bool flag; + tl::from_string (value, flag); + drop_small_cells (flag); + return true; + + } else if (name == cfg_drop_small_cells_cond) { + + unsigned int n; + tl::from_string (value, n); + drop_small_cells_cond (drop_small_cells_cond_type (n)); + return true; + + } else if (name == cfg_drop_small_cells_value) { + + unsigned int n; + tl::from_string (value, n); + drop_small_cells_value (n); + return true; + + } else if (name == cfg_array_border_instances) { + + bool f; + tl::from_string (value, f); + draw_array_border_instances (f); + return true; + + } else if (name == cfg_dbu_units) { + + bool flag; + tl::from_string (value, flag); + dbu_coordinates (flag); + return true; + + } else if (name == cfg_stipple_palette) { + + lay::StipplePalette palette = lay::StipplePalette::default_palette (); + + try { + // empty string means: default palette + if (! value.empty ()) { + palette.from_string (value); + } + } catch (...) { + // ignore errors: just reset the palette + palette = lay::StipplePalette::default_palette (); + } + + set_palette (palette); + + // others need this property too .. + return false; + + } else if (name == cfg_line_style_palette) { + + lay::LineStylePalette palette = lay::LineStylePalette::default_palette (); + + try { + // empty string means: default palette + if (! value.empty ()) { + palette.from_string (value); + } + } catch (...) { + // ignore errors: just reset the palette + palette = lay::LineStylePalette::default_palette (); + } + + set_palette (palette); + + // others need this property too .. + return false; + + } else if (name == cfg_color_palette) { + + lay::ColorPalette palette = lay::ColorPalette::default_palette (); + + try { + // empty string means: default palette + if (! value.empty ()) { + palette.from_string (value); + } + } catch (...) { + // ignore errors: just reset the palette + palette = lay::ColorPalette::default_palette (); + } + + set_palette (palette); + + // others need this property too .. + return false; + + } else if (name == cfg_sel_inside_pcells_mode) { + + bool flag; + tl::from_string (value, flag); + + if (m_sel_inside_pcells != flag) { + m_sel_inside_pcells = flag; + clear_selection (); + } + + return true; + + } else if (name == cfg_sel_transient_mode) { + + bool flag; + tl::from_string (value, flag); + m_transient_selection_mode = flag; + + if (! m_transient_selection_mode) { + clear_transient_selection (); + } + + // do not take - let others receive this configuration as well + return false; + + } else if (name == cfg_sel_color) { + + lay::Color color; + lay::ColorConverter ().from_string (value, color); + + // Change the color + if (lay::test_and_set (m_marker_color, color)) { + mp_canvas->update_image (); + } + + // do not take - let others receive this configuration as well + return false; + + } else if (name == cfg_sel_line_width) { + + int lw = 0; + tl::from_string (value, lw); + + // Change the line width + if (lay::test_and_set (m_marker_line_width, lw)) { + mp_canvas->update_image (); + } + + // do not take - let others receive this configuration as well + return false; + + } else if (name == cfg_sel_dither_pattern) { + + int dp = 0; + tl::from_string (value, dp); + + // Change the vertex_size + if (lay::test_and_set (m_marker_dither_pattern, dp)) { + mp_canvas->update_image (); + } + + // do not take - let others receive this configuration as well + return false; + + } else if (name == cfg_sel_line_style) { + + int dp = 0; + tl::from_string (value, dp); + + // Change the vertex_size + if (lay::test_and_set (m_marker_line_style, dp)) { + mp_canvas->update_image (); + } + + // do not take - let others receive this configuration as well + return false; + + } else if (name == cfg_sel_vertex_size) { + + int vs = 0; + tl::from_string (value, vs); + + // Change the vertex_size + if (lay::test_and_set (m_marker_vertex_size, vs)) { + mp_canvas->update_image (); + } + + // do not take - let others receive this configuration as well + return false; + + } else if (name == cfg_sel_halo) { + + bool halo = 0; + tl::from_string (value, halo); + + // Change the vertex_size + if (lay::test_and_set (m_marker_halo, halo)) { + mp_canvas->update_image (); + } + + // do not take - let others receive this configuration as well + return false; + + } else { + return false; + } +} + +void +LayoutViewBase::config_finalize () +{ + // It's important that the editor option pages are updated last - because the + // configuration change may trigger other configuration changes + dm_setup_editor_option_pages (); +} + +void +LayoutViewBase::enable_edits (bool enable) +{ + // enable or disable these services: + if (mp_selection_service) { + mp_selection_service->enable (enable); + } + if (mp_move_service) { + mp_move_service->enable (enable); + } + + // enable or disable the services that implement "lay::ViewService" + for (std::vector::iterator p = mp_plugins.begin (); p != mp_plugins.end (); ++p) { + lay::ViewService *svc = (*p)->view_service_interface (); + if (svc) { + svc->enable (enable); + } + } + + bool is_enabled = edits_enabled (); + + if (enable) { + if (m_disabled_edits > 0) { + --m_disabled_edits; + } + } else { + ++m_disabled_edits; + } + + if (edits_enabled () != is_enabled) { + emit edits_enabled_changed (); + } +} + +void +LayoutViewBase::set_line_styles (const lay::LineStyles &styles) +{ + if (mp_canvas->line_styles () != styles) { + + if (transacting ()) { + manager ()->queue (this, new OpSetLineStyles (mp_canvas->line_styles (), styles)); + } else if (manager () && ! replaying ()) { + manager ()->clear (); + } + mp_canvas->set_line_styles (styles); + + for (unsigned int i = 0; i < layer_lists (); ++i) { + m_layer_properties_lists [i]->set_line_styles (styles); + } + + layer_list_changed_event (1); + + } +} + +void +LayoutViewBase::set_dither_pattern (const lay::DitherPattern &pattern) +{ + if (mp_canvas->dither_pattern () != pattern) { + + if (transacting ()) { + manager ()->queue (this, new OpSetDitherPattern (mp_canvas->dither_pattern (), pattern)); + } else if (manager () && ! replaying ()) { + manager ()->clear (); + } + mp_canvas->set_dither_pattern (pattern); + + for (unsigned int i = 0; i < layer_lists (); ++i) { + m_layer_properties_lists [i]->set_dither_pattern (pattern); + } + + layer_list_changed_event (1); + + } +} + +const LayerPropertiesList & +LayoutViewBase::get_properties (unsigned int index) const +{ + if (index >= layer_lists ()) { + static lay::LayerPropertiesList empty; + return empty; + } else { + return *m_layer_properties_lists [index]; + } +} + +void +LayoutViewBase::set_current_layer_list (unsigned int index) +{ + if (index != m_current_layer_list && index < layer_lists ()) { + m_current_layer_list = index; + current_layer_list_changed_event (index); + redraw (); + } +} + +void +LayoutViewBase::insert_layer_list (unsigned index, const LayerPropertiesList &props) +{ + if (index > layer_lists ()) { + return; + } + + if (transacting ()) { + manager ()->queue (this, new OpInsertLayerList (index, props)); + } else if (manager () && ! replaying ()) { + manager ()->clear (); + } + + m_layer_properties_lists.insert (m_layer_properties_lists.begin () + index, new LayerPropertiesList (props)); + m_layer_properties_lists [index]->attach_view (this, index); + merge_dither_pattern (*m_layer_properties_lists [index]); + + m_current_layer_list = index; + current_layer_list_changed_event (index); + + layer_list_inserted_event (index); + + redraw (); + + dm_prop_changed (); +} + +void +LayoutViewBase::delete_layer_list (unsigned index) +{ + if (index >= layer_lists ()) { + return; + } + + if (transacting ()) { + manager ()->queue (this, new OpDeleteLayerList (index, *m_layer_properties_lists [index])); + } else if (manager () && ! replaying ()) { + manager ()->clear (); + } + + delete m_layer_properties_lists [index]; + m_layer_properties_lists.erase (m_layer_properties_lists.begin () + index); + + if (m_current_layer_list > index) { + + --m_current_layer_list; + current_layer_list_changed_event (m_current_layer_list); + + // don't tell the other observers because effectively nothing has changed. + + } else if (m_current_layer_list == index) { + + if (m_current_layer_list > 0) { + --m_current_layer_list; + } + + current_layer_list_changed_event (m_current_layer_list); + + // the current list has been deleted. + layer_list_changed_event (3); + + redraw (); + + } + + layer_list_deleted_event (index); + dm_prop_changed (); +} + +void +LayoutViewBase::rename_properties (unsigned int index, const std::string &new_name) +{ + if (index >= layer_lists ()) { + return; + } + + if (transacting ()) { + manager ()->queue (this, new OpRenameProps (index, m_layer_properties_lists [index]->name (), new_name)); + } else if (manager () && ! replaying ()) { + manager ()->clear (); + } + + m_layer_properties_lists [index]->set_name (new_name); + + layer_list_changed_event (4); +} + +void +LayoutViewBase::merge_dither_pattern (lay::LayerPropertiesList &props) +{ + { + lay::DitherPattern dp (dither_pattern ()); + + std::map index_map; + dp.merge (props.dither_pattern (), index_map); + + // remap the dither pattern index + for (lay::LayerPropertiesIterator l = props.begin_recursive (); l != props.end_recursive (); ++l) { + int dpi = l->dither_pattern (false /*local*/); + std::map ::iterator m = index_map.find ((unsigned int) dpi); + if (m != index_map.end ()) { + l->set_dither_pattern (int (m->second)); + } + } + + // install the new custom pattern table + if (mp_canvas->dither_pattern () != dp) { + mp_canvas->set_dither_pattern (dp); + for (unsigned int i = 0; i < layer_lists (); ++i) { + m_layer_properties_lists [i]->set_dither_pattern (dp); + } + } + } + + { + lay::LineStyles ls (line_styles ()); + + std::map index_map; + ls.merge (props.line_styles (), index_map); + + // remap the dither pattern index + for (lay::LayerPropertiesIterator l = props.begin_recursive (); l != props.end_recursive (); ++l) { + int lsi = l->line_style (false /*local*/); + std::map ::iterator m = index_map.find ((unsigned int) lsi); + if (m != index_map.end ()) { + l->set_line_style (int (m->second)); + } + } + + // install the new custom pattern table + if (mp_canvas->line_styles () != ls) { + mp_canvas->set_line_styles (ls); + for (unsigned int i = 0; i < layer_lists (); ++i) { + m_layer_properties_lists [i]->set_line_styles (ls); + } + } + } +} + +void +LayoutViewBase::set_properties (unsigned int index, const LayerPropertiesList &props) +{ + // If index is not a valid tab index, don't do anything except for the case of + // index 0 in which the first entry is created (this can happen as a result of + // delete_properties). + if (index >= layer_lists ()) { + if (index > 0) { + return; + } else { + m_layer_properties_lists.push_back (new LayerPropertiesList ()); + m_layer_properties_lists.back ()->attach_view (this, (unsigned int) (m_layer_properties_lists.size () - 1)); + } + } + + // HINT: this method is quite frequently used in an imperative way. + // Since it has some desired side effects such as forcing a recomputation of the internals, + // it should be executed in any case, even if props == get_properties (). + + if (transacting ()) { + manager ()->queue (this, new OpSetAllProps (index, get_properties (), props)); + } else if (manager () && ! replaying ()) { + manager ()->clear (); + } + + if (mp_control_panel && index == current_layer_list ()) { + mp_control_panel->begin_updates (); + } + + *m_layer_properties_lists [index] = props; + m_layer_properties_lists [index]->attach_view (this, index); + + merge_dither_pattern (*m_layer_properties_lists [index]); + + if (index == current_layer_list ()) { + + layer_list_changed_event (3); + + redraw (); + + dm_prop_changed (); + + } +} + +void +LayoutViewBase::expand_properties () +{ + expand_properties (std::map (), false); +} + +void +LayoutViewBase::expand_properties (unsigned int index) +{ + expand_properties (index, std::map (), false); +} + +void +LayoutViewBase::expand_properties (const std::map &map_cv_index, bool add_default) +{ + for (unsigned int i = 0; i < cellviews (); ++i) { + expand_properties (i, map_cv_index, add_default); + } +} + +void +LayoutViewBase::expand_properties (unsigned int index, const std::map &map_cv_index, bool add_default) +{ + if (index < m_layer_properties_lists.size ()) { + m_layer_properties_lists [index]->expand (map_cv_index, add_default); + } +} + +void +LayoutViewBase::replace_layer_node (unsigned int index, const LayerPropertiesConstIterator &iter, const LayerPropertiesNode &node) +{ + if (index >= layer_lists ()) { + return; + } + + // if the source specification changed, a redraw is required + if (*iter != node) { + + if (transacting ()) { + manager ()->queue (this, new OpSetLayerPropsNode (index, (unsigned int) iter.uint (), *iter, node)); + } else if (manager () && ! replaying ()) { + manager ()->clear (); + } + + if (mp_control_panel && index == current_layer_list ()) { + mp_control_panel->begin_updates (); + } + + LayerPropertiesIterator non_const_iter (get_properties (index), iter.uint ()); + *non_const_iter = node; + non_const_iter->attach_view (this, index); + + if (index == current_layer_list ()) { + + layer_list_changed_event (2); + + // TODO: check, if redraw is actually necessary (this is complex!) + redraw (); + + dm_prop_changed (); + + } + } +} + +void +LayoutViewBase::set_properties (unsigned int index, const LayerPropertiesConstIterator &iter, const LayerProperties &props) +{ + if (index >= layer_lists ()) { + return; + } + + // if the source specification changed, a redraw is required + const LayerProperties &l = *iter; + if (l != props) { + + if (transacting ()) { + manager ()->queue (this, new OpSetLayerProps (index, (unsigned int) iter.uint (), l, props)); + } else if (manager () && ! replaying ()) { + manager ()->clear (); + } + + bool need_redraw = (l.source (false /*local*/) != props.source (false /*local*/) || l.xfill (false /*local*/) != props.xfill (false /*local*/)); + bool visible_changed = (l.visible (true /*real*/) != props.visible (true /*real*/)); + + LayerPropertiesIterator non_const_iter (get_properties (index), iter.uint ()); + *non_const_iter = props; + + if (index == current_layer_list ()) { + + layer_list_changed_event (1); + + if (need_redraw) { + redraw (); + } + + if (visible_changed) { + m_visibility_changed = true; + } + + // perform the callbacks asynchronously to collect the necessary calls instead + // of executing them immediately. + dm_prop_changed (); + + } + } +} + +const LayerPropertiesNode & +LayoutViewBase::insert_layer (unsigned int index, const LayerPropertiesConstIterator &before, const LayerPropertiesNode &node) +{ + tl_assert (index < layer_lists ()); + + if (transacting ()) { + manager ()->queue (this, new OpInsertLayerProps (index, (unsigned int) before.uint (), node)); + } else if (manager () && ! replaying ()) { + manager ()->clear (); + } + + if (mp_control_panel && index == current_layer_list ()) { + mp_control_panel->begin_updates (); + } + + const LayerPropertiesNode &ret = m_layer_properties_lists [index]->insert (LayerPropertiesIterator (*m_layer_properties_lists [index], before.uint ()), node); + + // signal to the observers that something has changed + if (index == current_layer_list ()) { + layer_list_changed_event (2); + redraw (); + dm_prop_changed (); + } + + return ret; +} + +void +LayoutViewBase::delete_layer (unsigned int index, LayerPropertiesConstIterator &iter) +{ + if (index >= layer_lists ()) { + return; + } + + lay::LayerPropertiesNode orig = *iter; + + if (mp_control_panel && index == current_layer_list ()) { + mp_control_panel->begin_updates (); + } + + // delete the element + m_layer_properties_lists [index]->erase (LayerPropertiesIterator (*m_layer_properties_lists [index], iter.uint ())); + + if (transacting ()) { + manager ()->queue (this, new OpDeleteLayerProps (index, (unsigned int) iter.uint (), orig)); + } else if (manager () && ! replaying ()) { + manager ()->clear (); + } + + // signal to the observers that something has changed + if (index == current_layer_list ()) { + layer_list_changed_event (2); + redraw (); + dm_prop_changed (); + } + + // invalidate the iterator so it can be used to refer to the next element + iter.invalidate (); +} + +void +LayoutViewBase::signal_selection_changed () +{ + if (selection_size () > 1) { + message (tl::sprintf (tl::to_string (tr ("selected: %ld objects")), selection_size ())); + } + + lay::Editables::signal_selection_changed (); +} + +void +LayoutViewBase::save_as (unsigned int index, const std::string &filename, tl::OutputStream::OutputStreamMode om, const db::SaveLayoutOptions &options, bool update, int keep_backups) +{ + tl_assert (index < cellviews ()); + + tl::SelfTimer timer (tl::verbosity () >= 11, tl::to_string (tr ("Saving"))); + cellview (index)->save_as (filename, om, options, update, keep_backups); + + cellview_changed (index); +} + +void +LayoutViewBase::redo (db::Op *op) +{ + tl_assert (! transacting ()); + + OpSetLayerProps *sop = dynamic_cast (op); + if (sop) { + if (sop->m_list_index < m_layer_properties_lists.size ()) { + set_properties (sop->m_list_index, lay::LayerPropertiesConstIterator (*m_layer_properties_lists [sop->m_list_index], sop->m_index), sop->m_new); + } + return; + } + + OpSetLayerPropsNode *snop = dynamic_cast (op); + if (snop) { + if (snop->m_list_index < m_layer_properties_lists.size ()) { + replace_layer_node (snop->m_list_index, lay::LayerPropertiesConstIterator (*m_layer_properties_lists [snop->m_list_index], snop->m_index), snop->m_new); + } + return; + } + + OpInsertLayerList *ilop = dynamic_cast (op); + if (ilop) { + if (ilop->m_list_index <= m_layer_properties_lists.size ()) { + insert_layer_list (ilop->m_list_index, ilop->m_new); + } + return; + } + + OpDeleteLayerList *dlop = dynamic_cast (op); + if (dlop) { + if (dlop->m_list_index < m_layer_properties_lists.size ()) { + delete_layer_list (dlop->m_list_index); + } + return; + } + + OpSetAllProps *saop = dynamic_cast (op); + if (saop) { + if (saop->m_list_index < m_layer_properties_lists.size ()) { + set_properties (saop->m_list_index, saop->m_new); + } + return; + } + + OpRenameProps *rnop = dynamic_cast (op); + if (rnop) { + if (rnop->m_list_index < m_layer_properties_lists.size ()) { + rename_properties (rnop->m_list_index, rnop->m_new); + } + return; + } + + OpLayerList *lop = dynamic_cast (op); + if (lop) { + if (lop->m_list_index < m_layer_properties_lists.size ()) { + if (lop->m_mode == OpLayerList::Insert) { + insert_layer (lop->m_list_index, lay::LayerPropertiesConstIterator (*m_layer_properties_lists [lop->m_list_index], lop->m_index), lop->m_node); + } else { + lay::LayerPropertiesConstIterator iter (*m_layer_properties_lists [lop->m_list_index], lop->m_index); + delete_layer (lop->m_list_index, iter); + } + } + return; + } + + OpSetDitherPattern *stpop = dynamic_cast (op); + if (stpop) { + set_dither_pattern (stpop->m_new); + return; + } + + OpHideShowCell *hscop = dynamic_cast (op); + if (hscop) { + if (hscop->m_show) { + show_cell (hscop->m_cell_index, hscop->m_cellview_index); + } else { + hide_cell (hscop->m_cell_index, hscop->m_cellview_index); + } + return; + } + + db::Object::redo (op); +} + +void +LayoutViewBase::undo (db::Op *op) +{ + tl_assert (! transacting ()); + + OpSetLayerProps *sop = dynamic_cast (op); + if (sop) { + if (sop->m_list_index < m_layer_properties_lists.size ()) { + set_properties (sop->m_list_index, lay::LayerPropertiesConstIterator (*m_layer_properties_lists [sop->m_list_index], sop->m_index), sop->m_old); + } + return; + } + + OpSetLayerPropsNode *snop = dynamic_cast (op); + if (snop) { + if (snop->m_list_index < m_layer_properties_lists.size ()) { + replace_layer_node (snop->m_list_index, lay::LayerPropertiesConstIterator (*m_layer_properties_lists [snop->m_list_index], snop->m_index), snop->m_old); + } + return; + } + + OpInsertLayerList *ilop = dynamic_cast (op); + if (ilop) { + if (ilop->m_list_index <= m_layer_properties_lists.size ()) { + delete_layer_list (ilop->m_list_index); + } + return; + } + + OpDeleteLayerList *dlop = dynamic_cast (op); + if (dlop) { + if (dlop->m_list_index < m_layer_properties_lists.size ()) { + insert_layer_list (dlop->m_list_index, dlop->m_old); + } + return; + } + + OpSetAllProps *saop = dynamic_cast (op); + if (saop) { + if (saop->m_list_index < m_layer_properties_lists.size ()) { + set_properties (saop->m_list_index, saop->m_old); + } + return; + } + + OpRenameProps *rnop = dynamic_cast (op); + if (rnop) { + if (rnop->m_list_index < m_layer_properties_lists.size ()) { + rename_properties (rnop->m_list_index, rnop->m_old); + } + return; + } + + OpLayerList *lop = dynamic_cast (op); + if (lop) { + if (lop->m_list_index < m_layer_properties_lists.size ()) { + if (lop->m_mode == OpLayerList::Insert) { + lay::LayerPropertiesConstIterator iter (*m_layer_properties_lists [lop->m_list_index], lop->m_index); + delete_layer (lop->m_list_index, iter); + } else { + insert_layer (lop->m_list_index, lay::LayerPropertiesConstIterator (*m_layer_properties_lists [lop->m_list_index], lop->m_index), lop->m_node); + } + } + return; + } + + OpHideShowCell *hscop = dynamic_cast (op); + if (hscop) { + + if (hscop->m_show) { + hide_cell (hscop->m_cell_index, hscop->m_cellview_index); + } else { + show_cell (hscop->m_cell_index, hscop->m_cellview_index); + } + + return; + + } + + OpSetDitherPattern *stpop = dynamic_cast (op); + if (stpop) { + set_dither_pattern (stpop->m_old); + return; + } + + db::Object::undo (op); +} + +void +LayoutViewBase::signal_hier_changed () +{ + // schedule a redraw request for all layers + redraw (); + // forward this event to our observers + hier_changed_event (); +} + +void +LayoutViewBase::signal_bboxes_from_layer_changed (unsigned int cv_index, unsigned int layer_index) +{ + if (layer_index == std::numeric_limits::max ()) { + + // redraw all + signal_bboxes_changed (); + + } else { + + // redraw only the layers required for redrawing + for (std::vector::const_iterator l = mp_canvas->get_redraw_layers ().begin (); l != mp_canvas->get_redraw_layers ().end (); ++l) { + if (l->cellview_index == int (cv_index) && l->layer_index == int (layer_index)) { + redraw_layer ((unsigned int) (l - mp_canvas->get_redraw_layers ().begin ())); + } + } + + // forward this event to our observers + geom_changed_event (); + + } +} + +void +LayoutViewBase::signal_bboxes_changed () +{ + // schedule a redraw request for all layers + redraw (); + + // forward this event to our observers + geom_changed_event (); +} + +void +LayoutViewBase::signal_cell_name_changed () +{ + cell_visibility_changed_event (); // HINT: that is not what actually is intended, but it serves the function ... + redraw (); // needs redraw +} + +void +LayoutViewBase::signal_layer_properties_changed () +{ + // recompute the source + // TODO: this is a side effect of this method - provide a special method for this purpose + for (unsigned int i = 0; i < layer_lists (); ++i) { + m_layer_properties_lists [i]->attach_view (this, i); + } + + // schedule a redraw request - since the layer views might not have changed, this is necessary + redraw (); +} + +void +LayoutViewBase::signal_prop_ids_changed () +{ + // inform the layer list observers that they need to recompute the property selectors + layer_list_changed_event (1); + + // recompute the source + // TODO: this is a side effect of this method - provide a special method for this purpose + for (unsigned int i = 0; i < layer_lists (); ++i) { + m_layer_properties_lists [i]->attach_view (this, i); + } +} + +void +LayoutViewBase::signal_plugin_enabled_changed () +{ + for (std::vector::iterator p = mp_plugins.begin (); p != mp_plugins.end (); ++p) { + if ((*p)->editable_interface ()) { + enable ((*p)->editable_interface (), (*p)->plugin_declaration ()->editable_enabled ()); + } + } +} + +void +LayoutViewBase::signal_annotations_changed () +{ + // schedule a redraw request for the annotation shapes + redraw_deco_layer (); + // forward this event to our observers + annotations_changed_event (); +} + +void +LayoutViewBase::finish_cellviews_changed () +{ + update_event_handlers (); + + cellviews_changed_event (); + + redraw (); +} + +std::list::iterator +LayoutViewBase::cellview_iter (int cv_index) +{ + std::list::iterator i = m_cellviews.begin (); + while (cv_index > 0 && i != m_cellviews.end ()) { + ++i; + --cv_index; + } + tl_assert (i != m_cellviews.end ()); + return i; +} + +std::list::const_iterator +LayoutViewBase::cellview_iter (int cv_index) const +{ + std::list::const_iterator i = m_cellviews.begin (); + while (cv_index > 0 && i != m_cellviews.end ()) { + ++i; + --cv_index; + } + tl_assert (i != m_cellviews.end ()); + return i; +} + +void +LayoutViewBase::erase_cellview (unsigned int index) +{ + if (index >= m_cellviews.size ()) { + return; + } + + cancel_esc (); + + // issue to event that signals a change in the cellviews + cellviews_about_to_change_event (); + + // no undo available - clear all transactions + if (manager ()) { + manager ()->clear (); + } + + if (mp_control_panel) { + mp_control_panel->begin_updates (); + } + + m_cellviews.erase (cellview_iter (int (index))); + + if (m_hidden_cells.size () > index) { + m_hidden_cells.erase (m_hidden_cells.begin () + index); + } + + for (unsigned int lindex = 0; lindex < layer_lists (); ++lindex) { + + // remove all references to the cellview + m_layer_properties_lists [lindex]->remove_cv_references (index); + + // rename the ones that got shifted. + lay::LayerPropertiesConstIterator l = begin_layers (lindex); + while (! l.at_end ()) { + lay::ParsedLayerSource source (l->source (false)); + if (source.cv_index () >= int (index)) { + lay::LayerProperties new_props (*l); + source.cv_index (source.cv_index () == int (index) ? -1 : source.cv_index () - 1); + new_props.set_source (source); + LayerPropertiesIterator non_const_iter (*m_layer_properties_lists [lindex], l.uint ()); + *non_const_iter = new_props; + } + ++l; + } + + } + + // clear the history + m_display_states.clear (); + m_display_state_ptr = 0; + + // signal to the observers that something has changed + layer_list_changed_event (3); + + finish_cellviews_changed (); + + update_content (); + + if (m_title.empty ()) { + emit title_changed (); + } +} + +void +LayoutViewBase::clear_cellviews () +{ + // issue to event that signals a change in the cellviews + cellviews_about_to_change_event (); + + // no undo available - clear all transactions + if (manager ()) { + manager ()->clear (); + } + + // clear the layer lists and cellviews + while (layer_lists () > 0) { + delete_layer_list (layer_lists () - 1); + } + set_properties (lay::LayerPropertiesList ()); + m_cellviews.clear (); + + // clear the history, store path and zoom box + m_display_states.clear (); + m_display_state_ptr = 0; + + finish_cellviews_changed (); + + if (m_title.empty ()) { + emit title_changed (); + } +} + +const CellView & +LayoutViewBase::cellview (unsigned int index) const +{ + static const CellView empty; + if (index >= m_cellviews.size ()) { + return empty; + } else { + return *cellview_iter (int (index)); + } +} + +CellViewRef +LayoutViewBase::cellview_ref (unsigned int index) +{ + if (index >= m_cellviews.size ()) { + return CellViewRef (); + } else { + return CellViewRef (cellview_iter (index).operator-> (), this); + } +} + +int +LayoutViewBase::index_of_cellview (const lay::CellView *cv) const +{ + int index = 0; + for (std::list::const_iterator i = m_cellviews.begin (); i != m_cellviews.end (); ++i, ++index) { + if (cv == i.operator-> ()) { + return index; + } + } + return -1; +} + +void +LayoutViewBase::set_layout (const lay::CellView &cv, unsigned int cvindex) +{ + // issue to event that signals a change in the cellviews + cellviews_about_to_change_event (); + + // no undo available - clear all transactions + if (manager ()) { + manager ()->clear (); + } + + // signal the change of layer properties to the observer + layer_list_changed_event (3); + + // create a new cellview if required + while (m_cellviews.size () <= cvindex) { + m_cellviews.push_back (lay::CellView ()); + } + + // set the handle reference and clear all cell related stuff + *cellview_iter (cvindex) = cv; + + // clear the history, store path and zoom box + clear_states (); + + finish_cellviews_changed (); + + // since the hierarchy panel may hold cellviews, we explicitly request an initialization + // of the tree. This will release such references. This way, set_layout guarantees that + // the layouts are released as far as possible. This is important for reload () for example. + if (mp_hierarchy_panel) { + mp_hierarchy_panel->do_update_content (cvindex); + } + + if (m_title.empty ()) { + emit title_changed (); + } +} + +void +LayoutViewBase::signal_apply_technology (lay::LayoutHandle *layout_handle) +{ + // find the cellview which issued the event + for (unsigned int i = 0; i < cellviews (); ++i) { + + if (cellview (i).handle () == layout_handle) { + + cancel_esc (); + + std::string lyp_file; + const db::Technology *tech = db::Technologies::instance ()->technology_by_name (cellview (i)->tech_name ()); + if (tech && ! tech->eff_layer_properties_file ().empty ()) { + lyp_file = tech->eff_layer_properties_file (); + } + + if (! lyp_file.empty ()) { + + // interpolate the layout properties file name + tl::Eval expr; + expr.set_var ("layoutfile", cellview (i)->filename ()); + lyp_file = expr.interpolate (lyp_file); + + // remove all references to the cellview in the layer properties + for (unsigned int lindex = 0; lindex < layer_lists (); ++lindex) { + m_layer_properties_lists [lindex]->remove_cv_references (i); + } + + // if a layer properties file is set, create the layer properties now + create_initial_layer_props (i, lyp_file, tech->add_other_layers ()); + + } + + } + + } +} + +void +LayoutViewBase::load_layer_props (const std::string &fn) +{ + do_load_layer_props (fn, false, -1, false); +} + +void +LayoutViewBase::load_layer_props (const std::string &fn, bool add_default) +{ + do_load_layer_props (fn, false, -1, add_default); +} + +void +LayoutViewBase::load_layer_props (const std::string &fn, int cv_index, bool add_default) +{ + do_load_layer_props (fn, true, cv_index, add_default); +} + +void +LayoutViewBase::do_load_layer_props (const std::string &fn, bool map_cv, int cv_index, bool add_default) +{ + std::vector props; + bool single_list = false; + + // read the layer properties from the file + try { + tl::XMLFileSource in (fn); + props.push_back (lay::LayerPropertiesList ()); + props.back ().load (in); + single_list = true; + } catch (...) { + props.clear (); + tl::XMLFileSource in (fn); + lay::LayerPropertiesList::load (in, props); + } + + // expand the wildcards and map to the target cv. + for (std::vector::iterator p = props.begin (); p != props.end (); ++p) { + std::map cv_map; + if (map_cv) { + cv_map.insert (std::make_pair (-1, cv_index)); + } + p->attach_view (this, p - props.begin ()); + p->expand (cv_map, add_default); + } + + transaction (tl::to_string (tr ("Load layer properties"))); + + if (single_list) { + + // a single list will only replace the current tab + if (map_cv && cv_index >= 0) { + lay::LayerPropertiesList new_props (get_properties ()); + new_props.remove_cv_references (cv_index); + new_props.append (props [0]); + set_properties (new_props); + } else { + set_properties (props [0]); + } + + } else { + + for (unsigned int i = 0; i < props.size (); ++i) { + + if (i < layer_lists ()) { + + if (map_cv && cv_index >= 0) { + lay::LayerPropertiesList new_props (get_properties (i)); + new_props.remove_cv_references (cv_index); + new_props.append (props [i]); + set_properties (i, new_props); + } else { + set_properties (i, props [i]); + } + + } else { + insert_layer_list (i, props [i]); + } + + } + + while (layer_lists () > props.size () && layer_lists () > 1) { + delete_layer_list (layer_lists () - 1); + } + + } + + commit (); + + update_content (); + + tl::log << "Loaded layer properties from " << fn; +} + +void +LayoutViewBase::save_layer_props (const std::string &fn) +{ + tl::OutputStream os (fn, tl::OutputStream::OM_Plain); + + if (layer_lists () == 1) { + + // a single list is written in the traditional format + get_properties ().save (os); + + } else { + + // multiple tabs are written in the multi-tab format + std::vector props; + for (unsigned int i = 0; i < layer_lists (); ++i) { + props.push_back (get_properties (i)); + } + + lay::LayerPropertiesList::save (os, props); + + } + + tl::log << "Saved layer properties to " << fn; +} + +void +LayoutViewBase::add_new_layers (const std::vector &layer_ids, int cv_index) +{ + if (cv_index >= 0 && cv_index < int (cellviews ())) { + + const lay::CellView &cv = cellview (cv_index); + + // create the layers and do a basic recoloring .. + lay::LayerPropertiesList new_props (get_properties ()); + + bool was_empty = new_props.begin_const_recursive ().at_end (); + + // don't create new layers for those, for which there are layers already: compute a + // set of layers already present + std::set present_layers; + for (LayerPropertiesConstIterator lay_iter = begin_layers (); ! lay_iter.at_end (); ++lay_iter) { + if (! lay_iter->has_children () && lay_iter->cellview_index () == cv_index) { + present_layers.insert (lay_iter->source (true /*real*/).layer_props ()); + } + } + + // determine layers which are new and need to be created + std::vector new_layers; + for (std::vector ::const_iterator l = layer_ids.begin (); l != layer_ids.end (); ++l) { + const db::LayerProperties &lp = cv->layout ().get_properties (*l); + if (present_layers.find (lp) == present_layers.end ()) { + new_layers.push_back (lp); + } + } + + // create them in the sorting order provided by db::LayerProperties + std::sort (new_layers.begin (), new_layers.end (), db::LPLogicalLessFunc ()); + + // and actually create them + for (std::vector ::const_iterator l = new_layers.begin (); l != new_layers.end (); ++l) { + lay::LayerProperties p; + p.set_source (lay::ParsedLayerSource (*l, cv_index)); + init_layer_properties (p, new_props); + new_props.push_back (p); + } + + set_properties (new_props); + + if (was_empty) { + set_current_layer (new_props.begin_const_recursive ()); + } + + } +} + +void +LayoutViewBase::init_layer_properties (LayerProperties &p) const +{ + init_layer_properties (p, get_properties ()); +} + +void +LayoutViewBase::init_layer_properties (LayerProperties &p, const LayerPropertiesList &lp_list) const +{ + lay::color_t c = 0; + if (m_palette.luminous_colors () > 0) { + c = m_palette.luminous_color_by_index (p.source (true /*real*/).color_index ()); + } + + p.set_dither_pattern (m_stipple_palette.standard_stipple_by_index (lp_list.end_const () - lp_list.begin_const ())); + p.set_fill_color (c); + p.set_frame_color (c); + p.set_fill_brightness (0); + p.set_frame_brightness (0); + p.set_frame_brightness (0); + p.set_transparent (false); // :TODO: make variable + p.set_visible (true); + p.set_width (1); + p.set_animation (0); + p.set_marked (false); +} + +#if defined(HAVE_QT) +QImage +LayoutViewBase::get_screenshot () +{ + tl::SelfTimer timer (tl::verbosity () >= 11, tl::to_string (QObject::tr ("Save screenshot"))); + + // Execute all deferred methods - ensure there are no pending tasks + tl::DeferredMethodScheduler::execute (); + + return mp_canvas->screenshot (); +} + +void +LayoutViewBase::save_screenshot (const std::string &fn) +{ + tl::SelfTimer timer (tl::verbosity () >= 11, tl::to_string (QObject::tr ("Save screenshot"))); + + QImageWriter writer (tl::to_qstring (fn), QByteArray ("PNG")); + + // Unfortunately the PNG writer does not allow writing of long strings. + // We separate the description into a set of keys: + + for (unsigned int i = 0; i < cellviews (); ++i) { + if (cellview (i).is_valid ()) { + std::string name = cellview (i)->layout ().cell_name (cellview (i).cell_index ()); + writer.setText (tl::to_qstring ("Cell" + tl::to_string (int (i) + 1)), tl::to_qstring (name)); + } + } + + db::DBox b (box ()); + std::string desc; + desc += tl::micron_to_string (b.left ()) + "," + tl::micron_to_string (b.bottom ()); + desc += "/"; + desc += tl::micron_to_string (b.right ()) + "," + tl::micron_to_string (b.top ()); + writer.setText (QString::fromUtf8 ("Rect"), tl::to_qstring (desc)); + + // Execute all deferred methods - ensure there are no pending tasks + tl::DeferredMethodScheduler::execute (); + + if (! writer.write (mp_canvas->screenshot ())) { + throw tl::Exception (tl::to_string (QObject::tr ("Unable to write screenshot to file: %s (%s)")), fn, tl::to_string (writer.errorString ())); + } + + tl::log << "Saved screen shot to " << fn; +} + +QImage +LayoutViewBase::get_image (unsigned int width, unsigned int height) +{ + tl::SelfTimer timer (tl::verbosity () >= 11, tl::to_string (QObject::tr ("Save image"))); + + // Execute all deferred methods - ensure there are no pending tasks + tl::DeferredMethodScheduler::execute (); + + return mp_canvas->image (width, height); +} + +QImage +LayoutViewBase::get_image_with_options (unsigned int width, unsigned int height, int linewidth, int oversampling, double resolution, + lay::Color background, lay::Color foreground, lay::Color active, const db::DBox &target_box, bool monochrome) +{ + tl::SelfTimer timer (tl::verbosity () >= 11, tl::to_string (QObject::tr ("Save image"))); + + // Execute all deferred methods - ensure there are no pending tasks + tl::DeferredMethodScheduler::execute (); + + return mp_canvas->image_with_options (width, height, linewidth, oversampling, resolution, background, foreground, active, target_box, monochrome); +} + +void +LayoutViewBase::save_image (const std::string &fn, unsigned int width, unsigned int height) +{ + tl::SelfTimer timer (tl::verbosity () >= 11, tl::to_string (QObject::tr ("Save image"))); + + QImageWriter writer (tl::to_qstring (fn), QByteArray ("PNG")); + + // Unfortunately the PNG writer does not allow writing of long strings. + // We separate the description into a set of keys: + + for (unsigned int i = 0; i < cellviews (); ++i) { + if (cellview (i).is_valid ()) { + std::string name = cellview (i)->layout ().cell_name (cellview (i).cell_index ()); + writer.setText (tl::to_qstring ("Cell" + tl::to_string (int (i) + 1)), tl::to_qstring (name)); + } + } + + lay::Viewport vp (width, height, mp_canvas->viewport ().target_box ()); + writer.setText (QString::fromUtf8 ("Rect"), tl::to_qstring (vp.box ().to_string ())); + + // Execute all deferred methods - ensure there are no pending tasks + tl::DeferredMethodScheduler::execute (); + + if (! writer.write (mp_canvas->image (width, height))) { + throw tl::Exception (tl::to_string (QObject::tr ("Unable to write screenshot to file: %s (%s)")), fn, tl::to_string (writer.errorString ())); + } + + tl::log << "Saved screen shot to " << fn; +} + +void +LayoutViewBase::save_image_with_options (const std::string &fn, + unsigned int width, unsigned int height, int linewidth, int oversampling, double resolution, + lay::Color background, lay::Color foreground, lay::Color active, const db::DBox &target_box, bool monochrome) +{ + tl::SelfTimer timer (tl::verbosity () >= 11, tl::to_string (QObject::tr ("Save image"))); + + QImageWriter writer (tl::to_qstring (fn), QByteArray ("PNG")); + + // Unfortunately the PNG writer does not allow writing of long strings. + // We separate the description into a set of keys: + + for (unsigned int i = 0; i < cellviews (); ++i) { + if (cellview (i).is_valid ()) { + std::string name = cellview (i)->layout ().cell_name (cellview (i).cell_index ()); + writer.setText (tl::to_qstring ("Cell" + tl::to_string (int (i) + 1)), tl::to_qstring (name)); + } + } + + lay::Viewport vp (width, height, mp_canvas->viewport ().target_box ()); + writer.setText (QString::fromUtf8 ("Rect"), tl::to_qstring (vp.box ().to_string ())); + + // Execute all deferred methods - ensure there are no pending tasks + tl::DeferredMethodScheduler::execute (); + + if (! writer.write (mp_canvas->image_with_options (width, height, linewidth, oversampling, resolution, background, foreground, active, target_box, monochrome))) { + throw tl::Exception (tl::to_string (QObject::tr ("Unable to write screenshot to file: %s (%s)")), fn, tl::to_string (writer.errorString ())); + } + + tl::log << "Saved screen shot to " << fn; +} +#endif + +void +LayoutViewBase::reload_layout (unsigned int cv_index) +{ + stop (); + cancel_esc (); + + // save the current view state + lay::DisplayState state; + save_view (state); + + // this is the cellview at the given index (use a copy since the original is overwritten) + CellView cvorg = cellview (cv_index); + + // obtain the original filename + std::string filename = cvorg->filename (); + std::string technology = cvorg->tech_name (); + std::string name = cvorg->name (); + + // recreate hidden cells by doing a name referencing + std::vector hidden_cells; + if (m_hidden_cells.size () > cv_index) { + hidden_cells.reserve (m_hidden_cells [cv_index].size ()); + for (std::set ::const_iterator ci = m_hidden_cells [cv_index].begin (); ci != m_hidden_cells [cv_index].end (); ++ci) { + hidden_cells.push_back (std::string (cvorg->layout ().cell_name (*ci))); + } + } + + // Set up a list of present layers + std::set present_layers; + for (LayerPropertiesConstIterator lay_iter = begin_layers (); ! lay_iter.at_end (); ++lay_iter) { + if (! lay_iter->has_children ()) { + present_layers.insert (lay_iter->source (true /*real*/).layer_props ()); + } + } + + std::map org_layers; + + for (unsigned int i = 0; i < cvorg->layout ().layers (); ++i) { + if (cvorg->layout ().is_valid_layer (i)) { + const db::LayerProperties &p = cvorg->layout ().get_properties (i); + if (! p.log_equal (db::LayerProperties ())) { + org_layers.insert (std::make_pair (i, p)); + } + } + } + + lay::LayoutHandle *handle; + + // reset the layout: create a dummy handle and install this in between + // this will clear the original layout if not further referenced. + // Since the dummy layout will act as a placeholder if something goes wrong + // when reading the file, it must have the layers created as well + lay::CellView cv_empty; + + handle = new lay::LayoutHandle (new db::Layout (manager ()), filename); + handle->set_tech_name (technology); + cv_empty.set (handle); + + for (std::map ::const_iterator ol = org_layers.begin (); ol != org_layers.end (); ++ol) { + cv_empty->layout ().insert_layer (ol->first, ol->second); + } + cv_empty->rename (name, true); + + set_layout (cv_empty, cv_index); + + // create a new handle + lay::CellView cv; + handle = new lay::LayoutHandle (new db::Layout (manager ()), filename); + cv.set (handle); + + try { + + // re-create the layers required + for (std::map ::const_iterator ol = org_layers.begin (); ol != org_layers.end (); ++ol) { + cv->layout ().insert_layer (ol->first, ol->second); + } + + { + tl::log << tl::to_string (tr ("Loading file: ")) << filename; + tl::SelfTimer timer (tl::verbosity () >= 11, tl::to_string (tr ("Loading"))); + + // Load with the previous options again. + db::LoadLayoutOptions options (cvorg->load_options ()); + cv->load (cvorg->load_options (), technology); + } + + // sort the layout explicitly here. Otherwise it would be done + // implicitly at some other time. This may throw an exception + // if the operation was cancelled. + { + tl::SelfTimer timer (tl::verbosity () >= 11, tl::to_string (tr ("Sorting"))); + cv->layout ().update (); + } + + // print the memory statistics now. + if (tl::verbosity () >= 31) { + db::MemStatisticsCollector m (false); + cv->layout ().mem_stat (&m, db::MemStatistics::LayoutInfo, 0); + m.print (); + } + + // this is required to release every reference to the cv_empty layout + cv_empty = lay::CellView (); + + // install the new layout + cv->rename (name, true); + set_layout (cv, cv_index); + + } catch (...) { + update_content (); + throw; + } + + // recreate the hidden cell indices from the names + if (m_hidden_cells.size () > cv_index) { + m_hidden_cells [cv_index].clear (); + for (std::vector ::const_iterator cn = hidden_cells.begin (); cn != hidden_cells.end (); ++cn) { + std::pair cid = cv->layout ().cell_by_name (cn->c_str ()); + if (cid.first) { + m_hidden_cells [cv_index].insert (cid.second); + } + } + } + + // Determine which layers to create as new layers. New layer need to be created + // if these have not been present in the original layout and there are no layer views + // referring to them. + std::vector new_layers; + for (unsigned int i = 0; i < cv->layout ().layers (); ++i) { + if (cv->layout ().is_valid_layer (i)) { + std::map ::iterator ol = org_layers.find (i); + if (ol == org_layers.end () && present_layers.find (cv->layout ().get_properties (i)) == present_layers.end ()) { + new_layers.push_back (cv->layout ().get_properties (i)); + } + } + } + + std::sort (new_layers.begin (), new_layers.end (), db::LPLogicalLessFunc ()); + + // create the layers and do a basic recoloring .. + lay::LayerPropertiesList new_props (get_properties ()); + + for (std::vector ::const_iterator l = new_layers.begin (); l != new_layers.end (); ++l) { + lay::LayerProperties p; + p.set_source (lay::ParsedLayerSource (*l, int (cv_index))); + init_layer_properties (p, new_props); + new_props.push_back (p); + } + + set_properties (new_props); + + goto_view (state); + +} + +unsigned int +LayoutViewBase::add_layout (lay::LayoutHandle *layout_handle, bool add_cellview, bool initialize_layers) +{ + unsigned int cv_index = 0; + + try { + + m_active_cellview_changed_event_enabled = false; + + stop_redraw (); + + bool set_max_hier = (m_full_hier_new_cell || has_max_hier ()); + + lay::CellView cv; + + if (! add_cellview) { + clear_cellviews (); + } + + cv.set (layout_handle); + + cv->layout ().update (); + + // select the cell with the largest area as the first top cell + db::Layout::top_down_const_iterator top = cv->layout ().begin_top_down (); + for (db::Layout::top_down_const_iterator t = cv->layout ().begin_top_down (); t != cv->layout ().end_top_cells (); ++t) { + if (cv->layout ().cell (*t).bbox ().area () > cv->layout ().cell (*top).bbox ().area ()) { + top = t; + } + } + + if (top != cv->layout ().end_top_down ()) { + std::vector p; + p.push_back (*top); + cv.set_unspecific_path (p); + } + + cv_index = cellviews (); + set_layout (cv, cv_index); + + if (top != cv->layout ().end_top_cells ()) { + std::vector p; + p.push_back (*top); + select_cell (p, cv_index); + } else { + // even if there is no cell, select the cellview item + // to support applications with an active cellview (that is however invalid) + set_active_cellview_index (cv_index); + } + + if (initialize_layers) { + + bool add_other_layers = m_add_other_layers; + + // Use the "layer-properties-file" meta info from the handle to get the layer properties file. + // If no such file is present, use the default file or the technology specific file. + std::string lyp_file = m_def_lyp_file; + const db::Technology *tech = db::Technologies::instance ()->technology_by_name (layout_handle->tech_name ()); + if (tech && ! tech->eff_layer_properties_file ().empty ()) { + lyp_file = tech->eff_layer_properties_file (); + add_other_layers = tech->add_other_layers (); + } + + // Give the layout object a chance to specify a certain layer property file + for (db::Layout::meta_info_iterator meta = cv->layout ().begin_meta (); meta != cv->layout ().end_meta (); ++meta) { + if (meta->name == "layer-properties-file") { + lyp_file = meta->value; + } + if (meta->name == "layer-properties-add-other-layers") { + try { + tl::from_string (meta->value, add_other_layers); + } catch (...) { + } + } + } + + // interpolate the layout properties file name + tl::Eval expr; + expr.set_var ("layoutfile", layout_handle->filename ()); + lyp_file = expr.interpolate (lyp_file); + + // create the initial layer properties + create_initial_layer_props (cv_index, lyp_file, add_other_layers); + + } + + // select the first layer if nothing else is selected + if (cv_index == 0 && ! mp_control_panel->has_selection ()) { + const lay::LayerPropertiesList &lp = get_properties (); + lay::LayerPropertiesConstIterator li = lp.begin_const_recursive (); + while (! li.at_end () && li->has_children ()) { + ++li; + } + if (! li.at_end ()) { + mp_control_panel->set_current_layer (li); + } + } + + // signal to any observers + file_open_event (); + + if (cv->layout ().begin_top_down () != cv->layout ().end_top_down ()) { + + // do a fit and update layer lists etc. + zoom_fit (); + if (set_max_hier) { + max_hier (); + } + update_content (); + + } else { + // even if there is no cell, select the cellview item + // to support applications with an active cellview (that is however invalid) + set_active_cellview_index (cv_index); + } + + m_active_cellview_changed_event_enabled = true; + + } catch (...) { + + update_content (); + + m_active_cellview_changed_event_enabled = true; + throw; + + } + + // this event may not be generated otherwise, hence force it now. + active_cellview_changed (cv_index); + + return cv_index; +} + +unsigned int +LayoutViewBase::create_layout (const std::string &technology, bool add_cellview, bool initialize_layers) +{ + const db::Technology *tech = db::Technologies::instance ()->technology_by_name (technology); + + db::Layout *layout = new db::Layout (manager ()); + if (tech) { + layout->dbu (tech->dbu ()); + } + + lay::LayoutHandle *handle = new lay::LayoutHandle (layout, ""); + handle->set_tech_name (technology); + return add_layout (handle, add_cellview, initialize_layers); +} + +unsigned int +LayoutViewBase::load_layout (const std::string &filename, const std::string &technology, bool add_cellview) +{ + return load_layout (filename, db::LoadLayoutOptions (), technology, add_cellview); +} + +unsigned int +LayoutViewBase::load_layout (const std::string &filename, const db::LoadLayoutOptions &options, const std::string &technology, bool add_cellview) +{ + stop (); + + bool set_max_hier = (m_full_hier_new_cell || has_max_hier ()); + + const db::Technology *tech = db::Technologies::instance ()->technology_by_name (technology); + + // create a new layout handle + lay::CellView cv; + lay::LayoutHandle *handle = new lay::LayoutHandle (new db::Layout (manager ()), filename); + cv.set (handle); + + unsigned int cv_index; + db::LayerMap lmap; + + try { + + tl::SelfTimer timer (tl::verbosity () >= 11, tl::to_string (tr ("Loading"))); + + // load the file + { + tl::log << tl::to_string (tr ("Loading file: ")) << filename << tl::to_string (tr (" with technology: ")) << technology; + lmap = cv->load (options, technology); + } + + // sort the layout explicitly here. Otherwise it would be done + // implicitly at some other time. This may throw an exception + // if the operation was cancelled. + { + cv->layout ().update (); + } + + // print the memory statistics now. + if (tl::verbosity () >= 31) { + db::MemStatisticsCollector m (false); + cv->layout ().mem_stat (&m, db::MemStatistics::LayoutInfo, 0); + m.print (); + } + + // clear the cellviews if required + if (! add_cellview) { + clear_cellviews (); + } + + // set the new layout as the layout for the last cellview + cv_index = cellviews (); + set_layout (cv, cv_index); + + } catch (...) { + + update_content (); + throw; + + } + + try { + + m_active_cellview_changed_event_enabled = false; + + // select the cell with the largest area as the first top cell + db::Layout::top_down_const_iterator top = cv->layout ().begin_top_down (); + for (db::Layout::top_down_const_iterator t = cv->layout ().begin_top_down (); t != cv->layout ().end_top_cells (); ++t) { + if (cv->layout ().cell (*t).bbox ().area () > cv->layout ().cell (*top).bbox ().area ()) { + top = t; + } + } + if (top != cv->layout ().end_top_cells ()) { + std::vector p; + p.push_back (*top); + select_cell (p, cv_index); + } else { + // even if there is no cell, select the cellview item + // to support applications with an active cellview (that is however invalid) + set_active_cellview_index (cv_index); + } + + bool add_other_layers = m_add_other_layers; + + // Use the "layer-properties-file" meta info from the handle to get the layer properties file. + // If no such file is present, use the default file or the technology specific file. + std::string lyp_file = m_def_lyp_file; + if (tech && ! tech->eff_layer_properties_file ().empty ()) { + lyp_file = tech->eff_layer_properties_file (); + add_other_layers = tech->add_other_layers (); + } + + // Give the layout object a chance to specify a certain layer property file + for (db::Layout::meta_info_iterator meta = cv->layout().begin_meta (); meta != cv->layout().end_meta (); ++meta) { + if (meta->name == "layer-properties-file") { + lyp_file = meta->value; + } + if (meta->name == "layer-properties-add-other-layers") { + try { + tl::from_string (meta->value, add_other_layers); + } catch (...) { + } + } + } + + // interpolate the layout properties file name + tl::Eval expr; + expr.set_var ("layoutfile", filename); + lyp_file = expr.interpolate (lyp_file); + + // create the initial layer properties + create_initial_layer_props (cv_index, lyp_file, add_other_layers); + + // select the first layer if nothing else is selected + if (cv_index == 0 && ! mp_control_panel->has_selection ()) { + const lay::LayerPropertiesList &lp = get_properties (); + lay::LayerPropertiesConstIterator li = lp.begin_const_recursive (); + while (! li.at_end () && li->has_children ()) { + ++li; + } + if (! li.at_end ()) { + mp_control_panel->set_current_layer (li); + } + } + + // signal to any observers + file_open_event (); + + // do a fit and update layer lists etc. + zoom_fit (); + if (set_max_hier) { + max_hier (); + } + update_content (); + + m_active_cellview_changed_event_enabled = true; + + } catch (...) { + + update_content (); + + m_active_cellview_changed_event_enabled = true; + throw; + + } + + // this event may not be generated otherwise, hence force it now. + active_cellview_changed (cv_index); + + return cv_index; +} + +void +LayoutViewBase::create_initial_layer_props (int cv_index, const std::string &lyp_file, bool add_missing) +{ + std::vector props; + bool loaded = false; + + if (! lyp_file.empty ()) { + + // read the layer properties from the file + try { + + try { + tl::XMLFileSource in (lyp_file); + props.push_back (lay::LayerPropertiesList ()); + props.back ().load (in); + loaded = true; + } catch (...) { + props.clear (); + tl::XMLFileSource in (lyp_file); + tl::log << tl::to_string (tr ("Loading layer properties file: ")) << lyp_file; + lay::LayerPropertiesList::load (in, props); + loaded = true; + } + + } catch (tl::Exception &ex) { + tl::warn << tl::to_string (tr ("Initialization of layers failed: ")) << ex.msg (); + } catch (...) { + tl::warn << tl::to_string (tr ("Initialization of layers failed: unspecific error")); + } + + } + + std::map cv_map; + cv_map.insert (std::make_pair (-1, cv_index)); + + if (! loaded) { + + props.clear (); + props.push_back (lay::LayerPropertiesList ()); + + } else { + + // do't map cv's if the input file is a multi-cv one. + std::set cv; + for (std::vector::const_iterator p = props.begin (); p != props.end (); ++p) { + for (lay::LayerPropertiesConstIterator lp = p->begin_const_recursive (); ! lp.at_end (); ++lp) { + if (! lp->has_children ()) { + cv.insert (lp->source (true).cv_index ()); + if (cv.size () >= 2) { + cv_map.clear (); + cv_map.insert (std::make_pair (cv_index, cv_index)); + // erase the others: + cv_map.insert (std::make_pair (-1, -2)); + break; + } + } + } + } + + } + + // expand the wildcards and map to the target cv. + for (std::vector::iterator p = props.begin (); p != props.end (); ++p) { + p->attach_view (this, p - props.begin ()); + p->expand (cv_map, add_missing || !loaded); + } + + merge_layer_props (props); +} + +void +LayoutViewBase::merge_layer_props (const std::vector &props) +{ + lay::LayerPropertiesList p0; + if (layer_lists () > 0) { + p0 = get_properties (0); + } + + // merge the new layer views into the present ones + // If the specific list is a single list (no tabs), it is merged into every tab present. + if (props.size () == 1) { + + for (size_t n = 0; n < layer_lists () || n == 0; ++n) { + + std::vector::const_iterator p = props.begin (); + + if (n < layer_lists ()) { + lay::LayerPropertiesList new_props (get_properties ((unsigned int) n)); + new_props.append (*p); + if (! p->name ().empty ()) { + new_props.set_name (p->name ()); + } + set_properties ((unsigned int) n, new_props); + } else { + + lay::LayerPropertiesList new_props = p0; + new_props.append (*p); + if (! p->name ().empty ()) { + new_props.set_name (p->name ()); + } + insert_layer_list ((unsigned int) n, new_props); + } + + } + + } else { + + size_t n = 0; + for (std::vector::const_iterator p = props.begin (); p != props.end (); ++p, ++n) { + + if (n < layer_lists ()) { + lay::LayerPropertiesList new_props (get_properties ((unsigned int) n)); + new_props.append (*p); + if (! p->name ().empty ()) { + new_props.set_name (p->name ()); + } + set_properties ((unsigned int) n, new_props); + } else { + lay::LayerPropertiesList new_props = p0; + new_props.append (*p); + if (! p->name ().empty ()) { + new_props.set_name (p->name ()); + } + insert_layer_list ((unsigned int) n, new_props); + } + + } + + } +} + +void +LayoutViewBase::pop_state () +{ + if (m_display_state_ptr > 0) { + m_display_states.erase (m_display_states.begin () + m_display_state_ptr, m_display_states.end ()); + --m_display_state_ptr; + } +} + +void +LayoutViewBase::clear_states () +{ + m_display_states.clear (); + m_display_state_ptr = 0; +} + +void +LayoutViewBase::store_state () +{ + // erase all states after the current position + if (m_display_state_ptr + 1 < m_display_states.size ()) { + m_display_states.erase (m_display_states.begin () + m_display_state_ptr + 1, m_display_states.end ()); + } + + // save the state + DisplayState state (box (), get_min_hier_levels (), get_max_hier_levels (), m_cellviews); + m_display_states.push_back (state); + + m_display_state_ptr = (unsigned int) (m_display_states.size () - 1); +} + +db::DBox +LayoutViewBase::box () const +{ + return mp_canvas->viewport ().box (); +} + +void +LayoutViewBase::timer () +{ + bool dirty = false; + for (std::list::const_iterator i = m_cellviews.begin (); i != m_cellviews.end () && ! dirty; ++i) { + dirty = (*i)->layout ().is_editable () && (*i)->is_dirty (); + } + + if (dirty != m_dirty) { + m_dirty = dirty; + emit dirty_changed (); + } + + if (m_animated) { + set_view_ops (); + if (mp_control_panel) { + mp_control_panel->set_phase (int (m_phase)); + } + if (m_animated) { + ++m_phase; + } + } +} + +bool +LayoutViewBase::layer_model_updated () +{ + // because check_updated is called in the initialization phase, we check if the pointers + // to the widgets are non-null: + if (mp_control_panel) { + return mp_control_panel->model_updated (); + } else { + return false; + } +} + +void +LayoutViewBase::force_update_content () +{ + set_view_ops (); +} + +void +LayoutViewBase::update_content () +{ + if (m_activated) { + set_view_ops (); + } +} + +void +LayoutViewBase::zoom_fit_sel () +{ + db::DBox bbox = selection_bbox (); + if (! bbox.empty ()) { + bbox = db::DBox (bbox.left () - 0.025 * bbox.width (), bbox.bottom () - 0.025 * bbox.height (), + bbox.right () + 0.025 * bbox.width (), bbox.top () + 0.025 * bbox.height ()); + zoom_box (bbox); + } +} + +db::DBox +LayoutViewBase::full_box () const +{ + // compute the bounding box over all layers + // this will trigger the update procedures of the layout objects if not done yet .. + + db::DBox bbox; + + for (LayerPropertiesConstIterator l = get_properties ().begin_const_recursive (); ! l.at_end (); ++l) { + bbox += l->bbox (); + } + + for (lay::AnnotationShapes::iterator a = annotation_shapes ().begin (); ! a.at_end (); ++a) { + bbox += a->box (); + } + + if (bbox.empty ()) { + bbox = db::DBox (0, 0, 0, 0); // default box + } else { + bbox = db::DBox (bbox.left () - 0.025 * bbox.width (), bbox.bottom () - 0.025 * bbox.height (), + bbox.right () + 0.025 * bbox.width (), bbox.top () + 0.025 * bbox.height ()); + } + + return bbox; +} + +void +LayoutViewBase::zoom_fit () +{ + mp_canvas->zoom_box (full_box (), true /*precious*/); + store_state (); +} + +void +LayoutViewBase::ensure_selection_visible () +{ + ensure_visible (selection_bbox ()); +} + +void +LayoutViewBase::ensure_visible (const db::DBox &bbox) +{ + db::DBox new_box = bbox + viewport ().box (); + mp_canvas->zoom_box (new_box); + store_state (); +} + +void +LayoutViewBase::zoom_box_and_set_hier_levels (const db::DBox &bbox, const std::pair &levels) +{ + mp_canvas->zoom_box (bbox); + set_hier_levels_basic (levels); + store_state (); +} + +void +LayoutViewBase::zoom_box (const db::DBox &bbox) +{ + mp_canvas->zoom_box (bbox); + store_state (); +} + +void +LayoutViewBase::set_global_trans (const db::DCplxTrans &trans) +{ + mp_canvas->set_global_trans (trans); + store_state (); +} + +void +LayoutViewBase::zoom_trans (const db::DCplxTrans &trans) +{ + mp_canvas->zoom_trans (trans); + store_state (); +} + +void +LayoutViewBase::pan_left () +{ + shift_window (1.0, -m_pan_distance, 0.0); +} + +void +LayoutViewBase::pan_right () +{ + shift_window (1.0, m_pan_distance, 0.0); +} + +void +LayoutViewBase::pan_up () +{ + shift_window (1.0, 0.0, m_pan_distance); +} + +void +LayoutViewBase::pan_down () +{ + shift_window (1.0, 0.0, -m_pan_distance); +} + +void +LayoutViewBase::pan_left_fast () +{ + shift_window (1.0, -m_pan_distance * fast_factor, 0.0); +} + +void +LayoutViewBase::pan_right_fast () +{ + shift_window (1.0, m_pan_distance * fast_factor, 0.0); +} + +void +LayoutViewBase::pan_up_fast () +{ + shift_window (1.0, 0.0, m_pan_distance * fast_factor); +} + +void +LayoutViewBase::pan_down_fast () +{ + shift_window (1.0, 0.0, -m_pan_distance * fast_factor); +} + +void +LayoutViewBase::pan_center (const db::DPoint &p) +{ + db::DBox b = mp_canvas->viewport ().box (); + db::DVector d (b.width () * 0.5, b.height () * 0.5); + zoom_box (db::DBox (p - d, p + d)); +} + +void +LayoutViewBase::zoom_in () +{ + shift_window (zoom_factor, 0.0, 0.0); +} + +void +LayoutViewBase::zoom_out () +{ + shift_window (1.0 / zoom_factor, 0.0, 0.0); +} + +void +LayoutViewBase::shift_window (double f, double dx, double dy) +{ + db::DBox b = mp_canvas->viewport ().box (); + + db::DPoint s = mp_canvas->viewport ().global_trans ().inverted () * db::DPoint (dx, dy); + db::DPoint c = b.center () + db::DVector (b.width () * s.x (), b.height () * s.y ()); + + double w = b.width () * f; + double h = b.height () * f; + + db::DVector d (w * 0.5, h * 0.5); + + zoom_box (db::DBox (c - d, c + d)); +} + +void +LayoutViewBase::goto_window (const db::DPoint &p, double s) +{ + if (s > 1e-6) { + db::DBox b (p.x () - s * 0.5, p.y () - s * 0.5, p.x () + s * 0.5, p.y () + s * 0.5); + zoom_box (b); + } else { + db::DBox b (box ()); + b.move (p - b.center ()); + zoom_box (b); + } +} + +void +LayoutViewBase::redraw_layer (unsigned int index) +{ + do_redraw (index); +} + +void +LayoutViewBase::redraw_cell_boxes () +{ + do_redraw (lay::draw_boxes_queue_entry); +} + +void +LayoutViewBase::redraw_deco_layer () +{ + // redraw background annotations (images etc.) + mp_canvas->touch_bg (); + + // redraw other annotations: + do_redraw (lay::draw_custom_queue_entry); +} + +void +LayoutViewBase::redraw () +{ + std::vector layers; + + size_t nlayers = 0; + for (lay::LayerPropertiesConstIterator l = begin_layers (); !l.at_end (); ++l) { + if (! l->has_children ()) { + ++nlayers; + } + } + layers.reserve (nlayers); + + for (lay::LayerPropertiesConstIterator l = begin_layers (); !l.at_end (); ++l) { + if (! l->has_children ()) { + layers.push_back (RedrawLayerInfo (*l)); + } + } + + mp_canvas->redraw_new (layers); +} + +void +LayoutViewBase::cancel_edits () +{ + // cancel all drag and pending edit operations such as move operations. + mp_canvas->drag_cancel (); + lay::Editables::cancel_edits (); +} + +void +LayoutViewBase::cancel () +{ + // cancel all drags and pending edit operations such as move operations. + cancel_edits (); + // re-enable edit mode + enable_edits (true); + // and clear the selection + clear_selection (); +} + +void +LayoutViewBase::cancel_esc () +{ + cancel (); + switch_mode (default_mode ()); +} + +void +LayoutViewBase::goto_view (const DisplayState &state) +{ + mp_canvas->zoom_box (state.box ()); + + std::list cellviews; + for (unsigned int i = 0; i < m_cellviews.size (); ++i) { + cellviews.push_back (state.cellview (i, cellview_iter (i)->operator-> ())); + } + + select_cellviews (cellviews); + + if (state.min_hier () <= state.max_hier ()) { + set_hier_levels_basic (std::make_pair (state.min_hier (), state.max_hier ())); + } + + update_content (); +} + +void +LayoutViewBase::save_view (DisplayState &state) const +{ + state = DisplayState (box (), get_min_hier_levels (), get_max_hier_levels (), m_cellviews); +} + +void +LayoutViewBase::do_redraw (int layer) +{ + std::vector layers; + layers.push_back (layer); + + mp_canvas->redraw_selected (layers); +} + +void +LayoutViewBase::do_prop_changed () +{ + if (m_visibility_changed) { + + // change visibility and redraw exposed layers + std::vector visibility; + for (lay::LayerPropertiesConstIterator l = begin_layers (); !l.at_end (); ++l) { + if (! l->has_children ()) { + visibility.push_back (l->visible (true /*real*/)); + } + } + mp_canvas->change_visibility (visibility); + + m_visibility_changed = false; + + } + + update_content (); +} + +void +LayoutViewBase::layer_tab_changed () +{ + update_content (); +} + +void +LayoutViewBase::layer_order_changed () +{ + update_content (); +} + +void +LayoutViewBase::set_view_ops () +{ + bool bright_background = (mp_canvas->background_color ().green () > 128); + int brightness_for_context = ((bright_background ? m_ctx_dimming : -m_ctx_dimming) * 256) / 100; + int brightness_for_child_context = ((bright_background ? m_child_ctx_dimming : -m_child_ctx_dimming) * 256) / 100; + + // count the layers to be able to reserve the number of view_ops + size_t nlayers = 0; + for (LayerPropertiesConstIterator lp = get_properties ().begin_const_recursive (); !lp.at_end (); ++lp) { + if (! lp->has_children ()) { + ++nlayers; + } + } + + std::vector view_ops; + view_ops.reserve (nlayers * planes_per_layer + special_planes_before + special_planes_after); + + lay::Color box_color; + if (! m_box_color.is_valid ()) { + box_color = mp_canvas->foreground_color (); + } else { + box_color = m_box_color; + } + + // cell boxes + if (m_cell_box_visible) { + + lay::ViewOp vop; + + // context level + if (m_ctx_color.is_valid ()) { + vop = lay::ViewOp (m_ctx_color.rgb (), lay::ViewOp::Copy, 0, 0, 0); + } else { + vop = lay::ViewOp (lay::LayerProperties::brighter (box_color.rgb (), brightness_for_context), lay::ViewOp::Copy, 0, 0, 0); + } + + // fill, frame, text, vertex + view_ops.push_back (lay::ViewOp (0, lay::ViewOp::Or, 0, 0, 0)); + view_ops.push_back (vop); + view_ops.push_back (vop); + view_ops.push_back (lay::ViewOp (0, lay::ViewOp::Or, 0, 0, 0)); + + // child level + if (m_child_ctx_color.is_valid ()) { + vop = lay::ViewOp (m_child_ctx_color.rgb (), lay::ViewOp::Copy, 0, 0, 0); + } else { + vop = lay::ViewOp (lay::LayerProperties::brighter (box_color.rgb (), brightness_for_context), lay::ViewOp::Copy, 0, 0, 0); + } + + // fill, frame, text, vertex + view_ops.push_back (lay::ViewOp (0, lay::ViewOp::Or, 0, 0, 0)); + view_ops.push_back (vop); + view_ops.push_back (vop); + view_ops.push_back (lay::ViewOp (0, lay::ViewOp::Or, 0, 0, 0)); + + // current level + vop = lay::ViewOp (box_color.rgb (), lay::ViewOp::Copy, 0, 0, 0); + + // fill, frame, text, vertex + view_ops.push_back (lay::ViewOp (0, lay::ViewOp::Or, 0, 0, 0)); + view_ops.push_back (vop); + view_ops.push_back (vop); + view_ops.push_back (lay::ViewOp (0, lay::ViewOp::Or, 0, 0, 0)); + + } else { + // invisible + for (unsigned int i = 0; i < (unsigned int) planes_per_layer; ++i) { // frame, fill, vertex, text + view_ops.push_back (lay::ViewOp (0, lay::ViewOp::Or, 0, 0, 0)); + } + } + + // sanity check: number of planes defined in layRedrawThreadWorker must match to view_ops layout + tl_assert (view_ops.size () == (size_t)cell_box_planes); + + // produce the ViewOps for the guiding shapes + + color_t gs_color = box_color.rgb (); + if (m_guiding_shape_color.is_valid ()) { + gs_color = m_guiding_shape_color.rgb (); + } + + for (int ctx = 0; ctx < 3; ++ctx) { // 0 (context), 1 (child), 2 (current) + + lay::ViewOp::Mode mode = lay::ViewOp::Copy; + + color_t fill_color, frame_color, text_color; + int dp = 1; // no stipples for guiding shapes + + if (ctx == 0) { + + // context planes + if (m_ctx_color.is_valid ()) { + frame_color = text_color = fill_color = m_ctx_color.rgb (); + } else { + frame_color = text_color = fill_color = lay::LayerProperties::brighter (gs_color, brightness_for_context); + } + + if (m_ctx_hollow) { + dp = 1; + } + + } else if (ctx == 1) { + + // child level planes (if used) + if (m_child_ctx_color.is_valid ()) { + frame_color = text_color = fill_color = m_child_ctx_color.rgb (); + } else { + frame_color = text_color = fill_color = lay::LayerProperties::brighter (gs_color, brightness_for_child_context); + } + + if (m_child_ctx_hollow) { + dp = 1; + } + + } else { + + // current level planes + frame_color = text_color = fill_color = gs_color; + + } + + if (m_guiding_shape_visible) { + + // fill + view_ops.push_back (lay::ViewOp (fill_color, mode, 0, dp, 0)); // fill + + // frame + view_ops.push_back (lay::ViewOp (frame_color, mode, 0, 0, 0, lay::ViewOp::Rect, m_guiding_shape_line_width)); + + // text + if (m_text_visible) { + view_ops.push_back (lay::ViewOp (text_color, mode, 0, 0, 0)); + } else { + view_ops.push_back (lay::ViewOp (0, lay::ViewOp::Or, 0, 0, 0)); + } + + // vertex + view_ops.push_back (lay::ViewOp (frame_color, mode, 0, 0, 0, lay::ViewOp::Rect, m_guiding_shape_vertex_size /*mark size*/)); // vertex + + } else { + view_ops.push_back (lay::ViewOp ()); + view_ops.push_back (lay::ViewOp ()); + view_ops.push_back (lay::ViewOp ()); + view_ops.push_back (lay::ViewOp ()); + } + + } + + // sanity check: number of planes defined in layRedrawThreadWorker must match to view_ops layout + tl_assert (view_ops.size () == (size_t)special_planes_before); + + bool animated = false; + + for (int ctx = 0; ctx < 3; ++ctx) { // 0 (context), 1 (child), 2 (current) + + unsigned int ilayer = 0; + for (LayerPropertiesConstIterator lp = get_properties ().begin_const_recursive (); !lp.at_end (); ++lp, ++ilayer) { + + // because accessing the LayerPropertiesNode with lp->... is not quite efficient, we get the pointer here: + const lay::LayerPropertiesNode *l = &*lp; + + if (l->has_children ()) { + continue; + } + + bool animate_visible = true; + unsigned int di_off = m_stipple_offset ? ilayer : 0; + + if (l->animation (true /*real*/)) { + + animated = true; + if (! m_animated) { + m_animated = true; + m_phase = 0; + } + + if (l->animation (true /*real*/) == 1) { + // scrolling + di_off += m_phase; + } else if (l->animation (true /*real*/) == 2) { + // blinking + animate_visible = ((m_phase & 1) == 0); + } else { + // inversely blinking + animate_visible = ((m_phase & 1) != 0); + } + + } + + if (l->visible (true /*real*/) && animate_visible) { + + lay::ViewOp::Mode mode = lay::ViewOp::Copy; + if (l->transparent (true /*real*/)) { + if (bright_background) { + mode = lay::ViewOp::And; + } else { + mode = lay::ViewOp::Or; + } + } + + color_t fill_color, frame_color, text_color; + int dp = m_no_stipples ? 1 : l->dither_pattern (true /*real*/); + int ls = l->line_style (true /*real*/); + + if (ctx == 0) { + + // context planes + if (m_ctx_color.is_valid ()) { + frame_color = text_color = fill_color = m_ctx_color.rgb (); + } else { + fill_color = l->eff_fill_color_brighter (true /*real*/, brightness_for_context); + frame_color = l->eff_frame_color_brighter (true /*real*/, brightness_for_context); + if (m_text_color.is_valid ()) { + text_color = lay::LayerProperties::brighter (m_text_color.rgb (), brightness_for_context); + } else { + text_color = frame_color; + } + } + + if (m_ctx_hollow) { + dp = 1; + } + + } else if (ctx == 1) { + + // child level planes (if used) + if (m_child_ctx_color.is_valid ()) { + frame_color = text_color = fill_color = m_child_ctx_color.rgb (); + } else { + fill_color = l->eff_fill_color_brighter (true /*real*/, brightness_for_child_context); + frame_color = l->eff_frame_color_brighter (true /*real*/, brightness_for_child_context); + if (m_text_color.is_valid ()) { + text_color = lay::LayerProperties::brighter (m_text_color.rgb (), brightness_for_child_context); + } else { + text_color = frame_color; + } + } + + if (m_child_ctx_hollow) { + dp = 1; + } + + } else { + + // current level planes + fill_color = l->eff_fill_color (true /*real*/); + frame_color = l->eff_frame_color (true /*real*/); + if (m_text_color.is_valid ()) { + text_color = m_text_color.rgb (); + } else { + text_color = frame_color; + } + + } + + // fill + view_ops.push_back (lay::ViewOp (fill_color, mode, 0, dp, di_off)); // fill + + // frame + int lw = l->width (true /*real*/); + if (lw < 0) { + // default line width is 0 for parents and 1 for leafs + lw = l->has_children () ? 0 : 1; + } + view_ops.push_back (lay::ViewOp (frame_color, mode, ls, 0, 0, lay::ViewOp::Rect, lw)); + + // text + if (m_text_visible) { + view_ops.push_back (lay::ViewOp (text_color, mode, 0, 0, 0)); + } else { + view_ops.push_back (lay::ViewOp (0, lay::ViewOp::Or, 0, 0, 0)); + } + // vertex + view_ops.push_back (lay::ViewOp (frame_color, mode, 0, 0, 0, lay::ViewOp::Cross, l->marked (true /*real*/) ? 9/*mark size*/ : 0)); // vertex + + } else { + for (unsigned int i = 0; i < (unsigned int) planes_per_layer / 3; ++i) { + view_ops.push_back (lay::ViewOp (0, lay::ViewOp::Or, 0, 0, 0)); + } + } + + } + + } + + if (! animated) { + m_animated = false; + m_phase = 0; + } + + mp_canvas->set_view_ops (view_ops); +} + +void +LayoutViewBase::guiding_shapes_visible (bool v) +{ + if (v != m_guiding_shape_visible) { + m_guiding_shape_visible = v; + update_content (); + } +} + +void +LayoutViewBase::guiding_shapes_color (lay::Color c) +{ + if (c != m_guiding_shape_color) { + m_guiding_shape_color = c; + update_content (); + } +} + +void +LayoutViewBase::guiding_shapes_line_width (int v) +{ + if (v != m_guiding_shape_line_width) { + m_guiding_shape_line_width = v; + update_content (); + } +} + +void +LayoutViewBase::guiding_shapes_vertex_size (int v) +{ + if (v != m_guiding_shape_vertex_size) { + m_guiding_shape_vertex_size = v; + update_content (); + } +} + +void +LayoutViewBase::draw_array_border_instances (bool m) +{ + if (m != m_draw_array_border_instances) { + m_draw_array_border_instances = m; + redraw (); + } +} + +void +LayoutViewBase::drop_small_cells (bool m) +{ + if (m != m_drop_small_cells) { + m_drop_small_cells = m; + redraw (); + } +} + +void +LayoutViewBase::drop_small_cells_value (unsigned int s) +{ + if (s != m_drop_small_cells_value) { + m_drop_small_cells_value = s; + redraw (); + } +} + +void +LayoutViewBase::drop_small_cells_cond (drop_small_cells_cond_type t) +{ + if (t != m_drop_small_cells_cond) { + m_drop_small_cells_cond = t; + redraw (); + } +} + +void +LayoutViewBase::cell_box_color (lay::Color c) +{ + if (c != m_box_color) { + m_box_color = c; + update_content (); + } +} + +void +LayoutViewBase::cell_box_text_transform (bool xform) +{ + if (xform != m_box_text_transform) { + m_box_text_transform = xform; + redraw (); + } +} + +void +LayoutViewBase::cell_box_text_font (unsigned int f) +{ + if (f != m_box_font) { + m_box_font = f; + redraw (); + } +} + +bool +LayoutViewBase::set_hier_levels_basic (std::pair l) +{ + if (l != get_hier_levels ()) { + + if (mp_min_hier_spbx) { + mp_min_hier_spbx->blockSignals (true); + mp_min_hier_spbx->setValue (l.first); + mp_min_hier_spbx->setMaximum (l.second); + mp_min_hier_spbx->blockSignals (false); + } + + if (mp_max_hier_spbx) { + mp_max_hier_spbx->blockSignals (true); + mp_max_hier_spbx->setValue (l.second); + mp_max_hier_spbx->setMinimum (l.first); + mp_max_hier_spbx->blockSignals (false); + } + + m_from_level = l.first; + m_to_level = l.second; + + // notify all connected observers + hier_levels_changed_event (); + + redraw (); + + return true; + + } else { + return false; + } +} + +void +LayoutViewBase::set_hier_levels (std::pair l) +{ + if (set_hier_levels_basic (l)) { + store_state (); + } +} + +std::pair +LayoutViewBase::get_hier_levels () const +{ + return std::make_pair (m_from_level, m_to_level); +} + +void +LayoutViewBase::min_hier_changed (int i) +{ + mp_max_hier_spbx->setMinimum (i); + set_hier_levels (std::make_pair (i, m_to_level)); +} + +void +LayoutViewBase::max_hier_changed (int i) +{ + mp_min_hier_spbx->setMaximum (i); + set_hier_levels (std::make_pair (m_from_level, i)); +} + +/** + * @brief set the maximum hierarchy level to the number of levels available + */ +void +LayoutViewBase::max_hier () +{ + // determine the maximum level of hierarchies + int max_level = max_hier_level (); + + // and set the levels + if (max_level > 0) { + set_hier_levels (std::make_pair (std::min (m_from_level, max_level), max_level)); + } +} + +/** + * @brief determine the maximum hierarchy level + */ +int +LayoutViewBase::max_hier_level () const +{ + int max_level = 0; + for (std::list ::const_iterator cv = m_cellviews.begin (); cv != m_cellviews.end (); ++cv) { + if (cv->is_valid ()) { + int nl = cv->ctx_cell ()->hierarchy_levels () + 1; + if (nl > max_level) { + max_level = nl; + } + } + } + return max_level; +} + +/** + * @brief Returns a value indicating whether the maximum level is shown + */ +bool +LayoutViewBase::has_max_hier () const +{ + int ml = max_hier_level (); + return ml > 0 && m_to_level >= ml; +} + +void +LayoutViewBase::set_palette (const lay::ColorPalette &p) +{ + m_palette = p; +} + +void +LayoutViewBase::set_palette (const lay::StipplePalette &p) +{ + m_stipple_palette = p; +} + +void +LayoutViewBase::set_palette (const lay::LineStylePalette &p) +{ + m_line_style_palette = p; +} + +void +LayoutViewBase::ctx_color (lay::Color c) +{ + if (c != m_ctx_color) { + m_ctx_color = c; + update_content (); + } +} + +void +LayoutViewBase::ctx_dimming (int d) +{ + if (d != m_ctx_dimming) { + m_ctx_dimming = d; + update_content (); + } +} + +void +LayoutViewBase::ctx_hollow (bool h) +{ + if (h != m_ctx_hollow) { + m_ctx_hollow = h; + update_content (); + } +} + +void +LayoutViewBase::child_ctx_color (lay::Color c) +{ + if (c != m_child_ctx_color) { + m_child_ctx_color = c; + update_content (); + } +} + +void +LayoutViewBase::child_ctx_dimming (int d) +{ + if (d != m_child_ctx_dimming) { + m_child_ctx_dimming = d; + update_content (); + } +} + +void +LayoutViewBase::child_ctx_hollow (bool h) +{ + if (h != m_child_ctx_hollow) { + m_child_ctx_hollow = h; + update_content (); + } +} + +void +LayoutViewBase::child_ctx_enabled (bool f) +{ + if (f != m_child_ctx_enabled) { + m_child_ctx_enabled = f; + update_content (); + redraw (); + } +} + +void +LayoutViewBase::abstract_mode_width (double w) +{ + if (fabs (w - m_abstract_mode_width) > 1e-6) { + m_abstract_mode_width = w; + if (m_abstract_mode_enabled) { + redraw (); + } + } +} + +void +LayoutViewBase::abstract_mode_enabled (bool e) +{ + if (e != m_abstract_mode_enabled) { + m_abstract_mode_enabled = e; + redraw (); + } +} + +void +LayoutViewBase::background_color (lay::Color c) +{ + if (c == mp_canvas->background_color ()) { + return; + } + + // replace by "real" background color if required + if (! c.is_valid ()) { + c = lay::Color (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); + } + + if (mp_control_panel) { + mp_control_panel->set_background_color (c); + mp_control_panel->set_text_color (contrast); + } + + if (mp_hierarchy_panel) { + mp_hierarchy_panel->set_background_color (c); + mp_hierarchy_panel->set_text_color (contrast); + } + + if (mp_libraries_view) { + mp_libraries_view->set_background_color (c); + mp_libraries_view->set_text_color (contrast); + } + + if (mp_bookmarks_view) { + mp_bookmarks_view->set_background_color (c); + mp_bookmarks_view->set_text_color (contrast); + } + + if (mp_selection_service) { + mp_selection_service->set_colors (c, contrast); + } + if (mp_zoom_service) { + mp_zoom_service->set_colors (c, contrast); + } + + // Set the color for all ViewService interfaces + for (std::vector::iterator p = mp_plugins.begin (); p != mp_plugins.end (); ++p) { + lay::ViewService *svc = (*p)->view_service_interface (); + if (svc) { + svc->set_colors (c, contrast); + } + } + + mp_canvas->set_colors (c, contrast, mp_canvas->active_color ()); + + update_content (); + + background_color_changed_event (); +} + +void +LayoutViewBase::dbu_coordinates (bool f) +{ + m_dbu_coordinates = f; +} + +void +LayoutViewBase::absolute_coordinates (bool f) +{ + m_absolute_coordinates = f; +} + +void +LayoutViewBase::select_cellviews_fit (const std::list &cvs) +{ + if (m_cellviews != cvs) { + + for (int index = 0; index < int (m_cellviews.size ()); ++index) { + cellview_about_to_change_event (index); + } + + cellviews_about_to_change_event (); + + set_min_hier_levels (0); + cancel_esc (); + m_cellviews = cvs; + zoom_fit (); + finish_cellviews_changed (); + + for (int index = 0; index < int (m_cellviews.size ()); ++index) { + cellview_changed (index); + } + + update_content (); + + } else { + zoom_fit (); + } +} + +void +LayoutViewBase::active_cellview_changed (int index) +{ + if (m_active_cellview_changed_event_enabled) { + + // we need to cancel pending drawing or dragging operations to reflect the new cellview (different target, may have different technology etc.) + cancel_esc (); + + // we need to setup the editor option pages because the technology may have changed + dm_setup_editor_option_pages (); + + active_cellview_changed_event (); + active_cellview_changed_with_index_event (index); + + // Because the title reflects the active one, emit a title changed event + if (m_title.empty ()) { + emit title_changed (); + } + + } +} + +void +LayoutViewBase::active_library_changed (int /*index*/) +{ + std::string lib_name; + if (mp_libraries_view->active_lib ()) { + lib_name = mp_libraries_view->active_lib ()->get_name (); + } + + // commit the new active library to the other views and persist this state + // TODO: could be passed through the LibraryController (like through some LibraryController::active_library) + dispatcher ()->config_set (cfg_current_lib_view, lib_name); +} + +void +LayoutViewBase::cellview_changed (unsigned int index) +{ + if (mp_hierarchy_panel) { + mp_hierarchy_panel->do_update_content (index); + } + + cellview_changed_event (index); + + if (m_title.empty ()) { + emit title_changed (); + } +} + +void +LayoutViewBase::select_cell_dispatch (const cell_path_type &path, int cellview_index) +{ + bool set_max_hier = (m_full_hier_new_cell || has_max_hier ()); + if (m_clear_ruler_new_cell) { + + // This is a HACK, but the clean solution would be to provide a new editable + // method like "clear_annotations": + lay::Plugin *antPlugin = get_plugin_by_name ("ant::Plugin"); + if (antPlugin) { + antPlugin->menu_activated ("ant::clear_all_rulers_internal"); + } + + } + + if (m_fit_new_cell) { + select_cell_fit (path, cellview_index); + } else { + select_cell (path, cellview_index); + } + set_current_cell_path (cellview_index, path); + if (set_max_hier) { + max_hier (); + } +} + +void +LayoutViewBase::select_cell_fit (const cell_path_type &path, int index) +{ + if (index >= 0 && int (m_cellviews.size ()) > index && (cellview_iter (index)->specific_path ().size () > 0 || cellview_iter (index)->unspecific_path () != path)) { + + cellview_about_to_change_event (index); + + set_min_hier_levels (0); + cancel (); + cellview_iter (index)->set_specific_path (lay::CellView::specific_cell_path_type ()); + cellview_iter (index)->set_unspecific_path (path); + set_active_cellview_index (index); + redraw (); + zoom_fit (); + + cellview_changed (index); + + update_content (); + + } +} + +void +LayoutViewBase::select_cell_fit (cell_index_type cell_index, int index) +{ + if (index >= 0 && int (m_cellviews.size ()) > index && cellview_iter (index)->cell_index () != cell_index) { + + cellview_about_to_change_event (index); + + set_min_hier_levels (0); + cancel (); + cellview_iter (index)->set_cell (cell_index); + set_active_cellview_index (index); + redraw (); + zoom_fit (); + + cellview_changed (index); + + update_content (); + + } +} + +void +LayoutViewBase::select_cellviews (const std::list &cvs) +{ + if (m_cellviews != cvs) { + + for (int index = 0; index < int (m_cellviews.size ()); ++index) { + cellview_about_to_change_event (index); + } + cellviews_about_to_change_event (); + + set_min_hier_levels (0); + cancel_esc (); + m_cellviews = cvs; + redraw (); + + cellviews_changed_event (); + for (int index = 0; index < int (m_cellviews.size ()); ++index) { + cellview_changed (index); + } + + update_content (); + + } +} + +void +LayoutViewBase::select_cellview (int index, const CellView &cv) +{ + if (index < 0 || index >= int (m_cellviews.size ())) { + return; + } + + if (*cellview_iter (index) != cv) { + + cellview_about_to_change_event (index); + + cancel_esc (); + *cellview_iter (index) = cv; + redraw (); + + cellview_changed (index); + + update_content (); + + } +} + +void +LayoutViewBase::select_cell (const cell_path_type &path, int index) +{ + if (index >= 0 && int (m_cellviews.size ()) > index && (cellview_iter (index)->specific_path ().size () > 0 || cellview_iter (index)->unspecific_path () != path)) { + + cellview_about_to_change_event (index); + + set_min_hier_levels (0); + cancel (); + cellview_iter (index)->set_specific_path (lay::CellView::specific_cell_path_type ()); + cellview_iter (index)->set_unspecific_path (path); + set_active_cellview_index (index); + redraw (); + + cellview_changed (index); + + update_content (); + + } +} + +void +LayoutViewBase::select_cell (cell_index_type cell_index, int index) +{ + if (index >= 0 && int (m_cellviews.size ()) > index && (! cellview_iter (index)->is_valid () || cellview_iter (index)->cell_index () != cell_index)) { + + cellview_about_to_change_event (index); + + set_min_hier_levels (0); + cancel (); + cellview_iter (index)->set_cell (cell_index); + set_active_cellview_index (index); + redraw (); + + cellview_changed (index); + + update_content (); + + } +} + +bool +LayoutViewBase::is_cell_hidden (cell_index_type ci, int cellview_index) const +{ + if (int (m_hidden_cells.size ()) > cellview_index && cellview_index >= 0) { + return m_hidden_cells [cellview_index].find (ci) != m_hidden_cells [cellview_index].end (); + } else { + return false; + } +} + +const std::set & +LayoutViewBase::hidden_cells (int cellview_index) const +{ + if (int (m_hidden_cells.size ()) > cellview_index && cellview_index >= 0) { + return m_hidden_cells[cellview_index]; + } else { + static std::set empty_set; + return empty_set; + } +} + +void +LayoutViewBase::hide_cell (cell_index_type ci, int cellview_index) +{ + if (cellview_index < 0) { + return; + } + while (int (m_hidden_cells.size ()) <= cellview_index) { + m_hidden_cells.push_back (std::set ()); + } + if (m_hidden_cells [cellview_index].insert (ci).second) { + if (transacting ()) { + manager ()->queue (this, new OpHideShowCell (ci, cellview_index, false /*=hide*/)); + } else if (manager () && ! replaying ()) { + manager ()->clear (); + } + cell_visibility_changed_event (); + redraw (); // needs redraw + } +} + +void +LayoutViewBase::show_cell (cell_index_type ci, int cellview_index) +{ + if (cellview_index < 0) { + return; + } + if (int (m_hidden_cells.size ()) > cellview_index) { + if (m_hidden_cells [cellview_index].erase (ci) > 0) { + if (transacting ()) { + manager ()->queue (this, new OpHideShowCell (ci, cellview_index, true /*=show*/)); + } else if (manager () && ! replaying ()) { + manager ()->clear (); + } + cell_visibility_changed_event (); + redraw (); // needs redraw + } + } +} + +void +LayoutViewBase::show_all_cells (int cv_index) +{ + if (cv_index < 0 || cv_index >= int (m_hidden_cells.size ())) { + return; + } + + if (! m_hidden_cells [cv_index].empty ()) { + if (transacting ()) { + for (std::set::const_iterator ci = m_hidden_cells [cv_index].begin (); ci != m_hidden_cells [cv_index].end (); ++ci) { + manager ()->queue (this, new OpHideShowCell (*ci, cv_index, true /*=show*/)); + } + } else if (manager () && ! replaying ()) { + manager ()->clear (); + } + m_hidden_cells [cv_index].clear (); + cell_visibility_changed_event (); + redraw (); // needs redraw + } +} + +void +LayoutViewBase::show_all_cells () +{ + bool any = false; + + for (unsigned int i = 0; i < m_hidden_cells.size (); ++i) { + if (! m_hidden_cells [i].empty ()) { + if (transacting ()) { + for (std::set::const_iterator ci = m_hidden_cells [i].begin (); ci != m_hidden_cells [i].end (); ++ci) { + manager ()->queue (this, new OpHideShowCell (*ci, i, true /*=show*/)); + } + } else if (manager () && ! replaying ()) { + manager ()->clear (); + } + m_hidden_cells [i].clear (); + any = true; + } + } + + if (any) { + cell_visibility_changed_event (); + redraw (); // needs redraw + return; + } +} + +void +LayoutViewBase::min_inst_label_size (int px) +{ + if (m_min_size_for_label != px) { + m_min_size_for_label = px; + redraw (); + } +} + +void +LayoutViewBase::text_visible (bool vis) +{ + if (m_text_visible != vis) { + m_text_visible = vis; + update_content (); + redraw (); // required because we do some optimizations is text is not visible .. + } +} + +void +LayoutViewBase::show_properties_as_text (bool sp) +{ + if (m_show_properties != sp) { + m_show_properties = sp; + redraw (); // required because we do some optimizations is text is not visible .. + } +} + +void +LayoutViewBase::bitmap_caching (bool l) +{ + if (m_bitmap_caching != l) { + m_bitmap_caching = l; + redraw (); // required because we do some optimizations is text is not visible .. + } +} + +void +LayoutViewBase::text_lazy_rendering (bool l) +{ + if (m_text_lazy_rendering != l) { + m_text_lazy_rendering = l; + redraw (); // required because we do some optimizations is text is not visible .. + } +} + +void +LayoutViewBase::cell_box_visible (bool vis) +{ + if (m_cell_box_visible != vis) { + m_cell_box_visible = vis; + update_content (); + } +} + +void +LayoutViewBase::text_font (unsigned int f) +{ + if (m_text_font != f) { + m_text_font = f; + redraw (); + } +} + +void +LayoutViewBase::default_text_size (double fs) +{ + if (m_default_text_size != fs) { + m_default_text_size = fs; + redraw (); + } +} + +void +LayoutViewBase::clear_ruler_new_cell (bool f) +{ + m_clear_ruler_new_cell = f; +} + +void +LayoutViewBase::full_hier_new_cell (bool f) +{ + m_full_hier_new_cell = f; +} + +double +LayoutViewBase::pan_distance () const +{ + return m_pan_distance; +} + +void +LayoutViewBase::pan_distance (double pd) +{ + m_pan_distance = pd; +} + +void +LayoutViewBase::fit_new_cell (bool f) +{ + m_fit_new_cell = f; +} + +void +LayoutViewBase::apply_text_trans (bool f) +{ + if (m_apply_text_trans != f) { + m_apply_text_trans = f; + redraw (); + } +} + +void +LayoutViewBase::offset_stipples (bool f) +{ + if (m_stipple_offset != f) { + m_stipple_offset = f; + update_content (); + } +} + +void +LayoutViewBase::no_stipples (bool f) +{ + if (m_no_stipples != f) { + m_no_stipples = f; + if (mp_control_panel) { + mp_control_panel->set_no_stipples (m_no_stipples); + } + update_content (); + } +} + +void +LayoutViewBase::show_markers (bool f) +{ + if (m_show_markers != f) { + m_show_markers = f; + mp_canvas->update_image (); + } +} + +void +LayoutViewBase::text_color (lay::Color c) +{ + if (m_text_color != c) { + m_text_color = c; + update_content (); + } +} + +bool +LayoutViewBase::has_selection () +{ + if (mp_control_panel && mp_control_panel->has_focus ()) { + return mp_control_panel->has_selection (); + } else if (mp_hierarchy_panel && mp_hierarchy_panel->has_focus ()) { + return mp_hierarchy_panel->has_selection (); + } else { + return lay::Editables::has_selection (); + } +} + +void +LayoutViewBase::paste () +{ + clear_selection (); + + { + db::Transaction trans (manager (), tl::to_string (tr ("Paste"))); + + // let the receivers sort out who is pasting what .. + if (mp_hierarchy_panel) { + mp_hierarchy_panel->paste (); + } + if (mp_control_panel) { + mp_control_panel->paste (); + } + lay::Editables::paste (); + } + + // if we change the state, save it before + store_state (); + + db::DBox sel_bbox = selection_bbox (); + if (! sel_bbox.empty ()) { + if (m_paste_display_mode == 1) { + // just make selection visible, i.e. shift window somewhat + pan_center (sel_bbox.center ()); + } else if (m_paste_display_mode == 2) { + // or: make selection fit into the screen + zoom_fit_sel (); + } + } +} + +void +LayoutViewBase::paste_interactive () +{ + clear_selection (); + + std::unique_ptr trans (new db::Transaction (manager (), tl::to_string (QObject::tr ("Paste and move")))); + + { + // let the receivers sort out who is pasting what .. + if (mp_hierarchy_panel) { + mp_hierarchy_panel->paste (); + } + if (mp_control_panel) { + mp_control_panel->paste (); + } + lay::Editables::paste (); + } + + // temporarily close the transaction and pass to the move service for appending it's own + // operations. + trans->close (); + + if (mp_move_service->begin_move (trans.release (), false)) { + switch_mode (-1); // move mode + } +} + +void +LayoutViewBase::copy () +{ + if (mp_hierarchy_panel && mp_hierarchy_panel->has_focus ()) { + mp_hierarchy_panel->copy (); + } else if (mp_control_panel && mp_control_panel->has_focus ()) { + mp_control_panel->copy (); + } else { + + if (! lay::Editables::has_selection ()) { + // try to use the transient selection for the real one + lay::Editables::transient_to_selection (); + } + + lay::Editables::copy (); + + } +} + +void +LayoutViewBase::cut () +{ + if (mp_hierarchy_panel && mp_hierarchy_panel->has_focus ()) { + // TODO: currently the hierarchy panel's cut function does it's own transaction handling. + // Otherwise the cut function is not working propertly. + mp_hierarchy_panel->cut (); + } else if (mp_control_panel && mp_control_panel->has_focus ()) { + db::Transaction trans (manager (), tl::to_string (QObject::tr ("Cut Layers"))); + mp_control_panel->cut (); + } else { + + if (! lay::Editables::has_selection ()) { + // try to use the transient selection for the real one + lay::Editables::transient_to_selection (); + } + + db::Transaction trans (manager (), tl::to_string (QObject::tr ("Cut"))); + lay::Editables::cut (); + + } +} + +void +LayoutViewBase::add_missing_layers () +{ + std::set present; + LayerPropertiesConstIterator l = begin_layers (); + while (! l.at_end ()) { + if (! l->has_children ()) { + present.insert (l->source (true /*real*/)); + } + ++l; + } + + std::vector actual; + for (unsigned int cv = 0; cv < cellviews (); ++cv) { + const db::Layout &layout = cellview (cv)->layout (); + for (unsigned int l = 0; l < layout.layers (); ++l) { + if (layout.is_valid_layer (l)) { + actual.push_back (lay::ParsedLayerSource (layout.get_properties (l), cv)); + } + } + } + + std::sort (actual.begin (), actual.end ()); + + for (std::vector ::const_iterator a = actual.begin (); a != actual.end (); ++a) { + if (present.find (*a) == present.end ()) { + lay::LayerPropertiesNode node; + node.attach_view (this, current_layer_list ()); + node.set_source (*a); + init_layer_properties (node); + insert_layer (end_layers (), node); + } + } + + emit layer_order_changed (); +} + +LayerState +LayoutViewBase::layer_snapshot () const +{ + LayerState state; + LayerPropertiesConstIterator l = begin_layers (); + while (! l.at_end ()) { + if (! l->has_children ()) { + state.present.insert (l->source (true /*real*/)); + } + ++l; + } + return state; +} + +void +LayoutViewBase::current_layer_changed_slot (const lay::LayerPropertiesConstIterator &iter) +{ + current_layer_changed_event (iter); +} + +void +LayoutViewBase::add_new_layers (const LayerState &state) +{ + std::vector actual; + for (unsigned int cv = 0; cv < cellviews (); ++cv) { + const db::Layout &layout = cellview (cv)->layout (); + for (unsigned int l = 0; l < layout.layers (); ++l) { + if (layout.is_valid_layer (l)) { + actual.push_back (lay::ParsedLayerSource (layout.get_properties (l), cv)); + } + } + } + + std::sort (actual.begin (), actual.end ()); + + bool needs_update = false; + + for (std::vector ::const_iterator a = actual.begin (); a != actual.end (); ++a) { + if (state.present.find (*a) == state.present.end ()) { + needs_update = true; + lay::LayerPropertiesNode node; + node.attach_view (this, current_layer_list ()); + node.set_source (*a); + // HINT: in editable mode it is desireable to present all layers because otherwise they cannot be + // made visible to populate them. + if (is_editable () || ! node.bbox ().empty ()) { + init_layer_properties (node); + insert_layer (end_layers (), node); + } + } + } + + if (needs_update) { + emit layer_order_changed (); + } +} + +void +LayoutViewBase::remove_unused_layers () +{ + if (mp_control_panel) { + mp_control_panel->cm_remove_unused (); + } +} + +void +LayoutViewBase::prev_display_state () +{ + if (m_display_state_ptr > 0) { + m_display_state_ptr--; + goto_view (m_display_states [m_display_state_ptr]); + } +} + +bool +LayoutViewBase::has_prev_display_state () +{ + return m_display_state_ptr > 0; +} + +void +LayoutViewBase::next_display_state () +{ + if (m_display_state_ptr + 1 < m_display_states.size ()) { + m_display_state_ptr++; + goto_view (m_display_states [m_display_state_ptr]); + } +} + +bool +LayoutViewBase::has_next_display_state () +{ + return m_display_state_ptr + 1 < m_display_states.size (); +} + +void +LayoutViewBase::current_pos (double x, double y) +{ + if (m_activated) { + if (dbu_coordinates ()) { + double dx = 0.0, dy = 0.0; + if (active_cellview_index () >= 0) { + double dbu = cellview (active_cellview_index ())->layout ().dbu (); + dx = x / dbu; + dy = y / dbu; + } + emit current_pos_changed (dx, dy, true); + } else { + emit current_pos_changed (x, y, false); + } + } +} + +void +LayoutViewBase::stop_redraw () +{ + mp_canvas->stop_redraw (); +} + +void +LayoutViewBase::stop () +{ + stop_redraw (); + deactivate_all_browsers (); +} + +void +LayoutViewBase::mode (int m) +{ + if (m != m_mode) { + + m_mode = m; + lay::Plugin *active_plugin = 0; + + if (m > 0) { + + for (std::vector::iterator p = mp_plugins.begin (); p != mp_plugins.end (); ++p) { + if ((*p)->plugin_declaration ()->id () == m) { + active_plugin = *p; + mp_canvas->activate ((*p)->view_service_interface ()); + break; + } + } + + } else if (m == 0 && mp_selection_service) { + mp_canvas->activate (mp_selection_service); + } else if (m == -1 && mp_move_service) { + mp_canvas->activate (mp_move_service); + } + + lay::EditorOptionsPages *eo_pages = editor_options_pages (); + if (eo_pages) { + + // TODO: this is very inefficient as each "activate" will regenerate the tabs + for (std::vector::const_iterator op = eo_pages->pages ().begin (); op != eo_pages->pages ().end (); ++op) { + bool is_active = false; + if ((*op)->plugin_declaration () == 0) { + is_active = true; + } else if (active_plugin && active_plugin->plugin_declaration () == (*op)->plugin_declaration ()) { + is_active = true; + } + (*op)->activate (is_active); + } + + } + + } +} + +bool +LayoutViewBase::is_move_mode () const +{ + return m_mode == -1; +} + +bool +LayoutViewBase::is_selection_mode () const +{ + return m_mode == 0; +} + +unsigned int +LayoutViewBase::intrinsic_mouse_modes (std::vector *descriptions) +{ + if (descriptions) { + descriptions->push_back ("select\t" + tl::to_string (tr ("Select")) + "<:select.png>"); + descriptions->push_back ("move\t" + tl::to_string (tr ("Move")) + "<:move.png>"); + } + return 2; +} + +int +LayoutViewBase::default_mode () +{ + return 0; // TODO: any generic scheme? is select, should be ruler.. +} + +std::vector +LayoutViewBase::menu_symbols () +{ + // TODO: currently these are all symbols from all plugins + return lay::PluginDeclaration::menu_symbols (); +} + +void +LayoutViewBase::menu_activated (const std::string &symbol) +{ + // Try the plugin declarations if the view is the top-level dispatcher + if (dispatcher () == this) { + for (tl::Registrar::iterator cls = tl::Registrar::begin (); cls != tl::Registrar::end (); ++cls) { + if (cls->menu_activated (symbol)) { + return; + } + } + } + + // distribute the menu item call on the plugins - one should take it. + for (std::vector::const_iterator p = plugins ().begin (); p != plugins ().end (); ++p) { + (*p)->menu_activated (symbol); + } +} + +void +LayoutViewBase::rename_cellview (const std::string &name, int cellview_index) +{ + if (cellview_index >= 0 && cellview_index < int (m_cellviews.size ())) { + if ((*cellview_iter (cellview_index))->name () != name) { + (*cellview_iter (cellview_index))->rename (name); + mp_hierarchy_panel->do_update_content (cellview_index); + if (m_title.empty ()) { + emit title_changed (); + } + } + } +} + +std::vector +LayoutViewBase::cv_transform_variants (int cv_index) const +{ + std::set trns_variants; + for (lay::LayerPropertiesConstIterator l = begin_layers (); !l.at_end (); ++l) { + if (! l->has_children ()) { + int cvi = l->cellview_index () >= 0 ? l->cellview_index () : 0; + if (cv_index < int (cellviews ()) && cvi == cv_index) { + trns_variants.insert (l->trans ().begin (), l->trans ().end ()); + } + } + } + return std::vector (trns_variants.begin (), trns_variants.end ()); +} + +std::vector +LayoutViewBase::cv_transform_variants (int cv_index, unsigned int layer) const +{ + if (cellview (cv_index)->layout ().is_valid_layer (layer)) { + std::set trns_variants; + for (lay::LayerPropertiesConstIterator l = begin_layers (); !l.at_end (); ++l) { + if (! l->has_children () && l->layer_index () == int (layer)) { + int cvi = l->cellview_index () >= 0 ? l->cellview_index () : 0; + if (cv_index < int (cellviews ()) && cvi == cv_index) { + trns_variants.insert (l->trans ().begin (), l->trans ().end ()); + } + } + } + return std::vector (trns_variants.begin (), trns_variants.end ()); + } else { + // may happen if the layer is a guiding shape layer for example + return cv_transform_variants (cv_index); + } +} + +std::map > +LayoutViewBase::cv_transform_variants_by_layer (int cv_index) const +{ + std::map > tv_map; + + for (lay::LayerPropertiesConstIterator l = begin_layers (); !l.at_end (); ++l) { + if (! l->has_children () && l->layer_index () >= 0) { + int cvi = l->cellview_index () >= 0 ? l->cellview_index () : 0; + if (cv_index < int (cellviews ()) && cvi == cv_index) { + std::vector &v = tv_map.insert (std::make_pair (l->layer_index (), std::vector ())).first->second; + v.insert (v.end (), l->trans ().begin (), l->trans ().end ()); + } + } + } + + for (std::map >::iterator m = tv_map.begin (); m != tv_map.end (); ++m) { + std::sort (m->second.begin (), m->second.end ()); + m->second.erase (std::unique (m->second.begin (), m->second.end ()), m->second.end ()); + } + + return tv_map; +} + +std::set< std::pair > +LayoutViewBase::cv_transform_variants () const +{ + std::set< std::pair > box_variants; + for (lay::LayerPropertiesConstIterator l = begin_layers (); !l.at_end (); ++l) { + if (! l->has_children ()) { + unsigned int cv_index = l->cellview_index () >= 0 ? (unsigned int) l->cellview_index () : 0; + if (cv_index < cellviews ()) { + for (std::vector::const_iterator t = l->trans ().begin (); t != l->trans ().end (); ++t) { + box_variants.insert (std::make_pair (*t, cv_index)); + } + } + } + } + return box_variants; +} + +db::InstElement +LayoutViewBase::ascend (int index) +{ + tl_assert (int (m_cellviews.size ()) > index && cellview_iter (index)->is_valid ()); + + cellview_about_to_change_event (index); + + lay::CellView::specific_cell_path_type spath (cellview_iter (index)->specific_path ()); + if (spath.empty ()) { + return db::InstElement (); + } else { + + cancel (); + db::InstElement ret = spath.back (); + spath.pop_back (); + cellview_iter (index)->set_specific_path (spath); + + store_state (); + redraw (); + + cellview_changed (index); + + update_content (); + + return ret; + + } +} + +void +LayoutViewBase::descend (const std::vector &path, int index) +{ + if (! path.empty () && index >= 0 && int (m_cellviews.size ()) > index && cellview_iter (index)->is_valid ()) { + + cellview_about_to_change_event (index); + + cancel (); + + lay::CellView::specific_cell_path_type spath (cellview_iter (index)->specific_path ()); + spath.insert (spath.end (), path.begin (), path.end ()); + cellview_iter (index)->set_specific_path (spath); + + store_state (); + redraw (); + + cellview_changed (index); + + update_content (); + + } +} + +bool +LayoutViewBase::is_editable () const +{ + return m_editable; +} + +unsigned int +LayoutViewBase::search_range () +{ + return m_search_range; +} + +void +LayoutViewBase::set_search_range (unsigned int sr) +{ + m_search_range = sr; +} + +unsigned int +LayoutViewBase::search_range_box () +{ + return m_search_range_box; +} + +void +LayoutViewBase::set_search_range_box (unsigned int sr) +{ + m_search_range_box = sr; +} + +void +LayoutViewBase::message (const std::string &s, int timeout) +{ + emit show_message (s, timeout * 1000); +} + +db::cell_index_type +LayoutViewBase::new_cell (int cv_index, const std::string &cell_name) +{ + db::cell_index_type new_ci (0); + + if (cv_index >= 0 && int (m_cellviews.size ()) > cv_index) { + + db::Layout &layout = cellview (cv_index)->layout (); + if (! cell_name.empty () && layout.cell_by_name (cell_name.c_str ()).first) { + throw tl::Exception (tl::to_string (tr ("A cell with that name already exists: %s")), cell_name); + } + + transaction (tl::to_string (tr ("New cell"))); + new_ci = layout.add_cell (cell_name.empty () ? 0 : cell_name.c_str ()); + commit (); + + } + + return new_ci; +} + +void +LayoutViewBase::switch_mode (int m) +{ + if (m_mode != m) { + mode (m); + emit mode_change (m); + } +} + +template +static void make_unique_name (T *object, Iter from, Iter to) +{ + std::string n (object->name ()); + int nn = 0; + + do { + + bool found = n.empty (); + for (Iter i = from; i != to && !found; ++i) { + if ((*i)->name () == n) { + found = true; + } + } + + if (! found) { + break; + } + + n = object->name () + tl::sprintf ("[%d]", ++nn); + + } while (1); + + object->set_name (n); +} + +unsigned int +LayoutViewBase::add_l2ndb (db::LayoutToNetlist *l2ndb) +{ + make_unique_name (l2ndb, m_l2ndbs.begin (), m_l2ndbs.end ()); + m_l2ndbs.push_back (l2ndb); + + // Mark this object as owned by us (for GSI) + l2ndb->keep (); + + l2ndb_list_changed_event (); + + return (unsigned int)(m_l2ndbs.size () - 1); +} + +unsigned int +LayoutViewBase::replace_l2ndb (unsigned int db_index, db::LayoutToNetlist *l2ndb) +{ + tl_assert (l2ndb != 0); + + if (db_index < m_l2ndbs.size ()) { + + // keep the name as it is used for reference in the browser for example + std::string n = m_l2ndbs [db_index]->name (); + l2ndb->set_name (n); + + delete m_l2ndbs [db_index]; + m_l2ndbs [db_index] = l2ndb; + + // Mark this object as owned by us (for GSI) + l2ndb->keep (); + + l2ndb_list_changed_event (); + + return db_index; + + } else { + return add_l2ndb (l2ndb); + } +} + +db::LayoutToNetlist * +LayoutViewBase::get_l2ndb (int index) +{ + if (index >= 0 && index < int (m_l2ndbs.size ())) { + return m_l2ndbs [index]; + } else { + return 0; + } +} + +const db::LayoutToNetlist * +LayoutViewBase::get_l2ndb (int index) const +{ + if (index >= 0 && index < int (m_l2ndbs.size ())) { + return m_l2ndbs [index]; + } else { + return 0; + } +} + +void +LayoutViewBase::remove_l2ndb (unsigned int index) +{ + if (index < (unsigned int) (m_l2ndbs.size ())) { + delete m_l2ndbs [index]; + m_l2ndbs.erase (m_l2ndbs.begin () + index); + l2ndb_list_changed_event (); + } +} + +unsigned int +LayoutViewBase::add_rdb (rdb::Database *rdb) +{ + make_unique_name (rdb, m_rdbs.begin (), m_rdbs.end ()); + m_rdbs.push_back (rdb); + + // Mark this object as owned by us (for GSI) + rdb->keep (); + + rdb_list_changed_event (); + + return (unsigned int)(m_rdbs.size () - 1); +} + +unsigned int +LayoutViewBase::replace_rdb (unsigned int db_index, rdb::Database *rdb) +{ + tl_assert (rdb != 0); + + if (db_index < m_rdbs.size ()) { + + // keep name because it's used for reference in the browser for example + std::string n = m_rdbs [db_index]->name (); + rdb->set_name (n); + + delete m_rdbs [db_index]; + m_rdbs [db_index] = rdb; + + // Mark this object as owned by us (for GSI) + rdb->keep (); + + rdb_list_changed_event (); + + return db_index; + + } else { + return add_rdb (rdb); + } +} + +rdb::Database * +LayoutViewBase::get_rdb (int index) +{ + if (index >= 0 && index < int (m_rdbs.size ())) { + return m_rdbs [index]; + } else { + return 0; + } +} + +const rdb::Database * +LayoutViewBase::get_rdb (int index) const +{ + if (index >= 0 && index < int (m_rdbs.size ())) { + return m_rdbs [index]; + } else { + return 0; + } +} + +void +LayoutViewBase::remove_rdb (unsigned int index) +{ + if (index < (unsigned int) (m_rdbs.size ())) { + delete m_rdbs [index]; + m_rdbs.erase (m_rdbs.begin () + index); + rdb_list_changed_event (); + } +} + +} // namespace lay diff --git a/src/laybasic/laybasic/layLayoutViewBase.h b/src/laybasic/laybasic/layLayoutViewBase.h new file mode 100644 index 000000000..65e3af2b8 --- /dev/null +++ b/src/laybasic/laybasic/layLayoutViewBase.h @@ -0,0 +1,2566 @@ + +/* + + 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 + +*/ + + +#ifndef HDR_layLayoutViewBase +#define HDR_layLayoutViewBase + +#include "laybasicCommon.h" + +#include +#include +#include +#include +#include +#include + +#include "layLayerProperties.h" +#include "layAbstractMenu.h" +#include "layAnnotationShapes.h" +#include "layDispatcher.h" +#include "layLayoutCanvas.h" +#include "layColorPalette.h" +#include "layStipplePalette.h" +#include "layLineStylePalette.h" +#include "layCellView.h" +#include "layViewOp.h" +#include "layEditable.h" +#include "layPlugin.h" +#include "layDisplayState.h" +#include "layBookmarkList.h" +#include "gsi.h" +#include "tlException.h" +#include "tlEvents.h" +#include "dbInstElement.h" + +namespace rdb { + class Database; +} + +namespace db { + class Layout; + class Manager; + class SaveLayoutOptions; + class LayoutToNetlist; +} + +namespace lay { + +class MouseTracker; +class ZoomService; +class SelectionService; +class MoveService; +class ColorButton; +class ConfigureAction; + +/** + * @brief Stores a layer reference to create layers which have been added by some action + * + * This object is delivered by LayoutViewBase::layer_snapshot and can be used in add_missing_layers + * to create new layer views for layers which have been created between layer_snapshot and + * add_missing_layers. + */ +struct LayerState +{ + /** + * @brief Constructor + */ + LayerState () { } + + std::set present; +}; + +/** + * @brief A layer display properties structure + * + * The layer properties encapsulate the settings relevant for + * the display of a layer. + * + * "brightness" is a index that indicates how much to make the + * color brighter to darker rendering the effective color + * (eff_frame_color (), eff_fill_color ()). It's value is roughly between + * -255 and 255. + */ +struct LAYBASIC_PUBLIC LayerDisplayProperties +{ + LayerDisplayProperties (); + + bool operator== (const LayerDisplayProperties &d); + bool operator!= (const LayerDisplayProperties &d); + + /** + * @brief render the effective frame color + * + * The effective frame color is computed from the frame color brightness and the + * frame color. + */ + color_t eff_frame_color () const; + + /** + * @brief render the effective frame color + * + * The effective frame color is computed from the frame color brightness and the + * frame color. + */ + color_t eff_fill_color () const; + + // display styles + color_t frame_color; + color_t fill_color; + int frame_brightness; + int fill_brightness; + unsigned int dither_pattern; + bool visible; + bool transparent; + int width; + bool marked; + int animation; + std::string name; +}; + +/** + * @brief The layout view object + * + * The layout view is responsible for displaying one or a set of layouts. + * It is composed of a canvas and controls to control the appearance. + * It manages the layer display list, bookmark list etc. + */ +class LAYBASIC_PUBLIC LayoutViewBase : + public lay::Editables, + public lay::Dispatcher +{ +public: + typedef lay::CellView::unspecific_cell_path_type cell_path_type; + typedef lay::CellView::cell_index_type cell_index_type; + typedef std::pair bookmark_type; + + /** + * @brief Define some options for the view + */ + enum options_type { + LV_Normal = 0, + LV_NoLayers = 1, + LV_NoHierarchyPanel = 2, + LV_NoLibrariesView = 4, + LV_NoEditorOptionsPanel = 8, + LV_NoBookmarksView = 16, + LV_Naked = 32, + LV_NoZoom = 64, + LV_NoGrid = 128, + LV_NoMove = 256, + LV_NoTracker = 512, + LV_NoSelection = 1024, + LV_NoPlugins = 2048, + LV_NoServices = LV_NoMove + LV_NoTracker + LV_NoSelection + LV_NoPlugins + }; + + enum drop_small_cells_cond_type { DSC_Max = 0, DSC_Min = 1, DSC_Sum = 2 }; + + /** + * @brief Constructor + */ + LayoutViewBase (db::Manager *mgr, bool editable, lay::Plugin *plugin_parent, unsigned int options = (unsigned int) LV_Normal); + + /** + * @brief Constructor (clone from another view) + */ + LayoutViewBase (lay::LayoutViewBase *source, db::Manager *mgr, bool editable, lay::Plugin *plugin_parent, unsigned int options = (unsigned int) LV_Normal); + + /** + * @brief Destructor + */ + ~LayoutViewBase (); + + /** + * @brief Determine if there is something to copy + * + * This reimplementation of the lay::Editables interface additionally + * looks for content providers in the tree views for example. + */ + bool has_selection (); + + /** + * @brief Pastes from clipboard + * + * This reimplementation of the lay::Editables interface additionally + * looks for paste receivers in the tree views for example. + */ + void paste (); + + /** + * @brief Pastes from clipboard and initiates a move + */ + void paste_interactive (); + + /** + * @brief Copies to clipboard + * + * This reimplementation of the lay::Editables interface additionally + * looks for copy providers in the tree views for example. + */ + void copy (); + + /** + * @brief Cuts to clipboard + * + * This reimplementation of the lay::Editables interface additionally + * looks for cut & copy providers in the tree views for example. + */ + void cut (); + + /** + * @brief Gets the explicit title string of the view + * + * This is the one explicitly set, not the one displayed. The displayed text is composed of internal information + * if no title string is set. + */ + const std::string &title_string () const + { + return m_title; + } + + /** + * @brief The "dirty" flag indicates that one of the layout has been modified + * + * A signal is provided on a change of this flag (dirty_changed). + */ + bool is_dirty () const; + + /** + * @brief Fill the layer properties for a new layer + * + * The layer's source must be set already to allow computing of the initial color. + * It is assumed that the layer is appended at the end of the layer list. This + * is important to set the dither pattern index accordingly. + */ + void init_layer_properties (LayerProperties &props) const; + + /** + * @brief Create a set of new layers for the given layers of the given cellview + */ + void add_new_layers (const std::vector &layer_ids, int cv_index); + + /** + * @brief Set the layer properties of a layer with the given position (by iterator) for the current layer list + * + * @param iter Points to the layer to be replaced + * @param props The properties to replace the current properties + */ + void set_properties (const LayerPropertiesConstIterator &iter, const LayerProperties &props) + { + set_properties (current_layer_list (), iter, props); + } + + /** + * @brief Set the layer properties of a layer with the given position (by iterator) for the layer list with the given index + * + * @param index The layer list's index + * @param iter Points to the layer to be replaced + * @param props The properties to replace the current properties + */ + void set_properties (unsigned int index, const LayerPropertiesConstIterator &iter, const LayerProperties &props); + + /** + * @brief Expand the layer properties of all tabs + * + * This method will replace the wildcard specifications in the layer properties of all + * tabs. All unspecific cv index specifications will be expanded to all cellviews, all + * layer and datatype specs will be expanded into all available (remaining) specs. + */ + void expand_properties (); + + /** + * @brief Expand the layer properties for the given tab + * + * @param index The index of the tab to which to apply the expansion to. + */ + void expand_properties (unsigned int index); + + /** + * @brief Expand the layer properties of all tabs with some options + * + * @param map_cv_index Maps a specified cv index to the one to use. Use -1 for the first entry to map any present cv index. Map to -1 to specify expansion to all available cv indices. + * @param add_default Set this parameter to true to implicitly add an entry for all "missing" layers. + */ + void expand_properties (const std::map &map_cv_index, bool add_default); + + /** + * @brief Expand the layer properties of the specified tab with some options + * + * @param index The index of the tab to which to apply the expansion to. + * @param map_cv_index Maps a specified cv index to the one to use. Use -1 for the first entry to map any present cv index. Map to -1 to specify expansion to all available cv indices. + * @param add_default Set this parameter to true to implicitly add an entry for all "missing" layers. + */ + void expand_properties (unsigned int index, const std::map &map_cv_index, bool add_default); + + /** + * @brief Replace the layer node with a new one for the current layer list + */ + void replace_layer_node (const LayerPropertiesConstIterator &iter, const LayerPropertiesNode &props) + { + replace_layer_node (current_layer_list (), iter, props); + } + + /** + * @brief Replace the layer node with a new one for the layer list with the given index + */ + void replace_layer_node (unsigned int index, const LayerPropertiesConstIterator &iter, const LayerPropertiesNode &props); + + /** + * @brief Insert the given layer properties node into the list for the current layer list + * + * This method returns a reference to the element created. + */ + const LayerPropertiesNode &insert_layer (const LayerPropertiesConstIterator &iter, const LayerPropertiesNode &props) + { + return insert_layer (current_layer_list (), iter, props); + } + + /** + * @brief Insert the given layer properties node into the list before the given index + * + * This method returns a reference to the element created. + */ + const LayerPropertiesNode &insert_layer (unsigned int index, const LayerPropertiesConstIterator &iter, const LayerPropertiesNode &props); + + /** + * @brief Delete the layer properties node for the current layer list + * + * This method deletes the object that the iterator points to and invalidates + * the iterator since the object that the iterator points to is no longer valid. + */ + void delete_layer (LayerPropertiesConstIterator &iter) + { + delete_layer (current_layer_list (), iter); + } + + /** + * @brief Delete the layer properties node for the layer list with the given index + * + * This method deletes the object that the iterator points to and invalidates + * the iterator since the object that the iterator points to is no longer valid. + */ + void delete_layer (unsigned int index, LayerPropertiesConstIterator &iter); + + /** + * @brief Begin iterator for the layers + * + * This iterator delivers recursively the layers of this view + */ + LayerPropertiesConstIterator begin_layers () const + { + return get_properties ().begin_const_recursive (); + } + + /** + * @brief End iterator for the layers + */ + LayerPropertiesConstIterator end_layers () const + { + return get_properties ().end_const_recursive (); + } + + /** + * @brief Begin iterator for the layers for a given list + * + * This iterator delivers recursively the layers of this view + */ + LayerPropertiesConstIterator begin_layers (unsigned int index) const + { + return get_properties (index).begin_const_recursive (); + } + + /** + * @brief End iterator for the layers for a given list + */ + LayerPropertiesConstIterator end_layers (unsigned int index) const + { + return get_properties (index).end_const_recursive (); + } + + /** + * @brief Replace the current layer properties list + */ + void set_properties (const LayerPropertiesList &list) + { + set_properties (current_layer_list (), list); + } + + /** + * @brief Rename a layer properties list + */ + void rename_properties (unsigned int index, const std::string &new_name); + + /** + * @brief Replace the specified layer properties list + */ + void set_properties (unsigned int index, const LayerPropertiesList &list); + + /** + * @brief Clear the given layer view list + */ + void clear_layers (unsigned int index) + { + set_properties (index, LayerPropertiesList ()); + } + + /** + * @brief Clear the current layer view list + */ + void clear_layers () + { + set_properties (LayerPropertiesList ()); + } + + /** + * @brief Access the current layer properties list + */ + const LayerPropertiesList &get_properties () const + { + return get_properties (current_layer_list ()); + } + + /** + * @brief Access the specified layer properties list + */ + const LayerPropertiesList &get_properties (unsigned int index) const; + + /** + * @brief Get the number of lists present in this view + */ + unsigned int layer_lists () const + { + return (unsigned int) m_layer_properties_lists.size (); + } + + /** + * @brief Get the index of the current properties list + */ + unsigned int current_layer_list () const + { + return m_current_layer_list; + } + + /** + * @brief Set the index of the current properties list + */ + void set_current_layer_list (unsigned int index); + + /** + * @brief Delete the specified layer properties list + */ + void delete_layer_list (unsigned int index); + + /** + * @brief Insert the layer properties list at the given index and make it the current list. + */ + void insert_layer_list (unsigned int index, const LayerPropertiesList &props); + + /** + * @brief Insert the layer properties list at the given index and make it the current list. + */ + void insert_layer_list (unsigned int index) + { + insert_layer_list (index, LayerPropertiesList ()); + } + + /** + * @brief Set the custom dither pattern + */ + void set_dither_pattern (const DitherPattern &pattern); + + /** + * @brief Obtain the custom dither pattern + */ + const DitherPattern &dither_pattern () const + { + return mp_canvas->dither_pattern (); + } + + /** + * @brief Set the custom line styles + */ + void set_line_styles (const LineStyles &styles); + + /** + * @brief Obtain the custom line styles + */ + const LineStyles &line_styles () const + { + return mp_canvas->line_styles (); + } + + /** + * @brief An event signalling the change in the number of hierarchy levels shown + */ + tl::Event hier_levels_changed_event; + + /** + * @brief An event signalling a change in the annotations shape list + * + * If annotation shapes are added or removed, this event is triggered. + */ + tl::Event annotations_changed_event; + + /** + * @brief An event signalling a change in the hierarchy of the layouts + * + * If the hierarchy of a layout is changed, this event is triggered. + * This may happen due to the removal or insertion of cells or instances. + */ + tl::Event hier_changed_event; + + /** + * @brief An event signalling a change in the geometries of the layouts + * + * If something on the geometries of a cell in one the layouts changes, this + * event is triggered. This may happed due to the removal or insertion of shapes or cell instances. + * In general, this indicates the need for redrawing of the layout for example. + */ + tl::Event geom_changed_event; + + /** + * @brief An event triggered before something on a cellview is changed + * + * This event is triggered before something on the cellview (i.e. the current cell of + * of set of the cellview) is changed. The argument is the index of the cell view to be + * changed. + * This event is followed by a corresponding cellview_changed event after the cellview + * has changed. + */ + tl::event cellview_about_to_change_event; + + /** + * @brief An event triggered before something on the cellviews is changed + * + * This event is triggered before something on the cellviews is changed, i.e. a cellview is deleted or inserted. + * Each of these events is followed by a cellviews_changed event after the change has been made. + */ + tl::Event cellviews_about_to_change_event; + + /** + * @brief An event signalling that the cell views have changed. + * + * When a cellview is added or removed, this event is triggered after the change has been made. + * The corresponding event that is triggered before the change is made is cellviews_about_to_change_event. + */ + tl::Event cellviews_changed_event; + + /** + * @brief An event signalling a change in a cellview. + * + * If a cellview is changed (i.e. the cell is changed) this event is triggered. + * The integer argument will receive the index of the cellview that has changed. + * The corresponding event that is triggered before the change is made is cellview_about_to_change_event. + */ + tl::event cellview_changed_event; + + /** + * @brief An event signalling that a file has been loaded. + * + * If a new file is loaded, this event is triggered. + */ + tl::Event file_open_event; + + /** + * @brief An event signalling that the viewport has changed. + * + * If the viewport (the rectangle that is shown) changes, this event + * is triggered. + */ + tl::Event viewport_changed_event; + + /** + * @brief This event is triggered if the background color changed + */ + tl::Event background_color_changed_event; + + /** + * @brief An event signalling that the layer list has changed. + * + * If the layer list changes, this event is triggered with an integer argument. + * The arguments's bit 0 is set, if the properties have changed. If the arguments bit 1 is + * set, the hierarchy has changed. If the name of layer properties is changed, bit 2 is + * set. + */ + tl::event layer_list_changed_event; + + /** + * @brief An event signalling that a layer list was deleted. + * + * If a layer list is deleted from the layer list set, the event is triggered with + * the index of the deleted list as an integer parameter. + */ + tl::event layer_list_deleted_event; + + /** + * @brief An event signalling that a layer list was inserted. + * + * If a layer list is inserted into the layer list set, the event is triggered with + * the index of the new list as an integer parameter. + */ + tl::event layer_list_inserted_event; + + /** + * @brief An event signalling that the current layer list has changed. + * + * If the current layer list is changed, this event is triggered. + */ + tl::event current_layer_list_changed_event; + + /** + * @brief An event signalling that the current layer has changed + */ + tl::event current_layer_changed_event; + + + /** + * @brief An event signalling that the visibility of some cells has changed + */ + tl::Event cell_visibility_changed_event; + + /** + * @brief An event triggered if the active cellview changes + * This event is triggered after the active cellview changed. + */ + tl::Event active_cellview_changed_event; + + /** + * @brief An event triggered if the active cellview changes + * This event is triggered after the active cellview changed. The integer parameter is the index of the + * new cellview. + */ + tl::event active_cellview_changed_with_index_event; + + /** + * @brief Save the given cellview into the given file (with options) + * If "update" is true, the cell view's properties will be updated (options, filename etc.). + */ + void save_as (unsigned int index, const std::string &filename, tl::OutputStream::OutputStreamMode om, const db::SaveLayoutOptions &options, bool update, int keep_backups); + + /** + * @brief Implementation of the undo operations + */ + virtual void undo (db::Op *op); + + /** + * @brief Implementation of the redo operations + */ + virtual void redo (db::Op *op); + + /** + * @brief Set the cellview at the given index + * + * If cvindex is used as the cellview index to associate the + * layout with. As a side effect, this method will emit a + * title_changed signal, which means that the cellview passed + * should be correctly named before to reflect the correct + * title if no explicit title is set. + */ + void set_layout (const lay::CellView &cv, unsigned int cvindex); + + /** + * @brief clear the cellviews + */ + void clear_cellviews (); + + /** + * @brief erase one cellview with the given index + */ + void erase_cellview (unsigned int index); + + /** + * @brief Save the layer properties + */ + void save_layer_props (const std::string &fn); + + /** + * @brief Load the layer properties + * + * @param fn The file to load. + */ + void load_layer_props (const std::string &fn); + + /** + * @brief Load the layer properties + * + * @param fn The file to load + * + * This version allows one to specify whether defaults should be used for all other layers by + * setting add_default to true + */ + void load_layer_props (const std::string &fn, bool add_default); + + /** + * @brief Load the layer properties + * + * @param fn The file to load + * + * This version allows one to specify whether defaults should be used for all other layers by + * setting add_default to true. In addition, this version will apply the .lyp definitions + * to a specific cellview after removing all definitions for this one. If cv_index is set + * to -1, the .lyp file will be applied to each cellview. In any case, the cv index specs + * in the .lyp file will be overridden. + */ + void load_layer_props (const std::string &fn, int cv_index, bool add_default); + + /** + * @brief Save the screen content to a file + */ + void save_screenshot (const std::string &fn); + +#if defined(HAVE_QT) + /** + * @brief Get the screen content as a QImage object + */ + QImage get_screenshot (); + + /** + * @brief Save an image file with the given width and height + */ + void save_image (const std::string &fn, unsigned int width, unsigned int height); + + /** + * @brief Save an image file with some options + * + * @param fn The path of the file to write + * @param width The width of the image in pixels + * @param height The height of the image + * @param linewidth The width of a line in pixels (usually 1) or 0 for default + * @param oversampling The oversampling factor (1..3) or 0 for default + * @param resolution The resolution (pixel size compared to a screen pixel size, i.e 1/oversampling) or 0 for default + * @param background The background color or lay::Color() for default + * @param foreground The foreground color or lay::Color() for default + * @param active The active color or lay::Color() for default + * @param target_box The box to draw or db::DBox() for default + * @param monochrome If true, monochrome images will be produced + */ + void save_image_with_options (const std::string &fn, unsigned int width, unsigned int height, int linewidth, int oversampling, double resolution, Color background, Color foreground, Color active_color, const db::DBox &target_box, bool monochrome); + + /** + * @brief Get the screen content as a QImage object with the given width and height + */ + QImage get_image (unsigned int width, unsigned int height); + + /** + * @brief Get the screen content as a QImage object with the given width and height + * + * @param width The width of the image in pixels + * @param height The height of the image + * @param linewidth The width of a line in pixels (usually 1) or 0 for default + * @param oversampling The oversampling factor (1..3) or 0 for default + * @param resolution The resolution (pixel size compared to a screen pixel size, i.e 1/oversampling) or 0 for default + * @param background The background color or lay::Color() for default + * @param foreground The foreground color or lay::Color() for default + * @param active The active color or lay::Color() for default + * @param target_box The box to draw or db::DBox() for default + * @param monochrome If true, monochrome images will be produced + */ + QImage get_image_with_options (unsigned int width, unsigned int height, int linewidth, int oversampling, double resolution, lay::Color background, lay::Color foreground, lay::Color active_color, const db::DBox &target_box, bool monochrome); +#endif + + /** + * @brief Hierarchy level selection setter + */ + void set_hier_levels (std::pair l); + + /** + * @brief Hierarchy level selection setter + */ + void set_min_hier_levels (int l) + { + set_hier_levels (std::pair (l, get_max_hier_levels ())); + } + + /** + * @brief Hierarchy level selection setter + */ + void set_max_hier_levels (int l) + { + set_hier_levels (std::pair (get_min_hier_levels (), l)); + } + + /** + * @brief Hierarchy level selection getter + */ + std::pair get_hier_levels () const; + + /** + * @brief Hierarchy level selection getter + */ + int get_min_hier_levels () const + { + return get_hier_levels ().first; + } + + /** + * @brief Hierarchy level selection getter + */ + int get_max_hier_levels () const + { + return get_hier_levels ().second; + } + + /** + * @brief Return true, if there is a "last" display state + */ + bool has_prev_display_state (); + + /** + * @brief Return true, if there is a "next" display state + */ + bool has_next_display_state (); + + /** + * @brief Cell box/label color setter + */ + void cell_box_color (lay::Color c); + + /** + * @brief Cell box/label getter + */ + lay::Color cell_box_color () const + { + return m_box_color; + } + + /** + * @brief Transform label flag setter + */ + void cell_box_text_transform (bool xform); + + /** + * @brief Transform label flag getter + */ + bool cell_box_text_transform () const + { + return m_box_text_transform; + } + + /** + * @brief Label font setter + */ + void cell_box_text_font (unsigned int f); + + /** + * @brief Label font setter + */ + unsigned int cell_box_text_font () const + { + return m_box_font; + } + + /** + * @brief Visibility of cell boxes + */ + void cell_box_visible (bool vis); + + /** + * @brief Visibility of cell boxes + */ + bool cell_box_visible () const + { + return m_cell_box_visible; + } + + /** + * @brief Min instance label size setter + */ + void min_inst_label_size (int px); + + /** + * @brief Min instance label size getter + */ + int min_inst_label_size () const + { + return m_min_size_for_label; + } + + /** + * @brief Visibility of text objects + */ + void text_visible (bool vis); + + /** + * @brief Visibility of text objects + */ + bool text_visible () const + { + return m_text_visible; + } + + /** + * @brief Show properties + */ + void show_properties_as_text (bool sp); + + /** + * @brief Show properties + */ + bool show_properties_as_text () + { + return m_show_properties; + } + + /** + * @brief Enable or disable bitmap caching + * + * Bitmap caching is used to optimize drawing by storing bitmaps + * in a cache for each cell. Repeated cells will be drawn faster then. + */ + void bitmap_caching (bool en); + + /** + * @brief Lazy rendering of text objects + */ + bool bitmap_caching () + { + return m_bitmap_caching; + } + + /** + * @brief Lazy rendering of text objects + */ + void text_lazy_rendering (bool lzy); + + /** + * @brief Lazy rendering of text objects + */ + bool text_lazy_rendering () + { + return m_text_lazy_rendering; + } + + /** + * @brief Text object font setter + */ + void text_font (unsigned int f); + + /** + * @brief Text object font getter + */ + unsigned int text_font () const + { + return m_text_font; + } + + /** + * @brief The default text size property + */ + void default_text_size (double fs); + + /** + * @brief The default text size property + */ + double default_text_size () const + { + return m_default_text_size; + } + + /** + * @brief Show or hide markers + */ + void show_markers (bool f); + + /** + * @brief "show_markers" property getter + */ + bool show_markers () const + { + return m_show_markers; + } + + /** + * @brief Don't show stipples + */ + void no_stipples (bool f); + + /** + * @brief "Don't show stipples" property getter + */ + bool no_stipples () const + { + return m_no_stipples; + } + + /** + * @brief Offset stipples property + */ + void offset_stipples (bool f); + + /** + * @brief Offset stipples property getter + */ + bool offset_stipples () const + { + return m_stipple_offset; + } + + /** + * @brief Apply text transformation property + */ + void apply_text_trans (bool f); + + /** + * @brief Apply text transformation property + */ + bool apply_text_trans () const + { + return m_apply_text_trans; + } + + /** + * @brief Text object color + */ + void text_color (lay::Color c); + + /** + * @brief Text object color + */ + lay::Color text_color () const + { + return m_text_color; + } + + /** + * @brief Clear all rulers if a new cell is selected (setter) + * + * If this property is set to true, all rulers are cleared + * if the cell is changed. + */ + void clear_ruler_new_cell (bool f); + + /** + * @brief Clear all rulers if a new cell is selected (getter) + * + * If this property is set to true, all rulers are cleared + * if the cell is changed. + */ + bool clear_ruler_new_cell () const + { + return m_clear_ruler_new_cell; + } + + /** + * @brief Switch new cell to full hierarchy property + * + * If this property is set to true, all hierarchy levels are selected + * if the cell is changed. + */ + void full_hier_new_cell (bool f); + + /** + * @brief Switch new cell to full hierarchy property + * + * If this property is set to true, all hierarchy levels are selected + * if the cell is changed. + */ + bool full_hier_new_cell () const + { + return m_full_hier_new_cell; + } + + /** + * @brief Fit new cell property + * + * If this property is set to false, the coordinate window is not + * changed if the cell is changed. + */ + void fit_new_cell (bool f); + + /** + * @brief Fit new cell + * + * If this property is set to false, the coordinate window is not + * changed if the cell is changed. + */ + bool fit_new_cell () const + { + return m_fit_new_cell; + } + + /** + * @brief The pan distance + * + * The pan distance is given relative to the current width and height. + */ + void pan_distance (double d); + + /** + * @brief Gets the pan distance + */ + double pan_distance () const; + + /** + * @brief Get the mouse wheel mode + * + * The mouse wheel mode determines how the wheel behaves. Mode 0 is the + * default mode, mode 1 is the alternative mode (default is up/down, + * shift is left/right, ctrl is zoom). + */ + int mouse_wheel_mode () const + { + return m_wheel_mode; + } + + /** + * @brief Set the mouse wheel mode + * + * The mouse wheel mode determines how the wheel behaves. Mode 0 is the + * default mode, mode 1 is the alternative mode (default is up/down, + * shift is left/right, ctrl is zoom). + */ + void mouse_wheel_mode (int m) + { + m_wheel_mode = m; + } + + /** + * @brief Sets the color palette + * + * The color palette is used for coloring new layers and is shown in the + * layer toolbox. + */ + void set_palette (const lay::ColorPalette &); + + /** + * @brief Gets the color palette + */ + const lay::ColorPalette &get_palette () const + { + return m_palette; + } + + /** + * @brief Sets the stipple palette + * + * The stipple palette is used for selecting stipples for new layers and is shown in the + * layer toolbox. + */ + void set_palette (const lay::StipplePalette &); + + /** + * @brief Gets the stipple palette + */ + const lay::StipplePalette &get_stipple_palette () const + { + return m_stipple_palette; + } + + /** + * @brief Sets the line style palette + * + * The line style palette is used for selecting line styles and is shown in the + * layer toolbox. + */ + void set_palette (const lay::LineStylePalette &); + + /** + * @brief Gets the line style palette + */ + const lay::LineStylePalette &get_line_style_palette () const + { + return m_line_style_palette; + } + + /** + * @brief Reloads the given cellview into the current view + * + * The cellview is given by index in the current view's cellview list. + */ + void reload_layout (unsigned int cv_index); + + /** + * @brief Load a (new) file into the layout + * + * The add_cellview param controls whether to create a new cellview + * or clear all cellviews before. + * + * The new layout will use the default technology. + * + * @return The index of the cellview loaded. + */ + unsigned int load_layout (const std::string &filename, bool add_cellview) + { + return load_layout (filename, std::string (), add_cellview); + } + + /** + * @brief Load a (new) file into the layout associating it with the given technology + * + * The add_cellview param controls whether to create a new cellview + * or clear all cellviews before. + * + * @return The index of the cellview loaded. + */ + unsigned int load_layout (const std::string &filename, const std::string &technology, bool add_cellview); + + /** + * @brief Load a (new) file into the layout with the options + * + * The add_cellview param controls whether to create a new cellview + * or clear all cellviews before. + * + * The new layout will use the default technology. + * + * @param options The options to use when loading. + * @param add_cellview_param See above. + * @return The index of the cellview loaded. + */ + unsigned int load_layout (const std::string &filename, const db::LoadLayoutOptions &options, bool add_cellview) + { + return load_layout (filename, options, std::string (), add_cellview); + } + + /** + * @brief Load a (new) file into the layout with the options and using the specified technology + * + * The add_cellview param controls whether to create a new cellview + * or clear all cellviews before. + * + * @param options The options to use when loading. + * @param add_cellview_param See above. + * @return The index of the cellview loaded. + */ + unsigned int load_layout (const std::string &filename, const db::LoadLayoutOptions &options, const std::string &technology, bool add_cellview); + + /** + * @brief Create a new, empty layout + * + * The add_cellview param controls whether to create a new cellview + * or clear all cellviews before. + * + * The new layout will use the default technology. + * + * @return The index of the cellview loaded. + */ + unsigned int create_layout (bool add_cellview) + { + return create_layout (std::string (), add_cellview, true); + } + + /** + * @brief Create a new, empty layout using the specified technology + * + * The add_cellview param controls whether to create a new cellview + * or clear all cellviews before. + * + * @return The index of the cellview created. + */ + unsigned int create_layout (const std::string &technology, bool add_cellview) + { + return create_layout (technology, add_cellview, true); + } + + /** + * @brief Create a new, empty layout using the specified technology + * + * The add_cellview param controls whether to create a new cellview + * or clear all cellviews before. This version allows one to specify whether layer properties shall be created. + * + * @return The index of the cellview created. + */ + unsigned int create_layout (const std::string &technology, bool add_cellview, bool initialize_layers); + + /** + * @brief Add an existing layout or replace the current cellview by the given layout + * + * The add_cellview param controls whether to add the layout as a new cellview + * or clear all cellviews before. + * + * The "initialize_layers" parameter allows one to specify whether the layer properties shall be initialized. + * + * @return The index of the cellview loaded. + */ + unsigned int add_layout (lay::LayoutHandle *layout_handle, bool add_cellview, bool initialize_layers = true); + + /** + * @brief Pass the current position from the mouse tracker to the status bar + */ + void current_pos (double x, double y); + + /** + * @brief Obtain the number of cellviews + */ + unsigned int cellviews () const + { + return (unsigned int) m_cellviews.size (); + } + + /** + * @brief Obtain the cellviews as a vector + */ + const std::list &cellview_list () const + { + return m_cellviews; + } + + /** + * @brief Obtain the cell view reference for an index + * + * If the index is invalid, an empty cell view reference is returned + */ + const CellView &cellview (unsigned int index) const; + + /** + * @brief Gets a cellview reference to the active cellview + */ + lay::CellViewRef cellview_ref (unsigned int index); + + /** + * @brief Gets the index of the given cellview + * Based on the pointer passed to the function, the index of the respective cellview + * will be returned. If a null pointer is given or the pointer is not a valid cellview, + * -1 will be returned. + */ + int index_of_cellview (const lay::CellView *cv) const; + + /** + * @brief Obtain the list of annotation shapes + */ + const lay::AnnotationShapes &annotation_shapes () const + { + return m_annotation_shapes; + } + + /** + * @brief Obtain the list of annotation shapes (non-const version) + */ + lay::AnnotationShapes &annotation_shapes () + { + return m_annotation_shapes; + } + + /** + * @brief Select the list of cellviews for this window and fit cell + * + * Warning: use with care! + */ + void select_cellviews_fit (const std::list &cvs); + + /** + * @brief Select the list of cellviews for this window + * + * Warning: use with care! + */ + void select_cellviews (const std::list &cvs); + + /** + * @brief Configures the cellview with the given index + * @param index Index of the cellview to configure + * @param cv The cellview that provides the new configuration + */ + void select_cellview (int index, const CellView &cv); + + /** + * @brief Shift and scale the window + */ + void shift_window (double f, double dx, double dy); + + /** + * @brief Goto window + * + * Position the window to the new position x and y with a size of s (approximately). + * If s is negative or zero, the windows is just shifted. + */ + void goto_window (const db::DPoint &p, double s = -1.0); + + /** + * @brief Return the displayed window + */ + db::DBox box () const; + + /** + * @brief Display a status message + */ + void message (const std::string &s = "", int timeout = 10); + + /** + * @brief Create a new cell with the given in the given cellview + * + * @param cv_index The index of the cellview where to create the cell + * @param cell_name The name of the cell (an exception is thrown if a cell of that name already exists) + * @return The index of the new cell + */ + db::cell_index_type new_cell (int cv_index, const std::string &cell_name); + + std::pair redo_available (); + std::pair undo_available (); + + /** + * @brief Select a certain mode (by index) + */ + void mode (int m); + + /** + * @brief Switches the application's mode + * + * Switches the mode on application level. Use this method to initiate + * a mode switch from the view. + */ + void switch_mode (int m); + + /** + * @brief Test, if the view is currently in move mode. + */ + bool is_move_mode () const; + + /** + * @brief Test, if the view is currently in selection mode. + */ + bool is_selection_mode () const; + + /** + * @brief Query the intrinsic mouse modes available + */ + static unsigned int intrinsic_mouse_modes (std::vector *descriptions); + + /** + * @brief Updates the menu for the given view + * If the view is 0, the menu shall be updated to reflect "no view active" + */ + static void update_menu (lay::LayoutViewBase *view, lay::AbstractMenu &menu); + + /** + * @brief Query the default mode + */ + static int default_mode (); + + /** + * @brief Get a list of cellview index and transform variants + */ + std::set< std::pair > cv_transform_variants () const; + + /** + * @brief Get the global transform variants for a given cellview index + */ + std::vector cv_transform_variants (int cv_index) const; + + /** + * @brief Get the global transform variants for a given cellview index and layer + */ + std::vector cv_transform_variants (int cv_index, unsigned int layer) const; + + /** + * @brief Get the transformation variants for a given cellview index ordered by layer + */ + std::map > cv_transform_variants_by_layer (int cv_index) const; + + /** + * @brief Access to the hidden cell list + */ + const std::vector > &hidden_cells () const + { + return m_hidden_cells; + } + + /** + * @brief Get the "dbu_coordinates" flag + * + * If this flag is true, the property dialogs and other display functions should use + * database units to display coordinates etc. + */ + bool dbu_coordinates () const + { + return m_dbu_coordinates; + } + + /** + * @brief Set the "dbu_coordinates" flag + * + * If this flag is true, the property dialogs and other display functions should use + * database units to display coordinates etc. + */ + void dbu_coordinates (bool f); + + /** + * @brief Get the "absolute_coordinates" flag + * + * If this flag is true, the property dialogs and other display functions should use + * absolute (on top level) coordinates for points etc. + * "absolute" may as well refer to orientation, not only to coordinates, + * if transformations are considered. + */ + bool absolute_coordinates () const + { + return m_absolute_coordinates; + } + + /** + * @brief Set the "absolute_coordinates" flag + * + * If this flag is true, the property dialogs and other display functions should use + * absolute (on top level) coordinates for points etc. + * "absolute" may as well refer to orientation, not only to coordinates, + * if transformations are considered. + */ + void absolute_coordinates (bool f); + + /** + * @brief Get the view object widget + * + * This method intentionally delivers the ViewObjectWidget, not the + * LayoutCanvas to emphasize that the LayoutCanvas object shall not + * be modified. + */ + lay::ViewObjectWidget *view_object_widget () + { + return mp_canvas; + } + + /** + * @brief Get the current viewport + */ + const lay::Viewport &viewport () const + { + return mp_canvas->viewport (); + } + + /** + * @brief Background color property + */ + lay::Color background_color () const + { + return mp_canvas->background_color (); + } + + /** + * @brief Foreground color property + */ + lay::Color foreground_color () const + { + return mp_canvas->foreground_color (); + } + + /** + * @brief Active color property + */ + lay::Color active_color () const + { + return mp_canvas->active_color (); + } + + /** + * @brief Write accessor to the "drop small cells" flag + */ + void drop_small_cells (bool m); + + /** + * @brief Read accessor to the "drop small cells" flag + */ + bool drop_small_cells () const + { + return m_drop_small_cells; + } + + /** + * @brief Write accessor to the "drop small cells" value + */ + void drop_small_cells_value (unsigned int s); + + /** + * @brief Read accessor to the "drop small cells" value + */ + unsigned int drop_small_cells_value () const + { + return m_drop_small_cells_value; + } + + /** + * @brief Write accessor to the "drop small cells" condition + */ + void drop_small_cells_cond (drop_small_cells_cond_type t); + + /** + * @brief Read accessor to the "drop small cells" condition + */ + drop_small_cells_cond_type drop_small_cells_cond () const + { + return m_drop_small_cells_cond; + } + + /** + * @brief Gets a value indicating whether guiding shapes are visible + */ + bool guiding_shapes_visible () const + { + return m_guiding_shape_visible; + } + + /** + * @brief Sets a value indicating whether guiding shapes are visible + */ + void guiding_shapes_visible (bool v); + + /** + * @brief Gets the guiding shapes color + */ + lay::Color guiding_shapes_color () const + { + return m_guiding_shape_color; + } + + /** + * @brief Sets the guiding shapes color + */ + void guiding_shapes_color (lay::Color c); + + /** + * @brief Gets the guiding shapes line width + */ + int guiding_shapes_line_width () const + { + return m_guiding_shape_line_width; + } + + /** + * @brief Sets the guiding shapes line width + */ + void guiding_shapes_line_width (int lw); + + /** + * @brief Gets the guiding shapes vertex size + */ + int guiding_shapes_vertex_size () const + { + return m_guiding_shape_vertex_size; + } + + /** + * @brief Sets the guiding shapes vertex size + */ + void guiding_shapes_vertex_size (int lw); + + /** + * @brief Read accessor to the "abstract mode width" property. + * + * The abstract mode width enables abstract mode (for values > 0) and + * specifies the border to search for touching shapes. + */ + double abstract_mode_width () const + { + return m_abstract_mode_enabled ? m_abstract_mode_width : 0.0; + } + + /** + * @brief Read accessor to the "child context enabled" property. + * + * If child context is enabled, a third set of bit planes must be created by the redraw thread + * containing the shapes for the below-top-level objects. + */ + bool child_context_enabled () const + { + return m_child_ctx_enabled; + } + + /** + * @brief Write accessor to the "draw array border instances" flag + */ + void draw_array_border_instances (bool m); + + /** + * @brief Read accessor to the "draw array border instances" flag + */ + bool draw_array_border_instances () const + { + return m_draw_array_border_instances; + } + + /** + * @brief Get the Drawings interface + * + * Although the Drawings interface is implemented by LayoutCanvas, + * it is a different interface from ViewObjectWidget. + */ + lay::Drawings *drawings () + { + return mp_canvas; + } + + /** + * @brief Select synchronous mode or deselect it + */ + void set_synchronous (bool sync_mode); + + /** + * @brief Tell the state of synchronous mode + */ + bool synchronous () const + { + return m_synchronous; + } + + /** + * @brief Set the number of drawing workers (if not synchronous) + */ + void set_drawing_workers (int workers); + + /** + * @brief Get the number of drawing workers + */ + int drawing_workers () const + { + return m_drawing_workers; + } + + /** + * @brief Gets a value indicating whether the view will accept a dropped file with the given URL or path + */ + virtual bool accepts_drop (const std::string &path_or_url) const; + + /** + * @brief Gets called when a file or URL is dropped on the view + */ + virtual void drop_url (const std::string &path_or_url); + + /** + * @brief Gets a list of all plugins + */ + const std::vector &plugins () + { + return mp_plugins; + } + + /** + * @brief Localize a plugin by name + * + * This method will return 0, if no such plugin is registered + */ + Plugin *get_plugin_by_name (const std::string &name) const; + + /** + * @brief Localize the plugin of the given Type + * + * This method will return 0, if no such plugin is registered + */ + template + PI *get_plugin () const + { + PI *pi = 0; + for (std::vector::const_iterator p = mp_plugins.begin (); p != mp_plugins.end () && !pi; ++p) { + pi = dynamic_cast (*p); + } + return pi; + } + + /** + * @brief Localize the plugins of the given Type + * + * This method will return 0, if no such plugin is registered + */ + template + std::vector get_plugins () const + { + std::vector pi; + for (std::vector::const_iterator p = mp_plugins.begin (); p != mp_plugins.end (); ++p) { + if (dynamic_cast (*p) != 0) { + pi.push_back (dynamic_cast (*p)); + } + } + return pi; + } + + /** + * @brief Create a plugin of the given type + * + * This method can be used to selectively create plugins when the NoPlugin option + * is used. If no such plugin is registered, no plugin is created. + * If a plugin with that name is already registered, it is not created again. + * PD is the type of the declaration. + */ + template + void create_plugin () + { + for (std::vector::const_iterator p = mp_plugins.begin (); p != mp_plugins.end (); ++p) { + if (dynamic_cast ((*p)->plugin_declaration ()) != 0) { + return; + } + } + for (tl::Registrar::iterator cls = tl::Registrar::begin (); cls != tl::Registrar::end (); ++cls) { + if (dynamic_cast (&*cls) != 0) { + create_plugin (&*cls); + break; + } + } + } + + + /** + * @brief Enable or disable the actions for edit functions + * + * This method is used by non-modal dialogs that want to suppress any editing + * activities (like browsers) while they are open. + * + * This method can be called multiple times and will count the enable/disable + * transitions. Each disable will cancel on enable call. + */ + void enable_edits (bool enable); + + /** + * @brief Gets a value indicating whether edits are enabled or not + * + * "enable_edits" will change this value. + */ + bool edits_enabled () const + { + return m_disabled_edits <= 0; + } + + /** + * @brief Rename the given cellview to the given name + * + * The name of the cell view is shown in the title + */ + void rename_cellview (const std::string &name, int cellview_index); + + /** + * @brief Descend into the hierarchy along the given specific path for the given cellview + */ + void descend (const std::vector &path, int cellview_index); + + /** + * @brief Ascend one level in the hierarchy for the given cellview + * + * @return The instance element removed by ascending the path + */ + db::InstElement ascend (int cellview_index); + + /** + * @brief Select a cell by path for a certain cell view and fit cell + */ + void select_cell_fit (const cell_path_type &path, int cellview_index); + + /** + * @brief Select a cell by index for a certain cell view and fit cell + */ + void select_cell_fit (cell_index_type index, int cellview_index); + + /** + * @brief Select a cell by path for a certain cell view + */ + void select_cell (const cell_path_type &path, int cellview_index); + + /** + * @brief Select a cell by index for a certain cell view + */ + void select_cell (cell_index_type index, int cellview_index); + + /** + * @brief Check if a cell is hidden + */ + bool is_cell_hidden (cell_index_type ci, int cellview_index) const; + + /** + * @brief Get the hidden cells for a certain cellview + */ + const std::set &hidden_cells (int cellview_index) const; + + /** + * @brief Add a cell to the hidden cell list + */ + void hide_cell (cell_index_type ci, int cellview_index); + + /** + * @brief Remove a cell from the hidden cell list + */ + void show_cell (cell_index_type ci, int cellview_index); + + /** + * @brief Clears the hidden cell list + */ + void show_all_cells (); + + /** + * @brief Clears the hidden cell list for the given cellview + */ + void show_all_cells (int cv_index); + + /** + * @brief Update the layout view to the current state + * + * This method must be called in order to trigger the update of + * the contents. It will be known, what needs to be updated. + */ + void update_content (); + + /** + * @brief Force an unconditional update + * + * This method is supposed to be used to ensure everything is updated. + * TODO: this method should become obsolete once there is a consistent + * signalling of states implemented. + */ + void force_update_content (); + + /** + * @brief Create a set of initial layer properties for the given cellview + * + * @param cv_index The cellview for which to produce a set of layer properties + * @param lyp_file The layer properties file to load or empty if no file should be loaded + * @param add_missing True, if missing layers should be added (ignored if lyp_file is empty) + */ + void create_initial_layer_props (int cv_index, const std::string &lyp_file, bool add_missing); + + /** + * @brief Merges the given properties into the cell properties of this view + */ + void merge_layer_props (const std::vector &props); + + /** + * @brief Internal method: check, if the layer tree is and an consistent state. + * + * This method is used by the layer tree model to check, if the tree has been brought into + * a consistent state. + * HINT: for the layout this is solved more consistently with the "under construction" attribute + * of the layout. There is no equivalent object for the layer tree currently. + */ + bool layer_model_updated (); + + /** + * @brief Get the "select inside PCells" selection mode + * + * @return true, objects inside PCells can be selected + */ + bool select_inside_pcells_mode () const + { + return m_sel_inside_pcells; + } + + /** + * @brief Get the transient selection mode + * + * @return true, if transient (hover) selection mode is enabled + */ + bool transient_selection_mode () const + { + return m_transient_selection_mode; + } + + /** + * @brief Get the default color for markers + */ + lay::Color default_marker_color () const + { + return m_marker_color; + } + + /** + * @brief Get the default line width for markers + */ + int default_marker_line_width () const + { + return m_marker_line_width; + } + + /** + * @brief Get the default marker dither pattern index + */ + int default_dither_pattern () const + { + return m_marker_dither_pattern; + } + + /** + * @brief Get the default marker line style index + */ + int default_line_style () const + { + return m_marker_line_style; + } + + /** + * @brief Get the default vertex size for markers + */ + int default_marker_vertex_size () const + { + return m_marker_vertex_size; + } + + /** + * @brief Get the default halo flag for markers + */ + int default_marker_halo () const + { + return m_marker_halo; + } + + /** + * @brief Gets the "search range" in pixels (for single click) + * The search range applies whenever some object is looked up in the vicinity of the + * mouse cursor. This value gives the search range in pixels. + */ + unsigned int search_range (); + + /** + * @brief Sets the "search range" in pixels (for single click) + */ + void set_search_range (unsigned int sr); + + /** + * @brief Gets the "search range" in pixels (for box) + * The search range applies whenever some object is looked up in the vicinity of the + * mouse cursor. This value gives the search range in pixels. + */ + unsigned int search_range_box (); + + /** + * @brief Sets the "search range" in pixels (for box) + */ + void set_search_range_box (unsigned int sr); + + /** + * @brief Return true, if any cellview is editable + */ + bool is_editable () const; + + /** + * @brief Get the view_op's for rendering the layers + */ + const std::vector &get_view_ops () const + { + return mp_canvas->get_view_ops (); + } + + /** + * @brief Get the redraw layer info vector + */ + const std::vector &get_redraw_layers () const + { + return mp_canvas->get_redraw_layers (); + } + + /** + * @brief Add missing layers + */ + void add_missing_layers (); + + /** + * @brief Add layers which are not part of the LayerState + */ + void add_new_layers (const LayerState &snapshot); + + /** + * @brief Gets a snapshot of the current layers (can be used for add_missing_layers later) + */ + LayerState layer_snapshot () const; + + /** + * @brief Remove unused layers + */ + void remove_unused_layers (); + + /** + * @brief Returns true, if the layer source shall be shown always in the layer properties tree + */ + bool always_show_source () const + { + return m_always_show_source; + } + + /** + * @brief Returns true, if the layer/datatype shall be shown always in the layer properties tree + */ + bool always_show_ld () const + { + return m_always_show_ld; + } + + /** + * @brief Returns true, if the layout index shall be shown always in the layer properties tree + */ + bool always_show_layout_index () const + { + return m_always_show_layout_index; + } + + /** + * @brief Add a marker database + * + * The layout view will become owner of the database. + * + * @param rdb The database to add + * @return The index of the database + */ + unsigned int add_rdb (rdb::Database *rdb); + + /** + * @brief Replaces a marker database + * + * The layout view will become owner of the database. + * If the index is not valid, the database will be added and the new index will be returned. + * + * @param db_index The index of the database to replace + * @param rdb The database to add + */ + unsigned int replace_rdb (unsigned int db_index, rdb::Database *rdb); + + /** + * @brief Get the marker database by index + * + * @param index The index of the database + * @return A pointer to the database or 0 if the index was not valid. + */ + rdb::Database *get_rdb (int index); + + /** + * @brief Get the marker database by index (const version) + * + * @param index The index of the database + * @return A pointer to the database or 0 if the index was not valid. + */ + const rdb::Database *get_rdb (int index) const; + + /** + * @brief Remove the marker database with the given index + * + * This will release the marker database at the given index. The list + * will be reduced by that element. This means, that the following elements + * will have different indicies. + */ + void remove_rdb (unsigned int index); + + /** + * @brief Get the number of marker databases + */ + unsigned int num_rdbs () const + { + return (unsigned int) m_rdbs.size (); + } + + /** + * @brief An event signalling a change in the marker database list + * + * If marker databases are added or removed, this event is triggered. + */ + tl::Event rdb_list_changed_event; + + /** + * @brief Add a Netlist database + * + * The layout view will become owner of the database. + * + * @param l2ndb The database to add + * @return The index of the database + */ + unsigned int add_l2ndb (db::LayoutToNetlist *l2ndb); + + /** + * @brief Replaces a Netlist database + * + * The layout view will become owner of the database. + * If the index is not valid, the database will be added and the new index will be returned. + * + * @param db_index The index of the database to replace + * @param l2ndb The database to add + */ + unsigned int replace_l2ndb (unsigned int db_index, db::LayoutToNetlist *l2ndb); + + /** + * @brief Get the netlist database by index + * + * @param index The index of the database + * @return A pointer to the database or 0 if the index was not valid. + */ + db::LayoutToNetlist *get_l2ndb (int index); + + /** + * @brief Get the netlist database by index (const version) + * + * @param index The index of the database + * @return A pointer to the database or 0 if the index was not valid. + */ + const db::LayoutToNetlist *get_l2ndb (int index) const; + + /** + * @brief Remove the netlist database with the given index + * + * This will release the netlist database at the given index. The list + * will be reduced by that element. This means, that the following elements + * will have different indicies. + */ + void remove_l2ndb (unsigned int index); + + /** + * @brief Get the number of netlist databases + */ + unsigned int num_l2ndbs () const + { + return (unsigned int) m_l2ndbs.size (); + } + + /** + * @brief An event signalling a change in the netlist database list + * + * If netlist databases are added or removed, this event is triggered. + */ + tl::Event l2ndb_list_changed_event; + + /** + * @brief Ensure the given box is visible + */ + void ensure_visible (const db::DBox &b); + + /** + * @brief Specify the global transformation + */ + void set_global_trans (const db::DCplxTrans &b); + + /** + * @brief Gets the global transformation + */ + const db::DCplxTrans &global_trans () const + { + return mp_canvas->global_trans (); + } + + /** + * @brief Removes the previous state from the stack + */ + void pop_state (); + + /** + * @brief Clears the state stack + */ + void clear_states (); + + /** + * @brief Zoom the given box into view + */ + void zoom_box (const db::DBox &b); + + /** + * @brief Zoom the given box into view and select hierarchy levels + */ + void zoom_box_and_set_hier_levels (const db::DBox &b, const std::pair &levels); + + /** + * @brief Specify the transformation explicitly + */ + void zoom_trans (const db::DCplxTrans &b); + + /** + * @brief Move the viewport such that the given point is at the center of the viewport + */ + void pan_center (const db::DPoint &p); + + /** + * @brief Goto a position/cell view that was saved with save_view + */ + void goto_view (const DisplayState &state); + + /** + * @brief Save a position/cell view that can be used for "goto_view" + */ + void save_view (DisplayState &state) const; + + // access to the basic services + lay::MouseTracker *mouse_tracker () const { return mp_tracker; } + lay::ZoomService *zoom_service () const { return mp_zoom_service; } + lay::SelectionService *selection_service () const { return mp_selection_service; } + lay::MoveService *move_service () const { return mp_move_service; } + + /** + * @brief Create all plugins + * + * If plugins already exist, they are deleted and created again + */ + void create_plugins (const lay::PluginDeclaration *except_this = 0); + + /** + * @brief Gets the full field box + * + * This is the box to which the view will zoom on zoom_fit(). + * This box is supposed to cover everything inside the view. + */ + db::DBox full_box () const; + + /** + * @brief Gets called when a menu item is activated + */ + void menu_activated (const std::string &symbol); + + /** + * @brief Gets all available menu symbols + */ + static std::vector menu_symbols (); + + /** + * @brief Store the current state on the "previous states" stack + */ + void store_state (); + + /** + * @brief Cancels all edit operations, clears the selection and resets the mode to "Select" + */ + void cancel_esc (); + + /** + * @brief Cancels all edit operations and clears the selection + */ + void cancel (); + + /** + * @brief Cancels all edit operations but maintains selection + */ + void cancel_edits (); + + /** + * @brief Select all levels of hierarchy available + */ + void max_hier (); + + /** + * @brief Stop activities like shape browser and redrawing thread + */ + void stop (); + + /** + * @brief Stop redrawing thread + */ + void stop_redraw (); + + /** + * @brief Select last display state + */ + void prev_display_state (); + + /** + * @brief Select next display state + */ + void next_display_state (); + + /** + * @brief Ensure the selection is visible + */ + void ensure_selection_visible (); + + /** + * @brief Select a cell by index for a certain cell view + * + * This will be forwarded to select_cell or select_cell_fit depending + * on the m_fit_new_cell flag. + */ + void select_cell_dispatch (const cell_path_type &path, int cellview_index); + + /** + * @brief Called when the current layer changed + */ + void current_layer_changed_slot (const lay::LayerPropertiesConstIterator &iter); + + // zoom slots + void zoom_fit (); + void zoom_fit_sel (); + void zoom_in (); + void zoom_out (); + void pan_left (); + void pan_up (); + void pan_right (); + void pan_down (); + void pan_left_fast (); + void pan_up_fast (); + void pan_right_fast (); + void pan_down_fast (); + + // called by children and owner + void redraw (); + void redraw_layer (unsigned int index); + void redraw_deco_layer (); + void redraw_cell_boxes (); + void layer_tab_changed (); + void layer_order_changed (); + void timer (); + void min_hier_changed (int i); + void max_hier_changed (int i); + +private: + // event handlers used to connect to the layout object's events + void signal_hier_changed (); + void signal_bboxes_from_layer_changed (unsigned int cv_index, unsigned int layer_index); + void signal_bboxes_changed (); + void signal_prop_ids_changed (); + void signal_layer_properties_changed (); + void signal_cell_name_changed (); + void signal_annotations_changed (); + void signal_plugin_enabled_changed (); + void signal_apply_technology (lay::LayoutHandle *layout_handle); + + void active_cellview_changed (int index); + void active_library_changed (int index); + void side_panel_destroyed (); + +private: + bool m_editable; + int m_disabled_edits; + unsigned int m_options; + lay::LayoutCanvas *mp_canvas; + std::list m_cellviews; + lay::AnnotationShapes m_annotation_shapes; + std::vector > m_hidden_cells; + std::string m_title; + tl::vector m_rdbs; + tl::vector m_l2ndbs; + std::string m_def_lyp_file; + bool m_add_other_layers; + bool m_always_show_source; + bool m_always_show_ld; + bool m_always_show_layout_index; + bool m_synchronous; + int m_drawing_workers; + + int m_from_level, m_to_level; + double m_pan_distance; + int m_paste_display_mode; + int m_wheel_mode; + bool m_guiding_shape_visible; + lay::Color m_guiding_shape_color; + int m_guiding_shape_line_width; + int m_guiding_shape_vertex_size; + + lay::Color m_ctx_color; + int m_ctx_dimming; + bool m_ctx_hollow; + + lay::Color m_child_ctx_color; + int m_child_ctx_dimming; + bool m_child_ctx_hollow; + bool m_child_ctx_enabled; + + double m_abstract_mode_width; + bool m_abstract_mode_enabled; + + lay::Color m_box_color; + bool m_box_text_transform; + unsigned int m_box_font; + int m_min_size_for_label; + bool m_cell_box_visible; + + lay::Color m_marker_color; + int m_marker_line_width; + int m_marker_vertex_size; + int m_marker_dither_pattern; + int m_marker_line_style; + bool m_marker_halo; + + unsigned int m_search_range; + unsigned int m_search_range_box; + + bool m_transient_selection_mode; + bool m_sel_inside_pcells; + + int m_default_font_size; + bool m_text_visible; + bool m_text_lazy_rendering; + bool m_bitmap_caching; + bool m_show_properties; + lay::Color m_text_color; + bool m_apply_text_trans; + double m_default_text_size; + unsigned int m_text_font; + bool m_show_markers; + bool m_no_stipples; + bool m_stipple_offset; + + bool m_drop_small_cells; + unsigned int m_drop_small_cells_value; + drop_small_cells_cond_type m_drop_small_cells_cond; + + bool m_draw_array_border_instances; + + bool m_fit_new_cell; + bool m_full_hier_new_cell; + bool m_clear_ruler_new_cell; + bool m_dbu_coordinates; + bool m_absolute_coordinates; + + bool m_dirty; + bool m_activated; + bool m_animated; + unsigned int m_phase; + + lay::ColorPalette m_palette; + lay::StipplePalette m_stipple_palette; + lay::LineStylePalette m_line_style_palette; + + std::vector m_display_states; + unsigned int m_display_state_ptr; + + std::vector m_layer_properties_lists; + unsigned int m_current_layer_list; + + // service and editable management + int m_mode; + + // services & editables + lay::MouseTracker *mp_tracker; + lay::ZoomService *mp_zoom_service; + lay::SelectionService *mp_selection_service; + lay::MoveService *mp_move_service; + + std::vector mp_plugins; + + bool m_visibility_changed; + + void init (db::Manager *mgr); + + void do_prop_changed (); + void do_redraw (int layer); + void do_redraw (); + + void set_view_ops (); + void background_color (lay::Color c); + void ctx_color (lay::Color c); + void ctx_dimming (int percent); + void ctx_hollow (bool h); + void child_ctx_color (lay::Color c); + void child_ctx_dimming (int percent); + void child_ctx_hollow (bool h); + void child_ctx_enabled (bool e); + void abstract_mode_width (double w); + void abstract_mode_enabled (bool e); + bool has_max_hier () const; + int max_hier_level () const; + bool set_hier_levels_basic (std::pair l); + + void update_event_handlers (); + void viewport_changed (); + void cellview_changed (unsigned int index); + + bool configure (const std::string &name, const std::string &value); + void config_finalize (); + + void do_load_layer_props (const std::string &fn, bool map_cv, int cv_index, bool add_default); + void finish_cellviews_changed (); + void init_layer_properties (LayerProperties &props, const LayerPropertiesList &lp_list) const; + void merge_dither_pattern (lay::LayerPropertiesList &props); + + // overrides Editables method to display a message + void signal_selection_changed (); + + lay::Plugin *create_plugin (const lay::PluginDeclaration *cls); + + std::list::iterator cellview_iter (int cv_index); + std::list::const_iterator cellview_iter (int cv_index) const; +}; + +} + +#endif diff --git a/src/laybasic/laybasic/layMouseTracker.h b/src/laybasic/laybasic/layMouseTracker.h index 3e826606b..2eb5c33e5 100644 --- a/src/laybasic/laybasic/layMouseTracker.h +++ b/src/laybasic/laybasic/layMouseTracker.h @@ -31,17 +31,17 @@ class QMouseEvent; namespace lay { class LayoutCanvas; -class LayoutView; +class LayoutViewBase; class MouseTracker : public lay::ViewService { public: - MouseTracker (lay::LayoutView *view); + MouseTracker (lay::LayoutViewBase *view); virtual bool mouse_move_event (const db::DPoint &p, unsigned int buttons, bool prio); private: - lay::LayoutView *mp_view; + lay::LayoutViewBase *mp_view; }; } diff --git a/src/laybasic/laybasic/layMove.h b/src/laybasic/laybasic/layMove.h index 0bea3f5a9..3908c6505 100644 --- a/src/laybasic/laybasic/layMove.h +++ b/src/laybasic/laybasic/layMove.h @@ -20,32 +20,24 @@ */ - - #ifndef HDR_layMove #define HDR_layMove #include "dbManager.h" #include "layViewObject.h" -#include -#include - #include namespace lay { class Editables; -class LayoutView; +class LayoutViewBase; -class MoveService - : public QObject, +class MoveService : public lay::ViewService { -Q_OBJECT - public: - MoveService (lay::LayoutView *view); + MoveService (lay::LayoutViewBase *view); ~MoveService (); virtual bool configure (const std::string &name, const std::string &value); @@ -67,7 +59,7 @@ private: bool m_dragging; bool m_dragging_transient; lay::Editables *mp_editables; - lay::LayoutView *mp_view; + lay::LayoutViewBase *mp_view; double m_global_grid; db::DPoint m_shift; db::DPoint m_mouse_pos; diff --git a/src/laybasic/laybasic/layParsedLayerSource.cc b/src/laybasic/laybasic/layParsedLayerSource.cc index da2c51a16..5e7dee250 100644 --- a/src/laybasic/laybasic/layParsedLayerSource.cc +++ b/src/laybasic/laybasic/layParsedLayerSource.cc @@ -22,7 +22,7 @@ #include "layParsedLayerSource.h" -#include "layLayoutView.h" +#include "layLayoutViewBase.h" #include "tlString.h" #include "tlGlobPattern.h" @@ -1163,7 +1163,7 @@ ParsedLayerSource::to_string () const } std::string -ParsedLayerSource::display_string (const lay::LayoutView *view) const +ParsedLayerSource::display_string (const lay::LayoutViewBase *view) const { std::string r; diff --git a/src/laybasic/laybasic/layParsedLayerSource.h b/src/laybasic/laybasic/layParsedLayerSource.h index e3bbfa511..e2c7936bf 100644 --- a/src/laybasic/laybasic/layParsedLayerSource.h +++ b/src/laybasic/laybasic/layParsedLayerSource.h @@ -43,7 +43,7 @@ namespace lay { class LayerProperties; -class LayoutView; +class LayoutViewBase; class PropertySelectorBase; /** @@ -640,7 +640,7 @@ public: * This method delivers a display version that may be abbreviated and is supposed * to be used in the layer list display. */ - std::string display_string (const lay::LayoutView *view) const; + std::string display_string (const lay::LayoutViewBase *view) const; /** * @brief Comparison (equality) diff --git a/src/laybasic/laybasic/layPlugin.h b/src/laybasic/laybasic/layPlugin.h index 8f634c0a9..c03fae38e 100644 --- a/src/laybasic/laybasic/layPlugin.h +++ b/src/laybasic/laybasic/layPlugin.h @@ -48,7 +48,7 @@ namespace lay class Plugin; class Dispatcher; -class LayoutView; +class LayoutViewBase; class ViewService; class Editable; class Drawing; @@ -302,7 +302,7 @@ public: * This method may return 0 for "dummy" plugins that just register menu entries * or configuration options. */ - virtual lay::Plugin *create_plugin (db::Manager * /*manager*/, lay::Dispatcher * /*dispatcher*/, lay::LayoutView * /*view*/) const + virtual lay::Plugin *create_plugin (db::Manager * /*manager*/, lay::Dispatcher * /*dispatcher*/, lay::LayoutViewBase * /*view*/) const { return 0; } @@ -329,7 +329,7 @@ public: * * The new pages are returned in the "pages" vector. The layout view will take ownership of these pages. */ - virtual void get_editor_options_pages (std::vector & /*pages*/, lay::LayoutView * /*view*/, lay::Dispatcher * /*dispatcher*/) const + virtual void get_editor_options_pages (std::vector & /*pages*/, lay::LayoutViewBase * /*view*/, lay::Dispatcher * /*dispatcher*/) const { // .. no pages in the default implementation .. } @@ -351,8 +351,8 @@ public: /** * @brief Specifies the primary mouse modes * - * These are built-in modes from the LayoutView. This method is intended for - * the LayoutView's standard modes only. + * These are built-in modes from the LayoutViewBase. This method is intended for + * the LayoutViewBase's standard modes only. */ virtual void implements_primary_mouse_modes (std::vector > > & /*modes*/) { diff --git a/src/laybasic/laybasic/laySelector.h b/src/laybasic/laybasic/laySelector.h index b7f5f5e22..f804b243e 100644 --- a/src/laybasic/laybasic/laySelector.h +++ b/src/laybasic/laybasic/laySelector.h @@ -30,23 +30,29 @@ #include "layViewObject.h" #include "layEditable.h" -#include -#include +#if defined (HAVE_QT) +# include +# include +#endif namespace lay { class RubberBox; -class LayoutView; +class LayoutViewBase; class LayoutCanvas; -class LAYBASIC_PUBLIC SelectionService - : public QObject, +class LAYBASIC_PUBLIC SelectionService : +#if defined (HAVE_QT) + public QObject, +#endif public lay::ViewService { +#if defined (HAVE_QT) Q_OBJECT +#endif public: - SelectionService (lay::LayoutView *view); + SelectionService (lay::LayoutViewBase *view); ~SelectionService (); void set_colors (lay::Color background, lay::Color color); @@ -72,8 +78,10 @@ public: */ void hover_reset (); +#if defined (HAVE_QT) public slots: void timeout (); +#endif private: virtual void deactivated (); @@ -84,11 +92,13 @@ private: lay::RubberBox *mp_box; unsigned int m_color; unsigned int m_buttons; - QTimer m_timer; bool m_hover; bool m_hover_wait; db::DPoint m_hover_point; bool m_mouse_in_window; +#if defined (HAVE_QT) + QTimer m_timer; +#endif void reset_box (); }; diff --git a/src/laybasic/laybasic/layZoomBox.h b/src/laybasic/laybasic/layZoomBox.h index a0a497a83..7794c6473 100644 --- a/src/laybasic/laybasic/layZoomBox.h +++ b/src/laybasic/laybasic/layZoomBox.h @@ -30,7 +30,7 @@ namespace lay { -class LayoutView; +class LayoutViewBase; class LayoutCanvas; class RubberBox; @@ -38,7 +38,7 @@ class LAYBASIC_PUBLIC ZoomService : public lay::ViewService { public: - ZoomService (lay::LayoutView *view); + ZoomService (lay::LayoutViewBase *view); ~ZoomService (); void set_colors (lay::Color background, lay::Color text); @@ -55,7 +55,7 @@ private: db::DPoint m_p1, m_p2; db::DBox m_vp; - lay::LayoutView *mp_view; + lay::LayoutViewBase *mp_view; lay::RubberBox *mp_box; unsigned int m_color; }; diff --git a/src/laybasic/laybasic/laybasic.pro b/src/laybasic/laybasic/laybasic.pro index 5c370f207..6010e29b0 100644 --- a/src/laybasic/laybasic/laybasic.pro +++ b/src/laybasic/laybasic/laybasic.pro @@ -273,6 +273,7 @@ SOURCES += \ layStipplePalette.cc \ layStream.cc \ layCanvasPlane.cc \ + layLayoutViewBase.cc \ layLayerProperties.cc \ layViewObject.cc \ layViewOp.cc \ @@ -289,6 +290,7 @@ HEADERS += \ layEditable.h \ layFinder.h \ layFixedFont.h \ + layLayoutViewBase.h \ layLineStylePalette.h \ layLineStyles.h \ layMarker.h \