Merge pull request #1175 from KLayout/wip

Wip
This commit is contained in:
Matthias Köfferlein 2022-11-06 09:11:38 +01:00 committed by GitHub
commit 4a80a10a2d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
52 changed files with 1810 additions and 372 deletions

View File

@ -157,6 +157,53 @@ It is supposed to adjust parameters to render a consistent parameter set and to
parameter range errors. This method is called for example inside the PCell user interface to
compute the actual parameters when "Apply" is pressed.
@method callback_impl(name)
@brief Provides a callback on a parameter change
This method applies to user interface changes only. Whenever a parameter is changed
on the parameter page, this method is called with the name of the parameter.
On some occasions, this method called to establish a configuration unspecifically.
In this case, the name is an empty string - indicating "all parameters may have changed".
This method can change the state of this or any other parameter. For this, the
state objects are supplied instead of the parameter values. For example to enable
parameter "b" when a boolean parameter "a" is true, use the following code:
@code
def callback_impl(name)
if name == "a" || name == ""
b.enabled = a.value
end
end
@/code
The "enabled" attribute of the \\PCellParameterState object indicates whether the
parameter is enabled in the user interface. "a.value" delivers the value of the
(boolean type assumed) parameter "a".
Note that the above code also checks for empty name to consider the case of a
global refresh.
Further useful attributes of the parameters are:
@ul
@li
@b enabled @/b: the parameter entry is grayed out if false
@/li
@li
@b readonly @/b: the parameter cannot be edited (less strict than enabled)
@/li
@li
@b visible @/b: the parameter entry is not visible if false
@/li
@li
@b icon @/b: Sets an icon in front of the parameter indicating an error or a
warning (use \\PCellParameterState#WarningIcon or \\PCellParameterState#ErrorIcon).
@/li
@/ul
@method can_create_from_shape_impl
@brief Returns true if the PCell can be created from the given shape
@ -227,12 +274,13 @@ module RBA
def initialize
@param_decls = []
@param_values = nil
@param_states = nil
@layout = nil
@shape = nil
@layer = nil
@cell = nil
@layer_param_index = []
@layers = []
@layers = nil
end
# provide accessors for the current layout and cell (for prod)
@ -244,6 +292,40 @@ module RBA
def _layout; @layout; end
def _cell; @cell; end
def _shape; @shape; end
# A helper method to access the nth parameter
def _get_param(nth, name)
if @param_states
if ! @param_states.has_parameter?(name)
return RBA::PCellParameterState::new
else
return @param_states.parameter(name)
end
else
@param_values || raise("No parameters available.")
while @param_values.size <= nth
@param_values << nil
end
return @param_values[nth]
end
end
# A helper method to set the nth parameter
def _set_param(nth, value)
@param_values || raise("Cannot set parameter - inside 'callback_impl' use 'param_name.value = ...' to set the parameter's value.")
if @param_values.size > nth
@param_values[nth] = value
end
end
# A helper method to access the nth layer
def _get_layer(nth)
@layers || raise("No layer index available - layers can be used only inside 'produce_impl'.")
@layers[nth]
end
# define a parameter
# name -> the short name of the parameter
@ -267,14 +349,18 @@ module RBA
# param_{name}_layer
def param(name, type, description, args = {})
if name !~ /^[_A-Za-z]\w*$/
raise "Invalid parameter name #{name} (needs to be a word)"
end
# create accessor methods for the parameters
param_index = @param_decls.length
self.instance_eval("def #{name.to_s}; @param_values[#{param_index}]; end")
self.instance_eval("def set_#{name.to_s}(v); @param_values[#{param_index}] = v; end")
self.instance_eval("def #{name.to_s}=(v); @param_values[#{param_index}] = v; end")
self.instance_eval("def #{name.to_s}; self._get_param(#{param_index}, '#{name}'); end")
self.instance_eval("def set_#{name.to_s}(v); self._set_param(#{param_index}, v); end")
self.instance_eval("def #{name.to_s}=(v); self._set_param(#{param_index}, v); end")
if type == TypeLayer
self.instance_eval("def #{name.to_s}_layer; @layers[#{@layer_param_index.length}]; end")
self.instance_eval("def #{name.to_s}_layer; self._get_layer(#{@layer_param_index.length}); end")
@layer_param_index.push(param_index)
end
@ -307,8 +393,11 @@ module RBA
# implementation of display_text
def display_text(parameters)
@param_values = parameters
text = display_text_impl
@param_values = nil
begin
text = display_text_impl
ensure
@param_values = nil
end
text
end
@ -326,9 +415,28 @@ module RBA
def coerce_parameters(layout, parameters)
@param_values = parameters
@layout = layout
coerce_parameters_impl
@layout = nil
@param_values
ret = parameters
begin
coerce_parameters_impl
ensure
@layout = nil
ret = @param_values
@param_values = nil
end
ret
end
# parameter change callback
def callback(layout, name, states)
@param_values = nil
@param_states = states
@layout = layout
begin
callback_impl(name)
ensure
@param_states = nil
@layout = nil
end
end
# produce the layout
@ -337,22 +445,29 @@ module RBA
@cell = cell
@param_values = parameters
@layout = layout
produce_impl
@layers = nil
@cell = nil
@param_values = nil
@layout = nil
begin
produce_impl
ensure
@layers = nil
@cell = nil
@param_values = nil
@layout = nil
end
end
# produce a helper for can_create_from_shape
def can_create_from_shape(layout, shape, layer)
ret = false
@layout = layout
@shape = shape
@layer = layer
ret = can_create_from_shape_impl
@layout = nil
@shape = nil
@layer = nil
begin
ret = can_create_from_shape_impl
ensure
@layout = nil
@shape = nil
@layer = nil
end
ret
end
@ -361,10 +476,13 @@ module RBA
@layout = layout
@shape = shape
@layer = layer
t = transformation_from_shape_impl
@layout = nil
@shape = nil
@layer = nil
begin
t = transformation_from_shape_impl
ensure
@layout = nil
@shape = nil
@layer = nil
end
t
end
@ -375,10 +493,13 @@ module RBA
@layout = layout
@shape = shape
@layer = layer
parameters_from_shape_impl
@layout = nil
@shape = nil
@layer = nil
begin
parameters_from_shape_impl
ensure
@layout = nil
@shape = nil
@layer = nil
end
@param_values
end
@ -391,6 +512,10 @@ module RBA
def coerce_parameters_impl
end
# default implementation
def callback_impl(name)
end
# default implementation
def produce_impl
end

View File

@ -162,6 +162,51 @@ It is supposed to adjust parameters to render a consistent parameter set and to
parameter range errors. This method is called for example inside the PCell user interface to
compute the actual parameters when "Apply" is pressed.
@method callback_impl(name)
@brief Provides a callback on a parameter change
This method applies to user interface changes only. Whenever a parameter is changed
on the parameter page, this method is called with the name of the parameter.
On some occasions, this method called to establish a configuration unspecifically.
In this case, the name is an empty string - indicating "all parameters may have changed".
This method can change the state of this or any other parameter. For this, the
state objects are supplied instead of the parameter values. For example to enable
parameter "b" when a boolean parameter "a" is true, use the following code:
@code
def callback_impl(self, name):
if name == "a" or name == "":
b.enabled = a.value
@/code
The "enabled" attribute of the \\PCellParameterState object indicates whether the
parameter is enabled in the user interface. "a.value" delivers the value of the
(boolean type assumed) parameter "a".
Note that the above code also checks for empty name to consider the case of a
global refresh.
Further useful attributes of the parameters are:
@ul
@li
@b enabled @/b: the parameter entry is grayed out if false
@/li
@li
@b readonly @/b: the parameter cannot be edited (less strict than enabled)
@/li
@li
@b visible @/b: the parameter entry is not visible if false
@/li
@li
@b icon @/b: Sets an icon in front of the parameter indicating an error or a
warning (use \\PCellParameterState#WarningIcon or \\PCellParameterState#ErrorIcon).
@/li
@/ul
@method can_create_from_shape_impl
@brief Returns true if the PCell can be created from the given shape
@ -232,13 +277,16 @@ class _PCellDeclarationHelperParameterDescriptor(object):
the descriptor acts as a value holder (self.value)
"""
def __init__(self, param_index):
def __init__(self, param_index, param_name):
self.param_index = param_index
self.param_name = param_name
self.value = None
def __get__(self, obj, type = None):
if obj._param_values:
return obj._param_values[self.param_index]
elif obj._param_states:
return obj._param_states.parameter(self.param_name)
else:
return self.value
@ -261,6 +309,7 @@ class _PCellDeclarationHelper(pya.PCellDeclaration):
# "private" attributes
self._param_decls = []
self._param_values = None
self._param_states = None
self._layer_param_index = []
self._layers = []
# public attributes
@ -290,7 +339,7 @@ class _PCellDeclarationHelper(pya.PCellDeclaration):
# create accessor methods for the parameters
param_index = len(self._param_decls)
setattr(type(self), name, _PCellDeclarationHelperParameterDescriptor(param_index))
setattr(type(self), name, _PCellDeclarationHelperParameterDescriptor(param_index, name))
if value_type == type(self).TypeLayer:
setattr(type(self), name + "_layer", _PCellDeclarationHelperLayerDescriptor(len(self._layer_param_index)))
@ -323,8 +372,10 @@ class _PCellDeclarationHelper(pya.PCellDeclaration):
implementation of display_text
"""
self._param_values = parameters
text = self.display_text_impl()
self._param_values = None
try:
text = self.display_text_impl()
finally:
self._param_values = None
return text
def get_parameters(self):
@ -341,7 +392,7 @@ class _PCellDeclarationHelper(pya.PCellDeclaration):
self._param_values = None
return v
def init_values(self, values = None, layers = None):
def init_values(self, values = None, layers = None, states = None):
"""
initializes the temporary parameter values
"values" are the original values. If "None" is given, the
@ -349,7 +400,11 @@ class _PCellDeclarationHelper(pya.PCellDeclaration):
"layers" are the layer indexes corresponding to the layer
parameters.
"""
if not values:
self._param_values = None
self._param_states = None
if states:
self._param_states = states
elif not values:
self._param_values = []
for pd in self._param_decls:
self._param_values.append(pd.default)
@ -359,29 +414,48 @@ class _PCellDeclarationHelper(pya.PCellDeclaration):
def finish(self):
"""
Needs to be called at the end of produce() after init_values was used
Needs to be called at the end of an implementation
"""
self._param_values = None
self._param_states = None
self._layers = None
self._cell = None
self._layout = None
self._layer = None
self._shape = None
def get_layers(self, parameters):
"""
get the layer definitions
gets the layer definitions
"""
layers = []
for i in self._layer_param_index:
layers.append(parameters[i])
return layers
def callback(self, layout, name, states):
"""
callback (change state on parameter change)
"""
self.init_values(states = states)
self.layout = layout
try:
self.callback_impl(name)
finally:
self.finish()
def coerce_parameters(self, layout, parameters):
"""
coerce parameters (make consistent)
"""
self.init_values(parameters)
self.layout = layout
self.coerce_parameters_impl()
self.layout = None
return self.get_values()
try:
self.coerce_parameters_impl()
parameters = self.get_values()
finally:
self.finish()
return parameters
def produce(self, layout, layers, parameters, cell):
"""
@ -390,10 +464,10 @@ class _PCellDeclarationHelper(pya.PCellDeclaration):
self.init_values(parameters, layers)
self.cell = cell
self.layout = layout
self.produce_impl()
self.cell = None
self.layout = None
self.finish()
try:
self.produce_impl()
finally:
self.finish()
def can_create_from_shape(self, layout, shape, layer):
"""
@ -402,10 +476,10 @@ class _PCellDeclarationHelper(pya.PCellDeclaration):
self.layout = layout
self.shape = shape
self.layer = layer
ret = self.can_create_from_shape_impl()
self.layout = None
self.shape = None
self.layer = None
try:
ret = self.can_create_from_shape_impl()
finally:
self.finish()
return ret
def transformation_from_shape(self, layout, shape, layer):
@ -415,10 +489,10 @@ class _PCellDeclarationHelper(pya.PCellDeclaration):
self.layout = layout
self.shape = shape
self.layer = layer
t = self.transformation_from_shape_impl()
self.layout = None
self.shape = None
self.layer = None
try:
t = self.transformation_from_shape_impl()
finally:
self.finish()
return t
def parameters_from_shape(self, layout, shape, layer):
@ -430,11 +504,11 @@ class _PCellDeclarationHelper(pya.PCellDeclaration):
self.layout = layout
self.shape = shape
self.layer = layer
self.parameters_from_shape_impl()
param = self.get_values()
self.layout = None
self.shape = None
self.layer = None
try:
self.parameters_from_shape_impl()
param = self.get_values()
finally:
self.finish()
return param
def display_text_impl(self):
@ -449,6 +523,12 @@ class _PCellDeclarationHelper(pya.PCellDeclaration):
"""
pass
def callback_impl(self, name):
"""
default implementation
"""
pass
def produce_impl(self):
"""
default implementation

View File

@ -795,6 +795,8 @@ Layout::delete_cells (const std::set<cell_index_type> &cells_to_delete)
}
}
db::LayoutLocker locker (this);
// Clear all instances
for (std::set<cell_index_type>::const_iterator c = cells_to_delete.begin (); c != cells_to_delete.end (); ++c) {

View File

@ -1414,7 +1414,7 @@ get_merged_shapes_of_net (const db::hier_clusters<db::NetShape> &clusters, db::c
db::PolygonRef::polygon_edge_iterator e = pr.begin_edge ();
if (! e.at_end ()) {
// pick one reference point for the label
if (! any_ref && (*e).p1 () < ref) {
if (! any_ref || (*e).p1 () < ref) {
ref = (*e).p1 ();
any_ref = true;
}

View File

@ -27,6 +27,80 @@
namespace db
{
// -----------------------------------------------------------------------------------------
// ParameterStates implementation
ParameterStates::ParameterStates ()
: m_states ()
{
// .. nothing yet ..
}
ParameterStates::ParameterStates (const ParameterStates &other)
: m_states (other.m_states)
{
// .. nothing yet ..
}
ParameterStates::ParameterStates (ParameterStates &&other)
: m_states (std::move (other.m_states))
{
// .. nothing yet ..
}
ParameterStates &
ParameterStates::operator= (const ParameterStates &other)
{
if (this != &other) {
m_states = other.m_states;
}
return *this;
}
void
ParameterStates::set_parameter (const std::string &name, const ParameterState &ps)
{
m_states [name] = ps;
}
ParameterState &
ParameterStates::parameter (const std::string &name)
{
return m_states [name];
}
const ParameterState &
ParameterStates::parameter (const std::string &name) const
{
auto i = m_states.find (name);
if (i == m_states.end ()) {
static ParameterState empty;
return empty;
} else {
return i->second;
}
}
bool
ParameterStates::has_parameter (const std::string &name) const
{
return m_states.find (name) != m_states.end ();
}
bool
ParameterStates::values_are_equal (const db::ParameterStates &other) const
{
auto i = m_states.begin (), j = other.m_states.begin ();
while (i != m_states.end () && j != other.m_states.end () && i->first == j->first && i->second.value () == j->second.value ()) {
++i; ++j;
}
return i == m_states.end () && j == other.m_states.end ();
}
// -----------------------------------------------------------------------------------------
// PCellDeclaration implementation
PCellDeclaration::PCellDeclaration ()
: m_ref_count (0), m_id (0), mp_layout (0), m_has_parameter_declarations (false)
{

View File

@ -61,6 +61,7 @@ public:
t_layer, // a layer (value is a db::LayerProperties object)
t_shape, // a shape (a db::Point, db::Box, db::Polygon, db::Edge or db::Path) rendering a guiding shape
t_list, // a list of strings
t_callback, // callback only (button)
t_none // no specific type
};
@ -323,6 +324,193 @@ public:
std::string symbolic;
};
/**
* @brief Represents the dynamic state of a single parameter
*/
class DB_PUBLIC ParameterState
{
public:
/**
* @brief A enum describing the icon type
*/
enum Icon {
NoIcon = 0,
InfoIcon = 1,
ErrorIcon = 2,
WarningIcon = 3
};
/**
* @brief Parameterized constructor
*/
ParameterState ()
: m_value (), m_visible (true), m_enabled (true), m_readonly (false), m_icon (NoIcon)
{
// .. nothing yet ..
}
/**
* @brief Gets the value
*/
const tl::Variant &value () const
{
return m_value;
}
/**
* @brief Sets the value
*/
void set_value (const tl::Variant &v)
{
m_value = v;
}
/**
* @brief Gets the visibility state
*/
bool is_visible () const
{
return m_visible;
}
/**
* @brief Sets the visibility
*/
void set_visible (bool v)
{
m_visible = v;
}
/**
* @brief Gets the enabled state
*/
bool is_enabled () const
{
return m_enabled;
}
/**
* @brief Sets the enabled state
*/
void set_enabled (bool v)
{
m_enabled = v;
}
/**
* @brief Gets a value indicating whether the parameter is read-only
*/
bool is_readonly () const
{
return m_readonly;
}
/**
* @brief Sets a value indicating whether the parameter is read-only
*/
void set_readonly (bool f)
{
m_readonly = f;
}
/**
* @brief Gets the tooltip for the parameter
*/
const std::string &tooltip () const
{
return m_tooltip;
}
/**
* @brief Sets the tooltip
*/
void set_tooltip (const std::string &s)
{
m_tooltip = s;
}
/**
* @brief Gets the icon
*/
Icon icon () const
{
return m_icon;
}
/**
* @brief Sets the icon
*/
void set_icon (Icon i)
{
m_icon = i;
}
private:
tl::Variant m_value;
bool m_visible, m_enabled, m_readonly;
std::string m_tooltip;
Icon m_icon;
};
/**
* @brief Represents the state of call parameters for the callback implementation
*/
class DB_PUBLIC ParameterStates
{
public:
/**
* @brief Default constructor
*/
ParameterStates ();
/**
* @brief Copy constructor
*/
ParameterStates (const ParameterStates &other);
/**
* @brief Move constructor
*/
ParameterStates (ParameterStates &&other);
/**
* @brief Assignment
*/
ParameterStates &operator= (const ParameterStates &other);
/**
* @brief Sets a parameter from a given state
*/
void set_parameter (const std::string &name, const ParameterState &ps);
/**
* @brief Gets the parameter state for the parameter with the given name
*
* If the name is not a valid parameter name, the behavior is undefined.
*/
ParameterState &parameter (const std::string &name);
/**
* @brief Gets the parameter state for the parameter with the given name
*
* If the name is not a valid parameter name, the behavior is undefined.
*/
const ParameterState &parameter (const std::string &name) const;
/**
* @brief Gets a value indicating whether a parameter with that name is present
*/
bool has_parameter (const std::string &name) const;
/**
* @brief Returns true, if the values of the parameter states are equal
*/
bool values_are_equal (const db::ParameterStates &other) const;
public:
std::map<std::string, ParameterState> m_states;
};
/**
* @brief A declaration for a PCell
*/
@ -374,7 +562,25 @@ public:
}
/**
* @brief Produce a layout for the given parameter set and using the given layers.
* @brief Callback on parameter change
*
* This method allows implementing dynamic behavior on the change of a parameter value.
* A ParameterStatus object is supplied that allows changing parameter enabled status, visibility and value.
* The callback also acts as receiver for t_callback type parameters which only present a button.
*
* The callback function receives the name of the parameter that was changed.
* On some occasions, the callback is called unspecifically, for example for the initialization.
* In that case, the parameter name is empty.
*
* Exceptions from this implementation are ignored.
*/
virtual void callback (const db::Layout & /*layout*/, const std::string & /*name*/, ParameterStates & /*states*/) const
{
// the default implementation does nothing
}
/**
* @brief Produces a layout for the given parameter set and using the given layers.
*
* A reimplementation of that method should produce the desired layout for the given parameter set.
* The layout shall be put into the given cell. This code may create cell instances to other cells

View File

@ -124,6 +124,11 @@ public:
*/
virtual void put (const db::Edge &e);
/**
* @brief Implementation of the EdgeSink interface
*/
virtual void put (const db::Edge & /*e*/, int /*tag*/) { }
/**
* @brief Sets the way how holes are resolved dynamically
*
@ -261,6 +266,11 @@ public:
*/
virtual void put (const db::Edge &e);
/**
* @brief Implementation of the EdgeSink interface
*/
virtual void put (const db::Edge & /*e*/, int /*tag*/) { }
private:
db::Coord m_y;
PolygonSink *mp_psink;

View File

@ -911,6 +911,7 @@ class ErrorCatchingEdgeSink
// TODO: we should not use exceptions to indicate a condition, but right now, there is no good alternative
// and this is considered an error anyway.
virtual void put (const db::Edge &) { throw OddPolygonException (); }
virtual void put (const db::Edge &, int) { }
virtual void crossing_edge (const db::Edge &) { throw OddPolygonException (); }
};

View File

@ -248,6 +248,26 @@ public:
end_edge_differences_event ();
}
virtual void begin_edge_pair_differences ()
{
begin_edge_pair_differences_event ();
}
virtual void detailed_diff (const db::PropertiesRepository & /*pr*/, const std::vector <std::pair <db::EdgePair, db::properties_id_type> > &a, const std::vector <std::pair <db::EdgePair, db::properties_id_type> > &b)
{
for (std::vector <std::pair <db::EdgePair, db::properties_id_type> >::const_iterator i = a.begin (); i != a.end (); ++i) {
edge_pair_in_a_only_event (i->first, i->second);
}
for (std::vector <std::pair <db::EdgePair, db::properties_id_type> >::const_iterator i = b.begin (); i != b.end (); ++i) {
edge_pair_in_b_only_event (i->first, i->second);
}
}
virtual void end_edge_pair_differences ()
{
end_edge_pair_differences_event ();
}
virtual void begin_text_differences ()
{
begin_text_differences_event ();
@ -353,6 +373,10 @@ public:
tl::event<const db::Edge & /*anotb*/, db::properties_id_type /*prop_id*/> edge_in_a_only_event;
tl::event<const db::Edge & /*bnota*/, db::properties_id_type /*prop_id*/> edge_in_b_only_event;
tl::Event end_edge_differences_event;
tl::Event begin_edge_pair_differences_event;
tl::event<const db::EdgePair & /*anotb*/, db::properties_id_type /*prop_id*/> edge_pair_in_a_only_event;
tl::event<const db::EdgePair & /*bnota*/, db::properties_id_type /*prop_id*/> edge_pair_in_b_only_event;
tl::Event end_edge_pair_differences_event;
tl::Event begin_text_differences_event;
tl::event<const db::Text & /*anotb*/, db::properties_id_type /*prop_id*/> text_in_a_only_event;
tl::event<const db::Text & /*bnota*/, db::properties_id_type /*prop_id*/> text_in_b_only_event;
@ -671,6 +695,29 @@ gsi::Class<LayoutDiff> decl_LayoutDiff ("db", "LayoutDiff",
gsi::event ("on_end_edge_differences", &LayoutDiff::end_edge_differences_event,
"@brief This signal indicates the end of sequence of edge differences\n"
) +
gsi::event ("on_begin_edge_pair_differences", &LayoutDiff::begin_edge_pair_differences_event,
"@brief This signal indicates differences in the edge pairs on the current layer\n"
"The current layer is indicated by the \\begin_layer_event signal or can be obtained from the diff object "
"through \\LayoutDiff#layer_info_a, \\LayoutDiff#layer_index_a, \\LayoutDiff#layer_info_b and \\LayoutDiff#layer_index_b. "
"In verbose mode (see \\Verbose flag) more signals will be emitted for edge pairs that are different between the two layouts."
"\n"
"This event has been introduced in version 0.28."
) +
gsi::event ("on_edge_pair_in_a_only", &LayoutDiff::edge_pair_in_a_only_event, gsi::arg ("anotb"), gsi::arg ("prop_id"),
"@brief This signal indicates an edge pair that is present in the first layout only"
"\n"
"This event has been introduced in version 0.28."
) +
gsi::event ("on_edge_pair_in_b_only", &LayoutDiff::edge_pair_in_b_only_event, gsi::arg ("bnota"), gsi::arg ("prop_id"),
"@brief This signal indicates an edge pair that is present in the second layout only"
"\n"
"This event has been introduced in version 0.28."
) +
gsi::event ("on_end_edge_pair_differences", &LayoutDiff::end_edge_pair_differences_event,
"@brief This signal indicates the end of sequence of edge pair differences\n"
"\n"
"This event has been introduced in version 0.28."
) +
gsi::event ("on_begin_text_differences", &LayoutDiff::begin_text_differences_event,
"@brief This signal indicates differences in the texts on the current layer\n"
"The current layer is indicated by the \\begin_layer_event signal or can be obtained from the diff object "

View File

@ -23,6 +23,7 @@
#include "gsiDecl.h"
#include "gsiEnums.h"
#include "dbLayout.h"
#include "dbLibrary.h"
#include "dbPCellDeclaration.h"
@ -276,15 +277,16 @@ static db::pcell_parameters_type coerce_parameters_native (const db::PCellDeclar
// Provide a binding for db::PCellDeclaration for native PCell implementations
Class<db::PCellDeclaration> decl_PCellDeclaration_Native ("db", "PCellDeclaration_Native",
gsi::method_ext ("get_layers", &get_layer_declarations_native) +
gsi::method_ext ("get_layers", &get_layer_declarations_native, gsi::arg ("parameters")) +
gsi::method ("get_parameters", &db::PCellDeclaration::get_parameter_declarations) +
gsi::method ("produce", &db::PCellDeclaration::produce) +
gsi::method_ext ("coerce_parameters", &coerce_parameters_native) +
gsi::method ("can_create_from_shape", &db::PCellDeclaration::can_create_from_shape) +
gsi::method ("parameters_from_shape", &db::PCellDeclaration::parameters_from_shape) +
gsi::method ("transformation_from_shape", &db::PCellDeclaration::transformation_from_shape) +
gsi::method ("produce", &db::PCellDeclaration::produce, gsi::arg ("layout"), gsi::arg ("layers"), gsi::arg ("parameters"), gsi::arg ("cell")) +
gsi::method ("callback", &db::PCellDeclaration::callback, gsi::arg ("layout"), gsi::arg ("name"), gsi::arg ("states")) +
gsi::method_ext ("coerce_parameters", &coerce_parameters_native, gsi::arg ("layout"), gsi::arg ("parameters")) +
gsi::method ("can_create_from_shape", &db::PCellDeclaration::can_create_from_shape, gsi::arg ("layout"), gsi::arg ("shape"), gsi::arg ("layer")) +
gsi::method ("parameters_from_shape", &db::PCellDeclaration::parameters_from_shape, gsi::arg ("layout"), gsi::arg ("shape"), gsi::arg ("layer")) +
gsi::method ("transformation_from_shape", &db::PCellDeclaration::transformation_from_shape, gsi::arg ("layout"), gsi::arg ("shape"), gsi::arg ("layer")) +
gsi::method ("wants_lazy_evaluation", &db::PCellDeclaration::wants_lazy_evaluation) +
gsi::method ("display_text", &db::PCellDeclaration::get_display_name) +
gsi::method ("display_text", &db::PCellDeclaration::get_display_name, gsi::arg ("parameters")) +
gsi::method ("layout", &db::PCellDeclaration::layout,
"@brief Gets the Layout object the PCell is registered in or nil if it is not registered yet.\n"
"This attribute has been added in version 0.27.5."
@ -299,6 +301,97 @@ Class<db::PCellDeclaration> decl_PCellDeclaration_Native ("db", "PCellDeclaratio
"@hide\n@alias PCellDeclaration\n"
);
// Provide a binding for db::ParameterState for native PCell implementations
Class<db::ParameterState> decl_PCellParameterState ("db", "PCellParameterState",
gsi::method("value=", &db::ParameterState::set_value, gsi::arg ("v"),
"@brief Sets the value of the parameter\n"
) +
gsi::method("value", &db::ParameterState::value,
"@brief Gets the value of the parameter\n"
) +
gsi::method("visible=", &db::ParameterState::set_visible, gsi::arg ("f"),
"@brief Sets a value indicating whether the parameter is visible in the parameter form\n"
) +
gsi::method("is_visible?", &db::ParameterState::is_visible,
"@brief Gets a value indicating whether the parameter is visible in the parameter form\n"
) +
gsi::method("enabled=", &db::ParameterState::set_enabled, gsi::arg ("f"),
"@brief Sets a value indicating whether the parameter is enabled in the parameter form\n"
) +
gsi::method("is_enabled?", &db::ParameterState::is_enabled,
"@brief Gets a value indicating whether the parameter is enabled in the parameter form\n"
) +
gsi::method("readonly=", &db::ParameterState::set_readonly, gsi::arg ("f"),
"@brief Sets a value indicating whether the parameter is made read-only (not editable) in the parameter form\n"
) +
gsi::method("is_readonly?", &db::ParameterState::is_readonly,
"@brief Gets a value indicating whether the parameter is read-only (not editable) in the parameter form\n"
) +
gsi::method("tooltip=", &db::ParameterState::set_tooltip, gsi::arg ("s"),
"@brief Sets the tool tip text\n"
"\n"
"The tool tip is shown when hovering over the parameter label or edit field."
) +
gsi::method("tooltip", &db::ParameterState::tooltip,
"@brief Gets the tool tip text\n"
) +
gsi::method("icon=", &db::ParameterState::set_icon, gsi::arg ("i"),
"@brief Sets the icon for the parameter\n"
) +
gsi::method("tooltip", &db::ParameterState::tooltip,
"@brief Gets the icon for the parameter\n"
),
"@brief Provides access to the attributes of a single parameter within \\PCellParameterStates.\n"
"\n"
"See \\PCellParameterStates for details about this feature.\n"
"\n"
"This class has been introduced in version 0.28."
);
gsi::EnumIn<db::ParameterState, db::ParameterState::Icon> decl_PCellParameterState_Icon ("db", "ParameterStateIcon",
gsi::enum_const ("NoIcon", db::ParameterState::NoIcon,
"@brief No icon is shown for the parameter\n"
) +
gsi::enum_const ("InfoIcon", db::ParameterState::InfoIcon,
"@brief A general 'information' icon is shown\n"
) +
gsi::enum_const ("ErrorIcon", db::ParameterState::ErrorIcon,
"@brief An icon indicating an error is shown\n"
) +
gsi::enum_const ("WarningIcon", db::ParameterState::WarningIcon,
"@brief An icon indicating a warning is shown\n"
),
"@brief This enum specifies the icon shown next to the parameter in PCell parameter list.\n"
"\n"
"This enum was introduced in version 0.28.\n"
);
// Inject the NetlistCrossReference::Status declarations into NetlistCrossReference:
gsi::ClassExt<db::ParameterState> inject_PCellParameterState_Icon_in_parent (decl_PCellParameterState_Icon.defs ());
// Provide a binding for db::ParameterStates for native PCell implementations
Class<db::ParameterStates> decl_PCellParameterStates ("db", "PCellParameterStates",
gsi::method ("has_parameter?", &db::ParameterStates::has_parameter, gsi::arg ("name"),
"@brief Gets a value indicating whether a parameter with that name exists\n"
) +
gsi::method ("parameter", static_cast<db::ParameterState & (db::ParameterStates::*) (const std::string &name)> (&db::ParameterStates::parameter), gsi::arg ("name"),
"@brief Gets the parameter by name\n"
"\n"
"This will return a \\PCellParameterState object that can be used to manipulate the "
"parameter state."
),
"@brief Provides access to the parameter states inside a 'callback' implementation of a PCell\n"
"\n"
"Example: enables or disables a parameter 'n' based on the value:\n"
"\n"
"@code\n"
"n_param = states.parameter(\"n\")\n"
"n_param.enabled = n_param.value > 1.0\n"
"@/code\n"
"\n"
"This class has been introduced in version 0.28."
);
class PCellDeclarationImpl
: public db::PCellDeclaration
{
@ -359,6 +452,20 @@ public:
}
}
virtual void callback_fb (const db::Layout &layout, const std::string &name, db::ParameterStates &states) const
{
db::PCellDeclaration::callback (layout, name, states);
}
virtual void callback (const db::Layout &layout, const std::string &name, db::ParameterStates &states) const
{
if (cb_callback.can_issue ()) {
cb_callback.issue<db::PCellDeclaration, const db::Layout &, const std::string &, db::ParameterStates &> (&db::PCellDeclaration::callback, layout, name, states);
} else {
db::PCellDeclaration::callback (layout, name, states);
}
}
void produce_fb (const db::Layout &layout, const std::vector<unsigned int> &layer_ids, const db::pcell_parameters_type &parameters, db::Cell &cell) const
{
return db::PCellDeclaration::produce (layout, layer_ids, parameters, cell);
@ -451,6 +558,7 @@ public:
gsi::Callback cb_transformation_from_shape;
gsi::Callback cb_wants_lazy_evaluation;
gsi::Callback cb_coerce_parameters;
gsi::Callback cb_callback;
gsi::Callback cb_get_display_name;
};
@ -458,6 +566,7 @@ Class<PCellDeclarationImpl> decl_PCellDeclaration (decl_PCellDeclaration_Native,
// fallback implementations to reroute Ruby calls to the base class:
gsi::method ("get_parameters", &PCellDeclarationImpl::get_parameter_declarations_fb, "@hide") +
gsi::method ("produce", &PCellDeclarationImpl::produce_fb, "@hide") +
gsi::method ("callback", &PCellDeclarationImpl::callback_fb, "@hide") +
gsi::method ("can_create_from_shape", &PCellDeclarationImpl::can_create_from_shape_fb, "@hide") +
gsi::method ("parameters_from_shape", &PCellDeclarationImpl::parameters_from_shape_fb, "@hide") +
gsi::method ("transformation_from_shape", &PCellDeclarationImpl::transformation_from_shape_fb, "@hide") +
@ -493,6 +602,25 @@ Class<PCellDeclarationImpl> decl_PCellDeclaration (decl_PCellDeclaration_Native,
"\n"
"It can raise an exception to indicate that something is not correct.\n"
) +
gsi::callback ("callback", &PCellDeclarationImpl::callback, &PCellDeclarationImpl::cb_callback, gsi::arg ("layout"), gsi::arg ("name"), gsi::arg ("states"),
"@brief Indicates a parameter change and allows implementing actions based on the parameter value\n"
"@param layout The layout object in which the PCell will be produced\n"
"@param name The name of the parameter which has changed or an empty string if all parameters need to be considered\n"
"@param states A \\PCellParameterStates object which can be used to manipulate the parameter states\n"
"This method may be reimplemented to implement parameter-specific actions upon value change or button callbacks. "
"Whenever the value of a parameter is changed in the PCell parameter form, this method is called with the name of the parameter "
"in 'name'. The implementation can manipulate values or states (enabled, visible) or parameters using the "
"\\PCellParameterStates object passed in 'states'.\n"
"\n"
"Initially, this method will be called with an empty parameter name to indicate a global change. The implementation "
"may then consolidate all states. The initial state is build from the 'readonly' (disabled) or 'hidden' (invisible) parameter "
"declarations.\n"
"\n"
"This method is also called when a button-type parameter is present and the button is pressed. In this case the parameter "
"name is the name of the button.\n"
"\n"
"This feature has been introduced in version 0.28."
) +
gsi::callback ("produce", &PCellDeclarationImpl::produce, &PCellDeclarationImpl::cb_produce, gsi::arg ("layout"), gsi::arg ("layer_ids"), gsi::arg ("parameters"), gsi::arg ("cell"),
"@brief The production callback\n"
"@param layout The layout object where the cell resides\n"
@ -634,6 +762,11 @@ static unsigned int pd_type_list ()
return (unsigned int) db::PCellParameterDeclaration::t_list;
}
static unsigned int pd_type_callback ()
{
return (unsigned int) db::PCellParameterDeclaration::t_callback;
}
static unsigned int pd_type_none ()
{
return (unsigned int) db::PCellParameterDeclaration::t_none;
@ -763,7 +896,8 @@ Class<db::PCellParameterDeclaration> decl_PCellParameterDeclaration ("db", "PCel
gsi::method ("TypeList", &pd_type_list, "@brief Type code: a list of variants") +
gsi::method ("TypeLayer", &pd_type_layer, "@brief Type code: a layer (a \\LayerInfo object)") +
gsi::method ("TypeShape", &pd_type_shape, "@brief Type code: a guiding shape (Box, Edge, Point, Polygon or Path)") +
gsi::method ("TypeNone", &pd_type_none, "@brief Type code: unspecific type")
gsi::method ("TypeCallback", &pd_type_callback, "@brief Type code: a button triggering a callback\n\nThis code has been introduced in version 0.28.") +
gsi::method ("TypeNone", &pd_type_none, "@brief Type code: unspecific type")
,
"@brief A PCell parameter declaration\n"
"\n"

View File

@ -2452,7 +2452,6 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
"\n"
"\"metrics\" can be one of the constants \\Euclidian, \\Square or \\Projection. See there for "
"a description of these constants.\n"
"Use nil for this value to select the default (Euclidian metrics).\n"
"\n"
"\"ignore_angle\" specifies the angle limit of two edges. If two edges form an angle equal or "
"above the given value, they will not contribute in the check. "
@ -2491,7 +2490,6 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
"\n"
"\"metrics\" can be one of the constants \\Euclidian, \\Square or \\Projection. See there for "
"a description of these constants.\n"
"Use nil for this value to select the default (Euclidian metrics).\n"
"\n"
"\"ignore_angle\" specifies the angle limit of two edges. If two edges form an angle equal or "
"above the given value, they will not contribute in the check. "
@ -2535,7 +2533,6 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
"\n"
"\"metrics\" can be one of the constants \\Euclidian, \\Square or \\Projection. See there for "
"a description of these constants.\n"
"Use nil for this value to select the default (Euclidian metrics).\n"
"\n"
"\"ignore_angle\" specifies the angle limit of two edges. If two edges form an angle equal or "
"above the given value, they will not contribute in the check. "
@ -2574,7 +2571,6 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
"\n"
"\"metrics\" can be one of the constants \\Euclidian, \\Square or \\Projection. See there for "
"a description of these constants.\n"
"Use nil for this value to select the default (Euclidian metrics).\n"
"\n"
"\"ignore_angle\" specifies the angle limit of two edges. If two edges form an angle equal or "
"above the given value, they will not contribute in the check. "
@ -2617,7 +2613,6 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
"\n"
"\"metrics\" can be one of the constants \\Euclidian, \\Square or \\Projection. See there for "
"a description of these constants.\n"
"Use nil for this value to select the default (Euclidian metrics).\n"
"\n"
"\"ignore_angle\" specifies the angle limit of two edges. If two edges form an angle equal or "
"above the given value, they will not contribute in the check. "
@ -2667,7 +2662,6 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
"\n"
"\"metrics\" can be one of the constants \\Euclidian, \\Square or \\Projection. See there for "
"a description of these constants.\n"
"Use nil for this value to select the default (Euclidian metrics).\n"
"\n"
"\"ignore_angle\" specifies the angle limit of two edges. If two edges form an angle equal or "
"above the given value, they will not contribute in the check. "
@ -2716,7 +2710,6 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
"\n"
"\"metrics\" can be one of the constants \\Euclidian, \\Square or \\Projection. See there for "
"a description of these constants.\n"
"Use nil for this value to select the default (Euclidian metrics).\n"
"\n"
"\"ignore_angle\" specifies the angle limit of two edges. If two edges form an angle equal or "
"above the given value, they will not contribute in the check. "
@ -2765,7 +2758,6 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
"\n"
"\"metrics\" can be one of the constants \\Euclidian, \\Square or \\Projection. See there for "
"a description of these constants.\n"
"Use nil for this value to select the default (Euclidian metrics).\n"
"\n"
"\"ignore_angle\" specifies the angle limit of two edges. If two edges form an angle equal or "
"above the given value, they will not contribute in the check. "

View File

@ -83,7 +83,7 @@
<p>
Custom fonts are installed by copying the font file to a folder named "fonts"
in one of the places in KLayout's path. The standard font can be found in
"src/std_font.gds" in the source package.
"src/db/db/std_font.gds" in the source package.
</p>
<h2>CIRCLE and ELLIPSE</h2>

View File

@ -1125,6 +1125,25 @@ A more compact way of writing this is:
p = fill_pattern("FILL_CELL").shape(1, 0, box(0.0, 0.0, 1.0, 1.0))
</pre>
</p><p>
The "shape" method takes several forms:
</p><p>
<ul>
<li><tt>shape(layer, object, object ...) </tt>(1) </li>
<li><tt>shape(layer, datatype, object, object ...) </tt>(2) </li>
<li><tt>shape(name, object, object ...) </tt>(3) </li>
<li><tt>shape(layer_info, object, object ...) </tt>(4) </li>
</ul>
</p><p>
The first form takes a GDS2 layer number. The datatype is assumed to be 0.
The second form takes a GDS layer and datatype number.
The third form takes a layer name for layout systems with named layers
(like Magic, CIF or DXF).
The forth form takes a <class_doc href="LayerInfo">LayerInfo</class_doc> object to specify the layer.
All forms take one to many geometry objects which are written to the respective layer.
Geometry objects can either be created using the generator functions
(<a href="/about/drc_ref_global.xml#box">box</a>, <a href="/about/drc_ref_global.xml#polygon">polygon</a>, <a href="/about/drc_ref_global.xml#path">path</a>). The core classes <class_doc href="DBox">DBox</class_doc>, <class_doc href="DPolygon">DPolygon</class_doc>, <class_doc href="DPath">DPath</class_doc> or
<class_doc href="DText">DText</class_doc> are also accepted as geometry objects.
</p><p>
The fill pattern can be given a reference point which is used for placing the pattern. The reference point
is the one which is aligned with the pattern origin. The following code will assign (-0.5, -0.5) as the reference
point for the 1x1 micron rectangle. Hence the reference point is a little below and left of the rectangle which

View File

@ -34,20 +34,35 @@
<p>
Before nets can be extracted, a layer stack must be specified. Press "Layer Stack" on the user interface to open the
layer stack dialog. Layers must be specified in the "layer/datatype" notation. The
layer stack dialog or use "Edit Layer Stack" in the "Tools" menu. Layers must be specified in the "layer/datatype" notation. The
via specification is optional. If no via layer is specified, both metal layer shapes are required to touch in order to form a
connection. If a via layer is specified, a via shape must be present to form the connection.
</p>
<p>
KLayout allows specification of symbolic layers and to use boolean expressions. That way it is possible to
The layer stack (also referred to as "Connectivity") is also a technology component. This means
if you select a technology for layout, the technology specific stack is selected. To edit the stack
for all technologies, use the Technology Manager ("Tools/Manage Technologies") and use the
"Connectivity" section from the technologies.
</p>
<p>
A connectivity definition can specify multiple stacks, out of which one has to be selected.
This is useful, if your technology setup features multiple routing metal schemes for example.
You do not need to setup different technologies for each scheme. If you have declared multiple
stacks, you can choose one in the "Trace Net" dialog in the drop-down button right of the
"Layer Stack" and the "Configuration" button at the bottom left.
</p>
<p>
Within the stack definition, KLayout allows specification of symbolic layers and to use boolean expressions. That way it is possible to
assign meaningful names to layers (i.e. "POLY" or "VIA1") and to use derived layers (i.e. "ACTIVE-POLY" for
the source and drain regions of a CMOS transistor). Read more about these features in <link href="/about/connectivity.xml"/>
and <link href="/about/symbolic_layers.xml"/>.
</p>
<p>
If a layer stack has been defined, a net can be traced by pressing the "Trace Net" button and clicking on a point in the
Once a layer stack has been defined and selected, a net can be traced by pressing the "Trace Net" button and clicking on a point in the
layout. Starting from shapes found under this point, the net is extracted and listed in the net list on the left side of the
net tracing dialog. If "Lock" is checked, another net can be traced by clicking at another point without having to press
the "Trace Net" button again.

View File

@ -4712,6 +4712,25 @@ CODE
# p = fill_pattern("FILL_CELL").shape(1, 0, box(0.0, 0.0, 1.0, 1.0))
# @/code
#
# The "shape" method takes several forms:
#
# @ul
# @li @tt shape(layer, object, object ...) @/tt (1) @/li
# @li @tt shape(layer, datatype, object, object ...) @/tt (2) @/li
# @li @tt shape(name, object, object ...) @/tt (3) @/li
# @li @tt shape(layer_info, object, object ...) @/tt (4) @/li
# @/ul
#
# The first form takes a GDS2 layer number. The datatype is assumed to be 0.
# The second form takes a GDS layer and datatype number.
# The third form takes a layer name for layout systems with named layers
# (like Magic, CIF or DXF).
# The forth form takes a RBA::LayerInfo object to specify the layer.
# All forms take one to many geometry objects which are written to the respective layer.
# Geometry objects can either be created using the generator functions
# (\global#box, \global#polygon, \global#path). The core classes RBA::DBox, RBA::DPolygon, RBA::DPath or
# RBA::DText are also accepted as geometry objects.
#
# The fill pattern can be given a reference point which is used for placing the pattern. The reference point
# is the one which is aligned with the pattern origin. The following code will assign (-0.5, -0.5) as the reference
# point for the 1x1 micron rectangle. Hence the reference point is a little below and left of the rectangle which

View File

@ -256,6 +256,10 @@ module DRC
else
raise("Argument ##{ai+1} not understood for FillCell#shape")
end
elsif a.is_a?(RBA::LayerInfo)
layer = a.layer
datatype = a.datatype
name = a.name
elsif a.is_a?(String)
if !name
name = a

View File

@ -26,7 +26,7 @@
<string/>
</property>
<property name="icon">
<iconset resource="../../lay/lay/layResources.qrc">
<iconset resource="../../icons/icons.qrc">
<normaloff>:/align_none_32px.png</normaloff>:/align_none_32px.png</iconset>
</property>
<property name="iconSize">
@ -43,7 +43,7 @@
<string/>
</property>
<property name="icon">
<iconset resource="../../lay/lay/layResources.qrc">
<iconset resource="../../icons/icons.qrc">
<normaloff>:/align_left_32px.png</normaloff>:/align_left_32px.png</iconset>
</property>
<property name="iconSize">
@ -60,7 +60,7 @@
<string/>
</property>
<property name="icon">
<iconset resource="../../lay/lay/layResources.qrc">
<iconset resource="../../icons/icons.qrc">
<normaloff>:/align_hcenter_32px.png</normaloff>:/align_hcenter_32px.png</iconset>
</property>
<property name="iconSize">
@ -77,7 +77,7 @@
<string/>
</property>
<property name="icon">
<iconset resource="../../lay/lay/layResources.qrc">
<iconset resource="../../icons/icons.qrc">
<normaloff>:/align_right_32px.png</normaloff>:/align_right_32px.png</iconset>
</property>
<property name="iconSize">
@ -204,7 +204,7 @@
<string/>
</property>
<property name="icon">
<iconset resource="../../lay/lay/layResources.qrc">
<iconset resource="../../icons/icons.qrc">
<normaloff>:/align_none_32px.png</normaloff>:/align_none_32px.png</iconset>
</property>
<property name="iconSize">
@ -221,7 +221,7 @@
<string/>
</property>
<property name="icon">
<iconset resource="../../lay/lay/layResources.qrc">
<iconset resource="../../icons/icons.qrc">
<normaloff>:/align_top_32px.png</normaloff>:/align_top_32px.png</iconset>
</property>
<property name="iconSize">
@ -238,7 +238,7 @@
<string/>
</property>
<property name="icon">
<iconset resource="../../lay/lay/layResources.qrc">
<iconset resource="../../icons/icons.qrc">
<normaloff>:/align_vcenter_32px.png</normaloff>:/align_vcenter_32px.png</iconset>
</property>
<property name="iconSize">
@ -308,7 +308,7 @@
<string/>
</property>
<property name="icon">
<iconset resource="../../lay/lay/layResources.qrc">
<iconset resource="../../icons/icons.qrc">
<normaloff>:/align_bottom_32px.png</normaloff>:/align_bottom_32px.png</iconset>
</property>
<property name="iconSize">
@ -432,7 +432,7 @@
<tabstop>buttonBox</tabstop>
</tabstops>
<resources>
<include location="../../lay/lay/layResources.qrc"/>
<include location="../../icons/icons.qrc"/>
</resources>
<connections>
<connection>

View File

@ -0,0 +1,130 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>AreaAndPerimeterDialog</class>
<widget class="QDialog" name="AreaAndPerimeterDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>367</width>
<height>205</height>
</rect>
</property>
<property name="windowTitle">
<string>Area And Perimeter</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="4" column="0" colspan="3">
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>10</width>
<height>11</height>
</size>
</property>
</spacer>
</item>
<item row="1" column="1">
<widget class="QLineEdit" name="perimeter_le">
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>Area</string>
</property>
</widget>
</item>
<item row="1" column="2">
<widget class="QLabel" name="label_6">
<property name="text">
<string>µm</string>
</property>
</widget>
</item>
<item row="0" column="2">
<widget class="QLabel" name="label_5">
<property name="text">
<string>µm²</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_3">
<property name="text">
<string>Perimeter</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLineEdit" name="area_le">
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
<item row="5" column="0" colspan="3">
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
<item row="3" column="0" colspan="3">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Note: area and perimeter are computed in &quot;merged mode&quot;. This means, overlapping shapes are counted once for area calculation.
The perimeter calculation only takes true outside edges into account. Internal edges are ignored.</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item row="2" column="0" colspan="3">
<spacer name="verticalSpacer_2">
<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>5</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
<resources/>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>AreaAndPerimeterDialog</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>303</x>
<y>185</y>
</hint>
<hint type="destinationlabel">
<x>311</x>
<y>201</y>
</hint>
</hints>
</connection>
</connections>
</ui>

View File

@ -278,7 +278,7 @@
<string/>
</property>
<property name="icon">
<iconset resource="../../lay/lay/layResources.qrc">
<iconset resource="../../icons/icons.qrc">
<normaloff>:/align_none_32px.png</normaloff>:/align_none_32px.png</iconset>
</property>
<property name="iconSize">
@ -311,7 +311,7 @@
<string/>
</property>
<property name="icon">
<iconset resource="../../lay/lay/layResources.qrc">
<iconset resource="../../icons/icons.qrc">
<normaloff>:/align_left_32px.png</normaloff>:/align_left_32px.png</iconset>
</property>
<property name="iconSize">
@ -344,7 +344,7 @@
<string/>
</property>
<property name="icon">
<iconset resource="../../lay/lay/layResources.qrc">
<iconset resource="../../icons/icons.qrc">
<normaloff>:/align_hcenter_32px.png</normaloff>:/align_hcenter_32px.png</iconset>
</property>
<property name="iconSize">
@ -377,7 +377,7 @@
<string/>
</property>
<property name="icon">
<iconset resource="../../lay/lay/layResources.qrc">
<iconset resource="../../icons/icons.qrc">
<normaloff>:/align_right_32px.png</normaloff>:/align_right_32px.png</iconset>
</property>
<property name="iconSize">
@ -456,7 +456,7 @@
<string/>
</property>
<property name="icon">
<iconset resource="../../lay/lay/layResources.qrc">
<iconset resource="../../icons/icons.qrc">
<normaloff>:/align_none_32px.png</normaloff>:/align_none_32px.png</iconset>
</property>
<property name="iconSize">
@ -489,7 +489,7 @@
<string/>
</property>
<property name="icon">
<iconset resource="../../lay/lay/layResources.qrc">
<iconset resource="../../icons/icons.qrc">
<normaloff>:/align_top_32px.png</normaloff>:/align_top_32px.png</iconset>
</property>
<property name="iconSize">
@ -522,7 +522,7 @@
<string/>
</property>
<property name="icon">
<iconset resource="../../lay/lay/layResources.qrc">
<iconset resource="../../icons/icons.qrc">
<normaloff>:/align_vcenter_32px.png</normaloff>:/align_vcenter_32px.png</iconset>
</property>
<property name="iconSize">
@ -555,7 +555,7 @@
<string/>
</property>
<property name="icon">
<iconset resource="../../lay/lay/layResources.qrc">
<iconset resource="../../icons/icons.qrc">
<normaloff>:/align_bottom_32px.png</normaloff>:/align_bottom_32px.png</iconset>
</property>
<property name="iconSize">
@ -676,7 +676,7 @@
<tabstop>buttonBox</tabstop>
</tabstops>
<resources>
<include location="../../lay/lay/layResources.qrc"/>
<include location="../../icons/icons.qrc"/>
</resources>
<connections>
<connection>

View File

@ -158,7 +158,7 @@
<string>...</string>
</property>
<property name="icon">
<iconset resource="../../lay/lay/layResources.qrc">
<iconset resource="../../icons/icons.qrc">
<normaloff>:/find_16px.png</normaloff>:/find_16px.png</iconset>
</property>
<property name="autoRaise">
@ -549,7 +549,7 @@
</customwidget>
</customwidgets>
<resources>
<include location="../../lay/lay/layResources.qrc"/>
<include location="../../icons/icons.qrc"/>
</resources>
<connections/>
</ui>

View File

@ -59,7 +59,6 @@
<font>
<family>Sans Serif</family>
<pointsize>12</pointsize>
<weight>75</weight>
<italic>false</italic>
<bold>true</bold>
<underline>false</underline>
@ -731,7 +730,7 @@
<string/>
</property>
<property name="pixmap">
<pixmap resource="../../lay/lay/layResources.qrc">:/warn_16px@2x.png</pixmap>
<pixmap resource="../../icons/icons.qrc">:/warn_16px@2x.png</pixmap>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
@ -899,7 +898,7 @@
<tabstop>inst_pb</tabstop>
</tabstops>
<resources>
<include location="../../lay/lay/layResources.qrc"/>
<include location="../../icons/icons.qrc"/>
</resources>
<connections/>
</ui>

View File

@ -144,7 +144,7 @@
<string>...</string>
</property>
<property name="icon">
<iconset resource="../../lay/lay/layResources.qrc">
<iconset resource="../../icons/icons.qrc">
<normaloff>:/ct_31px.png</normaloff>:/ct_31px.png</iconset>
</property>
<property name="iconSize">
@ -164,7 +164,7 @@
<string>...</string>
</property>
<property name="icon">
<iconset resource="../../lay/lay/layResources.qrc">
<iconset resource="../../icons/icons.qrc">
<normaloff>:/lt_31px.png</normaloff>:/lt_31px.png</iconset>
</property>
<property name="iconSize">
@ -184,7 +184,7 @@
<string>...</string>
</property>
<property name="icon">
<iconset resource="../../lay/lay/layResources.qrc">
<iconset resource="../../icons/icons.qrc">
<normaloff>:/rt_31px.png</normaloff>:/rt_31px.png</iconset>
</property>
<property name="iconSize">
@ -204,7 +204,7 @@
<string>...</string>
</property>
<property name="icon">
<iconset resource="../../lay/lay/layResources.qrc">
<iconset resource="../../icons/icons.qrc">
<normaloff>:/lc_31px.png</normaloff>:/lc_31px.png</iconset>
</property>
<property name="iconSize">
@ -224,7 +224,7 @@
<string>...</string>
</property>
<property name="icon">
<iconset resource="../../lay/lay/layResources.qrc">
<iconset resource="../../icons/icons.qrc">
<normaloff>:/cc_31px.png</normaloff>:/cc_31px.png</iconset>
</property>
<property name="iconSize">
@ -244,7 +244,7 @@
<string>...</string>
</property>
<property name="icon">
<iconset resource="../../lay/lay/layResources.qrc">
<iconset resource="../../icons/icons.qrc">
<normaloff>:/rc_31px.png</normaloff>:/rc_31px.png</iconset>
</property>
<property name="iconSize">
@ -264,7 +264,7 @@
<string>...</string>
</property>
<property name="icon">
<iconset resource="../../lay/lay/layResources.qrc">
<iconset resource="../../icons/icons.qrc">
<normaloff>:/lb_31px.png</normaloff>:/lb_31px.png</iconset>
</property>
<property name="iconSize">
@ -284,7 +284,7 @@
<string>...</string>
</property>
<property name="icon">
<iconset resource="../../lay/lay/layResources.qrc">
<iconset resource="../../icons/icons.qrc">
<normaloff>:/cb_31px.png</normaloff>:/cb_31px.png</iconset>
</property>
<property name="iconSize">
@ -304,7 +304,7 @@
<string>...</string>
</property>
<property name="icon">
<iconset resource="../../lay/lay/layResources.qrc">
<iconset resource="../../icons/icons.qrc">
<normaloff>:/rb_31px.png</normaloff>:/rb_31px.png</iconset>
</property>
<property name="iconSize">
@ -366,7 +366,7 @@
</layout>
</widget>
<resources>
<include location="../../lay/lay/layResources.qrc"/>
<include location="../../icons/icons.qrc"/>
</resources>
<connections>
<connection>

View File

@ -27,7 +27,8 @@ DEFINES += MAKE_EDT_LIBRARY
RoundCornerOptionsDialog.ui \
TextPropertiesPage.ui \
DistributeOptionsDialog.ui \
EditorOptionsInstPCellParam.ui
EditorOptionsInstPCellParam.ui \
AreaAndPerimeterDialog.ui
}

View File

@ -683,6 +683,29 @@ BEGIN_PROTECTED;
END_PROTECTED;
}
// --------------------------------------------------------------------------------
// AreaAndPerimeterDialog implementation
AreaAndPerimeterDialog::AreaAndPerimeterDialog (QWidget *parent)
: QDialog (parent)
{
setupUi (this);
}
AreaAndPerimeterDialog::~AreaAndPerimeterDialog ()
{
// .. nothing yet ..
}
bool
AreaAndPerimeterDialog::exec_dialog (double area, double perimeter)
{
area_le->setText (tl::to_qstring (tl::sprintf ("%.12g", area)));
perimeter_le->setText (tl::to_qstring (tl::sprintf ("%.12g", perimeter)));
return exec () != 0;
}
}
#endif

View File

@ -43,6 +43,7 @@
#include "ui_MakeCellOptionsDialog.h"
#include "ui_MakeArrayOptionsDialog.h"
#include "ui_RoundCornerOptionsDialog.h"
#include "ui_AreaAndPerimeterDialog.h"
namespace lay
{
@ -205,6 +206,22 @@ private:
bool m_has_extracted;
};
/**
* @brief Result dialog for "area and perimeter"
*/
class AreaAndPerimeterDialog
: public QDialog,
private Ui::AreaAndPerimeterDialog
{
Q_OBJECT
public:
AreaAndPerimeterDialog (QWidget *parent);
~AreaAndPerimeterDialog ();
bool exec_dialog (double area, double perimeter);
};
} // namespace edt
#endif

View File

@ -555,7 +555,7 @@ InstPropertiesPage::create_applicator (db::Cell & /*cell*/, const db::Instance &
tl_assert (mp_pcell_parameters);
std::vector<tl::Variant> param = mp_pcell_parameters->get_parameters (0);
const std::vector<tl::Variant> &initial_param = mp_pcell_parameters->initial_parameters ();
std::vector<tl::Variant> initial_param = mp_pcell_parameters->initial_parameters ();
const std::vector<db::PCellParameterDeclaration> &pcp = mp_pcell_parameters->pcell_decl ()->parameter_declarations ();
for (std::vector<db::PCellParameterDeclaration>::const_iterator pd = pcp.begin (); pd != pcp.end (); ++pd) {

View File

@ -25,6 +25,7 @@
#include "dbPolygonTools.h"
#include "dbLibrary.h"
#include "dbLibraryManager.h"
#include "dbRegion.h"
#include "tlExceptions.h"
#include "layLayoutView.h"
#include "laySelector.h"
@ -82,6 +83,7 @@ MainService::MainService (db::Manager *manager, lay::LayoutViewBase *view, lay::
{
#if defined(HAVE_QT)
mp_round_corners_dialog = 0;
mp_area_and_perimeter_dialog = 0;
mp_align_options_dialog = 0;
mp_distribute_options_dialog = 0;
mp_flatten_inst_options_dialog = 0;
@ -106,6 +108,15 @@ MainService::round_corners_dialog ()
return mp_round_corners_dialog;
}
edt::AreaAndPerimeterDialog *
MainService::area_and_perimeter_dialog ()
{
if (! mp_area_and_perimeter_dialog) {
mp_area_and_perimeter_dialog = new edt::AreaAndPerimeterDialog (lay::widget_from_view (view ()));
}
return mp_area_and_perimeter_dialog;
}
edt::AlignOptionsDialog *
MainService::align_options_dialog ()
{
@ -168,6 +179,8 @@ MainService::menu_activated (const std::string &symbol)
cm_tap ();
} else if (symbol == "edt::sel_round_corners") {
cm_round_corners ();
} else if (symbol == "edt::sel_area_perimeter") {
cm_area_perimeter ();
} else if (symbol == "edt::sel_convert_to_pcell") {
cm_convert_to_pcell ();
} else if (symbol == "edt::sel_convert_to_cell") {
@ -1346,6 +1359,67 @@ MainService::cm_convert_to_pcell ()
}
}
void MainService::cm_area_perimeter ()
{
#if ! defined(HAVE_QT)
tl_assert (false); // see TODO
#endif
double dbu = 0.0;
std::vector<edt::Service *> edt_services = view ()->get_plugins <edt::Service> ();
db::Region region;
// get (common) cellview index of the primary selection
for (std::vector<edt::Service *>::const_iterator es = edt_services.begin (); es != edt_services.end (); ++es) {
for (edt::Service::obj_iterator s = (*es)->selection ().begin (); s != (*es)->selection ().end (); ++s) {
if (s->is_cell_inst ()) {
continue;
}
db::Polygon poly;
if (!s->shape ().polygon (poly)) {
continue;
}
double shape_dbu = view ()->cellview (s->cv_index ())->layout ().dbu ();
if (dbu == 0.0) {
// first CV is used for reference DBU
dbu = shape_dbu;
}
if (fabs (shape_dbu - dbu) < db::epsilon) {
region.insert (s->trans () * poly);
} else {
region.insert ((db::ICplxTrans (shape_dbu / dbu) * s->trans ()) * poly);
}
}
}
#if defined(HAVE_QT)
if (region.count () > 100000) {
if (QMessageBox::warning (lay::widget_from_view (view ()), tr ("Warning: Big Selection"),
tr ("The selection contains many shapes. Area and perimeter computation may take a long time.\nContinue anyway?"),
QMessageBox::Yes, QMessageBox::No) == QMessageBox::No) {
return;
}
}
#endif
double area = region.area () * dbu * dbu;
double perimeter = region.perimeter () * dbu;
#if defined(HAVE_QT)
area_and_perimeter_dialog ()->exec_dialog (area, perimeter);
#endif
}
static bool extract_rad (std::vector <db::Polygon> &poly, double &rinner, double &router, unsigned int &n)
{
std::vector <db::Point> new_pts;
@ -1356,7 +1430,7 @@ static bool extract_rad (std::vector <db::Polygon> &poly, double &rinner, double
db::Polygon new_poly;
new_pts.clear ();
if (! extract_rad_from_contour (p->begin_hull (), p->end_hull (), rinner, router, n, &new_pts) &&
if (! extract_rad_from_contour (p->begin_hull (), p->end_hull (), rinner, router, n, &new_pts) &&
! extract_rad_from_contour (p->begin_hull (), p->end_hull (), rinner, router, n, &new_pts, true)) {
// ultimate fallback: assign original contour
new_poly.assign_hull (p->begin_hull (), p->end_hull (), false /*don't compress*/);
@ -1368,7 +1442,7 @@ static bool extract_rad (std::vector <db::Polygon> &poly, double &rinner, double
for (unsigned int h = 0; h < p->holes (); ++h) {
new_pts.clear ();
if (! extract_rad_from_contour (p->begin_hole (h), p->end_hole (h), rinner, router, n, &new_pts) &&
if (! extract_rad_from_contour (p->begin_hole (h), p->end_hole (h), rinner, router, n, &new_pts) &&
! extract_rad_from_contour (p->begin_hole (h), p->end_hole (h), rinner, router, n, &new_pts, true)) {
// ultimate fallback: assign original contour
new_poly.insert_hole (p->begin_hole (h), p->end_hole (h), false /*don't compress*/);

View File

@ -48,6 +48,7 @@ class Service;
class EditorOptionsPages;
class EditorOptionsPage;
class RoundCornerOptionsDialog;
class AreaAndPerimeterDialog;
class MakeCellOptionsDialog;
class MakeArrayOptionsDialog;
class AlignOptionsDialog;
@ -104,6 +105,11 @@ public:
*/
void cm_round_corners ();
/**
* @brief Show area and perimeter of selection
*/
void cm_area_perimeter ();
/**
* @brief Convert selection to PCell
*/
@ -223,6 +229,7 @@ private:
bool m_undo_before_apply;
#if defined(HAVE_QT)
edt::RoundCornerOptionsDialog *mp_round_corners_dialog;
edt::AreaAndPerimeterDialog *mp_area_and_perimeter_dialog;
edt::AlignOptionsDialog *mp_align_options_dialog;
edt::DistributeOptionsDialog *mp_distribute_options_dialog;
lay::FlattenInstOptionsDialog *mp_flatten_inst_options_dialog;
@ -234,6 +241,7 @@ private:
void check_no_guiding_shapes ();
#if defined(HAVE_QT)
edt::RoundCornerOptionsDialog *round_corners_dialog ();
edt::AreaAndPerimeterDialog *area_and_perimeter_dialog ();
edt::AlignOptionsDialog *align_options_dialog ();
edt::DistributeOptionsDialog *distribute_options_dialog ();
lay::FlattenInstOptionsDialog *flatten_inst_options_dialog ();

View File

@ -149,7 +149,7 @@ static void set_value (const db::PCellParameterDeclaration &p, QWidget *widget,
}
PCellParametersPage::PCellParametersPage (QWidget *parent, bool dense)
: QFrame (parent), m_dense (dense), dm_parameter_changed (this, &PCellParametersPage::do_parameter_changed)
: QFrame (parent), m_dense (dense), m_show_parameter_names (false), dm_parameter_changed (this, &PCellParametersPage::do_parameter_changed)
{
init ();
}
@ -170,7 +170,7 @@ PCellParametersPage::init ()
frame_layout->setContentsMargins (0, 0, 0, 0);
setLayout (frame_layout);
mp_update_frame = new QFrame ();
mp_update_frame = new QFrame (this);
mp_update_frame->setFrameShape (QFrame::NoFrame);
frame_layout->addWidget (mp_update_frame, 0, 0, 1, 1);
@ -197,7 +197,7 @@ PCellParametersPage::init ()
update_frame_layout->setColumnStretch (2, 1);
mp_error_frame = new QFrame ();
mp_error_frame = new QFrame (this);
mp_error_frame->setFrameShape (QFrame::NoFrame);
frame_layout->addWidget (mp_error_frame, 1, 0, 1, 1);
@ -224,6 +224,13 @@ PCellParametersPage::init ()
error_frame_layout->addWidget (mp_error_label, 1, 1, 1, 2);
error_frame_layout->setColumnStretch (2, 1);
mp_show_parameter_names_cb = new QCheckBox (this);
mp_show_parameter_names_cb->setText (tr ("Show parameter names"));
mp_show_parameter_names_cb->setChecked (m_show_parameter_names);
frame_layout->addWidget (mp_show_parameter_names_cb, 3, 0, 1, 1);
connect (mp_show_parameter_names_cb, SIGNAL (clicked (bool)), this, SLOT (show_parameter_names (bool)));
}
bool
@ -232,19 +239,34 @@ PCellParametersPage::lazy_evaluation ()
return mp_pcell_decl.get () && mp_pcell_decl->wants_lazy_evaluation ();
}
void
PCellParametersPage::show_parameter_names (bool f)
{
if (m_show_parameter_names == f) {
return;
}
m_show_parameter_names = f;
mp_show_parameter_names_cb->setChecked (f);
setup (mp_view, m_cv_index, mp_pcell_decl.get (), get_parameters ());
}
void
PCellParametersPage::setup (lay::LayoutViewBase *view, int cv_index, const db::PCellDeclaration *pcell_decl, const db::pcell_parameters_type &parameters)
{
mp_pcell_decl.reset (const_cast<db::PCellDeclaration *> (pcell_decl)); // no const weak_ptr ...
mp_view = view;
m_cv_index = cv_index;
m_parameters = parameters;
m_states = db::ParameterStates ();
m_initial_states = db::ParameterStates ();
if (mp_parameters_area) {
delete mp_parameters_area;
}
m_widgets.clear ();
m_icon_widgets.clear ();
m_all_widgets.clear ();
mp_parameters_area = new QScrollArea (this);
mp_parameters_area->setFrameShape (QFrame::NoFrame);
@ -268,6 +290,12 @@ PCellParametersPage::setup (lay::LayoutViewBase *view, int cv_index, const db::P
QWidget *main_frame = inner_frame;
QGridLayout *main_grid = inner_grid;
if (! mp_pcell_decl) {
mp_parameters_area->setWidget (main_frame);
update_current_parameters ();
return;
}
int main_row = 0;
int row = 0;
std::string group_title;
@ -276,8 +304,23 @@ PCellParametersPage::setup (lay::LayoutViewBase *view, int cv_index, const db::P
const std::vector<db::PCellParameterDeclaration> &pcp = pcell_decl->parameter_declarations ();
for (std::vector<db::PCellParameterDeclaration>::const_iterator p = pcp.begin (); p != pcp.end (); ++p, ++r) {
if (p->is_hidden () || p->get_type () == db::PCellParameterDeclaration::t_shape) {
tl::Variant value;
if (r < int (parameters.size ())) {
value = parameters [r];
} else {
value = p->get_default ();
}
db::ParameterState &ps = m_states.parameter (p->get_name ());
ps.set_value (value);
ps.set_readonly (p->is_readonly ());
ps.set_visible (! p->is_hidden ());
m_all_widgets.push_back (std::vector<QWidget *> ());
if (p->get_type () == db::PCellParameterDeclaration::t_shape) {
m_widgets.push_back (0);
m_icon_widgets.push_back (0);
continue;
}
@ -297,7 +340,7 @@ PCellParametersPage::setup (lay::LayoutViewBase *view, int cv_index, const db::P
// create a new group
QGroupBox *gb = new QGroupBox (main_frame);
gb->setTitle (tl::to_qstring (gt));
main_grid->addWidget (gb, main_row, 0, 1, 2);
main_grid->addWidget (gb, main_row, 0, 1, 3);
inner_grid = new QGridLayout (gb);
if (m_dense) {
@ -324,13 +367,28 @@ PCellParametersPage::setup (lay::LayoutViewBase *view, int cv_index, const db::P
}
inner_grid->addWidget (new QLabel (tl::to_qstring (description), inner_frame), row, 0);
QLabel *icon_label = new QLabel (QString (), inner_frame);
inner_grid->addWidget (icon_label, row, 0);
m_icon_widgets.push_back (icon_label);
m_all_widgets.back ().push_back (icon_label);
if (p->get_type () != db::PCellParameterDeclaration::t_callback) {
std::string leader;
if (m_show_parameter_names) {
leader = tl::sprintf ("[%s] ", p->get_name ());
}
QLabel *l = new QLabel (tl::to_qstring (leader + description), inner_frame);
inner_grid->addWidget (l, row, 1);
m_all_widgets.back ().push_back (l);
} else if (m_show_parameter_names) {
QLabel *l = new QLabel (tl::to_qstring (tl::sprintf ("[%s]", p->get_name ())), inner_frame);
inner_grid->addWidget (l, row, 1);
m_all_widgets.back ().push_back (l);
tl::Variant value;
if (r < int (parameters.size ())) {
value = parameters [r];
} else {
value = p->get_default ();
}
if (p->get_choices ().empty ()) {
@ -347,7 +405,6 @@ PCellParametersPage::setup (lay::LayoutViewBase *view, int cv_index, const db::P
f->setFrameShape (QFrame::NoFrame);
QLineEdit *le = new QLineEdit (f);
le->setEnabled (! p->is_readonly ());
hb->addWidget (le);
le->setMaximumWidth (150);
le->setObjectName (tl::to_qstring (p->get_name ()));
@ -357,21 +414,37 @@ PCellParametersPage::setup (lay::LayoutViewBase *view, int cv_index, const db::P
hb->addWidget (ul, 1);
ul->setText (tl::to_qstring (p->get_unit ()));
inner_grid->addWidget (f, row, 1);
inner_grid->addWidget (f, row, 2);
m_all_widgets.back ().push_back (f);
connect (le, SIGNAL (editingFinished ()), this, SLOT (parameter_changed ()));
}
break;
case db::PCellParameterDeclaration::t_callback:
{
QPushButton *pb = new QPushButton (inner_frame);
pb->setObjectName (tl::to_qstring (p->get_name ()));
pb->setText (tl::to_qstring (description));
pb->setSizePolicy (QSizePolicy::Fixed, QSizePolicy::Preferred);
m_widgets.push_back (pb);
inner_grid->addWidget (pb, row, 2);
m_all_widgets.back ().push_back (pb);
connect (pb, SIGNAL (clicked ()), this, SLOT (parameter_changed ()));
}
break;
case db::PCellParameterDeclaration::t_string:
case db::PCellParameterDeclaration::t_shape:
case db::PCellParameterDeclaration::t_list:
{
QLineEdit *le = new QLineEdit (inner_frame);
le->setEnabled (! p->is_readonly ());
le->setObjectName (tl::to_qstring (p->get_name ()));
m_widgets.push_back (le);
inner_grid->addWidget (le, row, 1);
inner_grid->addWidget (le, row, 2);
m_all_widgets.back ().push_back (le);
connect (le, SIGNAL (editingFinished ()), this, SLOT (parameter_changed ()));
}
@ -380,12 +453,12 @@ PCellParametersPage::setup (lay::LayoutViewBase *view, int cv_index, const db::P
case db::PCellParameterDeclaration::t_layer:
{
lay::LayerSelectionComboBox *ly = new lay::LayerSelectionComboBox (inner_frame);
ly->setEnabled (! p->is_readonly ());
ly->set_no_layer_available (true);
ly->set_view (mp_view, m_cv_index, true /*all layers*/);
ly->setObjectName (tl::to_qstring (p->get_name ()));
m_widgets.push_back (ly);
inner_grid->addWidget (ly, row, 1);
inner_grid->addWidget (ly, row, 2);
m_all_widgets.back ().push_back (ly);
connect (ly, SIGNAL (activated (int)), this, SLOT (parameter_changed ()));
}
@ -396,10 +469,10 @@ PCellParametersPage::setup (lay::LayoutViewBase *view, int cv_index, const db::P
QCheckBox *cbx = new QCheckBox (inner_frame);
// this makes the checkbox not stretch over the full width - better when navigating with tab
cbx->setSizePolicy (QSizePolicy (QSizePolicy::Fixed, QSizePolicy::Preferred));
cbx->setEnabled (! p->is_readonly ());
cbx->setObjectName (tl::to_qstring (p->get_name ()));
m_widgets.push_back (cbx);
inner_grid->addWidget (cbx, row, 1);
inner_grid->addWidget (cbx, row, 2);
m_all_widgets.back ().push_back (cbx);
connect (cbx, SIGNAL (stateChanged (int)), this, SLOT (parameter_changed ()));
}
@ -426,16 +499,14 @@ PCellParametersPage::setup (lay::LayoutViewBase *view, int cv_index, const db::P
connect (cb, SIGNAL (activated (int)), this, SLOT (parameter_changed ()));
cb->setEnabled (! p->is_readonly ());
cb->setMinimumContentsLength (30);
cb->setSizeAdjustPolicy (QComboBox::AdjustToMinimumContentsLengthWithIcon);
m_widgets.push_back (cb);
inner_grid->addWidget (cb, row, 1);
inner_grid->addWidget (cb, row, 2);
m_all_widgets.back ().push_back (cb);
}
set_value (*p, m_widgets.back (), value);
++row;
if (inner_frame == main_frame) {
++main_row;
@ -443,6 +514,22 @@ PCellParametersPage::setup (lay::LayoutViewBase *view, int cv_index, const db::P
}
// initial callback
try {
mp_pcell_decl->callback (mp_view->cellview (m_cv_index)->layout (), std::string (), m_states);
} catch (tl::Exception &ex) {
// potentially caused by script errors in callback implementation
tl::error << ex.msg ();
} catch (std::runtime_error &ex) {
tl::error << ex.what ();
} catch (...) {
// ignore other errors
}
m_initial_states = m_states;
update_widgets_from_states (m_states);
mp_parameters_area->setWidget (main_frame);
main_frame->show ();
@ -458,6 +545,8 @@ PCellParametersPage::get_state ()
s.vScrollPosition = mp_parameters_area->verticalScrollBar ()->value ();
s.hScrollPosition = mp_parameters_area->horizontalScrollBar ()->value ();
s.show_parameter_names = m_show_parameter_names;
if (focusWidget ()) {
s.focusWidget = focusWidget ()->objectName ();
}
@ -473,6 +562,10 @@ PCellParametersPage::set_state (const State &s)
mp_parameters_area->verticalScrollBar ()->setValue (s.vScrollPosition);
mp_parameters_area->horizontalScrollBar ()->setValue (s.hScrollPosition);
if (s.show_parameter_names != m_show_parameter_names) {
show_parameter_names (s.show_parameter_names);
}
if (! s.focusWidget.isEmpty ()) {
QWidget *c = findChild<QWidget *> (s.focusWidget);
if (c) {
@ -483,18 +576,58 @@ PCellParametersPage::set_state (const State &s)
}
}
void
void
PCellParametersPage::parameter_changed ()
{
if (! mp_pcell_decl) {
return;
}
if (! mp_view->cellview (m_cv_index).is_valid ()) {
return;
}
const std::vector<db::PCellParameterDeclaration> &pcp = mp_pcell_decl->parameter_declarations ();
const db::PCellParameterDeclaration *pd = 0;
for (auto w = m_widgets.begin (); w != m_widgets.end (); ++w) {
if (*w == sender ()) {
pd = &pcp [w - m_widgets.begin ()];
break;
}
}
try {
db::ParameterStates states = m_states;
bool edit_error = false;
// Silent and without coerce - this will be done later in do_parameter_changed().
// This is just about providing the inputs for the callback.
get_parameters_internal (states, edit_error);
if (! edit_error) {
mp_pcell_decl->callback (mp_view->cellview (m_cv_index)->layout (), pd ? pd->get_name () : std::string (), states);
m_states = states;
}
} catch (tl::Exception &ex) {
// potentially caused by script errors in callback implementation
tl::error << ex.msg ();
} catch (std::runtime_error &ex) {
tl::error << ex.what ();
} catch (...) {
// ignore other errors
}
dm_parameter_changed ();
}
void
PCellParametersPage::do_parameter_changed ()
{
// does a coerce and update
bool ok = false;
std::vector<tl::Variant> parameters = get_parameters (&ok);
bool ok = true;
db::ParameterStates states = m_states;
get_parameters (states, &ok); // includes coerce
update_widgets_from_states (states);
if (ok && ! lazy_evaluation ()) {
emit edited ();
}
@ -511,159 +644,166 @@ PCellParametersPage::update_button_pressed ()
bool
PCellParametersPage::update_current_parameters ()
{
bool ok = false;
std::vector<tl::Variant> parameters = get_parameters (&ok);
bool ok = true;
db::ParameterStates states = m_states;
get_parameters (states, &ok); // includes coerce
if (ok) {
m_current_parameters = parameters;
m_current_states = states;
mp_update_frame->hide ();
}
return ok;
}
std::vector<tl::Variant>
PCellParametersPage::get_parameters (bool *ok)
void
PCellParametersPage::get_parameters_internal (db::ParameterStates &states, bool &edit_error)
{
std::vector<tl::Variant> parameters;
edit_error = false;
int r = 0;
const std::vector<db::PCellParameterDeclaration> &pcp = mp_pcell_decl->parameter_declarations ();
for (std::vector<db::PCellParameterDeclaration>::const_iterator p = pcp.begin (); p != pcp.end (); ++p, ++r) {
db::ParameterState &ps = states.parameter (p->get_name ());
if (! ps.is_visible () || ! ps.is_enabled () || ps.is_readonly () || p->get_type () == db::PCellParameterDeclaration::t_shape) {
continue;
}
if (p->get_choices ().empty ()) {
switch (p->get_type ()) {
case db::PCellParameterDeclaration::t_int:
{
QLineEdit *le = dynamic_cast<QLineEdit *> (m_widgets [r]);
if (le) {
try {
int v = 0;
tl::from_string_ext (tl::to_string (le->text ()), v);
ps.set_value (tl::Variant (v));
lay::indicate_error (le, (tl::Exception *) 0);
} catch (tl::Exception &ex) {
lay::indicate_error (le, &ex);
edit_error = true;
}
}
}
break;
case db::PCellParameterDeclaration::t_double:
{
QLineEdit *le = dynamic_cast<QLineEdit *> (m_widgets [r]);
if (le) {
try {
double v = 0;
tl::from_string_ext (tl::to_string (le->text ()), v);
ps.set_value (tl::Variant (v));
lay::indicate_error (le, (tl::Exception *) 0);
} catch (tl::Exception &ex) {
lay::indicate_error (le, &ex);
edit_error = true;
}
}
}
break;
case db::PCellParameterDeclaration::t_string:
{
QLineEdit *le = dynamic_cast<QLineEdit *> (m_widgets [r]);
if (le) {
ps.set_value (tl::Variant (tl::to_string (le->text ())));
}
}
break;
case db::PCellParameterDeclaration::t_list:
{
QLineEdit *le = dynamic_cast<QLineEdit *> (m_widgets [r]);
if (le) {
std::vector<std::string> values = tl::split (tl::to_string (le->text ()), ",");
ps.set_value (tl::Variant (values.begin (), values.end ()));
}
}
break;
case db::PCellParameterDeclaration::t_layer:
{
lay::LayerSelectionComboBox *ly = dynamic_cast<lay::LayerSelectionComboBox *> (m_widgets [r]);
if (ly) {
ps.set_value (tl::Variant (ly->current_layer_props ()));
}
}
break;
case db::PCellParameterDeclaration::t_boolean:
{
QCheckBox *cbx = dynamic_cast<QCheckBox *> (m_widgets [r]);
if (cbx) {
ps.set_value (tl::Variant (cbx->isChecked ()));
}
}
break;
default:
break;
}
} else {
QComboBox *cb = dynamic_cast<QComboBox*> (m_widgets [r]);
if (cb && cb->currentIndex () >= 0 && cb->currentIndex () < int (p->get_choices ().size ())) {
ps.set_value (p->get_choices () [cb->currentIndex ()]);
}
}
}
}
void
PCellParametersPage::get_parameters (db::ParameterStates &states, bool *ok)
{
try {
if (! mp_pcell_decl) {
throw tl::Exception (tl::to_string (tr ("PCell no longer valid.")));
}
bool edit_error = true;
bool edit_error = false;
int r = 0;
const std::vector<db::PCellParameterDeclaration> &pcp = mp_pcell_decl->parameter_declarations ();
for (std::vector<db::PCellParameterDeclaration>::const_iterator p = pcp.begin (); p != pcp.end (); ++p, ++r) {
get_parameters_internal (states, edit_error);
if (p->is_hidden () || p->get_type () == db::PCellParameterDeclaration::t_shape) {
if (r < (int) m_parameters.size ()) {
parameters.push_back (m_parameters [r]);
} else {
parameters.push_back (p->get_default ());
}
} else {
parameters.push_back (tl::Variant ());
if (p->get_choices ().empty ()) {
switch (p->get_type ()) {
case db::PCellParameterDeclaration::t_int:
{
QLineEdit *le = dynamic_cast<QLineEdit *> (m_widgets [r]);
if (le) {
try {
int v = 0;
tl::from_string_ext (tl::to_string (le->text ()), v);
parameters.back () = tl::Variant (v);
lay::indicate_error (le, (tl::Exception *) 0);
} catch (tl::Exception &ex) {
lay::indicate_error (le, &ex);
edit_error = false;
}
}
}
break;
case db::PCellParameterDeclaration::t_double:
{
QLineEdit *le = dynamic_cast<QLineEdit *> (m_widgets [r]);
if (le) {
try {
double v = 0;
tl::from_string_ext (tl::to_string (le->text ()), v);
parameters.back () = tl::Variant (v);
lay::indicate_error (le, (tl::Exception *) 0);
} catch (tl::Exception &ex) {
lay::indicate_error (le, &ex);
edit_error = false;
}
}
}
break;
case db::PCellParameterDeclaration::t_string:
{
QLineEdit *le = dynamic_cast<QLineEdit *> (m_widgets [r]);
if (le) {
parameters.back () = tl::Variant (tl::to_string (le->text ()));
}
}
break;
case db::PCellParameterDeclaration::t_list:
{
QLineEdit *le = dynamic_cast<QLineEdit *> (m_widgets [r]);
if (le) {
std::vector<std::string> values = tl::split (tl::to_string (le->text ()), ",");
parameters.back () = tl::Variant (values.begin (), values.end ());
}
}
break;
case db::PCellParameterDeclaration::t_layer:
{
lay::LayerSelectionComboBox *ly = dynamic_cast<lay::LayerSelectionComboBox *> (m_widgets [r]);
if (ly) {
parameters.back () = tl::Variant (ly->current_layer_props ());
}
}
break;
case db::PCellParameterDeclaration::t_boolean:
{
QCheckBox *cbx = dynamic_cast<QCheckBox *> (m_widgets [r]);
if (cbx) {
parameters.back () = tl::Variant (cbx->isChecked ());
}
}
break;
default:
break;
}
} else {
QComboBox *cb = dynamic_cast<QComboBox*> (m_widgets [r]);
if (cb && cb->currentIndex () >= 0 && cb->currentIndex () < int (p->get_choices ().size ())) {
parameters.back () = p->get_choices () [cb->currentIndex ()];
}
}
}
}
if (! edit_error) {
if (edit_error) {
throw tl::Exception (tl::to_string (tr ("There are errors. See the highlighted edit fields for details.")));
}
// coerce the parameters
// coerces the parameters and writes the changed values back
if (mp_view->cellview (m_cv_index).is_valid ()) {
auto parameters = parameter_from_states (states);
auto before_coerce = parameters;
mp_pcell_decl->coerce_parameters (mp_view->cellview (m_cv_index)->layout (), parameters);
if (parameters != before_coerce) {
states_from_parameters (states, parameters);
set_parameters_internal (states, lazy_evaluation ());
}
}
set_parameters_internal (parameters, lazy_evaluation ());
if (ok) {
*ok = true;
@ -691,19 +831,112 @@ PCellParametersPage::get_parameters (bool *ok)
}
}
}
return parameters;
std::vector<tl::Variant>
PCellParametersPage::get_parameters (bool *ok)
{
db::ParameterStates states = m_states;
get_parameters (states, ok);
return parameter_from_states (states);
}
void
PCellParametersPage::set_parameters (const std::vector<tl::Variant> &parameters)
{
m_parameters = parameters;
set_parameters_internal (parameters, false);
if (! mp_pcell_decl) {
return;
}
states_from_parameters (m_states, parameters);
try {
if (mp_view->cellview (m_cv_index).is_valid ()) {
mp_pcell_decl->callback (mp_view->cellview (m_cv_index)->layout (), std::string (), m_states);
}
} catch (tl::Exception &ex) {
// potentially caused by script errors in callback implementation
tl::error << ex.msg ();
} catch (std::runtime_error &ex) {
tl::error << ex.what ();
} catch (...) {
// ignore other errors
}
m_initial_states = m_states;
set_parameters_internal (m_states, false);
}
void
PCellParametersPage::set_parameters_internal (const std::vector<tl::Variant> &parameters, bool tentatively)
PCellParametersPage::update_widgets_from_states (const db::ParameterStates &states)
{
if (! mp_pcell_decl) {
return;
}
size_t i = 0;
const std::vector<db::PCellParameterDeclaration> &pcp = mp_pcell_decl->parameter_declarations ();
for (std::vector<db::PCellParameterDeclaration>::const_iterator p = pcp.begin (); p != pcp.end () && i < m_widgets.size (); ++p, ++i) {
const std::string &name = p->get_name ();
const db::ParameterState &ps = states.parameter (name);
if (m_widgets [i]) {
QLineEdit *le = dynamic_cast<QLineEdit *> (m_widgets [i]);
if (le) {
le->setEnabled (ps.is_enabled ());
le->setReadOnly (ps.is_readonly ());
} else {
m_widgets [i]->setEnabled (ps.is_enabled () && ! ps.is_readonly ());
}
}
for (auto w = m_all_widgets [i].begin (); w != m_all_widgets [i].end (); ++w) {
if (*w != m_widgets [i]) {
(*w)->setEnabled (ps.is_enabled ());
}
if (*w != m_icon_widgets [i]) {
(*w)->setVisible (ps.is_visible ());
}
(*w)->setToolTip (tl::to_qstring (ps.tooltip ()));
}
if (m_icon_widgets [i]) {
static QPixmap error (":/error_16px@2x.png");
static QPixmap info (":/info_16px@2x.png");
static QPixmap warning (":/warn_16px@2x.png");
switch (ps.icon ()) {
case db::ParameterState::NoIcon:
default:
m_icon_widgets [i]->setPixmap (QPixmap ());
m_icon_widgets [i]->hide ();
break;
case db::ParameterState::InfoIcon:
m_icon_widgets [i]->setPixmap (info);
m_icon_widgets [i]->show ();
break;
case db::ParameterState::WarningIcon:
m_icon_widgets [i]->setPixmap (warning);
m_icon_widgets [i]->show ();
break;
case db::ParameterState::ErrorIcon:
m_icon_widgets [i]->setPixmap (error);
m_icon_widgets [i]->show ();
break;
}
}
}
set_parameters_internal (states, lazy_evaluation ());
}
void
PCellParametersPage::set_parameters_internal (const db::ParameterStates &states, bool tentatively)
{
if (! mp_pcell_decl) {
return;
@ -713,8 +946,8 @@ PCellParametersPage::set_parameters_internal (const std::vector<tl::Variant> &pa
size_t r = 0;
const std::vector<db::PCellParameterDeclaration> &pcp = mp_pcell_decl->parameter_declarations ();
for (std::vector<db::PCellParameterDeclaration>::const_iterator p = pcp.begin (); p != pcp.end (); ++p, ++r) {
if (r < parameters.size () && m_widgets [r]) {
set_value (*p, m_widgets [r], parameters [r]);
if (m_widgets [r]) {
set_value (*p, m_widgets [r], states.parameter (p->get_name ()).value ());
}
}
@ -723,14 +956,53 @@ PCellParametersPage::set_parameters_internal (const std::vector<tl::Variant> &pa
bool update_needed = false;
if (! tentatively) {
m_current_parameters = parameters;
m_current_states = states;
} else {
update_needed = (m_current_parameters != parameters);
update_needed = ! m_current_states.values_are_equal (states);
}
mp_update_frame->setVisible (update_needed);
}
std::vector<tl::Variant>
PCellParametersPage::parameter_from_states (const db::ParameterStates &states) const
{
std::vector<tl::Variant> parameters;
if (mp_pcell_decl) {
const std::vector<db::PCellParameterDeclaration> &pcp = mp_pcell_decl->parameter_declarations ();
for (auto p = pcp.begin (); p != pcp.end (); ++p) {
if (! states.has_parameter (p->get_name ())) {
parameters.push_back (p->get_default ());
} else {
parameters.push_back (states.parameter (p->get_name ()).value ());
}
}
}
return parameters;
}
void
PCellParametersPage::states_from_parameters (db::ParameterStates &states, const std::vector<tl::Variant> &parameters)
{
if (! mp_pcell_decl) {
return;
}
size_t r = 0;
const std::vector<db::PCellParameterDeclaration> &pcp = mp_pcell_decl->parameter_declarations ();
for (std::vector<db::PCellParameterDeclaration>::const_iterator p = pcp.begin (); p != pcp.end (); ++p, ++r) {
db::ParameterState &ps = states.parameter (p->get_name ());
if (r < parameters.size ()) {
ps.set_value (parameters [r]);
} else {
ps.set_value (p->get_default ());
}
}
}
}
#endif

View File

@ -32,6 +32,7 @@
#include <QScrollArea>
#include <QLabel>
#include <QToolButton>
#include <QCheckBox>
namespace lay
{
@ -52,9 +53,10 @@ Q_OBJECT
public:
struct State
{
State () : valid (false), hScrollPosition (0), vScrollPosition (0) { }
State () : valid (false), show_parameter_names (false), hScrollPosition (0), vScrollPosition (0) { }
bool valid;
bool show_parameter_names;
int hScrollPosition;
int vScrollPosition;
QString focusWidget;
@ -93,7 +95,7 @@ public:
void set_state (const State &s);
/**
* @brief Get the current parameters
* @brief Gets the current parameters
*
* *ok is set to true, if there is no error. In case of an error it's set to false.
* The error is indicated in the error label in the editor page.
@ -102,13 +104,24 @@ public:
std::vector<tl::Variant> get_parameters (bool *ok = 0);
/**
* @brief Gets the initial parameters
* @brief Gets the current parameters into a ParameterStates object
*
* The initial parameters are the ones present on "setup".
* *ok is set to true, if there is no error. In case of an error it's set to false.
* The error is indicated in the error label in the editor page.
* If ok is null, an exception is thrown.
*
* The value fields of the ParameterState members is set to the parameter value.
* The other attributes are not changed. Parameters not present inside the
* ParameterStates object are created with their corresponding name.
*/
const std::vector<tl::Variant> &initial_parameters () const
void get_parameters (db::ParameterStates &states, bool *ok = 0);
/**
* @brief Gets the initial parameters
*/
std::vector<tl::Variant> initial_parameters () const
{
return m_parameters;
return parameter_from_states (m_initial_states);
}
/**
@ -127,6 +140,9 @@ public:
signals:
void edited ();
public slots:
void show_parameter_names (bool f);
private slots:
void parameter_changed ();
void update_button_pressed ();
@ -139,20 +155,27 @@ private:
QLabel *mp_changed_icon;
QToolButton *mp_update_button;
QFrame *mp_error_frame, *mp_update_frame;
QCheckBox *mp_show_parameter_names_cb;
tl::weak_ptr<db::PCellDeclaration> mp_pcell_decl;
std::vector<QWidget *> m_widgets;
std::vector<QLabel *> m_icon_widgets;
std::vector<std::vector<QWidget *> > m_all_widgets;
lay::LayoutViewBase *mp_view;
int m_cv_index;
db::pcell_parameters_type m_parameters;
bool m_dense;
bool m_dense, m_show_parameter_names;
tl::DeferredMethod<PCellParametersPage> dm_parameter_changed;
std::vector<tl::Variant> m_current_parameters;
db::ParameterStates m_current_states, m_initial_states;
db::ParameterStates m_states;
void init ();
void do_parameter_changed ();
bool lazy_evaluation ();
void set_parameters_internal (const std::vector<tl::Variant> &values, bool tentatively);
void set_parameters_internal (const db::ParameterStates &states, bool tentatively);
bool update_current_parameters ();
void update_widgets_from_states (const db::ParameterStates &states);
void get_parameters_internal (db::ParameterStates &states, bool &edit_error);
std::vector<tl::Variant> parameter_from_states (const db::ParameterStates &states) const;
void states_from_parameters (db::ParameterStates &states, const std::vector<tl::Variant> &parameters);
};
}

View File

@ -342,6 +342,8 @@ public:
menu_entries.push_back (lay::menu_item ("edt::sel_make_cell_variants", "make_cell_variants:edit_mode", "edit_menu.selection_menu.end", tl::to_string (tr ("Make Cell Variants"))));
menu_entries.push_back (lay::menu_item ("edt::sel_convert_to_pcell", "convert_to_pcell:edit_mode", "edit_menu.selection_menu.end", tl::to_string (tr ("Convert To PCell"))));
menu_entries.push_back (lay::menu_item ("edt::sel_convert_to_cell", "convert_to_cell:edit_mode", "edit_menu.selection_menu.end", tl::to_string (tr ("Convert To Static Cell"))));
menu_entries.push_back (lay::separator ("hier_group:edit_info", "edit_menu.selection_menu.end"));
menu_entries.push_back (lay::menu_item ("edt::sel_area_perimeter", "area_perimeter", "edit_menu.selection_menu.end", tl::to_string (tr ("Area and Perimeter"))));
menu_entries.push_back (lay::menu_item ("edt::combine_mode", "combine_mode:edit_mode", "@toolbar.end_modes", tl::to_string (tr ("Combine{Select background combination mode}"))));
}

View File

@ -52,8 +52,9 @@ public:
virtual size_t count () const;
virtual void select_entries (const std::vector<size_t> &entries);
virtual std::string description (size_t entry) const;
virtual QIcon icon (size_t entry, int w, int h) const;
virtual std::string description () const;
virtual QIcon icon (size_t entry, int w, int h) const;
virtual QIcon icon (int w, int h) const { return lay::PropertiesPage::icon (w, h); }
virtual void leave ();
protected:
@ -105,6 +106,7 @@ public:
PolygonPropertiesPage (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);
@ -129,6 +131,7 @@ public:
BoxPropertiesPage (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);
@ -159,6 +162,7 @@ public:
TextPropertiesPage (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);
@ -177,6 +181,7 @@ public:
PathPropertiesPage (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);
@ -198,6 +203,7 @@ public:
EditablePathPropertiesPage (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);

View File

@ -524,7 +524,7 @@ public:
// .. nothing yet ..
}
#if !defined(NDEBUG)
#if defined(TRACE_METHOD_CALLS)
public:
/**

View File

@ -130,6 +130,11 @@ equals(HAVE_CRONOLOGY, "1") {
INCLUDEPATH += $$CRONOLOGY_INCLUDE
}
!lessThan(QT_MAJOR_VERSION, 6) {
# internal resource readers to not support zstd so far
QMAKE_RESOURCE_FLAGS += --compress-algo zlib
}
msvc {
QMAKE_CXXFLAGS += \
@ -162,16 +167,25 @@ msvc {
QMAKE_CXXFLAGS_WARN_ON += \
-pedantic \
-Woverloaded-virtual \
-Wsign-promo \
-Wsynth \
-Wno-deprecated \
-Wno-long-long \
-Wno-strict-aliasing \
-Wno-deprecated-declarations \
-Wno-reserved-user-defined-literal \
# because we use unordered_map/unordered_set:
QMAKE_CXXFLAGS += -std=c++11
# too noisy on Qt:
# QMAKE_CXXFLAGS_WARN_ON += \
# -Wsign-promo \
# -Wno-reserved-user-defined-literal \
#
lessThan(QT_MAJOR_VERSION, 6) {
# because we use unordered_map/unordered_set:
QMAKE_CXXFLAGS += -std=c++11
} else {
# because we use unordered_map/unordered_set:
QMAKE_CXXFLAGS += -std=c++17
}
win32 {

View File

@ -17,7 +17,7 @@
<item>
<widget class="QTabWidget" name="mode_tab">
<property name="currentIndex">
<number>0</number>
<number>2</number>
</property>
<widget class="QWidget" name="tab_2">
<attribute name="title">
@ -217,6 +217,12 @@
</property>
<item>
<widget class="QLabel" name="label_6">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>1</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="font">
<font>
<bold>true</bold>
@ -227,6 +233,19 @@
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="detailed_view">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>More details</string>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="toolButton">
<property name="enabled">
@ -515,6 +534,12 @@
</property>
<item>
<widget class="QLabel" name="label_9">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>1</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="font">
<font>
<bold>true</bold>
@ -525,6 +550,13 @@
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="detailed_view2">
<property name="text">
<string>More details</string>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="toolButton_2">
<property name="enabled">
@ -935,8 +967,21 @@
<property name="bottomMargin">
<number>0</number>
</property>
<item row="1" column="0" colspan="3">
<widget class="lay::SaltGrainDetailsTextWidget" name="details_text">
<property name="openExternalLinks">
<bool>true</bool>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="label">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>1</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="font">
<font>
<bold>true</bold>
@ -947,7 +992,7 @@
</property>
</widget>
</item>
<item row="0" column="1">
<item row="0" column="2">
<widget class="QToolButton" name="edit_button">
<property name="toolTip">
<string>Edit Package Details</string>
@ -964,10 +1009,10 @@
</property>
</widget>
</item>
<item row="1" column="0" colspan="2">
<widget class="lay::SaltGrainDetailsTextWidget" name="details_text">
<property name="openExternalLinks">
<bool>true</bool>
<item row="0" column="1">
<widget class="QCheckBox" name="detailed_view3">
<property name="text">
<string>More details</string>
</property>
</widget>
</item>
@ -1157,20 +1202,33 @@
<class>lay::SaltGrainDetailsTextWidget</class>
<extends>QTextBrowser</extends>
<header>laySaltGrainDetailsTextWidget.h</header>
<slots>
<slot>show_detailed_view(bool)</slot>
</slots>
</customwidget>
</customwidgets>
<tabstops>
<tabstop>mode_tab</tabstop>
<tabstop>mark_new_button</tabstop>
<tabstop>search_new_edit</tabstop>
<tabstop>salt_mine_view_new</tabstop>
<tabstop>detailed_view</tabstop>
<tabstop>toolButton</tabstop>
<tabstop>details_new_text</tabstop>
<tabstop>mark_update_button</tabstop>
<tabstop>search_update_edit</tabstop>
<tabstop>salt_mine_view_update</tabstop>
<tabstop>detailed_view2</tabstop>
<tabstop>toolButton_2</tabstop>
<tabstop>details_update_text</tabstop>
<tabstop>search_installed_edit</tabstop>
<tabstop>salt_view</tabstop>
<tabstop>details_text</tabstop>
<tabstop>detailed_view3</tabstop>
<tabstop>edit_button</tabstop>
<tabstop>search_new_edit</tabstop>
<tabstop>mark_new_button</tabstop>
<tabstop>salt_mine_view_new</tabstop>
<tabstop>details_new_text</tabstop>
<tabstop>toolButton</tabstop>
<tabstop>details_text</tabstop>
<tabstop>create_button</tabstop>
<tabstop>apply_new_button</tabstop>
<tabstop>apply_update_button</tabstop>
<tabstop>scrollArea</tabstop>
</tabstops>
<resources>
@ -1193,5 +1251,53 @@
</hint>
</hints>
</connection>
<connection>
<sender>detailed_view</sender>
<signal>clicked(bool)</signal>
<receiver>details_new_text</receiver>
<slot>show_detailed_view(bool)</slot>
<hints>
<hint type="sourcelabel">
<x>588</x>
<y>57</y>
</hint>
<hint type="destinationlabel">
<x>578</x>
<y>121</y>
</hint>
</hints>
</connection>
<connection>
<sender>detailed_view2</sender>
<signal>clicked(bool)</signal>
<receiver>details_update_text</receiver>
<slot>show_detailed_view(bool)</slot>
<hints>
<hint type="sourcelabel">
<x>616</x>
<y>58</y>
</hint>
<hint type="destinationlabel">
<x>615</x>
<y>96</y>
</hint>
</hints>
</connection>
<connection>
<sender>detailed_view3</sender>
<signal>clicked(bool)</signal>
<receiver>details_text</receiver>
<slot>show_detailed_view(bool)</slot>
<hints>
<hint type="sourcelabel">
<x>602</x>
<y>58</y>
</hint>
<hint type="destinationlabel">
<x>603</x>
<y>91</y>
</hint>
</hints>
</connection>
</connections>
</ui>

View File

@ -328,6 +328,10 @@ MacroController::drop_url (const std::string &path_or_url)
void
MacroController::show_editor (const std::string &cat, bool force_add)
{
if (macro_categories ().empty ()) {
throw tl::Exception (tl::to_string (QObject::tr ("Application has not been compiled with scripting support - no macro IDE available")));
}
if (mp_macro_editor) {
mp_macro_editor->show (cat, force_add);
}

View File

@ -36,14 +36,15 @@ namespace lay
{
SaltGrainDetailsTextWidget::SaltGrainDetailsTextWidget (QWidget *w)
: QTextBrowser (w), mp_grain ()
: QTextBrowser (w), mp_grain (), m_detailed_view (false)
{
setOpenLinks (false);
setOpenExternalLinks (false);
connect (this, SIGNAL (anchorClicked (const QUrl &)), this, SLOT (open_link (const QUrl &)));
}
void SaltGrainDetailsTextWidget::set_grain (const SaltGrain *g)
void
SaltGrainDetailsTextWidget::set_grain (const SaltGrain *g)
{
if (g) {
mp_grain.reset (new SaltGrain (*g));
@ -53,6 +54,15 @@ void SaltGrainDetailsTextWidget::set_grain (const SaltGrain *g)
setHtml (details_text ());
}
void
SaltGrainDetailsTextWidget::show_detailed_view (bool f)
{
if (m_detailed_view != f) {
m_detailed_view = f;
setHtml (details_text ());
}
}
void
SaltGrainDetailsTextWidget::open_link (const QUrl &url)
{
@ -276,32 +286,36 @@ SaltGrainDetailsTextWidget::details_text ()
stream << "<h3>" << QObject::tr ("Screenshot") << "</h3><p><img src=\":/screenshot\"/></p>";
}
stream << "<br/>";
stream << "<h3>" << QObject::tr ("Installation") << "</h3>";
if (m_detailed_view) {
if (! g->url ().empty ()) {
stream << "<p><b>" << QObject::tr ("Download URL: ") << "</b>" << tl::to_qstring (tl::escaped_to_html (g->url ())) << "</p>";
}
if (! g->path ().empty () && ! g->installed_time ().isNull ()) {
stream << "<p><b>" << QObject::tr ("Installed: ") << "</b>" << g->installed_time ().toString () << "</p>";
}
if (! g->dependencies ().empty ()) {
stream << "<p><b>" << QObject::tr ("Depends on: ") << "</b><br/>";
for (std::vector<lay::SaltGrainDependency>::const_iterator d = g->dependencies ().begin (); d != g->dependencies ().end (); ++d) {
stream << "&nbsp;&nbsp;&nbsp;&nbsp;" << tl::to_qstring (tl::escaped_to_html (d->name)) << " ";
stream << tl::to_qstring (tl::escaped_to_html (d->version));
if (! d->url.empty ()) {
stream << " - ";
stream << "[" << tl::to_qstring (tl::escaped_to_html (d->url)) << "]<br/>";
}
stream << "<br/>";
stream << "<h3>" << QObject::tr ("Installation") << "</h3>";
if (! g->url ().empty ()) {
stream << "<p><b>" << QObject::tr ("Download URL: ") << "</b>" << tl::to_qstring (tl::escaped_to_html (g->url ())) << "</p>";
}
if (! g->path ().empty () && ! g->installed_time ().isNull ()) {
stream << "<p><b>" << QObject::tr ("Installed: ") << "</b>" << g->installed_time ().toString () << "</p>";
}
if (! g->dependencies ().empty ()) {
stream << "<p><b>" << QObject::tr ("Depends on: ") << "</b><br/>";
for (std::vector<lay::SaltGrainDependency>::const_iterator d = g->dependencies ().begin (); d != g->dependencies ().end (); ++d) {
stream << "&nbsp;&nbsp;&nbsp;&nbsp;" << tl::to_qstring (tl::escaped_to_html (d->name)) << " ";
stream << tl::to_qstring (tl::escaped_to_html (d->version));
if (! d->url.empty ()) {
stream << " - ";
stream << "[" << tl::to_qstring (tl::escaped_to_html (d->url)) << "]<br/>";
}
}
stream << "</p>";
}
if (! g->path ().empty ()) {
stream << "<p><b>" << QObject::tr ("Installed files: ") << "</b></p><p>";
produce_listing (stream, QDir (tl::to_qstring (g->path ())), 0);
stream << "</p>";
}
stream << "</p>";
}
if (! g->path ().empty ()) {
stream << "<p><b>" << QObject::tr ("Installed files: ") << "</b></p><p>";
produce_listing (stream, QDir (tl::to_qstring (g->path ())), 0);
stream << "</p>";
}
stream << "</td></tr></table>";

View File

@ -55,6 +55,9 @@ public:
protected:
virtual QVariant loadResource (int type, const QUrl &url);
public slots:
void show_detailed_view (bool f);
private slots:
void open_link (const QUrl &url);
@ -62,6 +65,7 @@ private:
std::unique_ptr<lay::SaltGrain> mp_grain;
QString details_text ();
bool m_detailed_view;
};
}

View File

@ -65,7 +65,7 @@ ObjectInstPath::is_valid (lay::LayoutViewBase *view) const
}
if (! is_cell_inst ()) {
if (! ly.is_valid_layer (layer ())) {
if (! ly.is_valid_layer (layer ()) && layer () != ly.guiding_shape_layer ()) {
return false;
}
if (! ly.cell (ci).shapes (layer ()).is_valid (shape ())) {

View File

@ -53,13 +53,13 @@ private:
std::string m_text;
};
#if defined(HAVE_RUBY)
static std::string np (const std::string &s)
{
return tl::replaced (s, "\\", "/");
}
#if defined(HAVE_RUBY)
TEST(1_BasicRuby)
{
tl_assert (rba::RubyInterpreter::instance () != 0);

View File

@ -190,7 +190,7 @@
<string>...</string>
</property>
<property name="icon">
<iconset resource="../../../../lay/lay/layResources.qrc">
<iconset resource="../../../../icons/icons.qrc">
<normaloff>:/clear_16px.png</normaloff>:/clear_16px.png</iconset>
</property>
</widget>
@ -204,7 +204,7 @@
<string>...</string>
</property>
<property name="icon">
<iconset resource="../../../../lay/lay/layResources.qrc">
<iconset resource="../../../../icons/icons.qrc">
<normaloff>:/add_16px.png</normaloff>:/add_16px.png</iconset>
</property>
</widget>
@ -218,7 +218,7 @@
<string>...</string>
</property>
<property name="icon">
<iconset resource="../../../../lay/lay/layResources.qrc">
<iconset resource="../../../../icons/icons.qrc">
<normaloff>:/up_16px.png</normaloff>:/up_16px.png</iconset>
</property>
</widget>
@ -232,7 +232,7 @@
<string>...</string>
</property>
<property name="icon">
<iconset resource="../../../../lay/lay/layResources.qrc">
<iconset resource="../../../../icons/icons.qrc">
<normaloff>:/down_16px.png</normaloff>:/down_16px.png</iconset>
</property>
</widget>
@ -298,7 +298,7 @@
<tabstop>buttonBox</tabstop>
</tabstops>
<resources>
<include location="../../../../lay/lay/layResources.qrc"/>
<include location="../../../../icons/icons.qrc"/>
</resources>
<connections>
<connection>

View File

@ -147,7 +147,7 @@
<string>...</string>
</property>
<property name="icon">
<iconset resource="../../../../lay/lay/layResources.qrc">
<iconset resource="../../../../icons/icons.qrc">
<normaloff>:/clear_16px.png</normaloff>:/clear_16px.png</iconset>
</property>
</widget>
@ -161,7 +161,7 @@
<string>...</string>
</property>
<property name="icon">
<iconset resource="../../../../lay/lay/layResources.qrc">
<iconset resource="../../../../icons/icons.qrc">
<normaloff>:/down_16px.png</normaloff>:/down_16px.png</iconset>
</property>
</widget>
@ -175,7 +175,7 @@
<string>...</string>
</property>
<property name="icon">
<iconset resource="../../../../lay/lay/layResources.qrc">
<iconset resource="../../../../icons/icons.qrc">
<normaloff>:/add_16px.png</normaloff>:/add_16px.png</iconset>
</property>
</widget>
@ -197,7 +197,7 @@ You can use expressions inside the path components for variable paths</string>
<string>...</string>
</property>
<property name="icon">
<iconset resource="../../../../lay/lay/layResources.qrc">
<iconset resource="../../../../icons/icons.qrc">
<normaloff>:/up_16px.png</normaloff>:/up_16px.png</iconset>
</property>
</widget>
@ -315,7 +315,7 @@ You can use expressions inside the path components for variable paths</string>
<tabstop>read_all_cbx</tabstop>
</tabstops>
<resources>
<include location="../../../../lay/lay/layResources.qrc"/>
<include location="../../../../icons/icons.qrc"/>
</resources>
<connections>
<connection>

View File

@ -284,7 +284,7 @@
<string/>
</property>
<property name="pixmap">
<pixmap resource="../../../../lay/lay/layResources.qrc">:/warn_16px@2x.png</pixmap>
<pixmap resource="../../../../icons/icons.qrc">:/warn_16px@2x.png</pixmap>
</property>
</widget>
</item>
@ -379,7 +379,7 @@
<string/>
</property>
<property name="pixmap">
<pixmap resource="../../../../lay/lay/layResources.qrc">:/warn_16px@2x.png</pixmap>
<pixmap resource="../../../../icons/icons.qrc">:/warn_16px@2x.png</pixmap>
</property>
</widget>
</item>
@ -430,7 +430,7 @@
<tabstop>subst_char</tabstop>
</tabstops>
<resources>
<include location="../../../../lay/lay/layResources.qrc"/>
<include location="../../../../icons/icons.qrc"/>
</resources>
<connections/>
</ui>

View File

@ -22,3 +22,4 @@ SOURCES = \
FORMS = \
OASISWriterOptionPage.ui \

View File

@ -202,13 +202,13 @@ public:
} else {
int y2 = m_pixmap_size - 1 - (iy * m_pixmap_size + m_pixmap_size / 2) / ny;
int y1 = m_pixmap_size - 1 - ((iy + 1) * m_pixmap_size + m_pixmap_size / 2) / ny;
int x1 = (ix * m_pixmap_size + m_pixmap_size / 2) / nx;
int x2 = ((ix + 1) * m_pixmap_size + m_pixmap_size / 2) / nx;
int y2 = std::min (m_pixmap_size - 1, m_pixmap_size - 1 - (iy * m_pixmap_size + ny / 2) / ny);
int y1 = std::max (0, m_pixmap_size - 1 - ((iy + 1) * m_pixmap_size + ny / 2) / ny);
int x1 = std::max (0, (ix * m_pixmap_size + nx / 2) / nx);
int x2 = std::min (m_pixmap_size - 1, ((ix + 1) * m_pixmap_size + nx / 2) / nx);
// "draw" the field
for (int y = y1; y <= y2 && y >= 0 && y < m_pixmap_size; ++y) {
for (int y = y1; y <= y2; ++y) {
*((uint32_t *) img->scanLine (y)) &= (((1 << x1) - 1) | ~((1 << (x2 + 1)) - 1));
}
@ -319,8 +319,8 @@ public:
grad.setColorAt (0.0, QColor (248, 248, 248));
grad.setColorAt (1.0, QColor (224, 224, 224));
painter.setBrush (QBrush (grad));
painter.setPen (QPen (Qt::black));
painter.drawRect (QRect (QPoint (x, y - 2), QSize (m_pixmap_size + 3, m_pixmap_size + 3)));
painter.setPen (QPen (Qt::black, 1.0, Qt::SolidLine, Qt::SquareCap, Qt::MiterJoin));
painter.drawRect (QRectF (QPointF (x + 1, y - 1), QSizeF (m_pixmap_size + 2, m_pixmap_size + 2)));
painter.setBackgroundMode (Qt::TransparentMode);
painter.setPen (QColor (128, 255, 128));

View File

@ -408,19 +408,19 @@ struct PythonClassClientData
: public gsi::PerClassClientSpecificData
{
PythonClassClientData (const gsi::ClassBase *_cls, PyTypeObject *_py_type, PyTypeObject *_py_type_static)
: py_type_object (_py_type), py_type_object_static (_py_type_static), method_table (_cls)
: py_type_object ((PyObject *) _py_type), py_type_object_static ((PyObject *) _py_type_static), method_table (_cls)
{
// .. nothing yet ..
}
PyTypeObject *py_type_object;
PyTypeObject *py_type_object_static;
PythonPtr py_type_object;
PythonPtr py_type_object_static;
MethodTable method_table;
static PyTypeObject *py_type (const gsi::ClassBase &cls_decl, bool as_static)
{
PythonClassClientData *cd = dynamic_cast<PythonClassClientData *>(cls_decl.data (gsi::ClientIndex::Python));
return cd ? (as_static ? cd->py_type_object_static : cd->py_type_object) : 0;
return (PyTypeObject *) (cd ? (as_static ? cd->py_type_object_static.get () : cd->py_type_object.get ()) : 0);
}
static void initialize (const gsi::ClassBase &cls_decl, PyTypeObject *py_type, bool as_static)
@ -428,9 +428,9 @@ struct PythonClassClientData
PythonClassClientData *cd = dynamic_cast<PythonClassClientData *>(cls_decl.data (gsi::ClientIndex::Python));
if (cd) {
if (as_static) {
cd->py_type_object_static = py_type;
cd->py_type_object_static = (PyObject *) py_type;
} else {
cd->py_type_object = py_type;
cd->py_type_object = (PyObject *) py_type;
}
} else {
cls_decl.set_data (gsi::ClientIndex::Python, new PythonClassClientData (&cls_decl, as_static ? NULL : py_type, as_static ? py_type : NULL));
@ -2475,7 +2475,11 @@ public:
PyTypeObject *type = (PyTypeObject *) PyObject_Call ((PyObject *) &PyType_Type, args.get (), NULL);
if (type == NULL) {
check_error ();
try {
check_error ();
} catch (tl::Exception &ex) {
tl::error << ex.msg ();
}
tl_assert (false);
}

View File

@ -79,20 +79,28 @@ LIBS += -L$$LIBDIR -lklayout_db
!msvc {
# Some standard compiler warnings on
QMAKE_CXXFLAGS_WARN_ON += \
-pedantic \
-Woverloaded-virtual \
-Wsign-promo \
-Wsynth \
-Wno-deprecated \
-Wno-long-long \
-Wno-strict-aliasing \
-Wno-deprecated-declarations \
-Wno-reserved-user-defined-literal \
# because we use unordered_map/unordered_set:
QMAKE_CXXFLAGS += -std=c++11
# too noisy on Qt:
# QMAKE_CXXFLAGS_WARN_ON += \
# -Wsign-promo \
# -Wno-reserved-user-defined-literal \
#
lessThan(QT_MAJOR_VERSION, 6) {
# because we use unordered_map/unordered_set:
QMAKE_CXXFLAGS += -std=c++11
} else {
# because we use unordered_map/unordered_set:
QMAKE_CXXFLAGS += -std=c++17
}
# Python is somewhat sloppy and relies on the compiler initializing fields
# of strucs to 0:

View File

@ -212,9 +212,9 @@ InputStream::InputStream (const std::string &abstract_path)
QByteArray data;
#if QT_VERSION >= 0x60000
if (res.compressionAlgorithm () == QResource::ZlibCompression) {
if (res.compressionAlgorithm () == QResource::ZlibCompression) {
#else
if (res.isCompressed ()) {
if (res.isCompressed ()) {
#endif
data = qUncompress ((const unsigned char *)res.data (), (int)res.size ());
} else {

View File

@ -14,10 +14,10 @@ to_fill = extent - l1
fp1 = fill_pattern("FP1").shape(10, 0, box(0, 0, 800.nm, 800.nm)).origin(-100.nm, -100.nm)
to_fill = to_fill.fill_with_left(fp1, hstep(1.um), vstep(200.nm, 1.um), multi_origin)
fp2 = fill_pattern("FP2").shape(10, 0, box(0, 0, 400.nm, 400.nm)).origin(-50.nm, -50.nm)
fp2 = fill_pattern("FP2").shape(10, box(0, 0, 400.nm, 400.nm)).origin(-50.nm, -50.nm)
to_fill = to_fill.fill_with_left(fp2, hstep(0.5.um), vstep(100.nm, 0.5.um), multi_origin)
fp3 = fill_pattern("FP3").shape(10, 0, box(0, 0, 200.nm, 200.nm)).origin(-25.nm, -25.nm)
fp3 = fill_pattern("FP3").shape(RBA::LayerInfo::new(10, 0), box(0, 0, 200.nm, 200.nm)).origin(-25.nm, -25.nm)
to_fill = to_fill.fill_with_left(fp3, hstep(0.25.um), vstep(50.nm, 0.25.um), multi_origin)
to_fill.output(100, 0)

Binary file not shown.

Binary file not shown.

Binary file not shown.