Merge pull request #1431 from KLayout/wip2

Wip2
This commit is contained in:
Matthias Köfferlein 2023-08-05 21:09:26 +02:00 committed by GitHub
commit ebfc506bd9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
99 changed files with 1673 additions and 217 deletions

View File

@ -105,7 +105,7 @@ GenericWriterOptions::add_options (tl::CommandLineOptions &cmd, const std::strin
if (format.empty () || format == gds2_format_name || format == gds2text_format_name) {
cmd << tl::arg (group +
"#--keep-instances", &m_keep_instances, "Keeps instances of dropped cells",
"If given, instances of dropped cell's won't be removed. Hence, ghost cells are "
"If given, instances of dropped cells won't be removed. Hence, ghost cells are "
"produced. The resulting layout may not be readable by consumers that require "
"all instantiated cells to be present as actual cells.\n"
"Dropped cells are those which are removed by a negative cell selection (see "
@ -136,11 +136,11 @@ GenericWriterOptions::add_options (tl::CommandLineOptions &cmd, const std::strin
"\n"
"Multiple operations can be specified by combining them with a comma. "
"Positive and negative selection happens in the order given. Hence it's possible "
"to select a cell with it's children and then unselect some children of this cell.\n"
"to select a cell with its children and then unselect some children of this cell.\n"
"\n"
"Examples:\n\n"
"* \"TOP1,TOP2\" - Select cells TOP1 and TOP2 with all of their children\n"
"* \"(TOP)\" - Select only cell TOP, but none of it's child cells\n"
"* \"(TOP)\" - Select only cell TOP, but none of its child cells\n"
"* \"TOP,-A\" - Select cell TOP (plus children), then remove A (with children)"
);

View File

@ -408,7 +408,7 @@ module RBA
# get the layer definitions
def get_layers(parameters)
@layer_param_index.collect { |i| parameters[i] }
@layer_param_index.collect { |i| parameters[i] || RBA::LayerInfo::new }
end
# coerce parameters (make consistent)

View File

@ -358,10 +358,10 @@ class _PCellDeclarationHelper(pya.PCellDeclaration):
pdecl.unit = unit
if not (choices is None):
if not isinstance(choices, list) and not isinstance(choices, tuple):
raise "choices value must be an list/tuple of two-element arrays (description, value)"
raise TypeError("choices value must be an list/tuple of two-element arrays (description, value)")
for c in choices:
if (not isinstance(choices, list) and not isinstance(choices, tuple)) or len(c) != 2:
raise "choices value must be an list/tuple of two-element arrays (description, value)"
raise TypeError("choices value must be an list/tuple of two-element arrays (description, value)")
pdecl.add_choice(c[0],c[1])
# return the declaration object for further operations
@ -430,7 +430,10 @@ class _PCellDeclarationHelper(pya.PCellDeclaration):
"""
layers = []
for i in self._layer_param_index:
layers.append(parameters[i])
if parameters[i] is not None:
layers.append(parameters[i])
else:
layers.append(pya.LayerInfo())
return layers
def callback(self, layout, name, states):

View File

@ -191,7 +191,7 @@ HierarchyBuilder::reset ()
void
HierarchyBuilder::register_variant (db::cell_index_type non_var, db::cell_index_type var)
{
// non_var (despite it's name) may be a variant created previously.
// non_var (despite its name) may be a variant created previously.
variant_to_original_target_map_type::const_iterator v = m_variants_to_original_target_map.find (non_var);
if (v != m_variants_to_original_target_map.end ()) {
non_var = v->second;

View File

@ -1358,7 +1358,7 @@ Layout::add_cell (const char *name)
m_cells.push_back_ptr (new_cell);
m_cell_ptrs [new_index] = new_cell;
// enter it's index and cell_name
// enter its index and cell_name
register_cell_name (name, new_index);
if (manager () && manager ()->transacting ()) {
@ -1380,7 +1380,7 @@ Layout::add_anonymous_cell ()
m_cells.push_back_ptr (new_cell);
m_cell_ptrs [new_index] = new_cell;
// enter it's index and cell_name
// enter its index and cell_name
register_cell_name (0, new_index);
if (manager () && manager ()->transacting ()) {
@ -1393,7 +1393,7 @@ Layout::add_anonymous_cell ()
void
Layout::register_cell_name (const char *name, cell_index_type ci)
{
// enter it's index and cell_name
// enter its index and cell_name
char *cp;
if (name == 0) {
@ -2254,7 +2254,7 @@ Layout::get_pcell_variant_dict (pcell_id_type pcell_id, const std::map<std::stri
m_cells.push_back_ptr (variant);
m_cell_ptrs [new_index] = variant;
// enter it's index and cell_name
// enter its index and cell_name
register_cell_name (b.c_str (), new_index);
if (manager () && manager ()->transacting ()) {
@ -2293,7 +2293,7 @@ Layout::get_pcell_variant (pcell_id_type pcell_id, const std::vector<tl::Variant
m_cells.push_back_ptr (variant);
m_cell_ptrs [new_index] = variant;
// enter it's index and cell_name
// enter its index and cell_name
register_cell_name (b.c_str (), new_index);
if (manager () && manager ()->transacting ()) {
@ -2932,7 +2932,7 @@ Layout::get_lib_proxy (Library *lib, cell_index_type cell_index)
m_cells.push_back_ptr (proxy);
m_cell_ptrs [new_index] = proxy;
// enter it's index and cell_name
// enter its index and cell_name
register_cell_name (b.c_str (), new_index);
if (manager () && manager ()->transacting ()) {
@ -2968,7 +2968,7 @@ Layout::create_cold_proxy (const db::LayoutOrCellContextInfo &info)
m_cells.push_back_ptr (proxy);
m_cell_ptrs [new_index] = proxy;
// enter it's index and cell_name
// enter its index and cell_name
register_cell_name (b.c_str (), new_index);
if (manager () && manager ()->transacting ()) {

View File

@ -199,51 +199,51 @@ PCellVariant::update (ImportLayerMapping *layer_mapping)
if (m_parameters[i].is_user<db::DBox> ()) {
shapes (layout ()->guiding_shape_layer ()).insert (db::BoxWithProperties(db::Box (m_parameters[i].to_user<db::DBox> () * (1.0 / layout ()->dbu ())), layout ()->properties_repository ().properties_id (props)));
shapes (layout ()->guiding_shape_layer ()).insert (db::BoxWithProperties (db::Box (m_parameters[i].to_user<db::DBox> () * (1.0 / layout ()->dbu ())), layout ()->properties_repository ().properties_id (props)));
} else if (m_parameters[i].is_user<db::Box> ()) {
shapes (layout ()->guiding_shape_layer ()).insert (db::BoxWithProperties(m_parameters[i].to_user<db::Box> (), layout ()->properties_repository ().properties_id (props)));
shapes (layout ()->guiding_shape_layer ()).insert (db::BoxWithProperties (m_parameters[i].to_user<db::Box> (), layout ()->properties_repository ().properties_id (props)));
} else if (m_parameters[i].is_user<db::DEdge> ()) {
shapes (layout ()->guiding_shape_layer ()).insert (db::EdgeWithProperties(db::Edge (m_parameters[i].to_user<db::DEdge> () * (1.0 / layout ()->dbu ())), layout ()->properties_repository ().properties_id (props)));
shapes (layout ()->guiding_shape_layer ()).insert (db::EdgeWithProperties (db::Edge (m_parameters[i].to_user<db::DEdge> () * (1.0 / layout ()->dbu ())), layout ()->properties_repository ().properties_id (props)));
} else if (m_parameters[i].is_user<db::Edge> ()) {
shapes (layout ()->guiding_shape_layer ()).insert (db::EdgeWithProperties(m_parameters[i].to_user<db::Edge> (), layout ()->properties_repository ().properties_id (props)));
shapes (layout ()->guiding_shape_layer ()).insert (db::EdgeWithProperties (m_parameters[i].to_user<db::Edge> (), layout ()->properties_repository ().properties_id (props)));
} else if (m_parameters[i].is_user<db::DPoint> ()) {
db::DPoint p = m_parameters[i].to_user<db::DPoint> ();
shapes (layout ()->guiding_shape_layer ()).insert (db::BoxWithProperties(db::Box (db::DBox (p, p) * (1.0 / layout ()->dbu ())), layout ()->properties_repository ().properties_id (props)));
shapes (layout ()->guiding_shape_layer ()).insert (db::PointWithProperties (db::Point (p * (1.0 / layout ()->dbu ())), layout ()->properties_repository ().properties_id (props)));
} else if (m_parameters[i].is_user<db::Point> ()) {
db::Point p = m_parameters[i].to_user<db::Point> ();
shapes (layout ()->guiding_shape_layer ()).insert (db::BoxWithProperties(db::Box (p, p), layout ()->properties_repository ().properties_id (props)));
shapes (layout ()->guiding_shape_layer ()).insert (db::PointWithProperties (p, layout ()->properties_repository ().properties_id (props)));
} else if (m_parameters[i].is_user<db::DPolygon> ()) {
db::complex_trans<db::DCoord, db::Coord> dbu_trans (1.0 / layout ()->dbu ());
db::Polygon poly = m_parameters[i].to_user<db::DPolygon> ().transformed (dbu_trans, false);
// Hint: we don't compress the polygon since we don't want to loose information
shapes (layout ()->guiding_shape_layer ()).insert (db::PolygonWithProperties(poly, layout ()->properties_repository ().properties_id (props)));
shapes (layout ()->guiding_shape_layer ()).insert (db::PolygonWithProperties (poly, layout ()->properties_repository ().properties_id (props)));
} else if (m_parameters[i].is_user<db::Polygon> ()) {
db::Polygon poly = m_parameters[i].to_user<db::Polygon> ();
// Hint: we don't compress the polygon since we don't want to loose information
shapes (layout ()->guiding_shape_layer ()).insert (db::PolygonWithProperties(poly, layout ()->properties_repository ().properties_id (props)));
shapes (layout ()->guiding_shape_layer ()).insert (db::PolygonWithProperties (poly, layout ()->properties_repository ().properties_id (props)));
} else if (m_parameters[i].is_user<db::DPath> ()) {
db::complex_trans<db::DCoord, db::Coord> dbu_trans (1.0 / layout ()->dbu ());
shapes (layout ()->guiding_shape_layer ()).insert (db::PathWithProperties(dbu_trans * m_parameters[i].to_user<db::DPath> (), layout ()->properties_repository ().properties_id (props)));
shapes (layout ()->guiding_shape_layer ()).insert (db::PathWithProperties (dbu_trans * m_parameters[i].to_user<db::DPath> (), layout ()->properties_repository ().properties_id (props)));
} else if (m_parameters[i].is_user<db::Path> ()) {
shapes (layout ()->guiding_shape_layer ()).insert (db::PathWithProperties(m_parameters[i].to_user<db::Path> (), layout ()->properties_repository ().properties_id (props)));
shapes (layout ()->guiding_shape_layer ()).insert (db::PathWithProperties (m_parameters[i].to_user<db::Path> (), layout ()->properties_repository ().properties_id (props)));
}

View File

@ -277,7 +277,7 @@ void path<C>::create_shifted_points (C start, C end, C width, bool forward, Iter
Iter ppp = pp;
++ppp;
// Compute the unit vector of the line and it's normal (times width)
// Compute the unit vector of the line and its normal (times width)
db::DVector ed (*pp - *p);
ed *= 1.0 / ed.double_length ();
@ -383,7 +383,7 @@ void path<C>::create_shifted_points (C start, C end, C width, bool forward, Iter
// Segments are too short - the won't intersect: In this case we create a loop of three
// points which define the area in self-overlapping way but confined to the path within
// the limits of it's width.
// the limits of its width.
// HINT: the execution of this code is a pretty strong evidence for the existence to loops
// in the contour delivered. A proof however is missing ..
*pts++ = *pp + vector<C> (nd);

View File

@ -32,7 +32,7 @@ db::DEdge compute_shifted (const db::edge<C> &e, C dx, C dy, double ext, int nsi
{
tl_assert (! e.is_degenerate ()); // no coincident points allowed
// Compute the unit vector of the line and it's normal (times width)
// Compute the unit vector of the line and its normal (times width)
db::DVector ec (e.d ());
ec *= 1.0 / ec.double_length ();
db::DVector nc (-ec.y (), ec.x ());
@ -47,7 +47,7 @@ db::DEdge compute_shifted (const db::edge<C> &e, C dx, C dy, double ext, int nsi
/**
* @brief Smart multiplication of a vector with a distance
* This function tries to keep the length of the vector on grid if it's
* This function tries to keep the length of the vector on grid if its
* a 45 degree or horizontal/vertical one.
*/
template <class C>

View File

@ -151,7 +151,7 @@ void create_shifted_points (C /*c*/, bool forward, Iter from, Iter to, WIter wfr
WIter www = ww;
++www;
// Compute the unit vector of the line and it's normal (times width)
// Compute the unit vector of the line and its normal (times width)
db::DVector ed (*pp - *p);
ed *= 1.0 / ed.double_length ();
@ -258,7 +258,7 @@ void create_shifted_points (C /*c*/, bool forward, Iter from, Iter to, WIter wfr
// Segments are too short - the won't intersect: In this case we create a loop of three
// points which define the area in self-overlapping way but confined to the path within
// the limits of it's width.
// the limits of its width.
// HINT: the execution of this code is a pretty strong evidence for the existence to loops
// in the contour delivered. A proof however is missing ..
*pts++ = *pp + vector<C> (nd2);

View File

@ -1875,14 +1875,14 @@ Class<db::Cell> decl_Cell ("db", "Cell",
gsi::method_ext ("write", &write_simple, gsi::arg ("file_name"),
"@brief Writes the cell to a layout file\n"
"The format of the file will be determined from the file name. Only the cell and "
"it's subtree below will be saved.\n"
"its subtree below will be saved.\n"
"\n"
"This method has been introduced in version 0.23.\n"
) +
gsi::method_ext ("write", &write_options, gsi::arg ("file_name"), gsi::arg ("options"),
"@brief Writes the cell to a layout file\n"
"The format of the file will be determined from the file name. Only the cell and "
"it's subtree below will be saved.\n"
"its subtree below will be saved.\n"
"In contrast to the other 'write' method, this version allows one to specify save options, i.e. "
"scaling etc.\n"
"\n"
@ -2576,7 +2576,7 @@ Class<db::Cell> decl_Cell ("db", "Cell",
"\n"
"In contrast to the \\transform method, this method allows propagation of the transformation into child cells. "
"More precisely: it applies just a part of the given transformation to the instance, such that when transforming "
"the cell instantiated and it's shapes with the same transformation, the result will reflect the desired transformation. Mathematically spoken, the "
"the cell instantiated and its shapes with the same transformation, the result will reflect the desired transformation. Mathematically spoken, the "
"transformation of the instance (A) is transformed with the given transformation T using \"A' = T * A * Tinv\" where "
"Tinv is the inverse of T. In effect, the transformation T commutes with the new instance transformation A' and can be "
"applied to child cells as well. This method is therefore useful to transform a hierarchy of cells.\n"
@ -3221,7 +3221,7 @@ Class<db::Cell> decl_Cell ("db", "Cell",
"\n"
"The parameters are given in the order the parameters are declared. Use \\pcell_declaration "
"on the instance to get the PCell declaration object of the cell. That PCellDeclaration object "
"delivers the parameter declaration with it's 'get_parameters' method.\n"
"delivers the parameter declaration with its 'get_parameters' method.\n"
"Each parameter in the variant list passed to the second list of values corresponds to "
"one parameter declaration.\n"
"\n"
@ -4013,7 +4013,7 @@ Class<db::Instance> decl_Instance ("db", "Instance",
"@param layer_index The index of the layer the bounding box will be computed for.\n"
"The bounding box incorporates all instances that the array represents. "
"It gives the overall extension of the child cell as seen in the calling cell (or all array members if the instance forms an array) "
"for the given layer. If the layer is empty in this cell and all it's children', an empty bounding box will be returned. "
"for the given layer. If the layer is empty in this cell and all its children', an empty bounding box will be returned. "
"\n"
"This method has been introduced in version 0.25. 'bbox' is the preferred synonym for it since version 0.28."
) +

View File

@ -132,7 +132,7 @@ Class<db::CellMapping> decl_CellMapping ("db", "CellMapping",
"If used as a pseudo-target for the cell mapping, this index indicates "
"that the cell shall be dropped rather than created on the target side "
"or skipped by flattening. Instead, all shapes of this cell are discarded "
"and it's children are not translated unless explicitly requested or "
"and its children are not translated unless explicitly requested or "
"if required are children for other cells.\n"
"\n"
"This constant has been introduced in version 0.25."

View File

@ -727,7 +727,7 @@ Class<db::CompoundRegionOperationNode> decl_CompoundRegionOperationNode ("db", "
"If 'is_square' is true, only squares will be selected. If 'inverse' is true, the non-rectangle/non-square shapes are returned.\n"
) +
gsi::constructor ("new_edges", &new_edges, gsi::arg ("input"),
"@brief Creates a node converting polygons into it's edges.\n"
"@brief Creates a node converting polygons into its edges.\n"
) +
gsi::constructor ("new_edge_length_filter", &new_edge_length_filter, gsi::arg ("input"), gsi::arg ("inverse", false), gsi::arg ("lmin", 0), gsi::arg ("lmax", std::numeric_limits<db::Edge::distance_type>::max (), "max"),
"@brief Creates a node filtering edges by their length.\n"

View File

@ -1410,7 +1410,7 @@ Class<db::Layout> decl_Layout ("db", "Layout",
"If the region is (conceptionally) a flat region, it will be inserted into the cell's shapes "
"list as a flat sequence of polygons.\n"
"If the region is a deep (hierarchical) region, it will create a subhierarchy below the given "
"cell and it's shapes will be put into the respective cells. Suitable subcells will be picked "
"cell and its shapes will be put into the respective cells. Suitable subcells will be picked "
"for inserting the shapes. If a hierarchy already exists below the given cell, the algorithm will "
"try to reuse this hierarchy.\n"
"\n"
@ -1422,7 +1422,7 @@ Class<db::Layout> decl_Layout ("db", "Layout",
"If the edge collection is (conceptionally) flat, it will be inserted into the cell's shapes "
"list as a flat sequence of edges.\n"
"If the edge collection is deep (hierarchical), it will create a subhierarchy below the given "
"cell and it's edges will be put into the respective cells. Suitable subcells will be picked "
"cell and its edges will be put into the respective cells. Suitable subcells will be picked "
"for inserting the edges. If a hierarchy already exists below the given cell, the algorithm will "
"try to reuse this hierarchy.\n"
"\n"
@ -1434,7 +1434,7 @@ Class<db::Layout> decl_Layout ("db", "Layout",
"If the edge pair collection is (conceptionally) flat, it will be inserted into the cell's shapes "
"list as a flat sequence of edge pairs.\n"
"If the edge pair collection is deep (hierarchical), it will create a subhierarchy below the given "
"cell and it's edge pairs will be put into the respective cells. Suitable subcells will be picked "
"cell and its edge pairs will be put into the respective cells. Suitable subcells will be picked "
"for inserting the edge pairs. If a hierarchy already exists below the given cell, the algorithm will "
"try to reuse this hierarchy.\n"
"\n"
@ -1446,7 +1446,7 @@ Class<db::Layout> decl_Layout ("db", "Layout",
"If the text collection is (conceptionally) flat, it will be inserted into the cell's shapes "
"list as a flat sequence of texts.\n"
"If the text collection is deep (hierarchical), it will create a subhierarchy below the given "
"cell and it's texts will be put into the respective cells. Suitable subcells will be picked "
"cell and its texts will be put into the respective cells. Suitable subcells will be picked "
"for inserting the texts. If a hierarchy already exists below the given cell, the algorithm will "
"try to reuse this hierarchy.\n"
"\n"

View File

@ -388,7 +388,7 @@ Class<db::LayoutToNetlist> decl_dbLayoutToNetlist ("db", "LayoutToNetlist",
"@brief Extracts devices\n"
"See the class description for more details.\n"
"This method will run device extraction for the given extractor. The layer map is specific\n"
"for the extractor and uses the region objects derived with \\make_layer and it's variants.\n"
"for the extractor and uses the region objects derived with \\make_layer and its variants.\n"
"\n"
"In addition, derived regions can be passed too. Certain limitations apply. It's safe to use\n"
"boolean operations for deriving layers. Other operations are applicable as long as they are\n"
@ -410,7 +410,7 @@ Class<db::LayoutToNetlist> decl_dbLayoutToNetlist ("db", "LayoutToNetlist",
) +
gsi::method ("connect", (void (db::LayoutToNetlist::*) (const db::Region &)) &db::LayoutToNetlist::connect, gsi::arg ("l"),
"@brief Defines an intra-layer connection for the given layer.\n"
"The layer is either an original layer created with \\make_includelayer and it's variants or\n"
"The layer is either an original layer created with \\make_includelayer and its variants or\n"
"a derived layer. Certain limitations apply. It's safe to use\n"
"boolean operations for deriving layers. Other operations are applicable as long as they are\n"
"capable of delivering hierarchical layers.\n"
@ -810,7 +810,7 @@ Class<db::LayoutToNetlist> decl_dbLayoutToNetlist ("db", "LayoutToNetlist",
"@li Preparation\n"
" In this step, the device recognition and extraction layers are drawn from\n"
" the framework. Derived can now be computed using boolean operations.\n"
" Methods to use in this step are \\make_layer and it's variants.\n"
" Methods to use in this step are \\make_layer and its variants.\n"
" Layer preparation is not necessarily required to happen before all\n"
" other steps. Layers can be computed shortly before they are required.\n"
"@/li\n"
@ -821,7 +821,7 @@ Class<db::LayoutToNetlist> decl_dbLayoutToNetlist ("db", "LayoutToNetlist",
" may be specified here. Layer preparation may happen between calls to \\extract_devices.\n"
"@/li\n"
"@li Once the devices are derived, the netlist connectivity can be defined and the\n"
" netlist extracted. The connectivity is defined with \\connect and it's\n"
" netlist extracted. The connectivity is defined with \\connect and its\n"
" flavours. The actual netlist extraction happens with \\extract_netlist.\n"
"@/li\n"
"@li After netlist extraction, the information is ready to be retrieved.\n"

View File

@ -263,7 +263,7 @@ static std::vector<db::LayerProperties> get_layer_declarations_native (const db:
std::vector<db::PCellLayerDeclaration> lp = pd->db::PCellDeclaration::get_layer_declarations (parameters);
std::vector<db::LayerProperties> ret;
for (std::vector<db::PCellLayerDeclaration>::const_iterator l = lp.begin (); l != lp.end (); ++l) {
ret.push_back (db::LayerProperties(*l));
ret.push_back (db::LayerProperties (*l));
}
return ret;
}

View File

@ -1701,7 +1701,7 @@ Class<db::Circuit> decl_dbCircuit (decl_dbNetlistObject, "db", "Circuit",
) +
gsi::method ("flatten_subcircuit", &db::Circuit::flatten_subcircuit, gsi::arg ("subcircuit"),
"@brief Flattens a subcircuit\n"
"This method will substitute the given subcircuit by it's contents. The subcircuit is removed "
"This method will substitute the given subcircuit by its contents. The subcircuit is removed "
"after this."
) +
gsi::iterator ("each_subcircuit", (db::Circuit::subcircuit_iterator (db::Circuit::*) ()) &db::Circuit::begin_subcircuits, (db::Circuit::subcircuit_iterator (db::Circuit::*) ()) &db::Circuit::end_subcircuits,
@ -1986,7 +1986,7 @@ Class<db::Netlist> decl_dbNetlist ("db", "Netlist",
) +
gsi::method ("flatten_circuit", &db::Netlist::flatten_circuit, gsi::arg ("circuit"),
"@brief Flattens a subcircuit\n"
"This method will substitute all instances (subcircuits) of the given circuit by it's "
"This method will substitute all instances (subcircuits) of the given circuit by its "
"contents. After this, the circuit is removed."
) +
gsi::method_ext ("flatten_circuit", &flatten_circuit_by_name, gsi::arg ("pattern"),

View File

@ -454,7 +454,7 @@ Class<GenericNetlistCompareLogger> decl_GenericNetlistCompareLogger (decl_dbNetl
),
"@brief An event receiver for the netlist compare feature.\n"
"The \\NetlistComparer class will send compare events to a logger derived from this class. "
"Use this class to implement your own logger class. You can override on of it's methods to receive certain "
"Use this class to implement your own logger class. You can override on of its methods to receive certain "
"kind of events."
"\n"
"This class has been introduced in version 0.26.\n"

View File

@ -325,7 +325,7 @@ Class<GenericDeviceExtractor> decl_GenericDeviceExtractor (decl_dbNetlistDeviceE
"This method is supposed to set up the device extractor. This involves three basic steps:\n"
"defining the name, the device class and setting up the device layers.\n"
"\n"
"Use \\name= to give the extractor and it's device class a name.\n"
"Use \\name= to give the extractor and its device class a name.\n"
"Use \\register_device_class to register the device class you need.\n"
"Defined the layers by calling \\define_layer once or several times.\n"
) +
@ -377,7 +377,7 @@ Class<GenericDeviceExtractor> decl_GenericDeviceExtractor (decl_dbNetlistDeviceE
"@return The layer descriptor object created for this layer (use 'index' to get the layer's index)\n"
"As \\define_layer, this method allows specification of device extraction layer. In addition to \\define_layout, it features "
"a fallback layer. If in the device extraction statement, the primary layer is not given, "
"the fallback layer will be used. Hence, this layer is optional. The fallback layer is given by it's "
"the fallback layer will be used. Hence, this layer is optional. The fallback layer is given by its "
"index and must be defined before the layer using the fallback layer is defined. "
"For the index, 0 is the first layer defined, 1 the second and so forth."
) +

View File

@ -372,7 +372,7 @@ struct simple_polygon_defs
method ("is_box?", &C::is_box,
"@brief Returns a value indicating whether the polygon is a simple box.\n"
"\n"
"A polygon is a box if it is identical to it's bounding box.\n"
"A polygon is a box if it is identical to its bounding box.\n"
"\n"
"@return True if the polygon is a box.\n"
"\n"
@ -1380,7 +1380,7 @@ struct polygon_defs
method ("is_box?", &C::is_box,
"@brief Returns true, if the polygon is a simple box.\n"
"\n"
"A polygon is a box if it is identical to it's bounding box.\n"
"A polygon is a box if it is identical to its bounding box.\n"
"\n"
"@return True if the polygon is a box.\n"
"\n"

View File

@ -120,7 +120,7 @@ gsi::Class<db::TechnologyComponent> technology_component_decl ("db", "Technology
"@brief A part of a technology definition\n"
"Technology components extend technology definitions (class \\Technology) by "
"specialized subfeature definitions. For example, the net tracer supplies "
"it's technology-dependent specification through a technology component called "
"its technology-dependent specification through a technology component called "
"\\NetTracerTechnology.\n"
"\n"
"Components are managed within technologies and can be accessed from a technology "

View File

@ -174,7 +174,7 @@ gsi::Class<db::TileOutputReceiver> &dbdecl_TileOutputReceiverBase ()
gsi::Class<TileOutputReceiver_Impl> decl_TileOutputReceiver (decl_TileOutputReceiverBase, "db", "TileOutputReceiver",
gsi::callback ("begin", &TileOutputReceiver_Impl::begin, &TileOutputReceiver_Impl::begin_cb, gsi::arg ("nx"), gsi::arg ("ny"), gsi::arg ("p0"), gsi::arg ("dx"), gsi::arg ("dy"), gsi::arg ("frame"),
"@brief Initiates the delivery\n"
"This method is called before the first tile delivers it's data.\n"
"This method is called before the first tile delivers its data.\n"
"\n"
"@param nx The number of tiles in x direction\n"
"@param ny The number of tiles in y direction\n"

View File

@ -739,7 +739,7 @@ struct cplx_trans_defs
method ("invert", &C::invert,
"@brief Inverts the transformation (in place)\n"
"\n"
"Inverts the transformation and replaces this transformation by it's\n"
"Inverts the transformation and replaces this transformation by its\n"
"inverted one.\n"
"\n"
"@return The inverted transformation\n"

View File

@ -62,7 +62,7 @@ namespace gsi
gsi::method ("spline_interpolation", &db::UtilsDummy::spi1, gsi::arg ("control_points"), gsi::arg ("weights"), gsi::arg ("degree"), gsi::arg ("knots"), gsi::arg ("relative_accuracy"), gsi::arg ("absolute_accuracy"),
"@brief This function computes the Spline curve for a given set of control points (point, weight), degree and knots.\n"
"\n"
"The knot vector needs to be padded and it's size must fulfill the condition:\n"
"The knot vector needs to be padded and its size must fulfill the condition:\n"
"\n"
"@code\n"
" knots.size == control_points.size + degree + 1\n"

View File

@ -2409,7 +2409,7 @@ TEST(15_EmptySubCircuitWithoutPinNames)
" subcircuit TRANS $3 ($1=OUT,$2=$5,$3=$2);\n"
" subcircuit TRANS $4 ($1=OUT,$2=$4,$3=$2);\n"
"end;\n"
// This circuit is an abstract and it's pins are not defined by the pin names ->
// This circuit is an abstract and its pins are not defined by the pin names ->
// they are internally marked as swappable
"circuit TRANS ($1=$1,$2=$2,$3=$3);\n"
"end;\n";
@ -4152,7 +4152,7 @@ TEST(23_NodesRemovedWithError)
" subcircuit INV2PAIR $5 ($2=$I25,$3=VDD,$4=VSS,$5=$I6,$6=$I7);\n"
"end;\n"
"circuit INV2PAIR ($2=$I8,$3=$I5,$4=$I4,$5=$I3,$6=$I2);\n"
// NOTE: $1 pin should not be connected to different nets, although it's not functional
// NOTE: $1 pin should not be connected to different nets, although its not functional
" subcircuit INV2 $1 ($1=$3,IN=$I3,$3=$I7,OUT=$I6,VSS=$I4,VDD=$I5);\n"
" subcircuit INV2 $2 ($1=$6,IN=$I6,$3=$I8,OUT=$I2,VSS=$I4,VDD=$I5);\n"
"end;\n"

View File

@ -768,7 +768,7 @@ is called on. This operation represents all "other" primary polygons while
</p><p>
This feature opens new options for processing layouts beyond the
abilities of the classical DRC concept. For classic DRC, intra-layer interactions
are always symmetric: a polygon cannot be considered separated from it's neighbors
are always symmetric: a polygon cannot be considered separated from its neighbors
on the same layer.
</p><p>
The following example computes every part of the input which is closer than

View File

@ -676,7 +676,7 @@ out = l1.drc((secondary(l2) &amp; primary).area &gt; 1.0)
</p><p>
Some filters operate on properties of the full, local, per-primary shape set.
While the loop is executed, the DRC expressions will collect shapes, either
from the primary, it's neighborhood (secondaries) or from deriving shape sets.
from the primary, its neighborhood (secondaries) or from deriving shape sets.
</p><p>
Obviously the primary is a simple one: it consists of a single shape, because
this is how the loop operates. Derived shape sets however can be more complex.
@ -1537,7 +1537,7 @@ from the other layer. Two polygons overlapping or touching at two locations are
</ul>
<p>
This operation is similar to the "&amp;" operator, but it does also report intersection points
between non-colinear, but intersection edges. Such points are reported as point-like,
between non-colinear, but intersecting edges. Such points are reported as point-like,
degenerated edge objects.
</p><p>
This method is available for edge layers. The argument must be an edge layer.
@ -3609,7 +3609,7 @@ This method is available for polygon or edge pair layers.
<li><tt>layer.with_area_ratio(min, max)</tt></li>
</ul>
<p>
The area ratio is a measure how far a polygon is approximated by it's
The area ratio is a measure how far a polygon is approximated by its
bounding box. The value is always larger or equal to 1. Boxes have a
area ratio of 1. Larger values mean more empty area inside the bounding box.
</p><p>
@ -3883,7 +3883,7 @@ upper limit.
</p><p>
This method is available for polygon layers only.
</p>
<a name="with_relative_height"/><h2>"with_relative_height" - Selects polygons by the ratio of the height vs. width of it's bounding box</h2>
<a name="with_relative_height"/><h2>"with_relative_height" - Selects polygons by the ratio of the height vs. width of its bounding box</h2>
<keyword name="with_relative_height"/>
<p>Usage:</p>
<ul>

View File

@ -335,7 +335,7 @@ module DRC
#
# Some filters operate on properties of the full, local, per-primary shape set.
# While the loop is executed, the DRC expressions will collect shapes, either
# from the primary, it's neighborhood (secondaries) or from deriving shape sets.
# from the primary, its neighborhood (secondaries) or from deriving shape sets.
#
# Obviously the primary is a simple one: it consists of a single shape, because
# this is how the loop operates. Derived shape sets however can be more complex.
@ -528,7 +528,7 @@ module DRC
#
# This feature opens new options for processing layouts beyond the
# abilities of the classical DRC concept. For classic DRC, intra-layer interactions
# are always symmetric: a polygon cannot be considered separated from it's neighbors
# are always symmetric: a polygon cannot be considered separated from its neighbors
# on the same layer.
#
# The following example computes every part of the input which is closer than

View File

@ -2317,7 +2317,11 @@ CODE
c !~ /drc.lym:/ && c !~ /_drc_\w+\.rb:/ && c !~ /\(eval\)/
end
if cc =~ /(.*)\s*:\s*(\d+)\s*:\s*in.*$/
return File::basename($1) + ":" + $2
path = $1
line = $2.to_i
real_path = RBA::Macro::real_path(path, line)
real_line = RBA::Macro::real_line(path, line)
return File::basename(real_path) + ":" + real_line.to_s
else
return cc
end
@ -2908,7 +2912,7 @@ CODE
def _make_path(file)
# resolves the file path relative to the source's path
sp = self.source.path
sp = (@def_source || @def_layout) && self.source.path
if sp
if File.respond_to?(:absolute_path)
return File::absolute_path(file, File::dirname(sp))
@ -3238,7 +3242,7 @@ CODE
cn = cellname && cellname.to_s
cn ||= @def_cell && @def_cell.name
cn ||= source && source.cell_name
cn ||= @def_source && @def_source.cell_obj && @def_source.cell_obj.name
cn || raise("No cell name specified - either the source was not specified before 'report' or there is no default source. In the latter case, specify a cell name as the third parameter")
@ -3281,7 +3285,7 @@ CODE
cn ||= @def_cell && @def_cell.name
cn ||= @def_source && @def_source.cell_obj && @def_source.cell_obj.name
cn || raise("No cell name specified - either the source was not specified before 'report' or there is no default source. In the latter case, specify a cell name as the third parameter")
cn || raise("No cell name specified - either the source was not specified before 'report' or there is no default source. In the latter case, specify a cell name as the second parameter")
output_layout = RBA::Layout::new
output_cell = output_layout.create_cell(cn)

View File

@ -630,7 +630,7 @@ CODE
# @synopsis layer.with_area_ratio(min .. max)
# @synopsis layer.with_area_ratio(value)
# @synopsis layer.with_area_ratio(min, max)
# The area ratio is a measure how far a polygon is approximated by it's
# The area ratio is a measure how far a polygon is approximated by its
# bounding box. The value is always larger or equal to 1. Boxes have a
# area ratio of 1. Larger values mean more empty area inside the bounding box.
#
@ -648,7 +648,7 @@ CODE
# %DRC%
# @name with_relative_height
# @brief Selects polygons by the ratio of the height vs. width of it's bounding box
# @brief Selects polygons by the ratio of the height vs. width of its bounding box
# @synopsis layer.with_relative_height(min .. max)
# @synopsis layer.with_relative_height(value)
# @synopsis layer.with_relative_height(min, max)

View File

@ -800,6 +800,77 @@ TEST(14b_SideTargetsAndReports)
compare_text_files (report2, au_report2);
}
TEST(14c_OnlySpecialInputsAndReports)
{
std::string rs = tl::testdata ();
rs += "/drc/drcSimpleTests_14c.drc";
// apart from that it's a variant of 14b ...
std::string input = tl::testdata ();
input += "/drc/drcSimpleTests_14b.gds";
std::string au = tl::testdata ();
au += "/drc/drcSimpleTests_au14b.gds";
std::string au2 = tl::testdata ();
au2 += "/drc/drcSimpleTests_au14b_2.gds";
std::string au_report = tl::testdata ();
au_report += "/drc/drcSimpleTests_au14b.lyrdb";
std::string au_report2 = tl::testdata ();
au_report2 += "/drc/drcSimpleTests_au14b_2.lyrdb";
std::string output = this->tmp_file ("tmp.gds");
std::string output2 = this->tmp_file ("tmp2.gds");
std::string report = this->tmp_file ("tmp.lydrc");
std::string report2 = this->tmp_file ("tmp2.lydrc");
{
// Set some variables
lym::Macro config;
config.set_text (tl::sprintf (
"$drc_force_gc = true\n"
"$drc_test_source = '%s'\n"
"$drc_test_target = '%s'\n"
"$drc_test_target2 = '%s'\n"
"$drc_test_report = '%s'\n"
"$drc_test_report2 = '%s'\n"
, input, output, output2, report, report2)
);
config.set_interpreter (lym::Macro::Ruby);
EXPECT_EQ (config.run (), 0);
}
lym::Macro drc;
drc.load_from (rs);
EXPECT_EQ (drc.run (), 0);
db::Layout layout;
{
tl::InputStream stream (output);
db::Reader reader (stream);
reader.read (layout);
}
db::compare_layouts (_this, layout, au, db::NoNormalization);
db::Layout layout2;
{
tl::InputStream stream (output2);
db::Reader reader (stream);
reader.read (layout2);
}
db::compare_layouts (_this, layout2, au2, db::NoNormalization);
compare_text_files (report, au_report);
compare_text_files (report2, au_report2);
}
TEST(15_issue548)
{
std::string rs = tl::testdata ();

View File

@ -0,0 +1,282 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>PointPropertiesPage</class>
<widget class="QWidget" name="PointPropertiesPage">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>531</width>
<height>370</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QVBoxLayout">
<property name="spacing">
<number>6</number>
</property>
<property name="margin" stdset="0">
<number>9</number>
</property>
<item>
<widget class="QFrame" name="frame1">
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Raised</enum>
</property>
<layout class="QHBoxLayout">
<property name="spacing">
<number>6</number>
</property>
<property name="margin" stdset="0">
<number>0</number>
</property>
<item>
<widget class="QLabel" name="label_12">
<property name="font">
<font>
<family>Sans Serif</family>
<pointsize>12</pointsize>
<italic>false</italic>
<bold>true</bold>
<underline>false</underline>
<strikeout>false</strikeout>
</font>
</property>
<property name="text">
<string>Point Properties</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="layer_lbl">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string/>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<spacer>
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>10</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QLabel" name="label">
<property name="text">
<string>Point position</string>
</property>
</widget>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>6</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QFrame" name="frame">
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Raised</enum>
</property>
<layout class="QHBoxLayout" name="horizontalLayout">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QLabel" name="label_14">
<property name="text">
<string>x = </string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="x_le">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>1</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_19">
<property name="text">
<string>y = </string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="y_le">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>1</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</item>
<item>
<spacer>
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>478</width>
<height>10</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QCheckBox" name="dbu_cb">
<property name="text">
<string>Coordinates in database units</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="abs_cb">
<property name="text">
<string>Absolute (accumulated) transformations</string>
</property>
</widget>
</item>
<item>
<spacer>
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>478</width>
<height>16</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QFrame" name="frame2">
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Raised</enum>
</property>
<layout class="QHBoxLayout">
<property name="spacing">
<number>6</number>
</property>
<property name="margin" stdset="0">
<number>0</number>
</property>
<item>
<spacer>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>211</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="prop_pb">
<property name="text">
<string>User Properties</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="inst_pb">
<property name="text">
<string>Instantiation</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
<tabstops>
<tabstop>dbu_cb</tabstop>
<tabstop>abs_cb</tabstop>
<tabstop>prop_pb</tabstop>
<tabstop>inst_pb</tabstop>
</tabstops>
<resources/>
<connections/>
</ui>

View File

@ -92,3 +92,6 @@ LIBS += -L$$DESTDIR -lklayout_tl -lklayout_gsi -lklayout_laybasic -lklayout_layv
}
FORMS += \
PointPropertiesPage.ui

View File

@ -2537,6 +2537,7 @@ public:
{
mp_polygon_service = view->get_plugin <edt::PolygonService> ();
mp_box_service = view->get_plugin <edt::BoxService> ();
mp_point_service = view->get_plugin <edt::PointService> ();
mp_text_service = view->get_plugin <edt::TextService> ();
mp_path_service = view->get_plugin <edt::PathService> ();
mp_inst_service = view->get_plugin <edt::InstService> ();
@ -2587,6 +2588,7 @@ public:
private:
edt::PolygonService *mp_polygon_service;
edt::BoxService *mp_box_service;
edt::PointService *mp_point_service;
edt::TextService *mp_text_service;
edt::PathService *mp_path_service;
edt::InstService *mp_inst_service;

View File

@ -849,6 +849,14 @@ PartialShapeFinder::visit_cell (const db::Cell &cell, const db::Box &hit_box, co
}
} else if (shape->is_point ()) {
db::Point tp (shape->point ());
if (hit_box.contains (tp)) {
edges.push_back (EdgeWithIndex (db::Edge (tp, tp), 0, 0, 0));
}
} else if (shape->is_text ()) {
db::Point tp (shape->text_trans () * db::Point ());
@ -1000,6 +1008,17 @@ PartialShapeFinder::visit_cell (const db::Cell &cell, const db::Box &hit_box, co
}
} else if (shape->is_point ()) {
db::Point tp (shape->point ());
if (hit_box.contains (tp)) {
d = tp.distance (hit_box.center ());
edge_sel.clear ();
edge_sel.push_back (EdgeWithIndex (db::Edge (tp, tp), 0, 0, 0));
match = true;
}
} else if (shape->is_text ()) {
db::Point tp (shape->text_trans () * db::Point ());
@ -1258,6 +1277,11 @@ PartialService::timeout ()
db::Point tp (r->first.shape ().text_trans () * db::Point ());
enter_edge (EdgeWithIndex (db::Edge (tp, tp), 0, 0, 0), n_marker, r, new_points, new_edges, gt, *tv_list, true);
} else if (r->first.shape ().is_point ()) {
db::Point tp (r->first.shape ().point ());
enter_edge (EdgeWithIndex (db::Edge (tp, tp), 0, 0, 0), n_marker, r, new_points, new_edges, gt, *tv_list, true);
}
}
@ -1479,6 +1503,17 @@ PartialService::transform_selection (const db::DTrans &move_trans)
shape = shapes.replace (shape, t);
}
} else if (shape.is_point ()) {
db::Point p;
shape.point (p);
std::map <PointWithIndex, db::Point>::const_iterator np = new_points.find (PointWithIndex (p, 0, 0));
if (np != new_points.end ()) {
shape = shapes.replace (shape, np->second);
}
}
// transform the selection
@ -2204,7 +2239,7 @@ PartialService::del ()
shapes_to_delete_by_cell.insert (std::make_pair (std::make_pair (r->first.cell_index (), std::make_pair (r->first.cv_index (), r->first.layer ())), std::vector <partial_objects::const_iterator> ())).first->second.push_back (r);
}
} else if (shape.is_text ()) {
} else if (shape.is_text () || shape.is_point ()) {
shapes_to_delete_by_cell.insert (std::make_pair (std::make_pair (r->first.cell_index (), std::make_pair (r->first.cv_index (), r->first.layer ())), std::vector <partial_objects::const_iterator> ())).first->second.push_back (r);
@ -2684,6 +2719,11 @@ PartialService::do_selection_to_view ()
db::Point tp (r->first.shape ().text_trans () * db::Point ());
enter_edge (EdgeWithIndex (db::Edge (tp, tp), 0, 0, 0), n_marker, r, new_points, new_edges, gt, *tv_list, false);
} else if (r->first.shape ().is_point ()) {
db::Point tp (r->first.shape ().point ());
enter_edge (EdgeWithIndex (db::Edge (tp, tp), 0, 0, 0), n_marker, r, new_points, new_edges, gt, *tv_list, false);
}
}
@ -2795,6 +2835,9 @@ PartialService::partial_select (const db::DBox &box, lay::Editable::SelectionMod
if (edt::boxes_enabled ()) {
shape_flags |= db::ShapeIterator::Boxes;
}
if (edt::points_enabled ()) {
shape_flags |= db::ShapeIterator::Points;
}
if (edt::texts_enabled ()) {
shape_flags |= db::ShapeIterator::Texts;
}

View File

@ -245,8 +245,12 @@ public:
virtual bool implements_mouse_mode (std::string &title) const
{
title = m_mouse_mode;
return true;
if (! m_mouse_mode.empty ()) {
title = m_mouse_mode;
return true;
} else {
return false;
}
}
private:
@ -282,6 +286,11 @@ static tl::RegisteredClass<lay::PluginDeclaration> config_decl4 (
"edt::Service(Paths)"
);
static tl::RegisteredClass<lay::PluginDeclaration> config_decl5 (
new edt::PluginDeclaration<edt::PointService> (tl::to_string (tr ("Points")), std::string (), 0, &get_shape_editor_options_pages),
4014,
"edt::Service(Points)"
);
static tl::RegisteredClass<lay::PluginDeclaration> config_decl6 (
new edt::PluginDeclaration<edt::InstService> (tl::to_string (tr ("Instances")), "instance:edit_mode\t" + tl::to_string (tr ("Instance")) + "\t<:instance_24px.png>" + tl::to_string (tr ("{Create a cell instance}")), &get_inst_options, &get_inst_editor_options_pages),
4020,
"edt::Service(CellInstances)"
@ -302,6 +311,7 @@ bool is_enabled ()
bool polygons_enabled () { return is_enabled<edt::PolygonService> (); }
bool paths_enabled () { return is_enabled<edt::PathService> (); }
bool boxes_enabled () { return is_enabled<edt::BoxService> (); }
bool points_enabled () { return is_enabled<edt::PointService> (); }
bool texts_enabled () { return is_enabled<edt::TextService> (); }
bool instances_enabled () { return is_enabled<edt::InstService> (); }

View File

@ -54,6 +54,7 @@ namespace edt
// other types ...
bool paths_enabled ();
bool boxes_enabled ();
bool points_enabled ();
bool texts_enabled ();
bool instances_enabled ();

View File

@ -197,6 +197,42 @@ db::Shape BoxDimensionsChangeApplicator::do_apply (db::Shapes &shapes, const db:
}
}
// -------------------------------------------------------------------------
// PointDimensionsChangeApplicator implementation
PointDimensionsChangeApplicator::PointDimensionsChangeApplicator (const db::Point &point, const db::Point &org_point)
: m_point (point), m_org_point (org_point)
{
// .. nothing yet ..
}
db::Shape PointDimensionsChangeApplicator::do_apply (db::Shapes &shapes, const db::Shape &shape, double /*dbu*/, bool relative) const
{
db::Point org_point;
shape.point (org_point);
db::Point new_point;
if (relative) {
new_point = org_point + (m_point - m_org_point);
} else if (m_point != m_org_point) {
new_point = org_point;
if (m_point.x () != m_org_point.x ()) {
new_point.set_x (m_point.x ());
}
if (m_point.y () != m_org_point.y ()) {
new_point.set_y (m_point.y ());
}
}
if (new_point != org_point) {
// shape changed - replace the old by the new one
return shapes.replace (shape, new_point);
} else {
// shape did not change
return shape;
}
}
// -------------------------------------------------------------------------
// PolygonChangeApplicator implementation

View File

@ -131,6 +131,22 @@ private:
db::Coord m_l, m_b, m_r, m_t;
};
/**
* @brief A point change applicator
*/
class PointDimensionsChangeApplicator
: public ChangeApplicator
{
public:
PointDimensionsChangeApplicator (const db::Point &point, const db::Point &org_point);
bool supports_relative_mode () const { return true; }
db::Shape do_apply (db::Shapes &shapes, const db::Shape &shape, double dbu, bool relative) const;
private:
db::Point m_point, m_org_point;
};
/**
* @brief A polygon change applicator
*/

View File

@ -853,6 +853,124 @@ BoxPropertiesPage::changed ()
emit edited ();
}
// -------------------------------------------------------------------------
// PointPropertiesPage implementation
PointPropertiesPage::PointPropertiesPage (edt::Service *service, db::Manager *manager, QWidget *parent)
: ShapePropertiesPage (tl::to_string (tr ("Points")), service, manager, parent),
m_dbu (1.0)
{
setupUi (this);
setup ();
if (! readonly ()) {
connect (x_le, SIGNAL (editingFinished ()), this, SLOT (changed ()));
connect (y_le, SIGNAL (editingFinished ()), this, SLOT (changed ()));
} else {
x_le->setReadOnly (true);
y_le->setReadOnly (true);
}
connect (inst_pb, SIGNAL (clicked ()), this, SLOT (show_inst ()));
connect (prop_pb, SIGNAL (clicked ()), this, SLOT (show_props ()));
}
std::string
PointPropertiesPage::description (size_t entry) const
{
const db::Shape &sh = shape (entry);
db::CplxTrans dbu_trans (dbu (entry));
return ShapePropertiesPage::description (entry) + " - " + tl::sprintf (tl::to_string (tr ("Point%s")), (dbu_trans * sh.point ()).to_string ());
}
void
PointPropertiesPage::do_update (const db::Shape &shape, double dbu, const std::string &lname)
{
m_dbu = dbu;
layer_lbl->setText (tl::to_qstring (lname));
db::Point point;
shape.point (point);
set_point (point);
}
ChangeApplicator *
PointPropertiesPage::create_applicator (db::Shapes & /*shapes*/, const db::Shape &shape, double dbu)
{
m_dbu = dbu;
db::Point point = get_point ();
db::Point org_point;
shape.point (org_point);
if (point != org_point) {
return new PointDimensionsChangeApplicator (point, org_point);
} else {
return 0;
}
}
db::Point
PointPropertiesPage::get_point () const
{
bool has_error = false;
double x = 0.0, y = 0.0;
try {
tl::from_string_ext (tl::to_string (x_le->text ()), x);
lay::indicate_error (x_le, (tl::Exception *) 0);
} catch (tl::Exception &ex) {
lay::indicate_error (x_le, &ex);
has_error = true;
}
try {
tl::from_string_ext (tl::to_string (y_le->text ()), y);
lay::indicate_error (y_le, (tl::Exception *) 0);
} catch (tl::Exception &ex) {
lay::indicate_error (y_le, &ex);
has_error = true;
}
if (has_error) {
throw tl::Exception (tl::to_string (tr ("Invalid values - see highlighted entry boxes")));
}
db::VCplxTrans t = db::VCplxTrans (trans ().inverted ());
bool du = dbu_units ();
return point_from_dpoint (db::DPoint (x, y), m_dbu, du, t);
}
void
PointPropertiesPage::set_point (const db::Point &point)
{
db::CplxTrans t = db::CplxTrans (trans ());
db::DPoint pt = db::DPoint (t (point));
bool du = dbu_units ();
x_le->setText (tl::to_qstring (coord_to_string (pt.x (), m_dbu, du)));
y_le->setText (tl::to_qstring (coord_to_string (pt.y (), m_dbu, du)));
}
void
PointPropertiesPage::changed ()
{
try {
set_point (get_point ());
} catch (...) {
}
emit edited ();
}
// -------------------------------------------------------------------------
// TextPropertiesPage implementation

View File

@ -31,6 +31,7 @@
#include "edtService.h"
#include "ui_PolygonPropertiesPage.h"
#include "ui_BoxPropertiesPage.h"
#include "ui_PointPropertiesPage.h"
#include "ui_PathPropertiesPage.h"
#include "ui_EditablePathPropertiesPage.h"
#include "ui_TextPropertiesPage.h"
@ -152,6 +153,34 @@ private:
void set_box (const db::Box &box);
};
class PointPropertiesPage
: public ShapePropertiesPage,
public Ui::PointPropertiesPage
{
Q_OBJECT
public:
PointPropertiesPage (edt::Service *service, db::Manager *manager, QWidget *parent);
virtual std::string description (size_t entry) const;
virtual std::string description () const { return ShapePropertiesPage::description (); }
virtual void do_update (const db::Shape &shape, double dbu, const std::string &lname);
virtual ChangeApplicator *create_applicator (db::Shapes &shapes, const db::Shape &shape, double dbu);
public slots:
void changed ();
protected:
virtual QCheckBox *dbu_checkbox () const { return dbu_cb; }
virtual QCheckBox *abs_checkbox () const { return abs_cb; }
private:
double m_dbu;
db::Point get_point () const;
void set_point (const db::Point &point);
};
class TextPropertiesPage
: public ShapePropertiesPage,
public Ui::TextPropertiesPage

View File

@ -1108,7 +1108,20 @@ Service::transient_select (const db::DPoint &pos)
lay::ShapeMarker *marker = new lay::ShapeMarker (view (), r->cv_index ());
marker->set (r->shape (), gt, mp_view->cv_transform_variants (r->cv_index (), r->layer ()));
marker->set_vertex_size (0);
bool is_point = false;
if (r->shape ().is_edge () || r->shape ().is_box ()) {
is_point = r->shape ().bbox ().is_point ();
} else if (r->shape ().is_point ()) {
is_point = true;
}
if (is_point) {
marker->set_vertex_shape (lay::ViewOp::Cross);
marker->set_vertex_size (9 /*cross vertex size*/);
} else {
marker->set_vertex_size (0);
}
marker->set_line_width (1);
marker->set_halo (0);
@ -1602,7 +1615,15 @@ Service::do_selection_to_view ()
}
marker->set (r->shape (), gt, *tv_list);
if (r->shape ().is_text ()) {
bool is_point = false;
if (r->shape ().is_text () || r->shape ().is_point ()) {
is_point = true;
} else if (r->shape ().is_edge () || r->shape ().is_box ()) {
is_point = r->shape ().bbox ().is_point ();
}
if (is_point) {
// show the origins as crosses for texts
marker->set_vertex_shape (lay::ViewOp::Cross);
marker->set_vertex_size (9 /*cross vertex size*/);

View File

@ -386,6 +386,20 @@ ShapeEditService::deliver_shape (const db::Box &box)
}
}
void
ShapeEditService::deliver_shape (const db::Point &point)
{
if (m_combine_mode == CM_Add) {
if (manager ()) {
manager ()->transaction (tl::to_string (tr ("Create point")));
}
cell ().shapes (layer ()).insert (point);
if (manager ()) {
manager ()->commit ();
}
}
}
// -----------------------------------------------------------------------------
// PolygonService implementation
@ -816,6 +830,103 @@ BoxService::selection_applies (const lay::ObjectInstPath &sel) const
return !sel.is_cell_inst () && sel.shape ().is_box ();
}
// -----------------------------------------------------------------------------
// PointService implementation
PointService::PointService (db::Manager *manager, lay::LayoutViewBase *view)
: ShapeEditService (manager, view, db::ShapeIterator::Points)
{
// .. nothing yet ..
}
#if defined(HAVE_QT)
std::vector<lay::PropertiesPage *>
PointService::properties_pages (db::Manager *manager, QWidget *parent)
{
std::vector<lay::PropertiesPage *> pages;
pages.push_back (new edt::PointPropertiesPage (this, manager, parent));
return pages;
}
#endif
void
PointService::do_begin_edit (const db::DPoint &p)
{
get_edit_layer ();
db::DPoint pp = snap2 (p);
m_p = pp;
set_edit_marker (new lay::Marker (view (), cv_index ()));
update_marker ();
}
db::Point
PointService::get_point () const
{
return db::Point (trans () * m_p);
}
void
PointService::update_marker ()
{
lay::Marker *marker = dynamic_cast<lay::Marker *> (edit_marker ());
if (marker) {
db::Point pt = get_point ();
marker->set (db::Box (pt, pt), db::VCplxTrans (1.0 / layout ().dbu ()) * trans ().inverted ());
view ()->message (std::string ("x: ") +
tl::micron_to_string (m_p.x ()) +
std::string (" y: ") +
tl::micron_to_string (m_p.y ()));
}
}
void
PointService::do_mouse_move_inactive (const db::DPoint &p)
{
lay::PointSnapToObjectResult snap_details = snap2_details (p);
mouse_cursor_from_snap_details (snap_details);
}
void
PointService::do_mouse_move (const db::DPoint &p)
{
do_mouse_move_inactive (p);
set_cursor (lay::Cursor::cross);
m_p = snap2 (p);
update_marker ();
}
bool
PointService::do_mouse_click (const db::DPoint &p)
{
do_mouse_move (p);
return true;
}
void
PointService::do_finish_edit ()
{
deliver_shape (get_point ());
commit_recent (view ());
}
void
PointService::do_cancel_edit ()
{
// .. nothing yet ..
}
bool
PointService::selection_applies (const lay::ObjectInstPath &sel) const
{
return !sel.is_cell_inst () && sel.shape ().is_point ();
}
// -----------------------------------------------------------------------------
// TextService implementation

View File

@ -67,6 +67,7 @@ protected:
void deliver_shape (const db::Polygon &poly);
void deliver_shape (const db::Path &path);
void deliver_shape (const db::Box &box);
void deliver_shape (const db::Point &point);
virtual void current_layer_changed () { }
private:
@ -140,6 +141,33 @@ private:
db::Box get_box () const;
};
/**
* @brief Implementation of edt::Service for point editing
*/
class PointService
: public ShapeEditService
{
public:
PointService (db::Manager *manager, lay::LayoutViewBase *view);
#if defined(HAVE_QT)
virtual std::vector<lay::PropertiesPage *> properties_pages (db::Manager *manager, QWidget *parent);
#endif
virtual void do_begin_edit (const db::DPoint &p);
virtual void do_mouse_move (const db::DPoint &p);
virtual void do_mouse_move_inactive (const db::DPoint &p);
virtual bool do_mouse_click (const db::DPoint &p);
virtual void do_finish_edit ();
virtual void do_cancel_edit ();
virtual bool selection_applies (const lay::ObjectInstPath &sel) const;
private:
db::DPoint m_p;
void update_marker ();
db::Point get_point () const;
};
/**
* @brief Implementation of edt::Service for text editing
*/

View File

@ -260,19 +260,19 @@ get_parameters_from_pcell_and_guiding_shapes (db::Layout *layout, db::cell_index
std::map <std::string, size_t>::const_iterator pnm = pname_map.find (pv->second.to_string ());
if (pnm != pname_map.end ()) {
db::CplxTrans dbu_trans (layout->dbu ());
if (sh->is_box ()) {
if (sh->box ().width () == 0 && sh->box ().height () == 0) {
parameters_for_pcell [pnm->second] = tl::Variant (sh->box ().lower_left () * layout->dbu ());
} else {
parameters_for_pcell [pnm->second] = tl::Variant (sh->box () * layout->dbu ());
}
parameters_for_pcell [pnm->second] = tl::Variant (dbu_trans * sh->box ());
} else if (sh->is_edge ()) {
parameters_for_pcell [pnm->second] = tl::Variant (sh->edge () * layout->dbu ());
parameters_for_pcell [pnm->second] = tl::Variant (dbu_trans * sh->edge ());
} else if (sh->is_point ()) {
parameters_for_pcell [pnm->second] = tl::Variant (dbu_trans * sh->point ());
} else if (sh->is_polygon ()) {
// Hint: we don't compress since we don't want to loose information
parameters_for_pcell [pnm->second] = tl::Variant (sh->polygon ().transformed (db::CplxTrans (layout->dbu ()), false));
parameters_for_pcell [pnm->second] = tl::Variant (sh->polygon ().transformed (dbu_trans, false));
} else if (sh->is_path ()) {
parameters_for_pcell [pnm->second] = tl::Variant (db::CplxTrans (layout->dbu ()) * sh->path ());
parameters_for_pcell [pnm->second] = tl::Variant (dbu_trans * sh->path ());
}
}
@ -315,7 +315,7 @@ get_parameters_from_pcell_and_guiding_shapes (db::Layout *layout, db::cell_index
} else if (org_parameters[i].is_user<db::DPoint> ()) {
db::DPoint p = org_parameters[i].to_user<db::DPoint> ();
guiding_shapes.insert (db::BoxWithProperties(db::Box (db::DBox (p, p) * (1.0 / layout->dbu ())), layout->properties_repository ().properties_id (props)));
guiding_shapes.insert (db::PointWithProperties(db::Point (p * (1.0 / layout->dbu ())), layout->properties_repository ().properties_id (props)));
} else if (org_parameters[i].is_user<db::DPolygon> ()) {

View File

@ -496,7 +496,7 @@ struct writer
if (atype.is_ref () || atype.is_ptr ()) {
// TODO: morph the variant to the requested type and pass it's pointer (requires a non-const reference for arg)
// TODO: morph the variant to the requested type and pass its pointer (requires a non-const reference for arg)
// -> we would have a reference that can modify the argument (out parameter).
R *v = new R (var2c<R>::get (*arg));
heap->push (v);
@ -542,7 +542,7 @@ struct writer<StringType>
} else {
// TODO: morph the variant to the requested type and pass it's pointer (requires a non-const reference for arg)
// TODO: morph the variant to the requested type and pass its pointer (requires a non-const reference for arg)
// -> we would have a reference that can modify the argument (out parameter).
// NOTE: by convention we pass the ownership to the receiver for adaptors.
aa->write<void *> ((void *)new StringAdaptorImpl<std::string> (arg->to_string ()));

View File

@ -225,7 +225,7 @@ private:
};
/**
* @brief The template providing a binding of a "free iterator" (one that provides it's own at_end method)
* @brief The template providing a binding of a "free iterator" (one that provides its own at_end method)
*/
template <class I>
class FreeIterAdaptor

View File

@ -40,10 +40,10 @@ class QtLifetimeMonitor
};
/**
* @brief A helper object that is attached to a QObject to monitor it's lifetime
* @brief A helper object that is attached to a QObject to monitor its lifetime
*
* This object will be put into the properties table of the QObject (more precisely: a copy).
* When the QObject is destroyed, it's properties are destroyed too and through reference
* When the QObject is destroyed, its properties are destroyed too and through reference
* counting the destruction of the QObject is detected. The monitoring itself is implemented
* through a gsi::ObjectBase object which plugs seamlessly into the gsi type system:
*

View File

@ -284,5 +284,9 @@
<file alias="bookmark_16px@2x.png">images/bookmark_16px@2x.png</file>
<file alias="bookmark_24px.png">images/bookmark_24px.png</file>
<file alias="bookmark_24px@2x.png">images/bookmark_24px@2x.png</file>
<file alias="find_next_16px.png">images/find_next_16px.png</file>
<file alias="find_next_16px@2x.png">images/find_next_16px@2x.png</file>
<file alias="find_prev_16px.png">images/find_prev_16px.png</file>
<file alias="find_prev_16px@2x.png">images/find_prev_16px@2x.png</file>
</qresource>
</RCC>

Binary file not shown.

After

Width:  |  Height:  |  Size: 689 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 702 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

@ -0,0 +1,231 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
width="16"
height="16"
viewBox="0 0 4.2333332 4.2333335"
version="1.1"
id="svg1011"
inkscape:version="1.1.2 (0a00cf5339, 2022-02-04)"
sodipodi:docname="find_next_16px.svg"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<sodipodi:namedview
id="namedview1013"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:document-units="px"
showgrid="true"
units="px"
inkscape:snap-nodes="true"
inkscape:snap-bbox="true"
inkscape:bbox-nodes="true"
inkscape:snap-others="false"
inkscape:zoom="12.224789"
inkscape:cx="1.9223236"
inkscape:cy="9.7752198"
inkscape:window-width="1465"
inkscape:window-height="666"
inkscape:window-x="1099"
inkscape:window-y="250"
inkscape:window-maximized="0"
inkscape:current-layer="layer1"
width="16px"
inkscape:showpageshadow="2"
inkscape:deskcolor="#d1d1d1">
<inkscape:grid
type="xygrid"
id="grid1074"
spacingx="0.13229167"
spacingy="0.13229167"
empspacing="2" />
</sodipodi:namedview>
<defs
id="defs1008">
<linearGradient
id="linearGradient3600">
<stop
style="stop-color:#ff9f3f;stop-opacity:1;"
offset="0"
id="stop3602" />
<stop
style="stop-color:#ffffff;stop-opacity:1;"
offset="1"
id="stop3604" />
</linearGradient>
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient5268"
id="radialGradient5274"
cx="1240.1577"
cy="1031.1023"
fx="1240.1577"
fy="1031.1023"
r="17.716494"
gradientTransform="matrix(0.07467134,-2.1333204e-7,1.7097273e-7,0.05973699,-91.281506,-60.271751)"
gradientUnits="userSpaceOnUse" />
<linearGradient
id="linearGradient5268">
<stop
style="stop-color:#ffffff;stop-opacity:1;"
offset="0"
id="stop5270" />
<stop
style="stop-color:#adadad;stop-opacity:1;"
offset="1"
id="stop5272" />
</linearGradient>
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient5280"
id="radialGradient5286"
cx="1240.1576"
cy="1031.1023"
fx="1240.1576"
fy="1031.1023"
r="17.716494"
gradientTransform="matrix(0.07467134,-5.3367783e-7,4.263589e-7,0.05973696,-91.281753,-60.27133)"
gradientUnits="userSpaceOnUse" />
<linearGradient
id="linearGradient5280">
<stop
style="stop-color:#ababab;stop-opacity:1;"
offset="0"
id="stop5282" />
<stop
style="stop-color:#535353;stop-opacity:1;"
offset="1"
id="stop5284" />
</linearGradient>
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient5298"
id="linearGradient5304"
x1="1257.874"
y1="1059.4489"
x2="1264.9606"
y2="1052.3622"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.07467134,0,0,0.07467124,-91.281317,-75.670759)" />
<linearGradient
id="linearGradient5298">
<stop
style="stop-color:#000000;stop-opacity:1;"
offset="0"
id="stop5300" />
<stop
id="stop5306"
offset="0.50000167"
style="stop-color:#8f8f8f;stop-opacity:1;" />
<stop
style="stop-color:#353535;stop-opacity:1;"
offset="1"
id="stop5302" />
</linearGradient>
<linearGradient
id="linearGradient4099">
<stop
id="stop4101"
offset="0"
style="stop-color:#ffffff;stop-opacity:1;" />
<stop
style="stop-color:#ff9e3f;stop-opacity:1;"
offset="0.65753424"
id="stop4485" />
<stop
id="stop4103"
offset="1"
style="stop-color:#808080;stop-opacity:1;" />
</linearGradient>
</defs>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1">
<rect
style="fill:none;stroke:#865b26;stroke-width:0;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
id="rect3596"
width="4.2333326"
height="4.2333331"
x="3.3333333e-07"
y="3.3333333e-07"
inkscape:export-filename="/home/matthias/klayout/master/src/lay/lay/images/back.png"
inkscape:export-xdpi="27.093315"
inkscape:export-ydpi="27.093315" />
<rect
style="fill:none;fill-opacity:1;stroke:none;stroke-width:0;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
id="rect5220"
width="4.2333336"
height="4.2333336"
x="-8.8817842e-16"
y="-7.7715612e-16"
inkscape:export-filename="/home/matthias/klayout/trunk/src/lay/images/find.png"
inkscape:export-xdpi="25.399982"
inkscape:export-ydpi="25.399982" />
<ellipse
style="fill:url(#radialGradient5274);fill-opacity:1;stroke:url(#radialGradient5286);stroke-width:0.268817;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
id="path5258"
cx="1.5874953"
cy="1.5875114"
rx="1.188506"
ry="1.1885061"
inkscape:export-filename="/home/matthias/klayout/trunk/src/lay/images/find.png"
inkscape:export-xdpi="25"
inkscape:export-ydpi="25" />
<ellipse
style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.268817;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
id="path5278"
cx="0.65258032"
cy="2.108269"
rx="0.21676302"
ry="0.51771969"
transform="matrix(0.84080627,-0.54133615,0.68097313,0.7323084,0,0)"
inkscape:export-filename="/home/matthias/klayout/trunk/src/lay/images/find.png"
inkscape:export-xdpi="25"
inkscape:export-ydpi="25" />
<ellipse
style="fill:none;fill-opacity:1;stroke:#303030;stroke-width:0.0746713;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
id="path5308"
cx="1.5874953"
cy="1.5875114"
inkscape:export-filename="/home/matthias/klayout/trunk/src/lay/images/find.png"
inkscape:export-xdpi="25"
inkscape:export-ydpi="25"
rx="1.3229176"
ry="1.3229157" />
<path
style="fill:url(#linearGradient5304);fill-opacity:1;fill-rule:evenodd;stroke:#303030;stroke-width:0.0746713;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 3.9687491,3.4395946 3.4395757,3.9687602 2.1166608,2.645847 2.6458268,2.1166818 Z"
id="path5288"
inkscape:connector-curvature="0"
inkscape:export-filename="/home/matthias/klayout/trunk/src/lay/images/find.png"
inkscape:export-xdpi="25"
inkscape:export-ydpi="25" />
<path
inkscape:export-ydpi="25"
inkscape:export-xdpi="25"
inkscape:export-filename="/home/matthias/klayout/trunk/src/lay/images/replace.png"
sodipodi:nodetypes="cccccccc"
inkscape:connector-curvature="0"
id="path5342"
d="M 3.042749,1.4552217 H 1.9843342 l -7.36e-5,1.0595032 h -0.521379 l 1.05066,1.0761548 1.058786,-1.0722781 -0.529505,-0.00388 z"
style="fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#ffffff;stroke-width:1.05833334;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.98414469" />
<path
style="fill:#1a1a1a;fill-opacity:1;fill-rule:evenodd;stroke:#1a1a1a;stroke-width:0.26458333;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 3.0427083,1.4552084 H 1.984375 l -7.36e-5,1.0595163 H 1.4629626 l 1.050579,1.076168 1.0587045,-1.0722914 -0.5294642,-0.00389 z"
id="path5330"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cccccccc"
inkscape:export-filename="/home/matthias/klayout/trunk/src/lay/images/replace.png"
inkscape:export-xdpi="25"
inkscape:export-ydpi="25" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 8.4 KiB

View File

@ -0,0 +1,231 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
width="16"
height="16"
viewBox="0 0 4.2333332 4.2333335"
version="1.1"
id="svg1011"
inkscape:version="1.1.2 (0a00cf5339, 2022-02-04)"
sodipodi:docname="find_prev_16px.svg"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<sodipodi:namedview
id="namedview1013"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:document-units="px"
showgrid="true"
units="px"
inkscape:snap-nodes="true"
inkscape:snap-bbox="true"
inkscape:bbox-nodes="true"
inkscape:snap-others="false"
inkscape:zoom="12.224789"
inkscape:cx="6.666782"
inkscape:cy="14.192475"
inkscape:window-width="1092"
inkscape:window-height="666"
inkscape:window-x="1083"
inkscape:window-y="278"
inkscape:window-maximized="0"
inkscape:current-layer="layer1"
width="16px"
inkscape:showpageshadow="2"
inkscape:deskcolor="#d1d1d1">
<inkscape:grid
type="xygrid"
id="grid1074"
spacingx="0.13229167"
spacingy="0.13229167"
empspacing="2" />
</sodipodi:namedview>
<defs
id="defs1008">
<linearGradient
id="linearGradient3600">
<stop
style="stop-color:#ff9f3f;stop-opacity:1;"
offset="0"
id="stop3602" />
<stop
style="stop-color:#ffffff;stop-opacity:1;"
offset="1"
id="stop3604" />
</linearGradient>
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient5268"
id="radialGradient5274"
cx="1240.1577"
cy="1031.1023"
fx="1240.1577"
fy="1031.1023"
r="17.716494"
gradientTransform="matrix(0.07467134,-2.1333204e-7,1.7097273e-7,0.05973699,-91.281506,-60.271751)"
gradientUnits="userSpaceOnUse" />
<linearGradient
id="linearGradient5268">
<stop
style="stop-color:#ffffff;stop-opacity:1;"
offset="0"
id="stop5270" />
<stop
style="stop-color:#adadad;stop-opacity:1;"
offset="1"
id="stop5272" />
</linearGradient>
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient5280"
id="radialGradient5286"
cx="1240.1576"
cy="1031.1023"
fx="1240.1576"
fy="1031.1023"
r="17.716494"
gradientTransform="matrix(0.07467134,-5.3367783e-7,4.263589e-7,0.05973696,-91.281753,-60.27133)"
gradientUnits="userSpaceOnUse" />
<linearGradient
id="linearGradient5280">
<stop
style="stop-color:#ababab;stop-opacity:1;"
offset="0"
id="stop5282" />
<stop
style="stop-color:#535353;stop-opacity:1;"
offset="1"
id="stop5284" />
</linearGradient>
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient5298"
id="linearGradient5304"
x1="1257.874"
y1="1059.4489"
x2="1264.9606"
y2="1052.3622"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.07467134,0,0,0.07467124,-91.281317,-75.670759)" />
<linearGradient
id="linearGradient5298">
<stop
style="stop-color:#000000;stop-opacity:1;"
offset="0"
id="stop5300" />
<stop
id="stop5306"
offset="0.50000167"
style="stop-color:#8f8f8f;stop-opacity:1;" />
<stop
style="stop-color:#353535;stop-opacity:1;"
offset="1"
id="stop5302" />
</linearGradient>
<linearGradient
id="linearGradient4099">
<stop
id="stop4101"
offset="0"
style="stop-color:#ffffff;stop-opacity:1;" />
<stop
style="stop-color:#ff9e3f;stop-opacity:1;"
offset="0.65753424"
id="stop4485" />
<stop
id="stop4103"
offset="1"
style="stop-color:#808080;stop-opacity:1;" />
</linearGradient>
</defs>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1">
<rect
style="fill:none;stroke:#865b26;stroke-width:0;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
id="rect3596"
width="4.2333326"
height="4.2333331"
x="3.3333333e-07"
y="3.3333333e-07"
inkscape:export-filename="/home/matthias/klayout/master/src/lay/lay/images/back.png"
inkscape:export-xdpi="27.093315"
inkscape:export-ydpi="27.093315" />
<rect
style="fill:none;fill-opacity:1;stroke:none;stroke-width:0;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
id="rect5220"
width="4.2333336"
height="4.2333336"
x="-8.8817842e-16"
y="-7.7715612e-16"
inkscape:export-filename="/home/matthias/klayout/trunk/src/lay/images/find.png"
inkscape:export-xdpi="25.399982"
inkscape:export-ydpi="25.399982" />
<ellipse
style="fill:url(#radialGradient5274);fill-opacity:1;stroke:url(#radialGradient5286);stroke-width:0.268817;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
id="path5258"
cx="1.5874953"
cy="1.5875114"
rx="1.188506"
ry="1.1885061"
inkscape:export-filename="/home/matthias/klayout/trunk/src/lay/images/find.png"
inkscape:export-xdpi="25"
inkscape:export-ydpi="25" />
<ellipse
style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.268817;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
id="path5278"
cx="0.65258032"
cy="2.108269"
rx="0.21676302"
ry="0.51771969"
transform="matrix(0.84080627,-0.54133615,0.68097313,0.7323084,0,0)"
inkscape:export-filename="/home/matthias/klayout/trunk/src/lay/images/find.png"
inkscape:export-xdpi="25"
inkscape:export-ydpi="25" />
<ellipse
style="fill:none;fill-opacity:1;stroke:#303030;stroke-width:0.0746713;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
id="path5308"
cx="1.5874953"
cy="1.5875114"
inkscape:export-filename="/home/matthias/klayout/trunk/src/lay/images/find.png"
inkscape:export-xdpi="25"
inkscape:export-ydpi="25"
rx="1.3229176"
ry="1.3229157" />
<path
style="fill:url(#linearGradient5304);fill-opacity:1;fill-rule:evenodd;stroke:#303030;stroke-width:0.0746713;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 3.9687491,3.4395946 3.4395757,3.9687602 2.1166608,2.645847 2.6458268,2.1166818 Z"
id="path5288"
inkscape:connector-curvature="0"
inkscape:export-filename="/home/matthias/klayout/trunk/src/lay/images/find.png"
inkscape:export-xdpi="25"
inkscape:export-ydpi="25" />
<path
inkscape:export-ydpi="25"
inkscape:export-xdpi="25"
inkscape:export-filename="/home/matthias/klayout/trunk/src/lay/images/replace.png"
sodipodi:nodetypes="cccccccc"
inkscape:connector-curvature="0"
id="path5342"
d="M 3.0478337,3.5792109 H 1.9895004 L 1.9839304,2.5174183 H 1.4625915 l 1.0505791,-1.076168 1.0587045,1.0722914 -0.5294642,0.00389 z"
style="fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#ffffff;stroke-width:1.05833334;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<path
style="fill:#1a1a1a;fill-opacity:1;fill-rule:evenodd;stroke:#1a1a1a;stroke-width:0.26458333;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 3.0478337,3.5792109 H 1.9895004 L 1.9839304,2.5174183 H 1.4625915 l 1.0505791,-1.076168 1.0587045,1.0722914 -0.5294642,0.00389 z"
id="path5330"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cccccccc"
inkscape:export-filename="/home/matthias/klayout/trunk/src/lay/images/replace.png"
inkscape:export-xdpi="25"
inkscape:export-ydpi="25" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 8.4 KiB

View File

@ -451,7 +451,7 @@ static ImageRef *new_image_pbt (const tl::PixelBuffer &pixel_buffer, const db::D
return new ImageRef (img::Object (pixel_buffer, trans));
}
#if HAVE_QT
#if defined(HAVE_QTBINDINGS)
static ImageRef *new_image_qit (const QImage &image, const db::DCplxTrans &trans)
{
return new ImageRef (img::Object (image, trans));
@ -597,7 +597,7 @@ gsi::Class<ImageRef> decl_Image (decl_BasicImage, "lay", "Image",
"@param filename The path to the image file to load.\n"
"@param trans The transformation to apply to the image when displaying it.\n"
) +
#if defined(HAVE_QT)
#if defined(HAVE_QTBINDINGS)
gsi::constructor ("new", &gsi::new_image_qit, gsi::arg ("image"), gsi::arg ("trans", db::DCplxTrans (), "unity"),
"@brief Constructor from a image pixel buffer\n"
"\n"

View File

@ -463,10 +463,6 @@
<property name="text">
<string>...</string>
</property>
<property name="icon">
<iconset resource="../../icons/icons.qrc">
<normaloff>:/breakpoint_16px.png</normaloff>:/breakpoint_16px.png</iconset>
</property>
<property name="shortcut">
<string>F9</string>
</property>
@ -636,7 +632,7 @@
</property>
<property name="icon">
<iconset resource="../../icons/icons.qrc">
<normaloff>:/find_16px.png</normaloff>:/find_16px.png</iconset>
<normaloff>:/find_next_16px.png</normaloff>:/find_next_16px.png</iconset>
</property>
<property name="shortcut">
<string>Ctrl+F</string>
@ -646,6 +642,23 @@
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="findPrevButton">
<property name="text">
<string>...</string>
</property>
<property name="icon">
<iconset resource="../../icons/icons.qrc">
<normaloff>:/find_prev_16px.png</normaloff>:/find_prev_16px.png</iconset>
</property>
<property name="shortcut">
<string>Ctrl+Shift+F</string>
</property>
<property name="autoRaise">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="replaceModeButton">
<property name="sizePolicy">

View File

@ -7,7 +7,7 @@
@args id, ...
This method implements Ruby's fallback mechanism and adds some convenience to
QObject: through that implementation, each child object can be accessed through
it's name. That method will deliver a reference to the child object or nil if there
its name. That method will deliver a reference to the child object or nil if there
is no child element with that name.
For example:

View File

@ -124,9 +124,9 @@ static void ui_exception_handler_tl (const tl::Exception &ex, QWidget *parent)
if (gsi_excpt->line () > 0) {
tl::error << gsi_excpt->sourcefile () << ":" << gsi_excpt->line () << ": "
<< gsi_excpt->msg () << tl::to_string (QObject::tr (" (class ")) << gsi_excpt->cls () << ")";
<< gsi_excpt->msg ();
} else {
tl::error << gsi_excpt->msg () << tl::to_string (QObject::tr (" (class ")) << gsi_excpt->cls () << ")";
tl::error << gsi_excpt->msg ();
}
lay::RuntimeErrorForm error_dialog (parent, "ruby_error_form", gsi_excpt);
@ -686,28 +686,59 @@ ApplicationBase::init_app ()
tc->add_path (*p);
}
tc->load ();
bool needs_reload = false;
// disambiguator for tech name
std::map<std::string, int> tech_disambiguator;
std::map<std::string, std::string> tech_name_for_file;
for (auto t = db::Technologies::instance ()->begin (); t != db::Technologies::instance ()->end (); ++t) {
tech_disambiguator.insert (std::make_pair (t->name (), 0));
}
// import technologies from the command line
for (std::vector <std::pair<file_type, std::pair<std::string, std::string> > >::iterator f = m_files.begin (); f != m_files.end (); ++f) {
if (f->first == layout_file_with_tech_file) {
const std::string &tech_file = f->second.second;
if (tl::verbosity () >= 20) {
tl::info << "Importing technology from " << f->second.second;
}
db::Technology t;
t.load (f->second.second);
t.load (tech_file);
// disambiguate the name, so we do not overwrite technologies with the same name from the config
if (tech_name_for_file.find (tech_file) != tech_name_for_file.end ()) {
t.set_name (tech_name_for_file [tech_file]);
} else if (tech_disambiguator.find (t.name ()) != tech_disambiguator.end ()) {
int &index = tech_disambiguator [t.name ()];
index += 1;
t.set_name (t.name () + tl::sprintf ("[%d]", index));
tech_name_for_file.insert (std::make_pair (tech_file, t.name ()));
} else {
tech_disambiguator.insert (std::make_pair (t.name (), 0));
tech_name_for_file.insert (std::make_pair (tech_file, t.name ()));
}
tc->add_temp_tech (t);
f->first = layout_file_with_tech;
f->second.second = t.name ();
needs_reload = true;
}
}
tc->load ();
if (needs_reload) {
tc->load ();
}
}

View File

@ -493,6 +493,7 @@ MacroEditorDialog::MacroEditorDialog (lay::Dispatcher *pr, lym::MacroCollection
connect (replaceModeButton, SIGNAL (clicked ()), this, SLOT (replace_mode_button_clicked ()));
connect (replaceNextButton, SIGNAL (clicked ()), this, SLOT (replace_next_button_clicked ()));
connect (findNextButton, SIGNAL (clicked ()), this, SLOT (find_next_button_clicked ()));
connect (findPrevButton, SIGNAL (clicked ()), this, SLOT (find_prev_button_clicked ()));
connect (replaceAllButton, SIGNAL (clicked ()), this, SLOT (replace_all_button_clicked ()));
connect (allVariables, SIGNAL (clicked (bool)), variableList, SLOT (set_show_all (bool)));
@ -2021,7 +2022,7 @@ MacroEditorDialog::replace_all_button_clicked ()
}
void
MacroEditorDialog::search_requested (const QString &s)
MacroEditorDialog::search_requested (const QString &s, bool prev)
{
if (! s.isNull ()) {
searchEditBox->setText (s);
@ -2029,7 +2030,21 @@ MacroEditorDialog::search_requested (const QString &s)
searchEditBox->selectAll ();
}
searchEditBox->setFocus ();
search_editing ();
MacroEditorPage *page = dynamic_cast<MacroEditorPage *> (tabWidget->currentWidget ());
if (! page) {
return;
}
apply_search ();
page->find_reset (); // search from the initial position
if (! page->has_multi_block_selection ()) {
if (! prev) {
page->find_next ();
} else {
page->find_prev ();
}
}
}
void
@ -3511,7 +3526,7 @@ MacroEditorDialog::create_page (lym::Macro *macro)
editor->exec_model ()->set_run_mode (m_in_exec);
editor->connect_macro (macro);
connect (editor.get (), SIGNAL (help_requested (const QString &)), this, SLOT (help_requested (const QString &)));
connect (editor.get (), SIGNAL (search_requested (const QString &)), this, SLOT (search_requested (const QString &)));
connect (editor.get (), SIGNAL (search_requested (const QString &, bool)), this, SLOT (search_requested (const QString &, bool)));
connect (editor.get (), SIGNAL (edit_trace (bool)), this, SLOT (add_edit_trace (bool)));
return editor.release ();
}

View File

@ -222,7 +222,7 @@ private slots:
void find_next_button_clicked ();
void find_prev_button_clicked ();
void help_requested (const QString &s);
void search_requested (const QString &s);
void search_requested (const QString &s, bool prev);
void macro_changed (lym::Macro *macro);
void macro_deleted (lym::Macro *macro);
void macro_collection_deleted (lym::MacroCollection *collection);

View File

@ -1077,12 +1077,10 @@ MacroEditorPage::find_prev ()
first = false;
int i = -1;
int l = 0;
int p = 0;
while (true) {
int ii = m_current_search.indexIn (b.text (), p);
if (ii >= 0 && (o < 0 || ii < o)) {
l = m_current_search.matchedLength ();
i = ii;
p = ii + 1;
} else {
@ -1091,8 +1089,7 @@ MacroEditorPage::find_prev ()
}
if (i >= 0) {
QTextCursor newc (b);
newc.setPosition (i + b.position () + l);
newc.setPosition (i + b.position (), QTextCursor::KeepAnchor);
newc.setPosition (i + b.position ());
m_ignore_cursor_changed_event = true;
mp_text->setTextCursor (newc);
m_ignore_cursor_changed_event = false;
@ -1136,8 +1133,7 @@ MacroEditorPage::find_next ()
int i = m_current_search.indexIn (b.text (), o);
if (i >= 0) {
QTextCursor newc (b);
newc.setPosition (i + b.position () + m_current_search.matchedLength ());
newc.setPosition (i + b.position (), QTextCursor::KeepAnchor);
newc.setPosition (i + b.position ());
m_ignore_cursor_changed_event = true;
mp_text->setTextCursor (newc);
m_ignore_cursor_changed_event = false;
@ -1158,6 +1154,39 @@ MacroEditorPage::find_next ()
return false;
}
bool
MacroEditorPage::select_match_here ()
{
if (m_current_search == QRegExp ()) {
return false;
}
QTextCursor c = mp_text->textCursor ();
if (c.isNull ()) {
return false;
}
if (c.hasSelection ()) {
return true;
}
QTextBlock b = c.block ();
int pos = c.position () - b.position ();
int i = m_current_search.indexIn (b.text (), pos);
if (i == pos) {
QTextCursor newc (b);
newc.setPosition (i + b.position () + m_current_search.matchedLength ());
newc.setPosition (i + b.position (), QTextCursor::KeepAnchor);
m_ignore_cursor_changed_event = true;
mp_text->setTextCursor (newc);
m_ignore_cursor_changed_event = false;
emit edit_trace (false);
return true;
} else {
return false;
}
}
void
MacroEditorPage::set_editor_focus ()
{
@ -1196,7 +1225,9 @@ MacroEditorPage::replace_and_find_next (const QString &replace)
return;
}
replace_in_selection (replace, true);
if (select_match_here ()) {
replace_in_selection (replace, true);
}
find_next ();
}
@ -1280,12 +1311,8 @@ MacroEditorPage::replace_in_selection (const QString &replace, bool first)
o = i + r.size ();
if (first) {
// in single-selection mode, put cursor past substitution
c.setPosition (i + b.position ());
has_selection = false;
done = true;
} else if (b == be) {
pe += int (r.size ()) - int (m_current_search.matchedLength ());
}
@ -1734,6 +1761,11 @@ static bool is_find_key (QKeyEvent *ke)
return ke->key () == Qt::Key_F && (ke->modifiers () & Qt::ControlModifier) != 0;
}
static bool is_find_backwards_key (QKeyEvent *ke)
{
return ke->key () == Qt::Key_F && (ke->modifiers () & Qt::ControlModifier) != 0 && (ke->modifiers () & Qt::ShiftModifier) != 0;
}
static bool is_up_key (QKeyEvent *ke)
{
return ke->key () == Qt::Key_Up;
@ -1755,6 +1787,7 @@ static bool is_any_known_key (QKeyEvent *ke)
is_help_key (ke) ||
is_find_next_key (ke) ||
is_find_key (ke) ||
is_find_backwards_key (ke) ||
is_up_key (ke) ||
is_down_key (ke);
}
@ -1848,19 +1881,21 @@ MacroEditorPage::eventFilter (QObject *watched, QEvent *event)
QApplication::sendEvent (mp_completer_list, event);
return true;
} else if (is_find_key (ke)) {
} else if (is_find_key (ke) || is_find_backwards_key (ke)) {
bool prev = is_find_backwards_key (ke);
QTextCursor c = mp_text->textCursor ();
if (c.selectionStart () != c.selectionEnd ()) {
QTextBlock s = mp_text->document ()->findBlock (c.selectionStart ());
QTextBlock e = mp_text->document ()->findBlock (c.selectionEnd ());
if (e == s) {
emit search_requested (c.selectedText ());
emit search_requested (c.selectedText (), prev);
} else {
emit search_requested (QString ());
emit search_requested (QString (), prev);
}
} else {
emit search_requested (QString ());
emit search_requested (QString (), prev);
}
return true;

View File

@ -271,7 +271,7 @@ public:
signals:
void help_requested (const QString &s);
void search_requested (const QString &s);
void search_requested (const QString &s, bool backward);
void edit_trace (bool);
public slots:
@ -314,6 +314,7 @@ private:
void fill_completer_list ();
void complete ();
QTextCursor get_completer_cursor (int &pos0, int &pos);
bool select_match_here ();
void replace_in_selection (const QString &replace, bool first);
bool eventFilter (QObject *watched, QEvent *event);

View File

@ -541,7 +541,7 @@ MainWindow::init_menu ()
}
// if not in editable mode, hide all entries from "edit_mode" group
// TODO: later do this on each change of the view - each view might get it's own editable mode
// TODO: later do this on each change of the view - each view might get its own editable mode
bool view_mode = (lay::ApplicationBase::instance () && !lay::ApplicationBase::instance ()->is_editable ());
std::vector<std::string> edit_mode_grp = menu ()->group ("edit_mode");
@ -742,7 +742,7 @@ MainWindow::about_to_exec ()
}
}
// TODO: later, each view may get it's own editable flag
// TODO: later, each view may get its own editable flag
if (lay::ApplicationBase::instance () && !lay::ApplicationBase::instance ()->is_editable ()) {
TipDialog td (this,
tl::to_string (QObject::tr ("KLayout has been started in viewer mode. In this mode, editor functions are not available.\n\nTo enable these functions, start KLayout in editor mode by using the \"-e\" command line switch or select it as the default mode in the setup dialog. Choose \"Setup\" in the \"File\" menu and check \"Use editing mode by default\" on the \"Editing Mode\" page in the \"Application\" section.")),

View File

@ -201,10 +201,10 @@ SaltController::install_packages (const std::vector<std::string> &packages, bool
}
if (n.find ("http:") == 0 || n.find ("https:") == 0 || n.find ("file:") == 0 || n[0] == '/' || n[0] == '\\') {
// it's a URL
// its a URL
manager.register_download (std::string (), std::string (), n, v);
} else {
// it's a plain name
// its a plain name
manager.register_download (n, std::string (), std::string (), v);
}

View File

@ -580,7 +580,7 @@ SaltGrainPropertiesDialog::accept ()
if (d->version.empty ()) {
dependencies_alert->warn () << tr ("No version specified for dependency '%1'").arg (tl::to_qstring (d->name)) << tl::endl
<< tr ("Please consider giving a version here. Versions help deciding whether a package needs to be updated.") << tl::endl
<< tr ("If the dependency package has a version itself, the version is automatically set to it's current version.");
<< tr ("If the dependency package has a version itself, the version is automatically set to its current version.");
}
if (!d->url.empty ()) {

View File

@ -609,6 +609,9 @@ TechnologyController::rescan (db::Technologies &technologies)
for (std::vector<db::Technology>::const_iterator t = m_temp_tech.begin (); t != m_temp_tech.end (); ++t) {
db::Technology *tech = new db::Technology (*t);
if (tl::verbosity () >= 20) {
tl::info << "Registering special technology from " << tech->tech_file_path () << " as " << tech->name ();
}
tech->set_persisted (false); // don't save that one in the configuration
tech->set_tech_file_path (std::string ()); // don't save to a file either
tech->set_readonly (true); // don't edit

View File

@ -46,7 +46,7 @@ module PCellLibModule
end
def coerce_parameters_impl
# TODO: use x to access parameter x and set_x to modify it's value
# TODO: use x to access parameter x and set_x to modify its value
end
def produce_impl

View File

@ -34,11 +34,11 @@ class PCell(pya.PCellDeclarationHelper):
return "TODO: create description"
def coerce_parameters_impl(self):
# TODO: use x to access parameter x and set_x to modify it's value
# TODO: use x to access parameter x and set_x to modify its value
def produce_impl(self):
# TODO: produce the cell content
# i.e. self.cell().shapes(self.l_layer).insert(pya.Polygon(...))
# i.e. self.cell.shapes(self.l_layer).insert(pya.Polygon(...))
# optional:
# def can_create_from_shape_impl(self):

View File

@ -48,7 +48,7 @@ module PCellPackageModule
end
def coerce_parameters_impl
# TODO: use x to access parameter x and set_x to modify it's value
# TODO: use x to access parameter x and set_x to modify its value
end
def produce_impl

View File

@ -1241,7 +1241,7 @@ Class<lay::LayerPropertiesNode> decl_LayerPropertiesNode (
"Each layer properties node object has a unique ID that is created \n"
"when a new LayerPropertiesNode object is instantiated. The ID is\n"
"copied when the object is copied. The ID can be used to identify the\n"
"object irregardless of it's content.\n"
"object irregardless of its content.\n"
),
"@brief A layer properties node structure\n"
"\n"
@ -1441,7 +1441,7 @@ Class<lay::LayerPropertiesConstIterator> decl_LayerPropertiesIterator (
"@brief Returns the index of the child within the parent\n"
"\n"
"This method returns the index of that the properties node the iterator points to in the list\n"
"of children of it's parent. If the element does not have a parent, the \n"
"of children of its parent. If the element does not have a parent, the \n"
"index of the element in the global list is returned.\n"
),
"@brief Layer properties iterator\n"

View File

@ -1438,7 +1438,7 @@ LAYBASIC_PUBLIC Class<lay::LayoutViewBase> decl_LayoutViewBase ("lay", "LayoutVi
"@brief Hierarchically iterates over the layers in the given layer list\n"
"\n"
"This version of this method allows specification of the layer list to be iterated over. "
"The layer list is specified by it's index which is a value between 0 and \\num_layer_lists-1."
"The layer list is specified by its index which is a value between 0 and \\num_layer_lists-1."
"For details see the parameter-less version of this method.\n"
"\n"
"This method was introduced in version 0.25."
@ -1666,7 +1666,7 @@ LAYBASIC_PUBLIC Class<lay::LayoutViewBase> decl_LayoutViewBase ("lay", "LayoutVi
"\n"
"If a file is loaded, this event is triggered.\n"
"When this event is triggered, the file was already loaded and the new file is the new active cellview.\n"
"Despite it's name, this event is also triggered if a layout object is loaded into the view.\n"
"Despite its name, this event is also triggered if a layout object is loaded into the view.\n"
"\n"
"Before version 0.25 this event was based on the observer pattern obsolete now. The corresponding methods "
"(add_file_open_observer/remove_file_open_observer) have been removed in 0.25.\n"
@ -1683,7 +1683,7 @@ LAYBASIC_PUBLIC Class<lay::LayoutViewBase> decl_LayoutViewBase ("lay", "LayoutVi
gsi::event ("on_layer_list_changed", static_cast<tl::event<int> (lay::LayoutViewBase::*)> (&lay::LayoutViewBase::layer_list_changed_event), gsi::arg ("flags"),
"@brief An event indicating that the layer list has changed\n"
"\n"
"This event is triggered after the layer list has changed it's configuration.\n"
"This event is triggered after the layer list has changed its configuration.\n"
"The integer argument gives a hint about the nature of the changed:\n"
"Bit 0 is set, if the properties (visibility, color etc.) of one or more layers have changed. Bit 1 is\n"
"set if the hierarchy has changed. Bit 2 is set, if layer names have changed."
@ -2239,7 +2239,7 @@ Class<lay::CellViewRef> decl_CellView ("lay", "CellView",
"\n"
"This method will construct any path to this cell, not a \n"
"particular one. It will clear the context path\n"
"and update the context and target cell. Note that the cell is specified by it's index.\n"
"and update the context and target cell. Note that the cell is specified by its index.\n"
) +
method ("cell_name=|set_cell_name", (void (lay::CellViewRef::*) (const std::string &)) &lay::CellViewRef::set_cell, gsi::arg ("cell_name"),
"@brief Sets the cell by name\n"
@ -2394,9 +2394,9 @@ Class<lay::CellViewRef> decl_CellView ("lay", "CellView",
"is addressed by an cell_index or a cell object reference.\n"
"The layout pointer can be nil, indicating that the cell view is invalid.\n"
"\n"
"The cell is not only identified by it's index or object but also \n"
"The cell is not only identified by its index or object but also \n"
"by the path leading to that cell. This path indicates how to find the\n"
"cell in the hierarchical context of it's parent cells. \n"
"cell in the hierarchical context of its parent cells. \n"
"\n"
"The path is in fact composed of two parts: first in an unspecific fashion,\n"
"just describing which parent cells are used. The target of this path\n"

View File

@ -730,7 +730,7 @@ Class<gsi::PluginBase> decl_Plugin ("lay", "Plugin",
callback ("config_finalize", &gsi::PluginBase::config_finalize, &gsi::PluginBase::f_config_finalize,
"@brief Sends the post-configuration request to the plugin\n"
"After all configuration parameters have been sent, 'config_finalize' is called to given the plugin a chance to "
"update it's internal state according to the new configuration.\n"
"update its internal state according to the new configuration.\n"
) +
callback ("key_event", &gsi::PluginBase::key_event, &gsi::PluginBase::f_key_event, gsi::arg ("key"), gsi::arg ("buttons"),
"@brief Handles the key pressed event\n"
@ -840,7 +840,7 @@ Class<gsi::PluginBase> decl_Plugin ("lay", "Plugin",
),
"@brief The plugin object\n"
"\n"
"This class provides the actual plugin implementation. Each view gets it's own instance of the plugin class. The plugin factory \\PluginFactory class "
"This class provides the actual plugin implementation. Each view gets its own instance of the plugin class. The plugin factory \\PluginFactory class "
"must be specialized to provide a factory for new objects of the Plugin class. See the documentation there for details about the plugin mechanism and "
"the basic concepts.\n"
"\n"

View File

@ -1532,7 +1532,7 @@ Recorder::eventFilter (QObject *object, QEvent *event)
if (event->type() == QEvent::MouseButtonPress) {
// send the test event to make the object print it's content
// send the test event to make the object print its content
QEvent event (QEvent::MaxUser);
event.ignore ();

View File

@ -52,7 +52,7 @@ namespace lay
#if defined(__APPLE__)
// On MacOS, the main menu bar and it's decendent children
// On MacOS, the main menu bar and its decendent children
// can't be modified using "removeAction", followed by "addAction"
// to achieve a move operation.If we try to do so, segmentation faults happen
// in the timer event that presumably tries to merge the menu bar

View File

@ -54,7 +54,7 @@ void
BitmapRenderer::clear ()
{
// this implementation is efficient but does not free memory -
// the idea is to let the BitmapRenderer object manage it's workspace.
// the idea is to let the BitmapRenderer object manage its workspace.
m_edges.erase (m_edges.begin (), m_edges.end ());
// might be manhattan
m_ortho = true;
@ -427,7 +427,7 @@ BitmapRenderer::draw (const db::Shape &shape, const db::CplxTrans &trans,
db::Box bbox = shape.bbox ();
double threshold = 1.0 / trans.mag ();
if (bbox.width () <= threshold && bbox.height () <= threshold) {
if (bbox.width () <= threshold && bbox.height () <= threshold && !shape.is_point ()) {
db::DPoint dc = trans * bbox.center ();
if (fill && ! shape.is_edge ()) {
@ -440,7 +440,7 @@ BitmapRenderer::draw (const db::Shape &shape, const db::CplxTrans &trans,
render_dot (dc.x (), dc.y (), vertices);
}
} else if (shape.is_box ()) {
} else if (shape.is_box () || shape.is_point ()) {
draw (bbox, trans, fill, frame, vertices, text);

View File

@ -606,7 +606,7 @@ ShapeFinder::visit_cell (const db::Cell &cell, const db::Box &hit_box, const db:
match = true;
}
} else if (shape->is_box () || shape->is_text ()) {
} else if (shape->is_box () || shape->is_point () || shape->is_text ()) {
db::Box box = shape->bbox ();
if (text_info () && shape->is_text ()) {

View File

@ -5297,11 +5297,7 @@ LayoutViewBase::paste_interactive ()
std::unique_ptr<db::Transaction> trans (new db::Transaction (manager (), tl::to_string (tr ("Paste and move"))));
{
// let the receivers sort out who is pasting what ..
do_paste ();
lay::Editables::paste ();
}
lay::Editables::paste ();
// temporarily close the transaction and pass to the move service for appending it's own
// operations.
@ -5314,6 +5310,12 @@ LayoutViewBase::paste_interactive ()
void
LayoutViewBase::copy ()
{
copy_view_objects ();
}
void
LayoutViewBase::copy_view_objects ()
{
cancel_edits ();
if (! lay::Editables::has_selection ()) {

View File

@ -264,6 +264,13 @@ public:
*/
virtual void copy ();
/**
* @brief Copies to clipboard (view objects only)
*
* This version does not look for copy sources in the tree views.
*/
void copy_view_objects ();
/**
* @brief Cuts to clipboard
*

View File

@ -327,6 +327,10 @@ Plugin::~Plugin ()
if (mp_parent) {
mp_parent->unregister_plugin (this);
}
// remove us from the children's parent
for (auto c = m_children.begin (); c != m_children.end (); ++c) {
c->mp_parent = 0;
}
}
void

View File

@ -1059,7 +1059,7 @@ RedrawThreadWorker::any_shapes (db::cell_index_type cell_index, unsigned int lev
int ret = false;
const db::Cell &cell = mp_layout->cell (cell_index);
if (! cell.shapes (m_layer).begin (db::ShapeIterator::Polygons | db::ShapeIterator::Edges | db::ShapeIterator::Paths | db::ShapeIterator::Boxes, mp_prop_sel, m_inv_prop_sel).at_end ()) {
if (! cell.shapes (m_layer).begin (db::ShapeIterator::Polygons | db::ShapeIterator::Edges | db::ShapeIterator::Paths | db::ShapeIterator::Boxes | db::ShapeIterator::Points, mp_prop_sel, m_inv_prop_sel).at_end ()) {
ret = true;
} else if (levels > 1) {
for (db::Cell::child_cell_iterator cc = cell.begin_child_cells (); !cc.at_end () && !ret; ++cc) {
@ -1624,7 +1624,7 @@ RedrawThreadWorker::draw_layer_wo_cache (int from_level, int to_level, db::cell_
size_t current_quad_id = 0;
size_t current_array_quad_id = 0;
db::ShapeIterator shape (shapes.begin_touching (*v, db::ShapeIterator::Boxes | db::ShapeIterator::Polygons | db::ShapeIterator::Edges | db::ShapeIterator::Paths, mp_prop_sel, m_inv_prop_sel));
db::ShapeIterator shape (shapes.begin_touching (*v, db::ShapeIterator::Boxes | db::ShapeIterator::Polygons | db::ShapeIterator::Edges | db::ShapeIterator::Paths | db::ShapeIterator::Points, mp_prop_sel, m_inv_prop_sel));
while (! shape.at_end ()) {
test_snapshot (update_snapshot);

View File

@ -65,6 +65,8 @@ Renderer::draw_propstring (const db::Shape &shape, const db::PropertiesRepositor
dp = trans * (db::Point () + shape.text_trans ().disp ());
} else if (shape.is_box ()) {
dp = trans (shape.box ().p1 ());
} else if (shape.is_point ()) {
dp = trans (shape.point ());
} else if (shape.is_polygon ()) {
db::Shape::polygon_edge_iterator e = shape.begin_edge ();
dp = trans ((*e).p1 ());

View File

@ -598,7 +598,7 @@ private:
const db::Shapes &shapes = cell.shapes (l);
db::ShapeIterator shape = shapes.begin_touching (touch_box, db::ShapeIterator::Polygons | db::ShapeIterator::Paths | db::ShapeIterator::Boxes, mp_prop_sel, m_inv_prop_sel);
db::ShapeIterator shape = shapes.begin_touching (touch_box, db::ShapeIterator::Polygons | db::ShapeIterator::Paths | db::ShapeIterator::Boxes | db::ShapeIterator::Points, mp_prop_sel, m_inv_prop_sel);
while (! shape.at_end () && m_tests > 0) {
--m_tests;
@ -653,6 +653,12 @@ private:
test_edge (t * db::Edge (box.p2 (), db::Point (box.right (), box.bottom ())));
test_edge (t * db::Edge (db::Point (box.right (), box.bottom ()), box.p1 ()));
} else if (shape->is_point ()) {
const db::Point &p = shape->point ();
test_edge (t * db::Edge (p, p));
}
++shape;

View File

@ -216,7 +216,7 @@
<item row="1" column="0" colspan="2">
<widget class="QLabel" name="label">
<property name="text">
<string>If this option is selected, the subcircuits parts of a net are represented by individual cells. Otherwise the net with it's subcircuit parts is exported as a whole (flattened).</string>
<string>If this option is selected, the subcircuits parts of a net are represented by individual cells. Otherwise the net with its subcircuit parts is exported as a whole (flattened).</string>
</property>
<property name="wordWrap">
<bool>true</bool>

View File

@ -344,7 +344,7 @@ Class<BrowserDialog_Stub> decl_BrowserDialog (QT_EXTERNAL_BASE (QDialog) "lay",
"The browser dialog displays HTML code in a browser panel. The HTML code is delivered through a separate "
"object of class \\BrowserSource which acts as a \"server\" for a specific kind of URL scheme. Whenever the "
"browser sees a URL starting with \"int:\" it will ask the connected BrowserSource object for the HTML code "
"of that page using it's 'get' method. The task of the BrowserSource object is to format the data requested "
"of that page using its 'get' method. The task of the BrowserSource object is to format the data requested "
"in HTML and deliver it.\n"
"\n"
"One use case for that class is the implementation of rich data browsers for structured information. In a "
@ -699,7 +699,7 @@ Class<InputDialog> decl_InputDialog ("lay", "InputDialog",
"@param title The title to display for the dialog\n"
"@param label The label text to display for the dialog\n"
"@param value The initial value for the input field\n"
"@return A \\StringValue object with has_value? set to true, if \"Ok\" was pressed and the value given in it's value attribute\n"
"@return A \\StringValue object with has_value? set to true, if \"Ok\" was pressed and the value given in its value attribute\n"
"Starting from 0.22, this method is deprecated and it is recommended to use the ask_... equivalent."
) +
gsi::method ("#get_item", &get_item, gsi::arg ("title"), gsi::arg ("label"), gsi::arg ("items"), gsi::arg ("value"),
@ -708,7 +708,7 @@ Class<InputDialog> decl_InputDialog ("lay", "InputDialog",
"@param label The label text to display for the dialog\n"
"@param items The list of items to show in the selection element\n"
"@param selection The initial selection (index of the element selected initially)\n"
"@return A \\StringValue object with has_value? set to true, if \"Ok\" was pressed and the value given in it's value attribute\n"
"@return A \\StringValue object with has_value? set to true, if \"Ok\" was pressed and the value given in its value attribute\n"
"Starting from 0.22, this method is deprecated and it is recommended to use the ask_... equivalent."
) +
gsi::method ("#get_string_password", &get_string_password, gsi::arg ("title"), gsi::arg ("label"), gsi::arg ("value"),
@ -716,7 +716,7 @@ Class<InputDialog> decl_InputDialog ("lay", "InputDialog",
"@param title The title to display for the dialog\n"
"@param label The label text to display for the dialog\n"
"@param value The initial value for the input field\n"
"@return A \\StringValue object with has_value? set to true, if \"Ok\" was pressed and the value given in it's value attribute\n"
"@return A \\StringValue object with has_value? set to true, if \"Ok\" was pressed and the value given in its value attribute\n"
"Starting from 0.22, this method is deprecated and it is recommended to use the ask_... equivalent."
) +
gsi::method ("#get_double", &get_double, gsi::arg ("title"), gsi::arg ("label"), gsi::arg ("value"), gsi::arg ("digits"),
@ -725,7 +725,7 @@ Class<InputDialog> decl_InputDialog ("lay", "InputDialog",
"@param label The label text to display for the dialog\n"
"@param value The initial value for the input field\n"
"@param digits The number of digits allowed\n"
"@return A \\DoubleValue object with has_value? set to true, if \"Ok\" was pressed and the value given in it's value attribute\n"
"@return A \\DoubleValue object with has_value? set to true, if \"Ok\" was pressed and the value given in its value attribute\n"
"Starting from 0.22, this method is deprecated and it is recommended to use the ask_... equivalent."
) +
gsi::method ("#get_double_ex", &get_double_ex, gsi::arg ("title"), gsi::arg ("label"), gsi::arg ("value"), gsi::arg ("min"), gsi::arg ("max"), gsi::arg ("digits"),
@ -736,7 +736,7 @@ Class<InputDialog> decl_InputDialog ("lay", "InputDialog",
"@param min The minimum value allowed\n"
"@param max The maximum value allowed\n"
"@param digits The number of digits allowed\n"
"@return A \\DoubleValue object with has_value? set to true, if \"Ok\" was pressed and the value given in it's value attribute\n"
"@return A \\DoubleValue object with has_value? set to true, if \"Ok\" was pressed and the value given in its value attribute\n"
"Starting from 0.22, this method is deprecated and it is recommended to use the ask_... equivalent."
) +
gsi::method ("#get_int", &get_int, gsi::arg ("title"), gsi::arg ("label"), gsi::arg ("value"),
@ -744,7 +744,7 @@ Class<InputDialog> decl_InputDialog ("lay", "InputDialog",
"@param title The title to display for the dialog\n"
"@param label The label text to display for the dialog\n"
"@param value The initial value for the input field\n"
"@return A \\IntValue object with has_value? set to true, if \"Ok\" was pressed and the value given in it's value attribute\n"
"@return A \\IntValue object with has_value? set to true, if \"Ok\" was pressed and the value given in its value attribute\n"
"Starting from 0.22, this method is deprecated and it is recommended to use the ask_... equivalent."
) +
gsi::method ("#get_int_ex", &get_int_ex, gsi::arg ("title"), gsi::arg ("label"), gsi::arg ("value"), gsi::arg ("min"), gsi::arg ("max"), gsi::arg ("step"),
@ -755,7 +755,7 @@ Class<InputDialog> decl_InputDialog ("lay", "InputDialog",
"@param min The minimum value allowed\n"
"@param max The maximum value allowed\n"
"@param step The step size for the spin buttons\n"
"@return A \\IntValue object with has_value? set to true, if \"Ok\" was pressed and the value given in it's value attribute\n"
"@return A \\IntValue object with has_value? set to true, if \"Ok\" was pressed and the value given in its value attribute\n"
"Starting from 0.22, this method is deprecated and it is recommended to use the ask_... equivalent."
) +
gsi::method ("ask_string", &ask_string, gsi::arg ("title"), gsi::arg ("label"), gsi::arg ("value"),

View File

@ -84,7 +84,7 @@ HCPCellTreeWidget::HCPCellTreeWidget (QWidget *parent, const char *name, QWidget
HCPCellTreeWidget::~HCPCellTreeWidget ()
{
// NOTE: this should not be required, but I got a strange crash on closing the app with Qt 5.12.8
// after using changePersistentIndex inside the model when ~QTreeWidget tried to clean up it's
// after using changePersistentIndex inside the model when ~QTreeWidget tried to clean up its
// persistent indexes and only found a model which was deleted already.
QAbstractItemModel *m = model ();
if (m) {

View File

@ -735,7 +735,7 @@ void
LayoutViewFunctions::cm_cell_cut ()
{
if (view ()->hierarchy_panel ()) {
// TODO: currently the hierarchy panel's cut function does it's own transaction handling.
// TODO: currently the hierarchy panel's cut function does its own transaction handling.
// Otherwise the cut function is not working propertly.
view ()->hierarchy_panel ()->cut ();
}
@ -1177,7 +1177,7 @@ LayoutViewFunctions::do_cm_duplicate (bool interactive)
db::Clipboard::instance ().swap (saved_clipboard);
try {
view ()->copy ();
view ()->copy_view_objects ();
view ()->clear_selection ();
view ()->cancel ();
if (interactive) {
@ -1873,12 +1873,12 @@ LayoutViewFunctions::cm_edit_layer ()
{
lay::LayerPropertiesConstIterator sel = view ()->current_layer ();
if (sel.is_null ()) {
throw tl::Exception (tl::to_string (tr ("No layer selected for editing it's properties")));
throw tl::Exception (tl::to_string (tr ("No layer selected for editing its properties")));
}
int index = sel->cellview_index ();
if (sel->has_children () || index < 0 || int (view ()->cellviews ()) <= index || sel->layer_index () < 0) {
throw tl::Exception (tl::to_string (tr ("No valid layer selected for editing it's properties")));
throw tl::Exception (tl::to_string (tr ("No valid layer selected for editing its properties")));
}
const lay::CellView &cv = view ()->cellview (index);

View File

@ -1356,7 +1356,7 @@ void
LayoutView::cut ()
{
if (mp_hierarchy_panel && mp_hierarchy_panel->has_focus ()) {
// TODO: currently the hierarchy panel's cut function does it's own transaction handling.
// TODO: currently the hierarchy panel's cut function does its 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 ()) {

View File

@ -328,11 +328,11 @@ gsi::ClassExt<db::LoadLayoutOptions> dxf_reader_options (
"This method has been added in version 0.25.3."
) +
gsi::method_ext ("dxf_keep_other_cells=", &set_dxf_keep_other_cells, gsi::arg ("value"),
"@brief If this option is set to true, all cells are kept, not only the top cell and it's children\n"
"@brief If this option is set to true, all cells are kept, not only the top cell and its children\n"
"\nThis property has been added in version 0.21.15.\n"
) +
gsi::method_ext ("dxf_keep_other_cells?|#dxf_keep_other_cells", &get_dxf_keep_other_cells,
"@brief If this option is true, all cells are kept, not only the top cell and it's children\n"
"@brief If this option is true, all cells are kept, not only the top cell and its children\n"
"\nThis property has been added in version 0.21.15.\n"
) +
gsi::method_ext ("dxf_polyline_mode=", &set_dxf_polyline_mode, gsi::arg ("mode"),

View File

@ -266,7 +266,7 @@
<item row="6" column="1" colspan="3">
<widget class="QCheckBox" name="keep_other_cells_cbx">
<property name="text">
<string>Check this box to keep all cells, not only the top cell and it's children</string>
<string>Check this box to keep all cells, not only the top cell and its children</string>
</property>
</widget>
</item>

View File

@ -37,14 +37,29 @@ namespace db
// -----------------------------------------------------------------------------------
// Path resolution utility
std::string correct_path (const std::string &fn, const db::Layout &layout, const std::string &base_path)
std::string correct_path (const std::string &fn_in, const db::Layout &layout, const std::string &base_path)
{
const db::Technology *tech = layout.technology ();
// Allow LEF reference through expressions, i.e.
// $(base_path) - path of the main file
// $(tech_dir) - the location of the .lyt file if a technology is specified
// $(tech_name) - the name of the technology if one is specified
// In addition expressions are interpolated, e.g. "$(env('HOME'))".
tl::Eval expr;
expr.set_var ("base_path", base_path);
if (tech) {
expr.set_var ("tech_dir", tech->base_path ());
expr.set_var ("tech_name", tech->name ());
}
std::string fn = expr.interpolate (fn_in);
if (! tl::is_absolute (fn)) {
// if a technology is given and the file can be found in the technology's base path, take it
// from there.
const db::Technology *tech = layout.technology ();
if (tech && ! tech->base_path ().empty ()) {
std::string new_fn = tl::combine_path (tech->base_path (), fn);
if (tl::file_exists (new_fn)) {
@ -878,16 +893,18 @@ LEFDEFReaderOptions::special_routing_datatype_str () const
LEFDEFReaderState::LEFDEFReaderState (const LEFDEFReaderOptions *tc, db::Layout &layout, const std::string &base_path)
: mp_importer (0), m_create_layers (true), m_has_explicit_layer_mapping (false), m_laynum (1), mp_tech_comp (tc)
{
if (! tc->map_file ().empty ()) {
if (! tc) {
// use default options
} else if (! tc->map_file ().empty ()) {
read_map_file (tc->map_file (), layout, base_path);
} else {
if (tc) {
m_layer_map = tc->layer_map ();
m_create_layers = tc->read_all_layers ();
}
m_layer_map = tc->layer_map ();
m_create_layers = tc->read_all_layers ();
}
}
@ -992,7 +1009,6 @@ LEFDEFReaderState::read_map_file (const std::string &filename, db::Layout &layou
// build an explicit layer mapping now.
tl_assert (m_has_explicit_layer_mapping);
m_layers.clear ();
m_layer_map.clear ();
@ -1015,9 +1031,12 @@ LEFDEFReaderState::read_single_map_file (const std::string &path, std::map<std::
tl::log << tl::to_string (tr ("Reading LEF/DEF map file")) << " " << file_stream.absolute_path ();
// Purpose name to purpose code
std::map<std::string, LayerPurpose> purpose_translation;
purpose_translation ["LEFPIN"] = LEFPins;
purpose_translation ["PIN"] = Pins;
purpose_translation ["LEFPINNAME"] = LEFLabel;
purpose_translation ["PINNAME"] = Label;
purpose_translation ["FILL"] = Fills;
purpose_translation ["FILLOPC"] = FillsOPC;
purpose_translation ["LEFOBS"] = Obstructions;
@ -1027,6 +1046,11 @@ LEFDEFReaderState::read_single_map_file (const std::string &path, std::map<std::
purpose_translation ["BLOCKAGE"] = Blockage;
purpose_translation ["ALL"] = All;
// List of purposes corresponding to ALL
LayerPurpose all_purposes[] = {
LEFPins, Pins, Fills, FillsOPC, Obstructions, SpecialRouting, Routing, ViaGeometry
};
while (! ts.at_end ()) {
const std::string &l = ts.get_line ();
@ -1214,10 +1238,8 @@ LEFDEFReaderState::read_single_map_file (const std::string &path, std::map<std::
} else if (i->second == All) {
for (std::map<std::string, LayerPurpose>::const_iterator p = purpose_translation.begin (); p != purpose_translation.end (); ++p) {
if (p->second != All && p->second != Blockage) {
translated_purposes.insert (LayerDetailsKey (p->second, mask, via_size));
}
for (LayerPurpose *p = all_purposes; p != all_purposes + sizeof (all_purposes) / sizeof (all_purposes[0]); ++p) {
translated_purposes.insert (LayerDetailsKey (*p, mask, via_size));
}
} else {

View File

@ -540,6 +540,10 @@ TEST(111_mapfile)
options.set_map_file ("test.map");
run_test (_this, "mapfile", "read:in.def", "au.oas.gz", options, false);
options.set_map_file ("test-nonames.map");
run_test (_this, "mapfile", "read:in.def", "au.oas.gz", options, false);
}
TEST(112_via_properties)

View File

@ -456,24 +456,27 @@ public:
std::string name = mt->name (mid);
// does this method hide a property? -> append "_" in that case
std::pair<bool, size_t> t = mt->find_property (mt->is_static (mid), name);
if (t.first) {
name += "_";
}
// needs static/non-static disambiguation?
t = mt->find_method (! mt->is_static (mid), name);
std::pair<bool, size_t> t = mt->find_method (! mt->is_static (mid), name);
if (t.first) {
disambiguated_names.push_back (name);
if (mt->is_static (mid)) {
name = "_class_" + name;
mp_module->add_python_doc (*cls, mt, int (mid), tl::sprintf (tl::to_string (tr ("This class method is available as '%s' in Python")), name));
} else {
name = "_inst_" + name;
mp_module->add_python_doc (*cls, mt, int (mid), tl::sprintf (tl::to_string (tr ("This instance method is available as '%s' in Python")), name));
}
mp_module->add_python_doc (*cls, mt, int (mid), tl::sprintf (tl::to_string (tr ("This attribute is available as '%s' in Python")), name));
} else {
// does this method hide a property? -> append "_" in that case
t = mt->find_property (mt->is_static (mid), name);
if (t.first) {
name += "_";
mp_module->add_python_doc (*cls, mt, int (mid), tl::sprintf (tl::to_string (tr ("This method is available as '%s' in Python to distiguish it from the property with the same name")), name));
}
}

View File

@ -44,17 +44,19 @@ void check_error ()
{
PyObject *py_exc_type = NULL, *py_exc_value = NULL, *py_exc_traceback = NULL;
PyErr_Fetch (&py_exc_type, &py_exc_value, &py_exc_traceback);
PythonRef exc_type (py_exc_type);
PythonRef exc_value (py_exc_value);
PythonRef exc_traceback (py_exc_traceback);
if (py_exc_type != NULL) {
std::string exc_cls ("unknown");
const char *c = ((PyTypeObject *) exc_type.get ())->tp_name;
if (c) {
exc_cls = c;
}
PyErr_NormalizeException (&py_exc_type, &py_exc_value, &py_exc_traceback);
if (exc_type) {
PythonRef exc_type (py_exc_type);
PythonRef exc_value (py_exc_value);
PythonRef exc_traceback (py_exc_traceback);
std::string exc_cls ("unknown");
const char *c = ((PyTypeObject *) exc_type.get ())->tp_name;
if (c) {
exc_cls = c;
}
// fetch traceback
// TODO: really decref the stack trace? how about the other objects in the stack trace?

View File

@ -45,7 +45,7 @@ TEST (basic)
try {
pya::PythonInterpreter::instance ()->eval_string ("raise Exception(\"an error\")");
} catch (tl::ScriptError &ex) {
EXPECT_EQ (ex.basic_msg (), std::string ("an error"));
EXPECT_EQ (ex.basic_msg (), std::string ("Exception: an error"));
EXPECT_EQ (ex.cls () == std::string ("exceptions.Exception") || ex.cls () == std::string ("Exception"), true);
err = true;
}
@ -56,7 +56,7 @@ TEST (basic)
try {
pya::PythonInterpreter::instance ()->eval_string ("Quatsch");
} catch (tl::ScriptError &ex) {
EXPECT_EQ (ex.basic_msg (), std::string ("name 'Quatsch' is not defined"));
EXPECT_EQ (ex.basic_msg (), std::string ("NameError: name 'Quatsch' is not defined"));
EXPECT_EQ (ex.cls () == std::string ("exceptions.NameError") || ex.cls () == std::string ("NameError"), true);
err = true;
}

View File

@ -45,7 +45,7 @@ TEST (basic)
try {
rba::RubyInterpreter::instance ()->eval_string ("raise \"an error\"");
} catch (tl::Exception &ex) {
EXPECT_EQ (std::string (ex.msg (), 0, 8), std::string ("an error"));
EXPECT_EQ (std::string (ex.msg (), 0, 22), std::string ("RuntimeError: an error"));
err = true;
}
@ -56,8 +56,8 @@ TEST (basic)
try {
rba::RubyInterpreter::instance ()->eval_string ("Quatsch");
} catch (tl::Exception &ex) {
EXPECT_EQ (std::string (ex.msg (), 0, 30) == std::string ("uninitialized constant Quatsch") ||
std::string (ex.msg (), 0, 38) == std::string ("uninitialized constant Object::Quatsch"),
EXPECT_EQ (std::string (ex.msg (), 0, 41) == std::string ("NameError: uninitialized constant Quatsch") ||
std::string (ex.msg (), 0, 49) == std::string ("NameError: uninitialized constant Object::Quatsch"),
true);
err = true;
}

View File

@ -184,7 +184,7 @@ Class<rdb::Cell> decl_RdbCell ("rdb", "RdbCell",
"@brief Gets the cell name\n"
"The cell name is an string that identifies the category in the database. "
"Additionally, a cell may carry a variant identifier which is a string that uniquely identifies a cell "
"in the context of it's variants. The \"qualified name\" contains both the cell name and the variant name. "
"in the context of its variants. The \"qualified name\" contains both the cell name and the variant name. "
"Cell names are also used to identify report database cell's with layout cells. "
"@return The cell name\n"
) +
@ -347,7 +347,7 @@ Class<rdb::Category> decl_RdbCategory ("rdb", "RdbCategory",
) +
gsi::method_ext ("scan_layer", &scan_layer, gsi::arg ("layout"), gsi::arg ("layer"), gsi::arg ("cell", (const db::Cell *) 0, "nil"), gsi::arg ("levels", -1), gsi::arg ("with_properties", true),
"@brief Scans a layer from a layout into this category, starting with a given cell and a depth specification\n"
"Creates RDB items for each polygon or edge shape read from the cell and it's children in the layout on the given layer and puts them into this category.\n"
"Creates RDB items for each polygon or edge shape read from the cell and its children in the layout on the given layer and puts them into this category.\n"
"New cells will be generated when required.\n"
"\"levels\" is the number of hierarchy levels to take the child cells from. 0 means to use only \"cell\" and don't descend, -1 means \"all levels\".\n"
"Other settings like database unit, description, top cell etc. are not made in the RDB.\n"
@ -1031,7 +1031,7 @@ Class<rdb::Database> decl_ReportDatabase ("rdb", "ReportDatabase",
) +
gsi::method ("description", &rdb::Database::description,
"@brief Gets the databases description\n"
"The description is a general purpose string that is supposed to further describe the database and it's content "
"The description is a general purpose string that is supposed to further describe the database and its content "
"in a human-readable form.\n"
"@return The description string\n"
) +

View File

@ -79,14 +79,30 @@ BacktraceElement::to_string() const
// -------------------------------------------------------------------
// ScriptError implementation
static std::string make_basic_msg (const char *text, const char *cls)
{
std::string msg;
if (*cls) {
msg = cls;
}
if (*cls && *text) {
msg += ": ";
}
if (*text) {
msg += text;
}
return msg;
}
ScriptError::ScriptError (const char *msg, const char *cls, const std::vector<BacktraceElement> &backtrace)
: tl::Exception (msg), m_line (-1), m_cls (cls), m_backtrace (backtrace)
: tl::Exception (make_basic_msg (msg, cls)), m_line (-1), m_cls (cls), m_backtrace (backtrace)
{
// .. nothing yet ..
}
ScriptError::ScriptError (const char *msg, const char *sourcefile, int line, const char *cls, const std::vector<BacktraceElement> &backtrace)
: tl::Exception (msg), m_sourcefile (sourcefile), m_line (line), m_cls (cls), m_backtrace (backtrace)
: tl::Exception (make_basic_msg (msg, cls)), m_sourcefile (sourcefile), m_line (line), m_cls (cls), m_backtrace (backtrace)
{
translate_includes ();
}
@ -103,8 +119,8 @@ ScriptError::msg () const
std::string m = basic_msg ();
if (! m_context.empty ()) {
m += tl::to_string (tr (" in ")) + m_context;
}
m += tl::to_string (tr (" in ")) + m_context;
}
for (std::vector<BacktraceElement>::const_iterator bt = backtrace ().begin (); bt != backtrace ().end (); ++bt) {
m += "\n ";

27
testdata/drc/drcSimpleTests_14c.drc vendored Normal file
View File

@ -0,0 +1,27 @@
lyin = layout($drc_test_source)
cn = lyin.layout.top_cell.name
lyin2 = layout($drc_test_source)
target($drc_test_target, cn)
l1 = lyin.input(1, 0)
l2 = lyin2.input(2, 0)
tcopy = new_target($drc_test_target2, cn)
rcopy = new_report("Report 2", $drc_test_report2, cn)
l1.output(tcopy, 101, 0)
l2.output(tcopy, 102, 0)
l1.output(1, 0)
l1.space(1.0.um).output(100, 0)
report("Report 1", $drc_test_report, cn)
l2.space(1.0.um).output("l2 space < 1µm")
l1.width(1.0.um).output("l1 width < 1µm")
l1.sep(l2, 1.0.um).output(rcopy, "l1 sep l2 < 1µm")

View File

@ -0,0 +1,19 @@
DIEAREA ALL 100 0
M0PO LEFPIN,LEFOBS,PIN,NET,SPNET,VIA 10 0
VIA0 LEFPIN,LEFOBS,VIA,PIN,NET,SPNET 11 0
M1 LEFPIN 12 0
M1 LEFOBS 12 1
M1 PIN 12 2
M1 NET 12 3
M1 SPNET 12 4
M1 VIA 12 5
M1 FILLOPC 12 100
M1 FILLOPC:MASK:1 12 101
M1 FILLOPC:MASK:2 12 102
M1 BLOCKAGEFILL 12 150
M1 BLOCKAGE 12 151
M1 FILL 12 152
M1 PINNAME 12 10
M1 LEFPINNAME 12 10
VIA1 LEFPIN,LEFOBS,VIA,PIN,NET,SPNET 13 0
M2 LEFPIN,LEFOBS,PIN,NET,SPNET,VIA 14 0