/* KLayout Layout Viewer Copyright (C) 2006-2016 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_layLayerProperties #define HDR_layLayerProperties #include "laybasicCommon.h" #include "dbBox.h" #include "layViewOp.h" #include "layParsedLayerSource.h" #include "layDitherPattern.h" #include "layLineStyles.h" #include "tlStableVector.h" #include "tlXMLParser.h" #include "tlObject.h" #include "gsi.h" #include #include #include namespace tl { class XMLSource; } namespace lay { class LayoutView; class LayerPropertiesList; class LayerPropertiesNode; /** * @brief A layer properties structure * * The layer properties encapsulate the settings relevant for * the display and source of a layer. * * Each attribute is present in two incarnations: local and real. * "real" refers to the effective attribute after collecting the * attributes from the parents to the leaf property node. * The "real" attributes are computed when the property tree is * "realized". In the spirit of this distinction, all read accessors * are present in "local" and "real" form. The read accessors take * a boolean parameter "real" that must be set to true, if the real * value shall be returned. * * The source is specified in two ways: once in "source" and once * in an internal representation that can be used by the drawing engine. * The "realize" method converts the generic into the internal * representation. * * "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. */ class LAYBASIC_PUBLIC LayerProperties : public gsi::ObjectBase { public: /** * @brief Constructor */ LayerProperties (); /** * @brief Destructor */ virtual ~LayerProperties (); /** * @brief Copy constructor */ LayerProperties (const LayerProperties &d); /** * @brief assignment */ LayerProperties &operator= (const LayerProperties &d); /** * @brief Assignment alias for GSI binding */ void assign_lp (const LayerProperties &d) { operator= (d); } /** * @brief Equality */ bool operator== (const LayerProperties &d) const; /** * @brief Inequality */ bool operator!= (const LayerProperties &d) const { return !operator== (d); } /** * @brief Utility: compute the effective color from a color with brightness correction */ static color_t brighter (color_t in, int b); /** * @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 (bool real) const; /** * @brief render the effective fill color * * The effective fill color is computed from the frame color brightness and the * frame color. */ color_t eff_fill_color (bool real) const; /** * @brief render the effective frame color plus an additional brightness adjustment * * This method returns the effective frame color with an additional brightness adjustment * applied. */ color_t eff_frame_color_brighter (bool real, int plus_brightness) const; /** * @brief render the effective frame color plus an additional brightness adjustment * * This method returns the effective fill color with an additional brightness adjustment * applied. */ color_t eff_fill_color_brighter (bool real, int plus_brightness) const; /** * @brief Get the frame color * * This method may return an invalid color if the color is not set. */ color_t frame_color (bool real) const { if (real) { ensure_visual_realized (); return m_frame_color_real; } else { return m_frame_color; } } /** * @brief Set the frame color code to the given value * * To clear the frame color, pass 0 to this method. Valid colors have the * upper 8 bits set. */ void set_frame_color_code (color_t c) { if (m_frame_color != c) { m_frame_color = c; need_realize (nr_visual); } } /** * @brief Set the frame color to the given value */ void set_frame_color (color_t c) { set_frame_color_code (c | 0xff000000); } /** * @brief Reset the frame color */ void clear_frame_color () { set_frame_color_code (0); } /** * @brief Test, if the frame color is set */ bool has_frame_color (bool real) const { return frame_color (real) != 0; } /** * @brief Get the fill color * * This method may return an invalid color if the color is not set. */ color_t fill_color (bool real) const { if (real) { ensure_visual_realized (); return m_fill_color_real; } else { return m_fill_color; } } /** * @brief Set the fill color code to the given value * * To clear the fill color, pass 0 to this method. Valid colors have the * upper 8 bits set. */ void set_fill_color_code (color_t c) { if (m_fill_color != c) { m_fill_color = c; need_realize (nr_visual); } } /** * @brief Set the fill color to the given value */ void set_fill_color (color_t c) { set_fill_color_code (c | 0xff000000); } /** * @brief Reset the fill color */ void clear_fill_color () { set_fill_color_code (0); } /** * @brief Test, if the frame color is set */ bool has_fill_color (bool real) const { return fill_color (real) != 0; } /** * @brief Set the frame brightness * * For neutral brightness set this value to 0. */ void set_frame_brightness (int b) { if (m_frame_brightness != b) { m_frame_brightness = b; need_realize (nr_visual); } } /** * @brief Get the frame brightness value */ int frame_brightness (bool real) const { if (real) { ensure_visual_realized (); return m_frame_brightness_real; } else { return m_frame_brightness; } } /** * @brief Set the fill brightness * * For neutral brightness set this value to 0. */ void set_fill_brightness (int b) { if (m_fill_brightness != b) { m_fill_brightness = b; need_realize (nr_visual); } } /** * @brief Get the fill brightness value * * If the brightness is not set, this method may return an invalid value */ int fill_brightness (bool real) const { if (real) { ensure_visual_realized (); return m_fill_brightness_real; } else { return m_fill_brightness; } } /** * @brief Set the dither pattern index */ void set_dither_pattern (int index) { if (m_dither_pattern != index) { m_dither_pattern = index; need_realize (nr_visual); } } /** * @brief Get the effective dither pattern index */ unsigned int eff_dither_pattern (bool real) const { if (! has_dither_pattern (real)) { return 1; // empty fill pattern } else { return (unsigned int) dither_pattern (real); } } /** * @brief Get the dither pattern index * * This method may deliver an invalid dither pattern index if it is not set. */ int dither_pattern (bool real) const { if (real) { ensure_visual_realized (); return m_dither_pattern_real; } else { return m_dither_pattern; } } /** * @brief Clear the dither pattern */ void clear_dither_pattern () { set_dither_pattern (-1); } /** * @brief Test, if the dither pattern is set */ bool has_dither_pattern (bool real) const { return dither_pattern (real) >= 0; } /** * @brief Set the line style index */ void set_line_style (int index) { if (m_line_style != index) { m_line_style = index; need_realize (nr_visual); } } /** * @brief Get the effective line style index */ unsigned int eff_line_style (bool real) const { if (! has_line_style (real)) { return 0; // solid line style } else { return (unsigned int) line_style (real); } } /** * @brief Get the line style index * * This method may deliver an invalid line style index if it is not set. */ int line_style (bool real) const { if (real) { ensure_visual_realized (); return m_line_style_real; } else { return m_line_style; } } /** * @brief Clear the line style */ void clear_line_style () { set_line_style (-1); } /** * @brief Test, if the line style is set */ bool has_line_style (bool real) const { return line_style (real) >= 0; } /** * @brief Set the validity state */ void set_valid (bool v) { if (m_valid != v) { m_valid = v; need_realize (nr_visual); } } /** * @brief Get the validity state */ bool valid (bool real) const { if (real) { ensure_visual_realized (); return m_valid_real; } else { return m_valid; } } /** * @brief Set the visibility state */ void set_visible (bool v) { if (m_visible != v) { m_visible = v; need_realize (nr_visual); } } /** * @brief Get the visibility state */ bool visible (bool real) const { if (real) { ensure_visual_realized (); return m_visible_real; } else { return m_visible; } } /** * @brief Return true, if the layer is showing "something" * * A layer "shows something" if it is visible and it displays some information, * either shapes or cell boxes. Invalid layers, i.e. such that have a layer selection * which does not match one of the layers in the layout or invalid layers, are not considered "visual". * * Only "visual" layers are considered for selection, object snapping etc. * * This method evaluates the state in "real" mode. */ bool is_visual () const; /** * @brief shape layer attribute * * This attribute is true, if the layer provides shapes and is a valid layer. */ bool is_shape_layer () const { return layer_index () >= 0; } /** * @brief standard layer attribute * * This attribute is true, if the layer provides layout shapes. */ bool is_standard_layer () const { return source (true).special_purpose () == lay::ParsedLayerSource::SP_None; } /** * @brief cell_box layer attribute * * This attribute is true, if the layer provides cell boxes. */ bool is_cell_box_layer () const { return source (true).special_purpose () == lay::ParsedLayerSource::SP_CellFrame; } /** * @brief Set the transparency state */ void set_transparent (bool t) { if (m_transparent != t) { m_transparent = t; need_realize (nr_visual); } } /** * @brief Get the transparency state */ bool transparent (bool real) const { if (real) { ensure_visual_realized (); return m_transparent_real; } else { return m_transparent; } } /** * @brief Set the line width */ void set_width (int w) { if (m_width != w) { m_width = w; need_realize (nr_visual); } } /** * @brief Get the line width */ int width (bool real) const { if (real) { ensure_visual_realized (); return m_width_real; } else { return m_width; } } /** * @brief Set the marked state */ void set_marked (bool t) { if (m_marked != t) { m_marked = t; need_realize (nr_visual); } } /** * @brief Get the marked state */ bool marked (bool real) const { if (real) { ensure_visual_realized (); return m_marked_real; } else { return m_marked; } } /** * @brief Set the animation state */ void set_animation (int a) { if (m_animation != a) { m_animation = a; need_realize (nr_visual); } } /** * @brief Get the animation state */ int animation (bool real) const { if (real) { ensure_visual_realized (); return m_animation_real; } else { return m_animation; } } /** * @brief Gets a value indicating that shapes are drawn with a diagonal cross */ bool xfill (bool real) const { if (real) { ensure_visual_realized (); return m_xfill_real; } else { return m_xfill; } } /** * @brief Sets a value indicating that shapes are drawn with a diagonal cross */ void set_xfill (bool xf); /** * @brief Set the name */ void set_name (const std::string &n) { m_name = n; } /** * @brief Get the name */ const std::string &name () const { return m_name; } /** * @brief Obtain the display string for this layer * * This string is supposed to be shown in the layer list. It * reflects the source specification in an abbreviated fashion. * * If always_with_source is set to true, the source will be shown always. * 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; /** * @brief The source specification * * This method delivers the source specification as a string */ std::string source_string (bool real) const { return source(real).to_string (); } /** * @brief Load the source specification from a string * * 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. */ void set_source (const std::string &s); /** * @brief Load the source specification * * In order to make the layer usable, the properties * object must be "realized" with respect to a LayoutView object. */ void set_source (const lay::ParsedLayerSource &s); /** * @brief Access to the layer source */ const lay::ParsedLayerSource &source (bool real) const { if (real) { ensure_source_realized (); return m_source_real; } else { return m_source; } } /** * @brief The "source specification": layer index * * This is the layer index of the respective layer in the layout object. * The index may be negative, in which case no specific layer is addressed. * This is a property derived from the source specification that can only * be obtained in "real" semantics. */ int layer_index () const { ensure_source_realized (); return m_layer_index; } /** * @brief The "source specification": cellview index * * This is the index of the cell view that this layer resides on. * It may be negative to indicate that it is not considered. * This is a property derived from the source specification that can only * be obtained in "real" semantics. */ int cellview_index () const { ensure_source_realized (); return m_cellview_index; } /** * @brief Access to the transformation (in database units) * * This is a derived attribute that can only be obtained in "real" * semantics. */ const std::vector &trans () const { ensure_source_realized (); return m_trans; } /** * @brief Access to the hierarchy level specification * * This is a derived attribute that can only be obtained in "real" * semantics. */ const HierarchyLevelSelection &hier_levels () const { ensure_source_realized (); return m_hier_levels; } /** * @brief Access to the property selection * * This set will define the selected property set id's. * It is a derived attribute that can only be obtained in "real" * semantics. */ const std::set &prop_sel () const { ensure_source_realized (); return m_prop_set; } /** * @brief Access to the "inverse property selection" attribute * * This boolean is true, if the prop_sel selection is to be inverted, i.e. * all properties ids in this set are actually unselected. */ bool inverse_prop_sel () const { ensure_source_realized (); return m_inv_prop_set; } /** * @brief return the "flattened" object * * Compute the "effective" properties (if the object is part of a hierarchy) and create a * new object that represents the same properties but as "local". */ LayerProperties flat () const; /** * @brief Actually realize the visual properties (implemented by node class) */ virtual void realize_visual () const; /** * @brief Actually realize the source properties (implemented by node class) * * This method may be called for example, if new layers have been added to * a layout and the layer properties should reflect that. */ virtual void realize_source () const; /** * @brief Adaptors required for the XML reader */ color_t frame_color_loc () const { return frame_color (false); } color_t fill_color_loc () const { return fill_color (false); } int frame_brightness_loc () const { return frame_brightness (false); } int fill_brightness_loc () const { return fill_brightness (false); } int dither_pattern_loc () const { return dither_pattern (false); } int line_style_loc () const { return line_style (false); } bool visible_loc () const { return visible (false); } bool valid_loc () const { return valid (false); } bool transparent_loc () const { return transparent (false); } int width_loc () const { return width (false); } bool marked_loc () const { return marked (false); } bool xfill_loc () const { return xfill (false); } int animation_loc () const { return animation (false); } std::string source_string_loc () const { return source_string (false); } protected: /** * @brief Merge the parents "real" style with the child's (*this) local style and store the style in the child's real style. * * If the parent argument is zero, the local style is just copied into the * real style. * * @param d The parent properties object or 0 if there is no parent */ void merge_visual (const LayerProperties *d) const; /** * @brief Merge the parents "real" source with the child's (*this) source and store the style in the child's real style. * * If the parent argument is zero, the local source is just copied into the * real style. * * @param d The parent properties object or 0 if there is no parent */ void merge_source (const LayerProperties *d) const; /** * @brief Compute the internal state * * Computes the internal state such as property selection set. * * @param view The view the properties refer to or 0 if there is no view. */ void do_realize (const LayoutView *view) const; /** * @brief Tell the children that a realize of the visual properties is needed */ virtual void need_realize (unsigned int flags, bool force = false); /** * @brief Tell, if a realize of the visual properties is needed */ bool realize_needed_visual () const { return m_realize_needed_visual; } /** * @brief Tell, if a realize of the source properties is needed */ bool realize_needed_source () const { return m_realize_needed_source; } private: // display styles color_t m_frame_color; mutable color_t m_frame_color_real; color_t m_fill_color; mutable color_t m_fill_color_real; int m_frame_brightness; mutable int m_frame_brightness_real; int m_fill_brightness; mutable int m_fill_brightness_real; int m_dither_pattern; mutable int m_dither_pattern_real; int m_line_style; mutable int m_line_style_real; bool m_valid; mutable bool m_valid_real; bool m_visible; mutable bool m_visible_real; bool m_transparent; mutable bool m_transparent_real; int m_width; mutable int m_width_real; bool m_marked; mutable bool m_marked_real; bool m_xfill; mutable bool m_xfill_real; int m_animation; mutable int m_animation_real; std::string m_name; lay::ParsedLayerSource m_source; mutable lay::ParsedLayerSource m_source_real; // this set of members is realized with the realize method mutable int m_layer_index; mutable int m_cellview_index; mutable std::vector m_trans; mutable HierarchyLevelSelection m_hier_levels; mutable std::set m_prop_set; mutable bool m_inv_prop_set; void ensure_realized () const; void ensure_source_realized () const; void ensure_visual_realized () const; protected: enum { nr_visual = 1, nr_source = 2, nr_hierarchy = 4 }; mutable bool m_realize_needed_source : 1; mutable bool m_realize_needed_visual : 1; }; /** * @brief A layer properties node structure * * This adds a hierarchy to the layer properties. */ class LAYBASIC_PUBLIC LayerPropertiesNode : public LayerProperties, public tl::Object { public: typedef tl::stable_vector child_list; typedef child_list::const_iterator const_iterator; typedef child_list::iterator iterator; /** * @brief Constructor */ LayerPropertiesNode (); /** * @brief Destructor */ ~LayerPropertiesNode (); /** * @brief Constructor for a leaf element */ LayerPropertiesNode (const LayerProperties &d); /** * @brief Constructor for a leaf element */ LayerPropertiesNode (const LayerPropertiesNode &d); /** * @brief Assignment of a LayerProperties element */ LayerPropertiesNode &operator= (const LayerProperties &d) { LayerProperties::operator= (d); return *this; } /** * @brief Assignment of a LayerPropertiesNode element */ LayerPropertiesNode &operator= (const LayerPropertiesNode &d); /** * @brief Assignment alias for GSI binding */ void assign (const LayerPropertiesNode &d) { operator= (d); } /** * @brief Equality */ bool operator== (const LayerPropertiesNode &d) const; /** * @brief Inequality */ bool operator!= (const LayerPropertiesNode &d) const { return !operator== (d); } /** * @brief return the "flattened" object * * Contrary to what the name suggests, this method does not flatten the * hierarchy but rather returns an object that does not need a parent * for the "real" properties. See lay::LayerProperties::flat for a * description of this process. * The child list of the returned object will be the same that of the * original object. */ LayerPropertiesNode flat () const { LayerPropertiesNode r (*this); r = lay::LayerProperties::flat (); return r; } /** * @brief Child layers: begin iterator */ const_iterator begin_children () const { return m_children.begin (); } /** * @brief Child layers: end iterator */ const_iterator end_children () const { return m_children.end (); } /** * @brief Child layers: begin iterator */ iterator begin_children () { return m_children.begin (); } /** * @brief Child layers: end iterator */ iterator end_children () { return m_children.end (); } /** * @brief Add a child */ void add_child (const LayerPropertiesNode &child); /** * @brief clear the children */ void clear_children () { m_children.clear (); } /** * @brief Return a reference to the last child */ LayerPropertiesNode &last_child () { return m_children.back (); } /** * @brief Return a reference to the last child */ const LayerPropertiesNode &last_child () const { return m_children.back (); } /** * @brief Insert a child */ LayerPropertiesNode &insert_child (const iterator &iter, const LayerPropertiesNode &child); /** * @brief Delete a child */ void erase_child (const iterator &iter); /** * @brief Test, if there are children */ bool has_children () const { return ! m_children.empty (); } /** * @brief Compute the bbox of this layer * * This takes the layout and path definition (supported by the * given default layout or path, if no specific is given). * The node must have been attached to a view to make this * operation possible. * * @return A bbox in micron units */ db::DBox bbox () const; /** * @brief Attach to a view * * This method attaches the properties node and it's children to a view. * This enables the node to realize itself against the view, i.e. * compute the actual property selection set. * This method is supposed to be */ void attach_view (LayoutView *view, unsigned int list_index); /** * @brief Gets the layout view the node lives in */ LayoutView *view () const; /** * @brief Gets the index of the layer properties list that node lives in */ unsigned int list_index () const; /** * @brief Gets the parent node */ const LayerPropertiesNode *parent () const { return mp_parent.get (); } /** * @brief Obtain the unique ID * * Each layer properties node object has a unique ID that is created * when a new LayerPropertiesNode object is instantiated. The ID is * copied when the object is copied. The ID can be used to identify the * object irregardless of it's content. */ unsigned int id () const { return m_id; } virtual void realize_source () const; virtual void realize_visual () const; protected: virtual void need_realize (unsigned int flags, bool force); void set_parent (const LayerPropertiesNode *); private: // A reference to the view tl::weak_ptr mp_view; unsigned int m_list_index; // the parent node tl::weak_ptr mp_parent; // the list of children child_list m_children; // the unique Id unsigned int m_id; }; /** * @brief Flat layer iterator * * This iterator provides a flat view for the layers in the layer tree */ class LAYBASIC_PUBLIC LayerPropertiesConstIterator : public tl::Object { public: /** * @brief Default constructor */ LayerPropertiesConstIterator (); /** * @brief Creates an iterator from a LayerPropertiesNode pointer * This requires the node pointer to point to a node that is addressable by an iterator - i.e. * lives within a view and is either a direct member or a child of a member of a layer properties * list. If this is not the case, the resulting iterator will be a null iterator. */ LayerPropertiesConstIterator (const lay::LayerPropertiesNode *node); /** * @brief Constructor: create an iterator pointing either at the beginning or at the end */ LayerPropertiesConstIterator (const LayerPropertiesList &list, bool last = false); /** * @brief Constructor: create an iterator from a index */ LayerPropertiesConstIterator (const LayerPropertiesList &list, size_t uint); /** * @brief Copy constructor */ LayerPropertiesConstIterator (const LayerPropertiesConstIterator &d); /** * @brief Assignment */ LayerPropertiesConstIterator &operator= (const LayerPropertiesConstIterator &d); /** * @brief Inequality */ bool operator!= (const LayerPropertiesConstIterator &d) const { return ! operator== (d); } /** * @brief Equality */ bool operator== (const LayerPropertiesConstIterator &d) const { return m_uint == d.m_uint; } /** * @brief Comparison */ bool operator< (const LayerPropertiesConstIterator &d) const; /** * @brief At-the-top property * * This predicate is true if there is no parent level. */ bool at_top () const; /** * @brief At-the-end property * * This predicate is true if the iterator is at the end of either all elements or * at the end of the child list (if down_next_child() or down_first_child() is used to iterate). */ bool at_end () const; /** * @brief "is null" predicate * * This predicate is true if the iterator is "null". Such an iterator can be * created with the default constructor or by moving a top-level iterator up. */ bool is_null () const { return m_uint == 0; } /** * @brief Increment operator */ LayerPropertiesConstIterator &operator++ () { inc (1); return *this; } /** * @brief Move up * * The iterator is moved to point to the current element's parent. * If the current element does not have a parent, the iterator will * be undefined. */ LayerPropertiesConstIterator &up (); /** * @brief Move to the next sibling * * The iterator is moved to the nth next sibling of the current element. */ LayerPropertiesConstIterator &next_sibling (ptrdiff_t n = 1); /** * @brief Move to the sibling with the given index * * The iterator is moved to the nth sibling of the current element. */ LayerPropertiesConstIterator &to_sibling (size_t n); /** * @brief Return the number of siblings */ size_t num_siblings () const; /** * @brief Move to the first child * * This method moves to the child of the current element. If there is * no child, at_end() will be true. Even then, the iterator points to * the child level and up() can be used to move back. */ LayerPropertiesConstIterator &down_first_child (); /** * @brief Move to the last child * * This method moves to the child of the current element. at_end() will be * true then. Even then, the iterator points to the child level and up() * can be used to move back. */ LayerPropertiesConstIterator &down_last_child (); /** * @brief Access to the current element */ const LayerPropertiesNode &operator* () const { const LayerPropertiesNode *o = obj (); tl_assert (o != 0); return *o; } /** * @brief Access to the current element */ const LayerPropertiesNode *operator-> () const { const LayerPropertiesNode *o = obj (); tl_assert (o != 0); return o; } /** * @brief Invalidate the object pointer * * This method must be called whenever the object underlying the * current element is changed, i.e. deleted. This call invalidates * the pointer to the current element thus forcing a refresh of * the object reference. */ void invalidate (); /** * @brief Obtain the parent iterator * * If there is no parent, the returned iterator will be 'null'. */ LayerPropertiesConstIterator parent () const { LayerPropertiesConstIterator p (*this); p.up (); return p; } /** * @brief Obtain the iterator pointing to the first child * * If there is no children, the iterator will be a valid insert point but not * point to any valid element. It will report "at_end". */ LayerPropertiesConstIterator first_child () const { LayerPropertiesConstIterator p (*this); p.down_first_child (); return p; } /** * @brief Obtain the iterator pointing to the last child * * The iterator will be a valid insert point but not * point to any valid element. It will report "at_end". */ LayerPropertiesConstIterator last_child () const { LayerPropertiesConstIterator p (*this); p.down_last_child (); return p; } /** * @brief Obtain the parent object and the index of the child * * The parent object pointer is 0 if there is no parent. The second * member of the pair indicates which child is addressed. */ std::pair parent_obj () const; /** * @brief Obtain the current index */ size_t uint () const { return m_uint; } /** * @brief Obtain the index of the child within the parent * * This method returns the index, that the element pointed to has in the list * of children of it's parent. If the element does not have a parent, the * index of the element in the global list is returned. */ size_t child_index () const; /** * @brief Obtain a pointer to the object referenced * * If the iterator is null, the pointer returned is 0. */ const LayerPropertiesNode *obj () const { if (! mp_obj) { set_obj (); } return mp_obj; } /** * @brief Gets the layer properties list this iterator operates on */ const LayerPropertiesList *list () const { return m_list.get (); } private: friend class LayerPropertiesList; size_t m_uint; tl::weak_ptr m_list; mutable const LayerPropertiesNode *mp_obj; void inc (unsigned int d); std::pair factor () const; void set_obj () const; }; /** * @brief A helper function to compare layer properties nodes bottom-up */ struct LAYBASIC_PUBLIC CompareLayerIteratorBottomUp { bool operator() (const lay::LayerPropertiesConstIterator &a, const lay::LayerPropertiesConstIterator &b) { return a.uint () > b.uint (); } }; /** * @brief Flat, non-const layer iterator * * This iterator provides a flat view for the layers in the layer tree * and allows to change the item pointed to. */ class LAYBASIC_PUBLIC LayerPropertiesIterator : public LayerPropertiesConstIterator { public: /** * @brief Default constructor */ LayerPropertiesIterator () : LayerPropertiesConstIterator () { // .. nothing yet .. } /** * @brief Creates an iterator from a LayerPropertiesNode pointer * This requires the node pointer to point to a node that is addressable by an iterator - i.e. * lives within a view and is either a direct member or a child of a member of a layer properties * list. If this is not the case, the resulting iterator will be a null iterator. */ LayerPropertiesIterator (lay::LayerPropertiesNode *node) : LayerPropertiesConstIterator (node) { // .. nothing yet .. } /** * @brief Constructor: create an iterator pointing either at the beginning or at the end */ LayerPropertiesIterator (const LayerPropertiesList &list, bool last = false) : LayerPropertiesConstIterator (list, last) { // .. nothing yet .. } /** * @brief Constructor: create an iterator from a index */ LayerPropertiesIterator (const LayerPropertiesList &list, size_t uint) : LayerPropertiesConstIterator (list, uint) { // .. nothing yet .. } /** * @brief Copy constructor */ LayerPropertiesIterator (const LayerPropertiesIterator &d) : LayerPropertiesConstIterator (d) { // .. nothing yet .. } /** * @brief Assignment */ LayerPropertiesConstIterator &operator= (const LayerPropertiesConstIterator &d) { LayerPropertiesConstIterator::operator= (d); return *this; } /** * @brief Increment operator */ LayerPropertiesIterator &operator++ () { LayerPropertiesConstIterator::operator++ (); return *this; } /** * @brief Access to the current element */ LayerPropertiesNode &operator* () const { return const_cast (LayerPropertiesConstIterator::operator* ()); } /** * @brief Access to the current element */ LayerPropertiesNode *operator-> () const { return const_cast (LayerPropertiesConstIterator::operator-> ()); } /** * @brief Obtain the parent iterator */ LayerPropertiesIterator parent () const { return LayerPropertiesIterator (LayerPropertiesConstIterator::parent ()); } /** * @brief Obtain the parent object and the index of the child */ std::pair parent_obj () const { std::pair pp = LayerPropertiesConstIterator::parent_obj (); return std::make_pair (const_cast (pp.first), pp.second); } /** * @brief Move up */ LayerPropertiesIterator &up () { LayerPropertiesConstIterator::up (); return *this; } private: LayerPropertiesIterator (const LayerPropertiesConstIterator &d) : LayerPropertiesConstIterator (d) { } }; /** * @brief A list of layer properties * * This object represents a list of layer properties. */ class LAYBASIC_PUBLIC LayerPropertiesList : public tl::Object { public: typedef LayerPropertiesNode::child_list layer_list; typedef LayerPropertiesNode::const_iterator const_iterator; typedef LayerPropertiesNode::iterator iterator; /** * @brief Constructor */ LayerPropertiesList (); /** * @brief Destructor */ virtual ~LayerPropertiesList (); /** * @brief Copy constructor */ LayerPropertiesList (const LayerPropertiesList &d); /** * @brief Assignment */ LayerPropertiesList &operator= (const LayerPropertiesList &d); /** * @brief Equality */ bool operator== (const LayerPropertiesList &d) const; /** * @brief Inequality */ bool operator!= (const LayerPropertiesList &d) const { return !operator== (d); } /** * @brief Flat iterator * * This iterator delivers all elements including the nodes. */ LayerPropertiesConstIterator begin_const_recursive () const; /** * @brief Flat iterator * * This iterator delivers the past-the-end flat iterator */ LayerPropertiesConstIterator end_const_recursive () const; /** * @brief Flat iterator * * This iterator delivers all elements including the nodes. */ LayerPropertiesIterator begin_recursive (); /** * @brief Flat iterator * * This iterator delivers the past-the-end flat iterator */ LayerPropertiesIterator end_recursive (); /** * @brief Start iterator for the layers (top-level) */ const_iterator begin_const () const; /** * @brief End iterator for the layers (top-level) */ const_iterator end_const () const; /** * @brief Start iterator for the layers (top-level) */ iterator begin (); /** * @brief End iterator for the layers (top-level) */ iterator end (); /** * @brief Last element of the list */ LayerPropertiesNode &back (); /** * @brief Last element of the list */ const LayerPropertiesNode &back () const; /** * @brief Expand the layer properties list * * Expansion of the layer properties list means to apply wildcards - i.e. * "@*" is expanded into an outer iteration of layout indices. * * @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 (const std::map &map_cv_index, bool add_default); /** * @brief Remove all entries related to a certain cv index or not related to a certain cv index * * @param cv_index The index of the cellview whose references shall be removed if except is false or the index of the cellview which shall be retained if except is true */ void remove_cv_references (int cv_index, bool except = false); /** * @brief Translate all cv references to the given cv_index */ void translate_cv_references (int cv_index); /** * @brief Append another list to this list * * This does not attach the view. It is provided to encapsulate the merging of the dither pattern. */ void append (const LayerPropertiesList &other); /** * @brief Add a new layer properties element */ void push_back (const LayerPropertiesNode &d); /** * @brief Insert a new element into the tree before the given position * * The iterator specifies at which element to insert the new element. * The iterator may have a special form in which it points to a parent * and past-the-end of the respective child list (stack.back ().first==stack.back ().second). * In this case, the element is inserted at the end of the respective parent's child * list. * A reference to the element created is returned. */ LayerPropertiesNode & insert (const LayerPropertiesIterator &iter, const LayerPropertiesNode &node); /** * @brief Delete the given element from the tree * * The iterator specifies the element to delete. */ void erase (const LayerPropertiesIterator &iter); /** * @brief Iterator over the custom dither pattern: begin iterator */ lay::DitherPattern::iterator begin_custom_dither_pattern () const { return m_dither_pattern.begin_custom (); } /** * @brief Iterator over the custom dither pattern: end iterator */ lay::DitherPattern::iterator end_custom_dither_pattern () const { return m_dither_pattern.end (); } /** * @brief Add a new custom dither pattern */ void push_custom_dither_pattern (const lay::DitherPatternInfo &info) { return m_dither_pattern.replace_pattern (m_dither_pattern.count (), info); } /** * @brief Access the dither pattern object */ const lay::DitherPattern &dither_pattern () const { return m_dither_pattern; } /** * @brief Replace the dither pattern object */ void set_dither_pattern (const lay::DitherPattern &pattern); /** * @brief Iterator over the custom line_styles: begin iterator */ lay::LineStyles::iterator begin_custom_line_styles () const { return m_line_styles.begin_custom (); } /** * @brief Iterator over the custom line_styles: end iterator */ lay::LineStyles::iterator end_custom_line_styles () const { return m_line_styles.end (); } /** * @brief Add a new custom line style */ void push_custom_line_style (const lay::LineStyleInfo &info) { return m_line_styles.replace_style (m_line_styles.count (), info); } /** * @brief Access the line styles object */ const lay::LineStyles &line_styles () const { return m_line_styles; } /** * @brief Replace the line styles object */ void set_line_styles (const lay::LineStyles &styles); /** * @brief Get the name of the layer properties set (for tabbed layer properties) */ const std::string &name () const { return m_name; } /** * @brief Set the name of the layer properties set */ void set_name (const std::string &name) { m_name = name; } /** * @brief Deliver the XML format description for external use */ static const tl::XMLElementList *xml_format (); /** * @brief Load the layers from a XML stream */ void load (tl::XMLSource &stream); /** * @brief Save the layers in XML format */ void save (tl::OutputStream &os) const; /** * @brief Load a set of layer properties lists from a XML stream */ static void load (tl::XMLSource &stream, std::vector &properties_lists); /** * @brief Save a set of layers in XML format */ static void save (tl::OutputStream &os, const std::vector &properties_lists); /** * @brief Attach the list to the view * * This step attaches all nodes in the list to the given view. * It is required before the nodes can be fully realized. * "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); /** * @brief Gets the layout view this list is attached to */ lay::LayoutView *view () const; /** * @brief Gets the layout list */ unsigned int list_index () const; private: tl::weak_ptr mp_view; unsigned int m_list_index; layer_list m_layer_properties; lay::DitherPattern m_dither_pattern; lay::LineStyles m_line_styles; std::string m_name; }; /** * @brief A reference into a node hierarchy in the layout view * * This object is employed to provide "live" modification of the layer * properties hierarchy and properties. * First, it acts as a proxy for the properties of the node. Changing * a node's property will update the properties in the view as well. * Second, changes in the node's hierarchy will be reflected in the * view's layer hierarchy too. */ class LAYBASIC_PUBLIC LayerPropertiesNodeRef : public LayerPropertiesNode { public: /** * @brief Constructor */ LayerPropertiesNodeRef (LayerPropertiesNode *node); /** * @brief Constructor from an iterator * The iterator is a pointer since the erase implementation requires us to * modify the iterator. Hence with this version, the original iterator will * follow up after the erase. */ LayerPropertiesNodeRef (LayerPropertiesConstIterator *iter); /** * @brief Constructor from an iterator with an iterator copy */ LayerPropertiesNodeRef (const LayerPropertiesConstIterator &iter); /** * @brief Default constructor * This constructor will create an invalid reference. */ LayerPropertiesNodeRef (); /** * @brief Copy constructor */ LayerPropertiesNodeRef (const LayerPropertiesNodeRef &other); /** * @brief Assignment */ LayerPropertiesNodeRef &operator= (const LayerPropertiesNodeRef &other); /** * @brief Deletes the current node * After this operation, the reference will point to the */ void erase (); /** * @brief Returns true, if the reference is actively connected to a view */ bool is_valid () const; /** * @brief Gets the iterator the reference uses as a pointer * This method returns null if the reference is not through an iterator. */ const LayerPropertiesConstIterator &iter () const; /** * @brief Gets the target pointer of the reference * This method returns null if the reference does not point to a specific target. * This method returns a const pointer since the target is not supposed to be * modified directly. */ const LayerPropertiesNode *target () const { return mp_node.get (); } private: LayerPropertiesConstIterator m_iter; tl::weak_ptr mp_iter; tl::weak_ptr mp_node; void need_realize (unsigned int flags, bool force); }; } #endif