/* 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_layCellView #define HDR_layCellView #include "laybasicCommon.h" #include #include #include "tlObject.h" #include "tlFileSystemWatcher.h" #include "layTechnology.h" #include "dbLayout.h" #include "dbMetaInfo.h" #include "dbReader.h" #include "dbSaveLayoutOptions.h" #include "dbLoadLayoutOptions.h" #include "dbInstElement.h" #include "gsi.h" namespace lay { class LayoutView; /** * @brief A layout handle * * This object controls a layout object. A layout object can be * identified through a name. Additionally, a reference count * is maintained that controls when the layout object is deleted. */ class LAYBASIC_PUBLIC LayoutHandle : public tl::Object { public: /** * @brief Creates a layout handle to the given object * * This constructor creates a new handle to the given * layout object. The handle takes over the ownership over the * layout object. * The initial reference count is zero (see remove_ref). * The filename is a string that is supposed to identify * the layout further. It can be retrieved with the filename * method. */ LayoutHandle (db::Layout *layout, const std::string &filename); /** * @brief Destructor * * The destructor will delete the layout object that * was associated with this handle. */ ~LayoutHandle (); /** * @brief Renames the layout object * * If "force" is set to true, the layout will be given that name, irregardless if * the name already is being used. If "force" is false, a new unique name is created. */ void rename (const std::string &name, bool force = false) throw (tl::Exception); /** * @brief Gets the name of the handle */ const std::string &name () const; /** * @brief Gets the layout object that this handle points to */ db::Layout &layout () const; /** * @brief Sets the file name associated with this handle */ void set_filename (const std::string &); /** * @brief Gets the file name associated with this handle */ const std::string &filename () const; /** * @brief Gets the technology attached to this layout */ const lay::Technology *technology () const; /** * @brief Gets the technology name for this layout * * An empty name indicates the default technology should be used. */ const std::string &tech_name () const { return m_tech_name; } /** * @brief Applies the given technology * * This will set the technology to the new one and send the apply event. * This event is sent always, even if the technology did not change. */ void apply_technology (const std::string &tn); /** * @brief Sets the technology name * * If there is no technology with that name, the default technology * will be used. */ void set_tech_name (const std::string &tn); /** * @brief Finds a layout object by name * * @param name The name under which to find the layout object * @return 0, if there is no layout object with this name. Otherwise a pointer to its handle */ static LayoutHandle *find (const std::string &name); /** * @brief Gets the names of all registered layout objects */ static void get_names (std::vector &names); /** * @brief Gets the reference count */ int get_ref_count () const { return m_ref_count; } /** * @brief Adds a reference to the layout handle * * This method will increment the reference counter of this handle */ void add_ref (); /** * @brief Removes a reference to the layout handle * * This method will decrement the reference counter. Once the * reference count reaches zero, the layout object and the * handle is deleted. * Upon initialization, the reference count is zero. * Hint: it is generally not safe to access the handle after * a remove_ref was issued. */ void remove_ref (); /** * @brief Returns true, if the layout is "dirty" * * A layout is "dirty", if it needs to be saved. * It is set dirty if one of the signal handlers is triggered. */ bool is_dirty () const { return m_dirty; } /** * @brief Loads the layout * * Load the layout from the file given in the constructor using the given layer map. * The dirty flag is reset. * * @param lmap The layer map specifying the layers to read * @param technology The technology to use for layer map and other settings or empty for "default technology" * @return The new layer map (can differ from the input since layers may be created) */ db::LayerMap load (const db::LoadLayoutOptions &options, const std::string &technology); /** * @brief Loads the layout * * Load the layout from the file given in the constructor. * The dirty flag is reset. * * @return The new layer map */ db::LayerMap load (); /** * @brief Saves the layout * * Save the layout under the given file name and with the given options. * If update is true, this method updates the cell view's filename, title, save options and dirty flag. */ void save_as (const std::string &filename, tl::OutputStream::OutputStreamMode om, const db::SaveLayoutOptions &options, bool update = true); /** * @brief Sets the save options and a flag indicating whether they are valid * * This method is mainly used by the session restore feature to restore the handle's state. */ void set_save_options (const db::SaveLayoutOptions &options, bool valid); /** * @brief Gets the current saving options * * The saving options are set by the last save_as method call. */ const db::SaveLayoutOptions &save_options () const { return m_save_options; } /** * @brief Gets a flag indicating whether the save options are valid * * The save options are valid once the layout has been saved with specific * options using "save_as" with the "update" options. */ bool save_options_valid () const { return m_save_options_valid; } /** * @brief Gets the current reader options * * The reader options are set by the load method call. */ const db::LoadLayoutOptions &load_options () const { return m_load_options; } /** * @brief An event indicating that the technology has changed * This event is triggered if the technology was changed. */ tl::Event technology_changed_event; /** * @brief An event indicating that a technology shall be applied * This event is triggered to make the listeners apply a new technology * to the layout. */ tl::Event apply_technology_event; /** * @brief An event indicating that a technology shall be applied * This event is triggered to make the listeners apply a new technology * to the layout. This version supplies a sender pointer. */ tl::event apply_technology_with_sender_event; /** * @brief An event handler for a layout change * This handler is attached to a layout changed event and will invalidate the handle. */ void layout_changed (); /** * @brief Gets the file system watcher that delivers events when one of the layouts gets updated */ static tl::FileSystemWatcher &file_watcher (); private: db::Layout *mp_layout; int m_ref_count; std::string m_name; std::string m_filename; std::string m_tech_name; bool m_dirty; db::SaveLayoutOptions m_save_options; bool m_save_options_valid; db::LoadLayoutOptions m_load_options; static std::map ms_dict; static tl::FileSystemWatcher *mp_file_watcher; }; /** * @brief A layout handle reference * * This class encapsulates a reference to a layout handle. * The main purpose for this class is to automate the reference * counting on the handle. */ class LAYBASIC_PUBLIC LayoutHandleRef { public: LayoutHandleRef (); LayoutHandleRef (LayoutHandle *h); LayoutHandleRef (const LayoutHandleRef &r); ~LayoutHandleRef (); LayoutHandleRef &operator= (const LayoutHandleRef &r); bool operator== (const LayoutHandleRef &r) const; bool operator!= (const LayoutHandleRef &r) const { return !operator== (r); } LayoutHandle *operator-> () const; LayoutHandle *get () const; void set (LayoutHandle *h); private: LayoutHandle *mp_handle; }; /** * @brief A "cell view" reference * * A cell view reference points to a certain cell within a certain layout. * The layout pointer can be 0, indicating that it is invalid. * Also, the cell view describes a cell within that layout. The cell * is addressed by an cell_index or a cell pointer. * The cell is not only identified by it's index or pointer but as well * by the path leading to that cell. This path describes how to find the * cell in the context of parent cells. * The path is in fact composed in twofold: once in an unspecific fashion, * just describing which parent cells are used. The target of this path * is called the context cell. It is accessible by the ctx_cell_index * or ctx_cell method. * Additionally the path may further identify a certain instance of a certain * subcell in the context cell. This is done through a set of db::InstElement * objects. The target of this context path is the actual cell addressed by the * cellview. * In the viewer, the target cell is shown in the context of the context cell. * The hierarchy levels are counted from the context cell, which is on level 0. * If the context path is empty, the context cell is identical with the target cell. */ class LAYBASIC_PUBLIC CellView : public tl::Object { public: typedef db::cell_index_type cell_index_type; typedef std::vector unspecific_cell_path_type; typedef std::vector specific_cell_path_type; /** * @brief Constructor: create an invalid cellview */ CellView (); /** * @brief Equality: compares the cell the cv points to, not the path */ bool operator== (const CellView &cv) const; /** * @brief Inequality */ bool operator!= (const CellView &cv) const { return !operator== (cv); } /** * @brief Test if the cv points to a valid cell */ bool is_valid () const; /** * @brief Return the layout handle */ lay::LayoutHandle *operator-> () const { return m_layout_href.get (); } /** * @brief Return the layout handle (not via operator->) */ lay::LayoutHandle *handle () const { return m_layout_href.get (); } /** * @brief Set the unspecific part of the path explicitly * * Setting the unspecific part will clear the context part and * update the context and target cell. */ void set_unspecific_path (const unspecific_cell_path_type &p); /** * @brief Set the context part of the path explicitly * * This method assumes that the unspecific part of the path * is established already and that the context part starts * from the context cell. */ void set_specific_path (const specific_cell_path_type &p); /** * @brief Set the path to the given cell * * This method will construct any path to this cell, not a * particular one. It will clear the context part of the path * and update the context and target cell. */ void set_cell (cell_index_type index); /** * @brief Set the cell by name * * If the name is not a valid one, the cellview will become * invalid. * This method will construct any path to this cell, not a * particular one. It will clear the context part of the path * and update the context and target cell. */ void set_cell (const std::string &name); /** * @brief Reset the cell * * The cellview will become invalid. The layout object will * still be attached to the cellview. */ void reset_cell (); /** * @brief Set the layout handle * * Connect the cellview with a certain layout. * This will reset the target and context cell. */ void set (lay::LayoutHandle *handle); /** * @brief Get the context cell pointer */ db::Cell *ctx_cell () const { return mp_ctx_cell; } /** * @brief Get the context cell index */ cell_index_type ctx_cell_index () const { return m_ctx_cell_index; } /** * @brief Get the target cell pointer */ db::Cell *cell () const { return mp_cell; } /** * @brief Get the target cell index */ cell_index_type cell_index () const { return m_cell_index; } /** * @brief Get the cell's combined path in an unspecific form */ unspecific_cell_path_type combined_unspecific_path () const; /** * @brief Get the cell's unspecific part of the path */ const unspecific_cell_path_type &unspecific_path () const { return m_unspecific_path; } /** * @brief Get the cell's unspecific part of the path */ const specific_cell_path_type &specific_path () const { return m_specific_path; } /** * @brief Retrive the accumulated transformation induced by the context part of the path */ db::ICplxTrans context_trans () const; /** * @brief Deep copy of the cellview * * This method performs a deep copy on the cellview. * A layout must be set already. Rather the creating another reference to the layout * (which is done on operator= for example), this method copies the content of the * source layout to the current one and transfers cell path and other parameters. * * @param manager The database object manager that the new layout is put under */ CellView deep_copy (db::Manager *manager) const; private: lay::LayoutHandleRef m_layout_href; db::Cell *mp_ctx_cell; cell_index_type m_ctx_cell_index; db::Cell *mp_cell; cell_index_type m_cell_index; unspecific_cell_path_type m_unspecific_path; specific_cell_path_type m_specific_path; }; /** * @brief A cellview reference * * This object acts like a proxy to a lay::CellView object. It is connected to a cellview * and a LayoutView and upon changes, the LayoutView will be configured accordingly. */ class LAYBASIC_PUBLIC CellViewRef : public gsi::ObjectBase { public: typedef CellView::unspecific_cell_path_type unspecific_cell_path_type; typedef CellView::specific_cell_path_type specific_cell_path_type; typedef CellView::cell_index_type cell_index_type; /** * @brief Default constructor * This constructor creates an invalid cellview reference */ CellViewRef (); /** * @brief Constructor * @param cv The reference to the target cellview * @param view The reference to the layout view */ CellViewRef (lay::CellView *cv, lay::LayoutView *view); /** * @brief Gets the cellview index of this reference * If the cellview is not valid, -1 will be returned. */ int index () const; /** * @brief Gets the LayoutView the reference is pointing to */ lay::LayoutView *view (); /** * @brief Equality: Gives true, if the cellviews are identical */ bool operator== (const CellView &cv) const; /** * @brief Inequality */ bool operator!= (const CellView &cv) const { return !operator== (cv); } /** * @brief Equality: Gives true, if the references point to the same cellview */ bool operator== (const CellViewRef &cv) const { return mp_cv.get () == cv.mp_cv.get (); } /** * @brief Inequality */ bool operator!= (const CellViewRef &cv) const { return !operator== (cv); } /** * @brief Test if the cv points to a valid cell and is valid otherwise */ bool is_valid () const; /** * @brief Returns the layout handle */ lay::LayoutHandle *operator-> () const; /** * @brief Return the layout handle (not via operator->) */ lay::LayoutHandle *handle () const { return operator-> (); } /** * @brief Sets the name of the cellview * * This equivalent to calling Layout#rename_cellview. * The name is made unique, hence the final name may * differ from the one given. */ void set_name (const std::string &name); /** * @brief Set the unspecific part of the path explicitly * * Setting the unspecific part will clear the context part and * update the context and target cell. */ void set_unspecific_path (const unspecific_cell_path_type &p); /** * @brief Set the context part of the path explicitly * * This method assumes that the unspecific part of the path * is established already and that the context part starts * from the context cell. */ void set_specific_path (const specific_cell_path_type &p); /** * @brief Set the path to the given cell * * This method will construct any path to this cell, not a * particular one. It will clear the context part of the path * and update the context and target cell. */ void set_cell (cell_index_type index); /** * @brief Set the cell by name * * If the name is not a valid one, the cellview will become * invalid. * This method will construct any path to this cell, not a * particular one. It will clear the context part of the path * and update the context and target cell. */ void set_cell (const std::string &name); /** * @brief Resets the cell */ void reset_cell (); /** * @brief Get the context cell pointer * An invalid cellview reference will return a null pointer. */ db::Cell *ctx_cell () const; /** * @brief Get the context cell index */ cell_index_type ctx_cell_index () const { db::Cell *c = ctx_cell (); return c ? c->cell_index () : 0; } /** * @brief Get the target cell pointer * An invalid cellview reference will return a null pointer. */ db::Cell *cell () const; /** * @brief Get the target cell index */ cell_index_type cell_index () const { db::Cell *c = cell (); return c ? c->cell_index () : 0; } /** * @brief Get the cell's combined path in an unspecific form */ unspecific_cell_path_type combined_unspecific_path () const; /** * @brief Get the cell's unspecific part of the path */ const unspecific_cell_path_type &unspecific_path () const; /** * @brief Get the cell's unspecific part of the path */ const specific_cell_path_type &specific_path () const; /** * @brief Retrive the accumulated transformation induced by the context part of the path */ db::ICplxTrans context_trans () const; private: tl::weak_ptr mp_cv; tl::weak_ptr mp_view; }; } #endif