mirror of https://github.com/KLayout/klayout.git
Merge remote-tracking branch 'origin/master' into master-mac-qt6
This commit is contained in:
commit
40b845693c
|
|
@ -89,7 +89,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>
|
||||
|
|
@ -103,7 +103,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>
|
||||
|
|
@ -117,7 +117,7 @@
|
|||
<string>...</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../../lay/lay/layResources.qrc">
|
||||
<iconset resource="../../icons/icons.qrc">
|
||||
<normaloff>:/del_16px.png</normaloff>:/del_16px.png</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
|
|
@ -131,7 +131,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>
|
||||
|
|
@ -574,6 +574,16 @@
|
|||
<string>Ellipse</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Angle measurement</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Radius measurement</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="0">
|
||||
|
|
@ -833,6 +843,16 @@
|
|||
<string>Auto measure (points will be set automatically)</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Angle measurement (three mouse clicks)</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Multi-segment (finish with double click)</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="9" column="0">
|
||||
|
|
@ -866,7 +886,7 @@
|
|||
<tabstop>t_snap_cbx</tabstop>
|
||||
</tabstops>
|
||||
<resources>
|
||||
<include location="../../lay/lay/layResources.qrc"/>
|
||||
<include location="../../icons/icons.qrc"/>
|
||||
</resources>
|
||||
<connections/>
|
||||
</ui>
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -136,6 +136,10 @@ OutlineConverter::to_string (ant::Object::outline_type o)
|
|||
return "box";
|
||||
} else if (o == ant::Object::OL_ellipse) {
|
||||
return "ellipse";
|
||||
} else if (o == ant::Object::OL_radius) {
|
||||
return "radius";
|
||||
} else if (o == ant::Object::OL_angle) {
|
||||
return "angle";
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
|
|
@ -159,6 +163,10 @@ OutlineConverter::from_string (const std::string &s, ant::Object::outline_type &
|
|||
o = ant::Object::OL_box;
|
||||
} else if (t == "ellipse") {
|
||||
o = ant::Object::OL_ellipse;
|
||||
} else if (t == "radius") {
|
||||
o = ant::Object::OL_radius;
|
||||
} else if (t == "angle") {
|
||||
o = ant::Object::OL_angle;
|
||||
} else {
|
||||
o = ant::Object::OL_diag;
|
||||
}
|
||||
|
|
@ -239,6 +247,10 @@ RulerModeConverter::to_string (ant::Template::ruler_mode_type m)
|
|||
return "single_click";
|
||||
} else if (m == ant::Template::RulerAutoMetric) {
|
||||
return "auto_metric";
|
||||
} else if (m == ant::Template::RulerMultiSegment) {
|
||||
return "multi_segment";
|
||||
} else if (m == ant::Template::RulerThreeClicks) {
|
||||
return "angle";
|
||||
} else {
|
||||
return "normal";
|
||||
}
|
||||
|
|
@ -254,6 +266,10 @@ RulerModeConverter::from_string (const std::string &s, ant::Template::ruler_mode
|
|||
a = ant::Template::RulerSingleClick;
|
||||
} else if (t == "auto_metric") {
|
||||
a = ant::Template::RulerAutoMetric;
|
||||
} else if (t == "multi_segment") {
|
||||
a = ant::Template::RulerMultiSegment;
|
||||
} else if (t == "angle") {
|
||||
a = ant::Template::RulerThreeClicks;
|
||||
} else {
|
||||
a = ant::Template::RulerNormal;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -32,8 +32,26 @@
|
|||
namespace ant
|
||||
{
|
||||
|
||||
static void
|
||||
clean_points_impl (ant::Object::point_list &points)
|
||||
{
|
||||
auto wp = points.begin ();
|
||||
auto p = points.begin ();
|
||||
while (p != points.end ()) {
|
||||
auto pp = p + 1;
|
||||
while (pp != points.end () && *pp == *p) {
|
||||
++pp;
|
||||
}
|
||||
*wp++ = *p;
|
||||
p = pp;
|
||||
}
|
||||
|
||||
points.erase (wp, points.end ());
|
||||
}
|
||||
|
||||
|
||||
Object::Object ()
|
||||
: m_p1 (), m_p2 (), m_id (-1),
|
||||
: m_id (-1),
|
||||
m_fmt_x ("$X"), m_fmt_y ("$Y"), m_fmt ("$D"),
|
||||
m_style (STY_ruler), m_outline (OL_diag),
|
||||
m_snap (true), m_angle_constraint (lay::AC_Global),
|
||||
|
|
@ -45,8 +63,8 @@ Object::Object ()
|
|||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
Object::Object (const db::DPoint &p1, const db::DPoint &p2, int id, const std::string &fmt_x, const std::string &fmt_y, const std::string &fmt, style_type style, outline_type outline, bool snap, lay::angle_constraint_type angle_constraint)
|
||||
: m_p1 (p1), m_p2 (p2), m_id (id),
|
||||
Object::Object (const db::DPoint &_p1, const db::DPoint &_p2, int id, const std::string &fmt_x, const std::string &fmt_y, const std::string &fmt, style_type style, outline_type outline, bool snap, lay::angle_constraint_type angle_constraint)
|
||||
: m_id (id),
|
||||
m_fmt_x (fmt_x), m_fmt_y (fmt_y), m_fmt (fmt),
|
||||
m_style (style), m_outline (outline),
|
||||
m_snap (snap), m_angle_constraint (angle_constraint),
|
||||
|
|
@ -55,11 +73,25 @@ Object::Object (const db::DPoint &p1, const db::DPoint &p2, int id, const std::s
|
|||
m_xlabel_xalign (AL_auto), m_xlabel_yalign (AL_auto),
|
||||
m_ylabel_xalign (AL_auto), m_ylabel_yalign (AL_auto)
|
||||
{
|
||||
// .. nothing else ..
|
||||
p1 (_p1);
|
||||
p2 (_p2);
|
||||
}
|
||||
|
||||
Object::Object (const db::DPoint &p1, const db::DPoint &p2, int id, const ant::Template &t)
|
||||
: m_p1 (p1), m_p2 (p2), m_id (id),
|
||||
Object::Object (const Object::point_list &pts, int id, const std::string &fmt_x, const std::string &fmt_y, const std::string &fmt, style_type style, outline_type outline, bool snap, lay::angle_constraint_type angle_constraint)
|
||||
: m_id (id),
|
||||
m_fmt_x (fmt_x), m_fmt_y (fmt_y), m_fmt (fmt),
|
||||
m_style (style), m_outline (outline),
|
||||
m_snap (snap), m_angle_constraint (angle_constraint),
|
||||
m_main_position (POS_auto),
|
||||
m_main_xalign (AL_auto), m_main_yalign (AL_auto),
|
||||
m_xlabel_xalign (AL_auto), m_xlabel_yalign (AL_auto),
|
||||
m_ylabel_xalign (AL_auto), m_ylabel_yalign (AL_auto)
|
||||
{
|
||||
set_points (pts);
|
||||
}
|
||||
|
||||
Object::Object (const db::DPoint &_p1, const db::DPoint &_p2, int id, const ant::Template &t)
|
||||
: m_id (id),
|
||||
m_fmt_x (t.fmt_x ()), m_fmt_y (t.fmt_y ()), m_fmt (t.fmt ()),
|
||||
m_style (t.style ()), m_outline (t.outline ()),
|
||||
m_snap (t.snap ()), m_angle_constraint (t.angle_constraint ()),
|
||||
|
|
@ -69,11 +101,26 @@ Object::Object (const db::DPoint &p1, const db::DPoint &p2, int id, const ant::T
|
|||
m_xlabel_xalign (t.xlabel_xalign ()), m_xlabel_yalign (t.xlabel_yalign ()),
|
||||
m_ylabel_xalign (t.ylabel_xalign ()), m_ylabel_yalign (t.ylabel_yalign ())
|
||||
{
|
||||
// .. nothing else ..
|
||||
p1 (_p1);
|
||||
p2 (_p2);
|
||||
}
|
||||
|
||||
Object::Object (const Object::point_list &pts, int id, const ant::Template &t)
|
||||
: m_points (pts), m_id (id),
|
||||
m_fmt_x (t.fmt_x ()), m_fmt_y (t.fmt_y ()), m_fmt (t.fmt ()),
|
||||
m_style (t.style ()), m_outline (t.outline ()),
|
||||
m_snap (t.snap ()), m_angle_constraint (t.angle_constraint ()),
|
||||
m_category (t.category ()),
|
||||
m_main_position (t.main_position ()),
|
||||
m_main_xalign (t.main_xalign ()), m_main_yalign (t.main_yalign ()),
|
||||
m_xlabel_xalign (t.xlabel_xalign ()), m_xlabel_yalign (t.xlabel_yalign ()),
|
||||
m_ylabel_xalign (t.ylabel_xalign ()), m_ylabel_yalign (t.ylabel_yalign ())
|
||||
{
|
||||
clean_points_impl (m_points);
|
||||
}
|
||||
|
||||
Object::Object (const ant::Object &d)
|
||||
: m_p1 (d.m_p1), m_p2 (d.m_p2), m_id (d.m_id),
|
||||
: m_points (d.m_points), m_id (d.m_id),
|
||||
m_fmt_x (d.m_fmt_x), m_fmt_y (d.m_fmt_y), m_fmt (d.m_fmt),
|
||||
m_style (d.m_style), m_outline (d.m_outline),
|
||||
m_snap (d.m_snap), m_angle_constraint (d.m_angle_constraint),
|
||||
|
|
@ -90,8 +137,7 @@ Object &
|
|||
Object::operator= (const ant::Object &d)
|
||||
{
|
||||
if (this != &d) {
|
||||
m_p1 = d.m_p1;
|
||||
m_p2 = d.m_p2;
|
||||
m_points = d.m_points;
|
||||
m_id = d.m_id;
|
||||
m_fmt_x = d.m_fmt_x;
|
||||
m_fmt_y = d.m_fmt_y;
|
||||
|
|
@ -119,11 +165,8 @@ Object::operator< (const ant::Object &b) const
|
|||
if (m_id != b.m_id) {
|
||||
return m_id < b.m_id;
|
||||
}
|
||||
if (m_p1 != b.m_p1) {
|
||||
return m_p1 < b.m_p1;
|
||||
}
|
||||
if (m_p2 != b.m_p2) {
|
||||
return m_p2 < b.m_p2;
|
||||
if (m_points != b.m_points) {
|
||||
return m_points < b.m_points;
|
||||
}
|
||||
if (m_fmt_x != b.m_fmt_x) {
|
||||
return m_fmt_x < b.m_fmt_x;
|
||||
|
|
@ -187,7 +230,7 @@ Object::equals (const db::DUserObjectBase *d) const
|
|||
bool
|
||||
Object::operator== (const ant::Object &d) const
|
||||
{
|
||||
return m_p1 == d.m_p1 && m_p2 == d.m_p2 && m_id == d.m_id &&
|
||||
return m_points == d.m_points && m_id == d.m_id &&
|
||||
m_fmt_x == d.m_fmt_x && m_fmt_y == d.m_fmt_y && m_fmt == d.m_fmt &&
|
||||
m_style == d.m_style && m_outline == d.m_outline &&
|
||||
m_snap == d.m_snap && m_angle_constraint == d.m_angle_constraint &&
|
||||
|
|
@ -199,6 +242,129 @@ Object::operator== (const ant::Object &d) const
|
|||
;
|
||||
}
|
||||
|
||||
void
|
||||
Object::clean_points ()
|
||||
{
|
||||
auto new_points = m_points;
|
||||
clean_points_impl (new_points);
|
||||
set_points_exact (std::move (new_points));
|
||||
}
|
||||
|
||||
void
|
||||
Object::set_points (const point_list &points)
|
||||
{
|
||||
auto new_points = points;
|
||||
clean_points_impl (new_points);
|
||||
set_points_exact (std::move (new_points));
|
||||
}
|
||||
|
||||
void
|
||||
Object::set_points_exact (const point_list &points)
|
||||
{
|
||||
if (m_points != points) {
|
||||
m_points = points;
|
||||
property_changed ();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Object::set_points_exact (point_list &&points)
|
||||
{
|
||||
if (m_points != points) {
|
||||
m_points.swap (points);
|
||||
property_changed ();
|
||||
}
|
||||
}
|
||||
|
||||
db::DPoint
|
||||
Object::seg_p1 (size_t seg_index) const
|
||||
{
|
||||
if (seg_index == std::numeric_limits<size_t>::max ()) {
|
||||
return p1 ();
|
||||
} else if (seg_index < m_points.size ()) {
|
||||
return m_points[seg_index];
|
||||
} else if (m_points.empty ()) {
|
||||
return db::DPoint ();
|
||||
} else {
|
||||
return m_points.back ();
|
||||
}
|
||||
}
|
||||
|
||||
db::DPoint
|
||||
Object::seg_p2 (size_t seg_index) const
|
||||
{
|
||||
if (seg_index == std::numeric_limits<size_t>::max ()) {
|
||||
return p2 ();
|
||||
} else if (seg_index + 1 < m_points.size ()) {
|
||||
return m_points[seg_index + 1];
|
||||
} else if (m_points.empty ()) {
|
||||
return db::DPoint ();
|
||||
} else {
|
||||
return m_points.back ();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Object::seg_p1 (size_t seg_index, const db::DPoint &p)
|
||||
{
|
||||
if (seg_index == std::numeric_limits<size_t>::max ()) {
|
||||
p1 (p);
|
||||
} else if (seg_index < m_points.size ()) {
|
||||
m_points[seg_index] = p;
|
||||
} else if (! m_points.empty ()) {
|
||||
m_points.back () = p;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Object::seg_p2 (size_t seg_index, const db::DPoint &p)
|
||||
{
|
||||
if (seg_index == std::numeric_limits<size_t>::max ()) {
|
||||
p2 (p);
|
||||
} else if (seg_index + 1 < m_points.size ()) {
|
||||
m_points[seg_index + 1] = p;
|
||||
} else if (! m_points.empty ()) {
|
||||
m_points.back () = p;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Object::p1 (const db::DPoint &p)
|
||||
{
|
||||
if (! p1 ().equal (p)) {
|
||||
if (m_points.size () < 1) {
|
||||
m_points.push_back (p);
|
||||
} else {
|
||||
m_points.front () = p;
|
||||
// makes sure there is only one point if p1 == p2
|
||||
if (m_points.size () == 2 && m_points.back () == m_points.front ()) {
|
||||
m_points.pop_back ();
|
||||
}
|
||||
}
|
||||
property_changed ();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Object::p2 (const db::DPoint &p)
|
||||
{
|
||||
if (! p2 ().equal (p)) {
|
||||
if (m_points.size () < 2) {
|
||||
if (m_points.empty ()) {
|
||||
m_points.push_back (db::DPoint ());
|
||||
}
|
||||
m_points.push_back (p);
|
||||
} else {
|
||||
m_points.back () = p;
|
||||
}
|
||||
// makes sure there is only one point if p1 == p2
|
||||
if (m_points.size () == 2 && m_points.back () == m_points.front ()) {
|
||||
m_points.pop_back ();
|
||||
}
|
||||
property_changed ();
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
Object::less (const db::DUserObjectBase *d) const
|
||||
{
|
||||
|
|
@ -226,7 +392,11 @@ Object::clone () const
|
|||
db::DBox
|
||||
Object::box () const
|
||||
{
|
||||
return db::DBox (m_p1, m_p2);
|
||||
db::DBox bx;
|
||||
for (auto d = m_points.begin (); d != m_points.end (); ++d) {
|
||||
bx += *d;
|
||||
}
|
||||
return bx;
|
||||
}
|
||||
|
||||
class AnnotationEval
|
||||
|
|
@ -245,38 +415,12 @@ private:
|
|||
db::DFTrans m_trans;
|
||||
};
|
||||
|
||||
static double
|
||||
delta_x (const Object &obj, const db::DFTrans &t)
|
||||
{
|
||||
double dx = ((t * obj.p2 ()).x () - (t * obj.p1 ()).x ());
|
||||
|
||||
// avoid "almost 0" outputs
|
||||
if (fabs (dx) < 1e-5 /*micron*/) {
|
||||
dx = 0;
|
||||
}
|
||||
|
||||
return dx;
|
||||
}
|
||||
|
||||
static double
|
||||
delta_y (const Object &obj, const db::DFTrans &t)
|
||||
{
|
||||
double dy = ((t * obj.p2 ()).y () - (t * obj.p1 ()).y ());
|
||||
|
||||
// avoid "almost 0" outputs
|
||||
if (fabs (dy) < 1e-5 /*micron*/) {
|
||||
dy = 0;
|
||||
}
|
||||
|
||||
return dy;
|
||||
}
|
||||
|
||||
class AnnotationEvalFunction
|
||||
: public tl::EvalFunction
|
||||
{
|
||||
public:
|
||||
AnnotationEvalFunction (char function, const AnnotationEval *eval)
|
||||
: m_function (function), mp_eval (eval)
|
||||
AnnotationEvalFunction (char function, const AnnotationEval *eval, size_t index)
|
||||
: m_function (function), mp_eval (eval), m_index (index)
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
|
@ -301,36 +445,82 @@ public:
|
|||
} else if (m_function == 'Y') {
|
||||
out = delta_y (obj, trans);
|
||||
} else if (m_function == 'U') {
|
||||
out = (trans * obj.p1 ()).x ();
|
||||
out = (trans * p1 (obj)).x ();
|
||||
} else if (m_function == 'V') {
|
||||
out = (trans * obj.p1 ()).y ();
|
||||
out = (trans * p1 (obj)).y ();
|
||||
} else if (m_function == 'P') {
|
||||
out = (trans * obj.p2 ()).x ();
|
||||
out = (trans * p2 (obj)).x ();
|
||||
} else if (m_function == 'Q') {
|
||||
out = (trans * obj.p2 ()).y ();
|
||||
out = (trans * p2 (obj)).y ();
|
||||
} else if (m_function == 'G') {
|
||||
double r, a1, a2;
|
||||
db::DPoint c;
|
||||
if (obj.compute_angle_parameters (r, c, a1, a2)) {
|
||||
out = tl::Variant ((a2 - a1) * 180.0 / M_PI);
|
||||
} else {
|
||||
out = tl::Variant ();
|
||||
}
|
||||
} else {
|
||||
out = tl::Variant ();
|
||||
}
|
||||
}
|
||||
|
||||
db::DPoint p1 (const Object &obj) const
|
||||
{
|
||||
return obj.seg_p1 (m_index);
|
||||
}
|
||||
|
||||
db::DPoint p2 (const Object &obj) const
|
||||
{
|
||||
return obj.seg_p2 (m_index);
|
||||
}
|
||||
|
||||
double
|
||||
delta_x (const Object &obj, const db::DFTrans &t) const
|
||||
{
|
||||
double dx = ((t * p2 (obj)).x () - (t * p1 (obj)).x ());
|
||||
|
||||
// avoid "almost 0" outputs
|
||||
if (fabs (dx) < 1e-5 /*micron*/) {
|
||||
dx = 0;
|
||||
}
|
||||
|
||||
return dx;
|
||||
}
|
||||
|
||||
double
|
||||
delta_y (const Object &obj, const db::DFTrans &t) const
|
||||
{
|
||||
double dy = ((t * p2 (obj)).y () - (t * p1 (obj)).y ());
|
||||
|
||||
// avoid "almost 0" outputs
|
||||
if (fabs (dy) < 1e-5 /*micron*/) {
|
||||
dy = 0;
|
||||
}
|
||||
|
||||
return dy;
|
||||
}
|
||||
|
||||
private:
|
||||
char m_function;
|
||||
const AnnotationEval *mp_eval;
|
||||
size_t m_index;
|
||||
};
|
||||
|
||||
std::string
|
||||
Object::formatted (const std::string &fmt, const db::DFTrans &t) const
|
||||
Object::formatted (const std::string &fmt, const db::DFTrans &t, size_t index) const
|
||||
{
|
||||
AnnotationEval eval (*this, t);
|
||||
eval.define_function ("L", new AnnotationEvalFunction('L', &eval)); // manhattan length
|
||||
eval.define_function ("D", new AnnotationEvalFunction('D', &eval)); // euclidian distance
|
||||
eval.define_function ("X", new AnnotationEvalFunction('X', &eval)); // x delta
|
||||
eval.define_function ("Y", new AnnotationEvalFunction('Y', &eval)); // y delta
|
||||
eval.define_function ("U", new AnnotationEvalFunction('U', &eval)); // p1.x
|
||||
eval.define_function ("V", new AnnotationEvalFunction('V', &eval)); // p1.y
|
||||
eval.define_function ("P", new AnnotationEvalFunction('P', &eval)); // p2.x
|
||||
eval.define_function ("Q", new AnnotationEvalFunction('Q', &eval)); // p2.y
|
||||
eval.define_function ("A", new AnnotationEvalFunction('A', &eval)); // area mm2
|
||||
eval.define_function ("L", new AnnotationEvalFunction('L', &eval, index)); // manhattan length
|
||||
eval.define_function ("D", new AnnotationEvalFunction('D', &eval, index)); // euclidian distance
|
||||
eval.define_function ("X", new AnnotationEvalFunction('X', &eval, index)); // x delta
|
||||
eval.define_function ("Y", new AnnotationEvalFunction('Y', &eval, index)); // y delta
|
||||
eval.define_function ("U", new AnnotationEvalFunction('U', &eval, index)); // p1.x
|
||||
eval.define_function ("V", new AnnotationEvalFunction('V', &eval, index)); // p1.y
|
||||
eval.define_function ("P", new AnnotationEvalFunction('P', &eval, index)); // p2.x
|
||||
eval.define_function ("Q", new AnnotationEvalFunction('Q', &eval, index)); // p2.y
|
||||
eval.define_function ("A", new AnnotationEvalFunction('A', &eval, index)); // area mm2
|
||||
eval.define_function ("G", new AnnotationEvalFunction('G', &eval, index)); // angle (if applicable)
|
||||
return eval.interpolate (fmt);
|
||||
}
|
||||
|
||||
|
|
@ -343,6 +533,9 @@ Object::class_name () const
|
|||
void
|
||||
Object::from_string (const char *s, const char * /*base_dir*/)
|
||||
{
|
||||
m_points.clear ();
|
||||
point_list new_points;
|
||||
|
||||
tl::Extractor ex (s);
|
||||
while (! ex.at_end ()) {
|
||||
|
||||
|
|
@ -408,6 +601,14 @@ Object::from_string (const char *s, const char * /*base_dir*/)
|
|||
p.set_y (q);
|
||||
p2 (p);
|
||||
|
||||
} else if (ex.test ("pt=")) {
|
||||
|
||||
double x = 0.0, y = 0.0;
|
||||
ex.read (x);
|
||||
ex.expect (":");
|
||||
ex.read (y);
|
||||
new_points.push_back (db::DPoint (x, y));
|
||||
|
||||
} else if (ex.test ("position=")) {
|
||||
|
||||
std::string s;
|
||||
|
|
@ -518,6 +719,10 @@ Object::from_string (const char *s, const char * /*base_dir*/)
|
|||
ex.test (",");
|
||||
|
||||
}
|
||||
|
||||
if (! new_points.empty ()) {
|
||||
set_points (new_points);
|
||||
}
|
||||
}
|
||||
|
||||
std::string
|
||||
|
|
@ -529,18 +734,28 @@ Object::to_string () const
|
|||
r += tl::to_string (id ());
|
||||
r += ",";
|
||||
|
||||
r += "x1=";
|
||||
r += tl::to_string (p1 ().x ());
|
||||
r += ",";
|
||||
r += "y1=";
|
||||
r += tl::to_string (p1 ().y ());
|
||||
r += ",";
|
||||
r += "x2=";
|
||||
r += tl::to_string (p2 ().x ());
|
||||
r += ",";
|
||||
r += "y2=";
|
||||
r += tl::to_string (p2 ().y ());
|
||||
r += ",";
|
||||
if (m_points.size () > 2) {
|
||||
for (auto p = m_points.begin (); p != m_points.end (); ++p) {
|
||||
r += "pt=";
|
||||
r += tl::to_string (p->x ());
|
||||
r += ":";
|
||||
r += tl::to_string (p->y ());
|
||||
r += ",";
|
||||
}
|
||||
} else {
|
||||
r += "x1=";
|
||||
r += tl::to_string (p1 ().x ());
|
||||
r += ",";
|
||||
r += "y1=";
|
||||
r += tl::to_string (p1 ().y ());
|
||||
r += ",";
|
||||
r += "x2=";
|
||||
r += tl::to_string (p2 ().x ());
|
||||
r += ",";
|
||||
r += "y2=";
|
||||
r += tl::to_string (p2 ().y ());
|
||||
r += ",";
|
||||
}
|
||||
|
||||
r += "category=";
|
||||
r += tl::to_word_or_quoted_string (category ());
|
||||
|
|
@ -602,6 +817,117 @@ Object::to_string () const
|
|||
return r;
|
||||
}
|
||||
|
||||
bool
|
||||
Object::compute_interpolating_circle (double &radius, db::DPoint ¢er, double &start_angle, double &stop_angle) const
|
||||
{
|
||||
if (m_points.size () < 2) {
|
||||
return false;
|
||||
}
|
||||
|
||||
double d = m_points.back ().distance (m_points.front ()) * 0.5;
|
||||
if (d < db::epsilon) {
|
||||
return false;
|
||||
}
|
||||
|
||||
db::DVector n = m_points.back () - m_points.front ();
|
||||
db::DPoint m = m_points.front () + n * 0.5;
|
||||
n = db::DVector (n.y (), -n.x ()) * (0.5 / d);
|
||||
|
||||
double nom = 0.0;
|
||||
double div = 0.0;
|
||||
|
||||
for (size_t i = 1; i + 1 < m_points.size (); ++i) {
|
||||
db::DVector p = m_points [i] - m;
|
||||
double pn = db::sprod (p, n);
|
||||
div += pn * pn;
|
||||
nom += pn * (p.sq_double_length () - d * d);
|
||||
}
|
||||
|
||||
if (div < db::epsilon) {
|
||||
return false;
|
||||
}
|
||||
|
||||
double l = 0.5 * nom / div;
|
||||
radius = sqrt (l * l + d * d);
|
||||
center = m + n * l;
|
||||
|
||||
double a = atan2 (-n.y (), -n.x ());
|
||||
double da = atan2 (d, l);
|
||||
|
||||
if (fabs (l) < db::epsilon) {
|
||||
|
||||
start_angle = 0.0;
|
||||
stop_angle = M_PI * 2.0;
|
||||
|
||||
} else if (l < 0.0) {
|
||||
|
||||
stop_angle = a + da;
|
||||
start_angle = stop_angle + 2.0 * (M_PI - da);
|
||||
|
||||
} else {
|
||||
|
||||
start_angle = a - da;
|
||||
stop_angle = a + da;
|
||||
|
||||
}
|
||||
|
||||
while (stop_angle < start_angle - db::epsilon) {
|
||||
stop_angle += M_PI * 2.0;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
Object::compute_angle_parameters (double &radius, db::DPoint ¢er, double &start_angle, double &stop_angle) const
|
||||
{
|
||||
if (m_points.size () < 3) {
|
||||
return false;
|
||||
}
|
||||
|
||||
db::DPoint p1 = m_points.front (), p2 = m_points.back ();
|
||||
|
||||
db::DVector pc;
|
||||
for (size_t i = 1; i + 1 < m_points.size (); ++i) {
|
||||
pc += m_points[i] - db::DPoint ();
|
||||
}
|
||||
center = db::DPoint () + pc * (1.0 / double (m_points.size () - 2));
|
||||
|
||||
db::DVector v1 (p1 - center);
|
||||
if (v1.double_length () < db::epsilon) {
|
||||
return false;
|
||||
}
|
||||
|
||||
db::DVector v2 (p2 - center);
|
||||
if (v2.double_length () < db::epsilon) {
|
||||
return false;
|
||||
}
|
||||
|
||||
radius = std::min (v1.double_length (), v2.double_length ());
|
||||
|
||||
v1 *= 1.0 / v1.double_length ();
|
||||
v2 *= 1.0 / v2.double_length ();
|
||||
|
||||
if (db::vprod_sign (v1, v2) == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
start_angle = 0.0;
|
||||
stop_angle = 0.0;
|
||||
start_angle = atan2 (v1.y (), v1.x ());
|
||||
stop_angle = atan2 (v2.y (), v2.x ());
|
||||
|
||||
if (db::vprod_sign (v1, v2) < 0) {
|
||||
std::swap (stop_angle, start_angle);
|
||||
}
|
||||
|
||||
while (stop_angle < start_angle - db::epsilon) {
|
||||
stop_angle += M_PI * 2.0;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
Object::property_changed ()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -50,6 +50,7 @@ class ANT_PUBLIC Object
|
|||
{
|
||||
public:
|
||||
typedef db::coord_traits<coord_type> coord_traits;
|
||||
typedef std::vector<db::DPoint> point_list;
|
||||
|
||||
/**
|
||||
* @brief The ruler style
|
||||
|
|
@ -76,8 +77,10 @@ public:
|
|||
* OL_diag_yx: both OL_diag and OL_yx
|
||||
* OL_box: draw a box defined by start and end point
|
||||
* OL_ellipse: draws an ellipse with p1 and p2 defining the extension (style is ignored)
|
||||
* OL_angle: an angle measurement ruler (first vs. last segment)
|
||||
* OL_radius: a radius measurement ruler
|
||||
*/
|
||||
enum outline_type { OL_diag = 0, OL_xy = 1, OL_diag_xy = 2, OL_yx = 3, OL_diag_yx = 4, OL_box = 5, OL_ellipse = 6 };
|
||||
enum outline_type { OL_diag = 0, OL_xy = 1, OL_diag_xy = 2, OL_yx = 3, OL_diag_yx = 4, OL_box = 5, OL_ellipse = 6, OL_angle = 7, OL_radius = 8 };
|
||||
|
||||
/**
|
||||
* @brief The position type of the main label
|
||||
|
|
@ -109,11 +112,21 @@ public:
|
|||
*/
|
||||
Object (const db::DPoint &p1, const db::DPoint &p2, int id, const std::string &fmt_x, const std::string &fmt_y, const std::string &fmt, style_type style, outline_type outline, bool snap, lay::angle_constraint_type angle_constraint);
|
||||
|
||||
/**
|
||||
* @brief Parametrized constructor and a list of points
|
||||
*/
|
||||
Object (const point_list &points, int id, const std::string &fmt_x, const std::string &fmt_y, const std::string &fmt, style_type style, outline_type outline, bool snap, lay::angle_constraint_type angle_constraint);
|
||||
|
||||
/**
|
||||
* @brief Parametrized constructor from a template
|
||||
*/
|
||||
Object (const db::DPoint &p1, const db::DPoint &p2, int id, const ant::Template &d);
|
||||
|
||||
/**
|
||||
* @brief Parametrized constructor from a template and a list of points
|
||||
*/
|
||||
Object (const point_list &points, int id, const ant::Template &d);
|
||||
|
||||
/**
|
||||
* @brief Copy constructor
|
||||
*/
|
||||
|
|
@ -185,8 +198,9 @@ public:
|
|||
*/
|
||||
virtual void transform (const db::DCplxTrans &t)
|
||||
{
|
||||
m_p1 = t * m_p1;
|
||||
m_p2 = t * m_p2;
|
||||
for (auto p = m_points.begin (); p != m_points.end (); ++p) {
|
||||
*p = t * *p;
|
||||
}
|
||||
property_changed ();
|
||||
}
|
||||
|
||||
|
|
@ -195,8 +209,9 @@ public:
|
|||
*/
|
||||
virtual void transform (const db::DTrans &t)
|
||||
{
|
||||
m_p1 = t * m_p1;
|
||||
m_p2 = t * m_p2;
|
||||
for (auto p = m_points.begin (); p != m_points.end (); ++p) {
|
||||
*p = t * *p;
|
||||
}
|
||||
property_changed ();
|
||||
}
|
||||
|
||||
|
|
@ -205,8 +220,9 @@ public:
|
|||
*/
|
||||
virtual void transform (const db::DFTrans &t)
|
||||
{
|
||||
m_p1 = t * m_p1;
|
||||
m_p2 = t * m_p2;
|
||||
for (auto p = m_points.begin (); p != m_points.end (); ++p) {
|
||||
*p = t * *p;
|
||||
}
|
||||
property_changed ();
|
||||
}
|
||||
|
||||
|
|
@ -224,10 +240,11 @@ public:
|
|||
/**
|
||||
* @brief Moves the object by the given distance
|
||||
*/
|
||||
Object &move (const db::DVector &p)
|
||||
Object &move (const db::DVector &d)
|
||||
{
|
||||
m_p1 += p;
|
||||
m_p2 += p;
|
||||
for (auto p = m_points.begin (); p != m_points.end (); ++p) {
|
||||
*p += d;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
|
@ -265,42 +282,96 @@ public:
|
|||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the first definition point
|
||||
* @brief Gets the ruler's definition points
|
||||
*/
|
||||
const db::DPoint &p1 () const
|
||||
const point_list &points () const
|
||||
{
|
||||
return m_p1;
|
||||
return m_points;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Sets the ruler's definition points
|
||||
*/
|
||||
void set_points (const point_list &points);
|
||||
|
||||
/**
|
||||
* @brief Sets the ruler's definition points without cleaning
|
||||
*/
|
||||
void set_points_exact (const point_list &points);
|
||||
|
||||
/**
|
||||
* @brief Sets the ruler's definition points without cleaning (move semantics)
|
||||
*/
|
||||
void set_points_exact (point_list &&points);
|
||||
|
||||
/**
|
||||
* @brief Cleans the point list
|
||||
*/
|
||||
void clean_points ();
|
||||
|
||||
/**
|
||||
* @brief Gets the first point of the indicated segment
|
||||
*/
|
||||
db::DPoint seg_p1 (size_t seg_index) const;
|
||||
|
||||
/**
|
||||
* @brief Gets the second point of the indicated segment
|
||||
*/
|
||||
db::DPoint seg_p2 (size_t seg_index) const;
|
||||
|
||||
/**
|
||||
* @brief Sets the first point of the indicated segment
|
||||
*/
|
||||
void seg_p1 (size_t seg_index, const db::DPoint &p);
|
||||
|
||||
/**
|
||||
* @brief Sets the second point of the indicated segment
|
||||
*/
|
||||
void seg_p2 (size_t seg_index, const db::DPoint &p);
|
||||
|
||||
/**
|
||||
* @brief Gets the number of segments
|
||||
*
|
||||
* The number of segments is at least 1 for backward compatibility.
|
||||
*/
|
||||
size_t segments () const
|
||||
{
|
||||
return m_points.size () < 2 ? 1 : m_points.size () - 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the first definition point
|
||||
*
|
||||
* This method is provided for backward compatibility. Use the point list accessor for generic point retrieval.
|
||||
*/
|
||||
db::DPoint p1 () const
|
||||
{
|
||||
return seg_p1 (0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the second definition point
|
||||
*
|
||||
* This method is provided for backward compatibility. Use the point list accessor for generic point retrieval.
|
||||
*/
|
||||
const db::DPoint &p2 () const
|
||||
db::DPoint p2 () const
|
||||
{
|
||||
return m_p2;
|
||||
return seg_p2 (segments () - 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Sets the first definition point
|
||||
*
|
||||
* This method is provided for backward compatibility. Use the point list accessor for generic point retrieval.
|
||||
*/
|
||||
void p1 (const db::DPoint &p)
|
||||
{
|
||||
if (!m_p1.equal (p)) {
|
||||
m_p1 = p;
|
||||
property_changed ();
|
||||
}
|
||||
}
|
||||
void p1 (const db::DPoint &p);
|
||||
|
||||
/**
|
||||
* @brief Sets the second definition point
|
||||
*
|
||||
* This method is provided for backward compatibility. Use the point list accessor for generic point retrieval.
|
||||
*/
|
||||
void p2 (const db::DPoint &p)
|
||||
{
|
||||
if (!m_p2.equal (p)) {
|
||||
m_p2 = p;
|
||||
property_changed ();
|
||||
}
|
||||
}
|
||||
void p2 (const db::DPoint &p);
|
||||
|
||||
/**
|
||||
* @brief Gets the ID of the annotation object
|
||||
|
|
@ -619,52 +690,52 @@ public:
|
|||
/**
|
||||
* @brief Gets the formatted text for the x label
|
||||
*/
|
||||
std::string text_x () const
|
||||
std::string text_x (size_t index) const
|
||||
{
|
||||
return formatted (m_fmt_x, db::DFTrans ());
|
||||
return formatted (m_fmt_x, db::DFTrans (), index);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the formatted text for the y label
|
||||
*/
|
||||
std::string text_y () const
|
||||
std::string text_y (size_t index) const
|
||||
{
|
||||
return formatted (m_fmt_y, db::DFTrans ());
|
||||
return formatted (m_fmt_y, db::DFTrans (), index);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the formatted text for the main label
|
||||
*/
|
||||
std::string text () const
|
||||
std::string text (size_t index) const
|
||||
{
|
||||
return formatted (m_fmt, db::DFTrans ());
|
||||
return formatted (m_fmt, db::DFTrans (), index);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the formatted text for the x label
|
||||
* @param t The transformation to apply to the vector before producing the text
|
||||
*/
|
||||
std::string text_x (const db::DFTrans &t) const
|
||||
std::string text_x (size_t index, const db::DFTrans &t) const
|
||||
{
|
||||
return formatted (m_fmt_x, t);
|
||||
return formatted (m_fmt_x, t, index);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the formatted text for the y label
|
||||
* @param t The transformation to apply to the vector before producing the text
|
||||
*/
|
||||
std::string text_y (const db::DFTrans &t) const
|
||||
std::string text_y (size_t index, const db::DFTrans &t) const
|
||||
{
|
||||
return formatted (m_fmt_y, t);
|
||||
return formatted (m_fmt_y, t, index);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the formatted text for the main label
|
||||
* @param t The transformation to apply to the vector before producing the text
|
||||
*/
|
||||
std::string text (const db::DFTrans &t) const
|
||||
std::string text (size_t index, const db::DFTrans &t) const
|
||||
{
|
||||
return formatted (m_fmt, t);
|
||||
return formatted (m_fmt, t, index);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -688,6 +759,26 @@ public:
|
|||
*/
|
||||
virtual std::string to_string () const;
|
||||
|
||||
/**
|
||||
* @brief Computes the parameters for an angle ruler
|
||||
* @param radius Returns the radius
|
||||
* @param center Returns the center point
|
||||
* @param start_angle Returns the start angle (in radians)
|
||||
* @param stop_angle Returns the stop angle (in radians)
|
||||
* @return True, if the ruler represents an angle measurement
|
||||
*/
|
||||
bool compute_angle_parameters (double &radius, db::DPoint ¢er, double &start_angle, double &stop_angle) const;
|
||||
|
||||
/**
|
||||
* @brief Computes the parameters for a radius ruler
|
||||
* @param radius Returns the radius
|
||||
* @param center Returns the center point
|
||||
* @param start_angle Returns the start angle (in radians)
|
||||
* @param stop_angle Returns the stop angle (in radians)
|
||||
* @return True, if the ruler represents an angle measurement
|
||||
*/
|
||||
bool compute_interpolating_circle (double &radius, db::DPoint ¢er, double &start_angle, double &stop_angle) const;
|
||||
|
||||
protected:
|
||||
/**
|
||||
* @brief A notification method that is called when a property of the annotation has changed
|
||||
|
|
@ -695,7 +786,7 @@ protected:
|
|||
virtual void property_changed ();
|
||||
|
||||
private:
|
||||
db::DPoint m_p1, m_p2;
|
||||
point_list m_points;
|
||||
int m_id;
|
||||
std::string m_fmt_x;
|
||||
std::string m_fmt_y;
|
||||
|
|
@ -710,7 +801,7 @@ private:
|
|||
alignment_type m_xlabel_xalign, m_xlabel_yalign;
|
||||
alignment_type m_ylabel_xalign, m_ylabel_yalign;
|
||||
|
||||
std::string formatted (const std::string &fmt, const db::DFTrans &trans) const;
|
||||
std::string formatted (const std::string &fmt, const db::DFTrans &trans, size_t index) const;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -68,12 +68,22 @@ static std::vector<ant::Template> make_standard_templates ()
|
|||
|
||||
templates.push_back (ant::Template (tl::to_string (tr ("Ruler")), "$X", "$Y", "$D", ant::Object::STY_ruler, ant::Object::OL_diag, true, lay::AC_Global, "_ruler"));
|
||||
|
||||
templates.push_back (ant::Template (tl::to_string (tr ("Multi-ruler")), "$X", "$Y", "$D", ant::Object::STY_ruler, ant::Object::OL_diag, true, lay::AC_Global, "_multi_ruler"));
|
||||
templates.back ().set_mode (ant::Template::RulerMultiSegment);
|
||||
|
||||
templates.push_back (ant::Template (tl::to_string (tr ("Cross")), "", "", "$U,$V", ant::Object::STY_cross_both, ant::Object::OL_diag, true, lay::AC_Global, "_cross"));
|
||||
templates.back ().set_mode (ant::Template::RulerSingleClick);
|
||||
|
||||
templates.push_back (ant::Template (tl::to_string (tr ("Measure")), "$X", "$Y", "$D", ant::Object::STY_ruler, ant::Object::OL_diag, true, lay::AC_Global, "_measure"));
|
||||
templates.back ().set_mode (ant::Template::RulerAutoMetric);
|
||||
|
||||
templates.push_back (ant::Template (tl::to_string (tr ("Angle")), "", "", "$(sprintf('%.5g',G))°", ant::Object::STY_line, ant::Object::OL_angle, true, lay::AC_Global, "_angle"));
|
||||
templates.back ().set_mode (ant::Template::RulerThreeClicks);
|
||||
|
||||
templates.push_back (ant::Template (tl::to_string (tr ("Radius")), "", "", "R=$D", ant::Object::STY_arrow_end, ant::Object::OL_radius, true, lay::AC_Global, "_radius"));
|
||||
templates.back ().set_mode (ant::Template::RulerThreeClicks);
|
||||
templates.back ().set_main_position (ant::Object::POS_center);
|
||||
|
||||
templates.push_back (ant::Template (tl::to_string (tr ("Ellipse")), "W=$(abs(X))", "H=$(abs(Y))", "", ant::Object::STY_line, ant::Object::OL_ellipse, true, lay::AC_Global, std::string ()));
|
||||
|
||||
templates.push_back (ant::Template (tl::to_string (tr ("Box")), "W=$(abs(X))", "H=$(abs(Y))", "", ant::Object::STY_line, ant::Object::OL_box, true, lay::AC_Global, std::string ()));
|
||||
|
|
@ -197,14 +207,50 @@ PluginDeclaration::initialized (lay::Dispatcher *root)
|
|||
// Check if we already have templates (initial setup)
|
||||
// NOTE: this is not done by using a default value for the configuration item but dynamically.
|
||||
// This provides a migration path from earlier versions (not having templates) to recent ones.
|
||||
bool any_templates = false;
|
||||
for (std::vector<ant::Template>::iterator i = m_templates.begin (); ! any_templates && i != m_templates.end (); ++i) {
|
||||
any_templates = ! i->category ().empty ();
|
||||
std::map<std::string, const ant::Template *> cat_names;
|
||||
for (auto i = m_templates.begin (); i != m_templates.end (); ++i) {
|
||||
if (! i->category ().empty ()) {
|
||||
cat_names.insert (std::make_pair (i->category (), i.operator-> ()));
|
||||
}
|
||||
}
|
||||
|
||||
if (! any_templates) {
|
||||
bool any_missing = false;
|
||||
auto std_templates = make_standard_templates ();
|
||||
for (auto t = std_templates.begin (); ! any_missing && t != std_templates.end (); ++t) {
|
||||
if (! t->category ().empty () && cat_names.find (t->category ()) == cat_names.end ()) {
|
||||
any_missing = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (cat_names.empty ()) {
|
||||
|
||||
// full initial configuration
|
||||
root->config_set (cfg_ruler_templates, ant::TemplatesConverter ().to_string (make_standard_templates ()));
|
||||
root->config_end ();
|
||||
|
||||
} else if (any_missing) {
|
||||
|
||||
// some standard templates are missing - add them now (migration path for later versions)
|
||||
decltype (m_templates) new_templates;
|
||||
for (auto t = std_templates.begin (); t != std_templates.end (); ++t) {
|
||||
if (! t->category ().empty ()) {
|
||||
auto tt = cat_names.find (t->category ());
|
||||
if (tt != cat_names.end ()) {
|
||||
new_templates.push_back (*tt->second);
|
||||
} else {
|
||||
new_templates.push_back (*t);
|
||||
}
|
||||
}
|
||||
}
|
||||
for (auto i = m_templates.begin (); i != m_templates.end (); ++i) {
|
||||
if (i->category ().empty ()) {
|
||||
new_templates.push_back (*i);
|
||||
}
|
||||
}
|
||||
|
||||
root->config_set (cfg_ruler_templates, ant::TemplatesConverter ().to_string (new_templates));
|
||||
root->config_end ();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -30,14 +30,42 @@
|
|||
namespace ant
|
||||
{
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// A ruler that tells us if he was modified
|
||||
|
||||
class RulerWithModifiedProperty
|
||||
: public ant::Object
|
||||
{
|
||||
public:
|
||||
RulerWithModifiedProperty ()
|
||||
: ant::Object (), m_modified (false)
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
bool is_modified () const
|
||||
{
|
||||
return m_modified;
|
||||
}
|
||||
|
||||
protected:
|
||||
void property_changed ()
|
||||
{
|
||||
m_modified = true;
|
||||
ant::Object::property_changed ();
|
||||
}
|
||||
|
||||
bool m_modified;
|
||||
};
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// PropertiesPage implementation
|
||||
|
||||
PropertiesPage::PropertiesPage (ant::Service *rulers, db::Manager *manager, QWidget *parent)
|
||||
: lay::PropertiesPage (parent, manager, rulers), mp_rulers (rulers), m_enable_cb_callback (true)
|
||||
: lay::PropertiesPage (parent, manager, rulers), mp_rulers (rulers), m_enable_cb_callback (true), m_in_something_changed (false)
|
||||
{
|
||||
mp_rulers->get_selection (m_selection);
|
||||
m_pos = m_selection.begin ();
|
||||
m_index = 0;
|
||||
|
||||
setupUi (this);
|
||||
|
||||
|
|
@ -54,23 +82,27 @@ PropertiesPage::PropertiesPage (ant::Service *rulers, db::Manager *manager, QWid
|
|||
|
||||
if (! readonly ()) {
|
||||
|
||||
connect (fmt_le, SIGNAL (editingFinished ()), this, SIGNAL (edited ()));
|
||||
connect (fmt_x_le, SIGNAL (editingFinished ()), this, SIGNAL (edited ()));
|
||||
connect (fmt_y_le, SIGNAL (editingFinished ()), this, SIGNAL (edited ()));
|
||||
connect (x1, SIGNAL (editingFinished ()), this, SIGNAL (edited ()));
|
||||
connect (x2, SIGNAL (editingFinished ()), this, SIGNAL (edited ()));
|
||||
connect (y1, SIGNAL (editingFinished ()), this, SIGNAL (edited ()));
|
||||
connect (y2, SIGNAL (editingFinished ()), this, SIGNAL (edited ()));
|
||||
connect (fmt_le, SIGNAL (editingFinished ()), this, SLOT (something_changed ()));
|
||||
connect (fmt_x_le, SIGNAL (editingFinished ()), this, SLOT (something_changed ()));
|
||||
connect (fmt_y_le, SIGNAL (editingFinished ()), this, SLOT (something_changed ()));
|
||||
connect (x0, SIGNAL (editingFinished ()), this, SLOT (something_changed ()));
|
||||
connect (x1, SIGNAL (editingFinished ()), this, SLOT (something_changed ()));
|
||||
connect (x2, SIGNAL (editingFinished ()), this, SLOT (something_changed ()));
|
||||
connect (y0, SIGNAL (editingFinished ()), this, SLOT (something_changed ()));
|
||||
connect (y1, SIGNAL (editingFinished ()), this, SLOT (something_changed ()));
|
||||
connect (y2, SIGNAL (editingFinished ()), this, SLOT (something_changed ()));
|
||||
|
||||
connect (style_cb, SIGNAL (activated (int)), this, SIGNAL (edited ()));
|
||||
connect (outline_cb, SIGNAL (activated (int)), this, SIGNAL (edited ()));
|
||||
connect (main_position, SIGNAL (activated (int)), this, SIGNAL (edited ()));
|
||||
connect (main_xalign, SIGNAL (activated (int)), this, SIGNAL (edited ()));
|
||||
connect (main_yalign, SIGNAL (activated (int)), this, SIGNAL (edited ()));
|
||||
connect (xlabel_xalign, SIGNAL (activated (int)), this, SIGNAL (edited ()));
|
||||
connect (xlabel_yalign, SIGNAL (activated (int)), this, SIGNAL (edited ()));
|
||||
connect (ylabel_xalign, SIGNAL (activated (int)), this, SIGNAL (edited ()));
|
||||
connect (ylabel_yalign, SIGNAL (activated (int)), this, SIGNAL (edited ()));
|
||||
connect (style_cb, SIGNAL (activated (int)), this, SLOT (something_changed ()));
|
||||
connect (outline_cb, SIGNAL (activated (int)), this, SLOT (something_changed ()));
|
||||
connect (main_position, SIGNAL (activated (int)), this, SLOT (something_changed ()));
|
||||
connect (main_xalign, SIGNAL (activated (int)), this, SLOT (something_changed ()));
|
||||
connect (main_yalign, SIGNAL (activated (int)), this, SLOT (something_changed ()));
|
||||
connect (xlabel_xalign, SIGNAL (activated (int)), this, SLOT (something_changed ()));
|
||||
connect (xlabel_yalign, SIGNAL (activated (int)), this, SLOT (something_changed ()));
|
||||
connect (ylabel_xalign, SIGNAL (activated (int)), this, SLOT (something_changed ()));
|
||||
connect (ylabel_yalign, SIGNAL (activated (int)), this, SLOT (something_changed ()));
|
||||
|
||||
connect (points_edit, SIGNAL (textChanged ()), this, SLOT (something_changed ()));
|
||||
|
||||
} else {
|
||||
|
||||
|
|
@ -94,18 +126,6 @@ PropertiesPage::~PropertiesPage ()
|
|||
mp_rulers->restore_highlights ();
|
||||
}
|
||||
|
||||
void
|
||||
PropertiesPage::back ()
|
||||
{
|
||||
m_pos = m_selection.end ();
|
||||
}
|
||||
|
||||
void
|
||||
PropertiesPage::front ()
|
||||
{
|
||||
m_pos = m_selection.begin ();
|
||||
}
|
||||
|
||||
void
|
||||
PropertiesPage::swap_points_clicked ()
|
||||
{
|
||||
|
|
@ -173,6 +193,89 @@ PropertiesPage::get_points (db::DPoint &p1, db::DPoint &p2)
|
|||
p2 = db::DPoint (dx2, dy2);
|
||||
}
|
||||
|
||||
void
|
||||
PropertiesPage::get_point (db::DPoint &p)
|
||||
{
|
||||
double dx = 0.0, dy = 0.0;
|
||||
bool has_error = false;
|
||||
|
||||
try {
|
||||
tl::from_string_ext (tl::to_string (x0->text ()), dx);
|
||||
lay::indicate_error (x0, (tl::Exception *) 0);
|
||||
} catch (tl::Exception &ex) {
|
||||
lay::indicate_error (x0, &ex);
|
||||
has_error = true;
|
||||
}
|
||||
|
||||
try {
|
||||
tl::from_string_ext (tl::to_string (y0->text ()), dy);
|
||||
lay::indicate_error (y0, (tl::Exception *) 0);
|
||||
} catch (tl::Exception &ex) {
|
||||
lay::indicate_error (y0, &ex);
|
||||
has_error = true;
|
||||
}
|
||||
|
||||
if (has_error) {
|
||||
throw tl::Exception (tl::to_string (tr ("At least one value is invalid - see highlighted entry fields")));
|
||||
}
|
||||
|
||||
p = db::DPoint (dx, dy);
|
||||
}
|
||||
|
||||
void
|
||||
PropertiesPage::get_points (ant::Object::point_list &points)
|
||||
{
|
||||
std::string coordinates = tl::to_string (points_edit->toPlainText ());
|
||||
points.clear ();
|
||||
|
||||
try {
|
||||
|
||||
tl::Extractor ex (coordinates.c_str ());
|
||||
while (! ex.at_end ()) {
|
||||
double x = 0.0, y = 0.0;
|
||||
ex.read (x);
|
||||
ex.test (",");
|
||||
ex.read (y);
|
||||
ex.test (";");
|
||||
ex.test (",");
|
||||
points.push_back (db::DPoint (x, y));
|
||||
}
|
||||
|
||||
lay::indicate_error (points_edit, (tl::Exception *) 0);
|
||||
|
||||
} catch (tl::Exception &ex) {
|
||||
lay::indicate_error (points_edit, &ex);
|
||||
throw tl::Exception (tl::to_string (tr ("At least one value is invalid - see highlighted entry fields")));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
PropertiesPage::something_changed ()
|
||||
{
|
||||
if (m_in_something_changed) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
|
||||
m_in_something_changed = true;
|
||||
|
||||
RulerWithModifiedProperty obj;
|
||||
obj.ant::Object::operator= (current ());
|
||||
get_object (obj);
|
||||
if (obj.is_modified ()) {
|
||||
update_with (obj);
|
||||
emit edited ();
|
||||
}
|
||||
|
||||
m_in_something_changed = false;
|
||||
|
||||
} catch (...) {
|
||||
m_in_something_changed = false;
|
||||
// ignore exceptions - the edit field will be highlighted anyway
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
PropertiesPage::snap_to_layout_clicked ()
|
||||
{
|
||||
|
|
@ -259,32 +362,61 @@ PropertiesPage::snap_to_layout_clicked ()
|
|||
const ant::Object &
|
||||
PropertiesPage::current () const
|
||||
{
|
||||
const ant::Object *ruler = dynamic_cast <const ant::Object *> ((*m_pos)->ptr ());
|
||||
const ant::Object *ruler = dynamic_cast <const ant::Object *> (m_selection [m_index]->ptr ());
|
||||
return *ruler;
|
||||
}
|
||||
|
||||
bool
|
||||
PropertiesPage::at_begin () const
|
||||
size_t
|
||||
PropertiesPage::count () const
|
||||
{
|
||||
return (m_pos == m_selection.begin ());
|
||||
return m_selection.size ();
|
||||
}
|
||||
|
||||
bool
|
||||
PropertiesPage::at_end () const
|
||||
void
|
||||
PropertiesPage::select_entries (const std::vector<size_t> &entries)
|
||||
{
|
||||
return (m_pos == m_selection.end ());
|
||||
tl_assert (entries.size () == 1);
|
||||
m_index = entries.front ();
|
||||
}
|
||||
|
||||
void
|
||||
PropertiesPage::operator-- ()
|
||||
std::string
|
||||
PropertiesPage::description (size_t entry) const
|
||||
{
|
||||
--m_pos;
|
||||
const ant::Object *obj = dynamic_cast <const ant::Object *> (m_selection [entry]->ptr ());
|
||||
if (! obj) {
|
||||
return std::string ("nil");
|
||||
}
|
||||
|
||||
std::string d = tl::to_string (tr ("Ruler"));
|
||||
if (! obj->category ().empty ()) {
|
||||
std::string cat = obj->category ();
|
||||
// category is "_ruler" for example. Turn in into "Ruler".
|
||||
if (cat.size () >= 2 && cat [0] == '_') {
|
||||
cat = tl::to_upper_case (std::string (cat.begin () + 1, cat.begin () + 2)) + std::string (cat.begin () + 2, cat.end ());
|
||||
}
|
||||
d += "[" + cat + "]";
|
||||
}
|
||||
|
||||
if (obj->points ().size () > 3) {
|
||||
d += tl::sprintf (tl::to_string (tr ("(%d points)")), obj->points ().size ());
|
||||
} else {
|
||||
d += "(";
|
||||
for (auto p = obj->points ().begin (); p != obj->points ().end (); ++p) {
|
||||
if (p != obj->points ().begin ()) {
|
||||
d += ";";
|
||||
}
|
||||
d += p->to_string ();
|
||||
}
|
||||
d += ")";
|
||||
}
|
||||
|
||||
return d;
|
||||
}
|
||||
|
||||
void
|
||||
PropertiesPage::operator++ ()
|
||||
std::string
|
||||
PropertiesPage::description () const
|
||||
{
|
||||
++m_pos;
|
||||
return tl::to_string (tr ("Rulers and Annotations"));
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -296,33 +428,80 @@ PropertiesPage::leave ()
|
|||
void
|
||||
PropertiesPage::update ()
|
||||
{
|
||||
mp_rulers->highlight (std::distance (m_selection.begin (), m_pos));
|
||||
mp_rulers->highlight (m_index);
|
||||
update_with (current ());
|
||||
}
|
||||
|
||||
fmt_le->setText (tl::to_qstring (current ().fmt ()));
|
||||
fmt_x_le->setText (tl::to_qstring (current ().fmt_x ()));
|
||||
fmt_y_le->setText (tl::to_qstring (current ().fmt_y ()));
|
||||
style_cb->setCurrentIndex (current ().style ());
|
||||
outline_cb->setCurrentIndex (current ().outline ());
|
||||
void
|
||||
PropertiesPage::update_with (const ant::Object &obj)
|
||||
{
|
||||
fmt_le->setText (tl::to_qstring (obj.fmt ()));
|
||||
fmt_x_le->setText (tl::to_qstring (obj.fmt_x ()));
|
||||
fmt_y_le->setText (tl::to_qstring (obj.fmt_y ()));
|
||||
style_cb->setCurrentIndex (obj.style ());
|
||||
outline_cb->setCurrentIndex (obj.outline ());
|
||||
|
||||
x1->setText (tl::to_qstring (tl::micron_to_string (current ().p1 ().x ())));
|
||||
main_position->setCurrentIndex (obj.main_position ());
|
||||
main_xalign->setCurrentIndex (obj.main_xalign ());
|
||||
main_yalign->setCurrentIndex (obj.main_yalign ());
|
||||
xlabel_xalign->setCurrentIndex (obj.xlabel_xalign ());
|
||||
xlabel_yalign->setCurrentIndex (obj.xlabel_yalign ());
|
||||
ylabel_xalign->setCurrentIndex (obj.ylabel_xalign ());
|
||||
ylabel_yalign->setCurrentIndex (obj.ylabel_yalign ());
|
||||
|
||||
// change tabs if required
|
||||
if (segments_tab->currentIndex () == 1) {
|
||||
if (obj.points ().size () > 2 || obj.points ().size () == 0) {
|
||||
segments_tab->setCurrentIndex (2);
|
||||
}
|
||||
} else if (segments_tab->currentIndex () == 0) {
|
||||
if (obj.points ().size () > 2 || obj.points ().size () == 0) {
|
||||
segments_tab->setCurrentIndex (2);
|
||||
} else if (obj.points ().size () > 1) {
|
||||
segments_tab->setCurrentIndex (1);
|
||||
}
|
||||
}
|
||||
segments_tab->setTabEnabled (0, obj.points ().size () == 1);
|
||||
segments_tab->setTabEnabled (1, obj.points ().size () <= 2 && obj.points ().size () > 0);
|
||||
|
||||
point_list->clear ();
|
||||
for (auto p = obj.points ().begin (); p != obj.points ().end (); ++p) {
|
||||
QTreeWidgetItem *item = new QTreeWidgetItem (point_list);
|
||||
item->setData (0, Qt::DisplayRole, QVariant (tl::to_qstring (tl::micron_to_string (p->x ()))));
|
||||
item->setData (1, Qt::DisplayRole, QVariant (tl::to_qstring (tl::micron_to_string (p->y ()))));
|
||||
}
|
||||
|
||||
if (! m_in_something_changed || segments_tab->currentIndex () != 3) {
|
||||
|
||||
std::string text;
|
||||
for (auto p = obj.points ().begin (); p != obj.points ().end (); ++p) {
|
||||
text += tl::micron_to_string (p->x ());
|
||||
text += ", ";
|
||||
text += tl::micron_to_string (p->y ());
|
||||
text += "\n";
|
||||
}
|
||||
|
||||
lay::SignalBlocker blocker (points_edit);
|
||||
points_edit->setPlainText (tl::to_qstring (text));
|
||||
|
||||
}
|
||||
|
||||
x0->setText (tl::to_qstring (tl::micron_to_string (obj.p1 ().x ())));
|
||||
x0->setCursorPosition (0);
|
||||
y0->setText (tl::to_qstring (tl::micron_to_string (obj.p1 ().y ())));
|
||||
y0->setCursorPosition (0);
|
||||
|
||||
x1->setText (tl::to_qstring (tl::micron_to_string (obj.p1 ().x ())));
|
||||
x1->setCursorPosition (0);
|
||||
x2->setText (tl::to_qstring (tl::micron_to_string (current ().p2 ().x ())));
|
||||
x2->setText (tl::to_qstring (tl::micron_to_string (obj.p2 ().x ())));
|
||||
x2->setCursorPosition (0);
|
||||
y1->setText (tl::to_qstring (tl::micron_to_string (current ().p1 ().y ())));
|
||||
y1->setText (tl::to_qstring (tl::micron_to_string (obj.p1 ().y ())));
|
||||
y1->setCursorPosition (0);
|
||||
y2->setText (tl::to_qstring (tl::micron_to_string (current ().p2 ().y ())));
|
||||
y2->setText (tl::to_qstring (tl::micron_to_string (obj.p2 ().y ())));
|
||||
y2->setCursorPosition (0);
|
||||
|
||||
main_position->setCurrentIndex (current ().main_position ());
|
||||
main_xalign->setCurrentIndex (current ().main_xalign ());
|
||||
main_yalign->setCurrentIndex (current ().main_yalign ());
|
||||
xlabel_xalign->setCurrentIndex (current ().xlabel_xalign ());
|
||||
xlabel_yalign->setCurrentIndex (current ().xlabel_yalign ());
|
||||
ylabel_xalign->setCurrentIndex (current ().ylabel_xalign ());
|
||||
ylabel_yalign->setCurrentIndex (current ().ylabel_yalign ());
|
||||
|
||||
double sx = (current ().p2 ().x () - current ().p1 ().x ());
|
||||
double sy = (current ().p2 ().y () - current ().p1 ().y ());
|
||||
double sx = (obj.p2 ().x () - obj.p1 ().x ());
|
||||
double sy = (obj.p2 ().y () - obj.p1 ().y ());
|
||||
dx->setText (tl::to_qstring (tl::micron_to_string (sx)));
|
||||
dx->setCursorPosition (0);
|
||||
dy->setText (tl::to_qstring (tl::micron_to_string (sy)));
|
||||
|
|
@ -340,29 +519,49 @@ PropertiesPage::readonly ()
|
|||
void
|
||||
PropertiesPage::apply ()
|
||||
{
|
||||
// only adjust the values if the text has changed
|
||||
db::DPoint p1, p2;
|
||||
get_points (p1, p2);
|
||||
ant::Object obj;
|
||||
get_object (obj);
|
||||
mp_rulers->change_ruler (m_selection [m_index], obj);
|
||||
}
|
||||
|
||||
void PropertiesPage::get_object(ant::Object &obj)
|
||||
{
|
||||
std::string fmt = tl::to_string (fmt_le->text ());
|
||||
std::string fmt_x = tl::to_string (fmt_x_le->text ());
|
||||
std::string fmt_y = tl::to_string (fmt_y_le->text ());
|
||||
Object::style_type style = Object::style_type (style_cb->currentIndex ());
|
||||
Object::outline_type outline = Object::outline_type (outline_cb->currentIndex ());
|
||||
|
||||
ant::Object ruler (p1, p2, current ().id (), fmt_x, fmt_y, fmt, style, outline, current ().snap (), current ().angle_constraint ());
|
||||
if (segments_tab->currentIndex () == 0 || segments_tab->currentIndex () == 1) {
|
||||
|
||||
ruler.set_main_position (Object::position_type (main_position->currentIndex ()));
|
||||
ruler.set_main_xalign (Object::alignment_type (main_xalign->currentIndex ()));
|
||||
ruler.set_main_yalign (Object::alignment_type (main_yalign->currentIndex ()));
|
||||
ruler.set_xlabel_xalign (Object::alignment_type (xlabel_xalign->currentIndex ()));
|
||||
ruler.set_xlabel_yalign (Object::alignment_type (xlabel_yalign->currentIndex ()));
|
||||
ruler.set_ylabel_xalign (Object::alignment_type (ylabel_xalign->currentIndex ()));
|
||||
ruler.set_ylabel_yalign (Object::alignment_type (ylabel_yalign->currentIndex ()));
|
||||
db::DPoint p1, p2;
|
||||
if (segments_tab->currentIndex () == 1) {
|
||||
get_points (p1, p2);
|
||||
} else {
|
||||
get_point (p1);
|
||||
p2 = p1;
|
||||
}
|
||||
|
||||
ruler.set_category (current ().category ());
|
||||
obj = ant::Object (p1, p2, current ().id (), fmt_x, fmt_y, fmt, style, outline, current ().snap (), current ().angle_constraint ());
|
||||
|
||||
mp_rulers->change_ruler (*m_pos, ruler);
|
||||
} else if (segments_tab->currentIndex () == 2 || segments_tab->currentIndex () == 3) {
|
||||
|
||||
ant::Object::point_list points;
|
||||
get_points (points);
|
||||
|
||||
obj = ant::Object (points, current ().id (), fmt_x, fmt_y, fmt, style, outline, current ().snap (), current ().angle_constraint ());
|
||||
|
||||
}
|
||||
|
||||
obj.set_main_position (Object::position_type (main_position->currentIndex ()));
|
||||
obj.set_main_xalign (Object::alignment_type (main_xalign->currentIndex ()));
|
||||
obj.set_main_yalign (Object::alignment_type (main_yalign->currentIndex ()));
|
||||
obj.set_xlabel_xalign (Object::alignment_type (xlabel_xalign->currentIndex ()));
|
||||
obj.set_xlabel_yalign (Object::alignment_type (xlabel_yalign->currentIndex ()));
|
||||
obj.set_ylabel_xalign (Object::alignment_type (ylabel_xalign->currentIndex ()));
|
||||
obj.set_ylabel_yalign (Object::alignment_type (ylabel_yalign->currentIndex ()));
|
||||
|
||||
obj.set_category (current ().category ());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -43,29 +43,33 @@ public:
|
|||
PropertiesPage (ant::Service *rulers, db::Manager *manager, QWidget *parent);
|
||||
~PropertiesPage ();
|
||||
|
||||
virtual void back ();
|
||||
virtual void front ();
|
||||
virtual bool at_begin () const;
|
||||
virtual bool at_end () const;
|
||||
virtual void operator-- ();
|
||||
virtual void operator++ ();
|
||||
virtual size_t count () const;
|
||||
virtual void select_entries (const std::vector<size_t> &entries);
|
||||
virtual std::string description (size_t entry) const;
|
||||
virtual std::string description () const;
|
||||
virtual void update ();
|
||||
virtual void leave ();
|
||||
virtual bool readonly ();
|
||||
virtual void apply ();
|
||||
virtual void apply ();
|
||||
|
||||
private slots:
|
||||
void swap_points_clicked ();
|
||||
void snap_to_layout_clicked ();
|
||||
void something_changed ();
|
||||
|
||||
private:
|
||||
std::vector <ant::Service::obj_iterator> m_selection;
|
||||
std::vector <ant::Service::obj_iterator>::iterator m_pos;
|
||||
size_t m_index;
|
||||
ant::Service *mp_rulers;
|
||||
bool m_enable_cb_callback;
|
||||
bool m_in_something_changed;
|
||||
|
||||
const ant::Object ¤t () const;
|
||||
void get_points(db::DPoint &p1, db::DPoint &p2);
|
||||
void get_points (db::DPoint &p1, db::DPoint &p2);
|
||||
void get_point (db::DPoint &p);
|
||||
void get_points (ant::Object::point_list &points);
|
||||
void update_with (const ant::Object &obj);
|
||||
void get_object (ant::Object &obj);
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -350,7 +350,7 @@ public:
|
|||
/**
|
||||
* @brief Create the properties page
|
||||
*/
|
||||
virtual lay::PropertiesPage *properties_page (db::Manager *manager, QWidget *parent);
|
||||
virtual std::vector<lay::PropertiesPage *> properties_pages (db::Manager *manager, QWidget *parent);
|
||||
#endif
|
||||
|
||||
/**
|
||||
|
|
@ -545,6 +545,8 @@ private:
|
|||
ant::Object m_original;
|
||||
// The current move mode
|
||||
MoveMode m_move_mode;
|
||||
// The currently moving segment
|
||||
size_t m_seg_index;
|
||||
// The ruler template
|
||||
std::vector<ant::Template> m_ruler_templates;
|
||||
unsigned int m_current_template;
|
||||
|
|
@ -566,6 +568,7 @@ private:
|
|||
virtual bool mouse_move_event (const db::DPoint &p, unsigned int buttons, bool prio);
|
||||
virtual bool mouse_press_event (const db::DPoint &p, unsigned int buttons, bool prio);
|
||||
virtual bool mouse_click_event (const db::DPoint &p, unsigned int buttons, bool prio);
|
||||
virtual bool mouse_double_click_event (const db::DPoint &p, unsigned int buttons, bool prio);
|
||||
virtual void deactivated ();
|
||||
|
||||
/**
|
||||
|
|
@ -585,6 +588,11 @@ private:
|
|||
*/
|
||||
void reduce_rulers (int num);
|
||||
|
||||
/**
|
||||
* @brief Finishes drawing mode and creates the ruler
|
||||
*/
|
||||
void finish_drawing ();
|
||||
|
||||
/**
|
||||
* @brief Delete the selected rulers
|
||||
*
|
||||
|
|
|
|||
|
|
@ -62,7 +62,17 @@ public:
|
|||
/**
|
||||
* @brief The ruler is auto-metric: a single click will place a ruler and the ruler will extend to the next adjacent structures
|
||||
*/
|
||||
RulerAutoMetric = 2
|
||||
RulerAutoMetric = 2,
|
||||
|
||||
/**
|
||||
* @brief The ruler an angle type (two segments, three mouse clicks) for angle and circle radius measurements
|
||||
*/
|
||||
RulerThreeClicks = 3,
|
||||
|
||||
/**
|
||||
* @brief The ruler is a multi-segment type
|
||||
*/
|
||||
RulerMultiSegment = 4
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -48,6 +48,8 @@ static int outline_yx () { return int (ant::Object::OL_yx); }
|
|||
static int outline_diag_yx () { return int (ant::Object::OL_diag_yx); }
|
||||
static int outline_box () { return int (ant::Object::OL_box); }
|
||||
static int outline_ellipse () { return int (ant::Object::OL_ellipse); }
|
||||
static int outline_angle () { return int (ant::Object::OL_angle); }
|
||||
static int outline_radius () { return int (ant::Object::OL_radius); }
|
||||
|
||||
static int angle_any () { return int (lay::AC_Any); }
|
||||
static int angle_diagonal () { return int (lay::AC_Diagonal); }
|
||||
|
|
@ -236,6 +238,13 @@ static AnnotationRef create_measure_ruler (lay::LayoutViewBase *view, const db::
|
|||
}
|
||||
}
|
||||
|
||||
static AnnotationRef *ant_from_s (const std::string &s)
|
||||
{
|
||||
std::unique_ptr<AnnotationRef> aref (new AnnotationRef ());
|
||||
aref->from_string (s.c_str ());
|
||||
return aref.release ();
|
||||
}
|
||||
|
||||
static int get_style (const AnnotationRef *obj)
|
||||
{
|
||||
return int (obj->style ());
|
||||
|
|
@ -425,6 +434,16 @@ static int ruler_mode_auto_metric ()
|
|||
return ant::Template::RulerAutoMetric;
|
||||
}
|
||||
|
||||
static int ruler_mode_three_clicks ()
|
||||
{
|
||||
return ant::Template::RulerThreeClicks;
|
||||
}
|
||||
|
||||
static int ruler_mode_multi_segment ()
|
||||
{
|
||||
return ant::Template::RulerMultiSegment;
|
||||
}
|
||||
|
||||
static void register_annotation_template (const ant::Object &a, const std::string &title, int mode)
|
||||
{
|
||||
ant::Template t = ant::Template::from_object (a, title, mode);
|
||||
|
|
@ -496,68 +515,80 @@ gsi::Class<AnnotationRef> decl_Annotation (decl_BasicAnnotation, "lay", "Annotat
|
|||
) +
|
||||
gsi::method ("RulerModeSingleClick", &gsi::ruler_mode_single_click,
|
||||
"@brief Specifies single-click ruler mode for the \\register_template method\n"
|
||||
"In single click-mode, a ruler can be placed with a single click and p1 will be == p2."
|
||||
"In single click-mode, a ruler can be placed with a single click and p1 will be == p2.\n"
|
||||
"\n"
|
||||
"This constant has been introduced in version 0.25"
|
||||
) +
|
||||
gsi::method ("RulerModeAutoMetric", &gsi::ruler_mode_auto_metric,
|
||||
"@brief Specifies auto-metric ruler mode for the \\register_template method\n"
|
||||
"In auto-metric mode, a ruler can be placed with a single click and p1/p2 will be determined from the neighborhood."
|
||||
"In auto-metric mode, a ruler can be placed with a single click and p1/p2 will be determined from the neighborhood.\n"
|
||||
"\n"
|
||||
"This constant has been introduced in version 0.25"
|
||||
) +
|
||||
gsi::method ("StyleRuler|#style_ruler", &gsi::style_ruler,
|
||||
gsi::method ("RulerThreeClicks", &gsi::ruler_mode_three_clicks,
|
||||
"@brief Specifies three-click ruler mode for the \\register_template method\n"
|
||||
"In this ruler mode, two segments are created for angle and circle radius measurements. Three mouse clicks are required.\n"
|
||||
"\n"
|
||||
"This constant has been introduced in version 0.28"
|
||||
) +
|
||||
gsi::method ("RulerMultiSegment", &gsi::ruler_mode_multi_segment,
|
||||
"@brief Specifies multi-segment mode\n"
|
||||
"In multi-segment mode, multiple segments can be created. The ruler is finished with a double click.\n"
|
||||
"\n"
|
||||
"This constant has been introduced in version 0.28"
|
||||
) +
|
||||
gsi::method ("StyleRuler", &gsi::style_ruler,
|
||||
"@brief Gets the ruler style code for use the \\style method\n"
|
||||
"When this style is specified, the annotation will show a ruler with "
|
||||
"some ticks at distances indicating a decade of units and a suitable "
|
||||
"subdivision into minor ticks at intervals of 1, 2 or 5 units."
|
||||
) +
|
||||
gsi::method ("StyleArrowEnd|#style_arrow_end", &gsi::style_arrow_end,
|
||||
gsi::method ("StyleArrowEnd", &gsi::style_arrow_end,
|
||||
"@brief Gets the end arrow style code for use the \\style method\n"
|
||||
"When this style is specified, an arrow is drawn pointing from the start to the end point."
|
||||
) +
|
||||
gsi::method ("StyleArrowStart|#style_arrow_start", &gsi::style_arrow_start,
|
||||
gsi::method ("StyleArrowStart", &gsi::style_arrow_start,
|
||||
"@brief Gets the start arrow style code for use the \\style method\n"
|
||||
"When this style is specified, an arrow is drawn pointing from the end to the start point."
|
||||
) +
|
||||
gsi::method ("StyleArrowBoth|#style_arrow_both", &gsi::style_arrow_both,
|
||||
gsi::method ("StyleArrowBoth", &gsi::style_arrow_both,
|
||||
"@brief Gets the both arrow ends style code for use the \\style method\n"
|
||||
"When this style is specified, a two-headed arrow is drawn."
|
||||
) +
|
||||
gsi::method ("StyleLine|#style_line", &gsi::style_line,
|
||||
gsi::method ("StyleLine", &gsi::style_line,
|
||||
"@brief Gets the line style code for use with the \\style method\n"
|
||||
"When this style is specified, a plain line is drawn."
|
||||
) +
|
||||
gsi::method ("StyleCrossStart|#style_cross_start", &gsi::style_cross_start,
|
||||
gsi::method ("StyleCrossStart", &gsi::style_cross_start,
|
||||
"@brief Gets the line style code for use with the \\style method\n"
|
||||
"When this style is specified, a cross is drawn at the start point.\n"
|
||||
"\n"
|
||||
"This constant has been added in version 0.26."
|
||||
) +
|
||||
gsi::method ("StyleCrossEnd|#style_cross_end", &gsi::style_cross_end,
|
||||
gsi::method ("StyleCrossEnd", &gsi::style_cross_end,
|
||||
"@brief Gets the line style code for use with the \\style method\n"
|
||||
"When this style is specified, a cross is drawn at the end point.\n"
|
||||
"\n"
|
||||
"This constant has been added in version 0.26."
|
||||
) +
|
||||
gsi::method ("StyleCrossBoth|#style_cross_both", &gsi::style_cross_both,
|
||||
gsi::method ("StyleCrossBoth", &gsi::style_cross_both,
|
||||
"@brief Gets the line style code for use with the \\style method\n"
|
||||
"When this style is specified, a cross is drawn at both points.\n"
|
||||
"\n"
|
||||
"This constant has been added in version 0.26."
|
||||
) +
|
||||
gsi::method ("OutlineDiag|#outline_diag", &gsi::outline_diag,
|
||||
gsi::method ("OutlineDiag", &gsi::outline_diag,
|
||||
"@brief Gets the diagonal output code for use with the \\outline method\n"
|
||||
"When this outline style is specified, a line connecting start and "
|
||||
"end points in the given style (ruler, arrow or plain line) is drawn."
|
||||
) +
|
||||
gsi::method ("OutlineXY|#outline_xy", &gsi::outline_xy,
|
||||
gsi::method ("OutlineXY", &gsi::outline_xy,
|
||||
"@brief Gets the xy outline code for use with the \\outline method\n"
|
||||
"When this outline style is specified, two lines are drawn: one horizontal from left "
|
||||
"to right and attached to the end of that a line from the bottom to the top. The lines "
|
||||
"are drawn in the specified style (see \\style method)."
|
||||
) +
|
||||
gsi::method ("OutlineDiagXY|#outline_diag_xy", &gsi::outline_diag_xy,
|
||||
gsi::method ("OutlineDiagXY", &gsi::outline_diag_xy,
|
||||
"@brief Gets the xy plus diagonal outline code for use with the \\outline method\n"
|
||||
"@brief outline_xy code used by the \\outline method\n"
|
||||
"When this outline style is specified, three lines are drawn: one horizontal from left "
|
||||
|
|
@ -565,53 +596,65 @@ gsi::Class<AnnotationRef> decl_Annotation (decl_BasicAnnotation, "lay", "Annotat
|
|||
"is drawn connecting the start and end points directly. The lines "
|
||||
"are drawn in the specified style (see \\style method)."
|
||||
) +
|
||||
gsi::method ("OutlineYX|#outline_yx", &gsi::outline_yx ,
|
||||
gsi::method ("OutlineYX", &gsi::outline_yx ,
|
||||
"@brief Gets the yx outline code for use with the \\outline method\n"
|
||||
"When this outline style is specified, two lines are drawn: one vertical from bottom "
|
||||
"to top and attached to the end of that a line from the left to the right. The lines "
|
||||
"are drawn in the specified style (see \\style method)."
|
||||
) +
|
||||
gsi::method ("OutlineDiagYX|#outline_diag_yx", &gsi::outline_diag_yx ,
|
||||
gsi::method ("OutlineDiagYX", &gsi::outline_diag_yx ,
|
||||
"@brief Gets the yx plus diagonal outline code for use with the \\outline method\n"
|
||||
"When this outline style is specified, three lines are drawn: one vertical from bottom "
|
||||
"to top and attached to the end of that a line from the left to the right. Another line "
|
||||
"is drawn connecting the start and end points directly. The lines "
|
||||
"are drawn in the specified style (see \\style method)."
|
||||
) +
|
||||
gsi::method ("OutlineBox|#outline_box", &gsi::outline_box,
|
||||
gsi::method ("OutlineBox", &gsi::outline_box,
|
||||
"@brief Gets the box outline code for use with the \\outline method\n"
|
||||
"When this outline style is specified, a box is drawn with the corners specified by the "
|
||||
"start and end point. All box edges are drawn in the style specified with the \\style "
|
||||
"attribute."
|
||||
) +
|
||||
gsi::method ("OutlineEllipse|#outline_ellipse", &gsi::outline_ellipse,
|
||||
gsi::method ("OutlineEllipse", &gsi::outline_ellipse,
|
||||
"@brief Gets the ellipse outline code for use with the \\outline method\n"
|
||||
"When this outline style is specified, an ellipse is drawn with the extensions specified by the "
|
||||
"start and end point. The contour drawn as a line.\n"
|
||||
"\n"
|
||||
"This constant has been introduced in version 0.26."
|
||||
) +
|
||||
gsi::method ("AngleAny|#angle_any", &gsi::angle_any,
|
||||
gsi::method ("OutlineAngle", &gsi::outline_angle,
|
||||
"@brief Gets the angle measurement ruler outline code for use with the \\outline method\n"
|
||||
"When this outline style is specified, the ruler is drawn to indicate the angle between the first and last segment.\n"
|
||||
"\n"
|
||||
"This constant has been introduced in version 0.28."
|
||||
) +
|
||||
gsi::method ("OutlineRadius", &gsi::outline_radius,
|
||||
"@brief Gets the radius measurement ruler outline code for use with the \\outline method\n"
|
||||
"When this outline style is specified, the ruler is drawn to indicate a radius defined by at least three points of the ruler.\n"
|
||||
"\n"
|
||||
"This constant has been introduced in version 0.28."
|
||||
) +
|
||||
gsi::method ("AngleAny", &gsi::angle_any,
|
||||
"@brief Gets the any angle code for use with the \\angle_constraint method\n"
|
||||
"If this value is specified for the angle constraint, all angles will be allowed."
|
||||
) +
|
||||
gsi::method ("AngleDiagonal|#angle_diagonal", &gsi::angle_diagonal,
|
||||
gsi::method ("AngleDiagonal", &gsi::angle_diagonal,
|
||||
"@brief Gets the diagonal angle code for use with the \\angle_constraint method\n"
|
||||
"If this value is specified for the angle constraint, only multiples of 45 degree are allowed."
|
||||
) +
|
||||
gsi::method ("AngleOrtho|#angle_ortho", &gsi::angle_ortho,
|
||||
gsi::method ("AngleOrtho", &gsi::angle_ortho,
|
||||
"@brief Gets the ortho angle code for use with the \\angle_constraint method\n"
|
||||
"If this value is specified for the angle constraint, only multiples of 90 degree are allowed."
|
||||
) +
|
||||
gsi::method ("AngleHorizontal|#angle_horizontal", &gsi::angle_horizontal,
|
||||
gsi::method ("AngleHorizontal", &gsi::angle_horizontal,
|
||||
"@brief Gets the horizontal angle code for use with the \\angle_constraint method\n"
|
||||
"If this value is specified for the angle constraint, only horizontal rulers are allowed."
|
||||
) +
|
||||
gsi::method ("AngleVertical|#angle_vertical", &gsi::angle_vertical,
|
||||
gsi::method ("AngleVertical", &gsi::angle_vertical,
|
||||
"@brief Gets the vertical angle code for use with the \\angle_constraint method\n"
|
||||
"If this value is specified for the angle constraint, only vertical rulers are allowed."
|
||||
) +
|
||||
gsi::method ("AngleGlobal|#angle_global", &gsi::angle_global,
|
||||
gsi::method ("AngleGlobal", &gsi::angle_global,
|
||||
"@brief Gets the global angle code for use with the \\angle_constraint method.\n"
|
||||
"This code will tell the ruler or marker to use the angle constraint defined globally."
|
||||
) +
|
||||
|
|
@ -704,27 +747,80 @@ gsi::Class<AnnotationRef> decl_Annotation (decl_BasicAnnotation, "lay", "Annotat
|
|||
"\n"
|
||||
"This method has been introduced in version 0.25."
|
||||
) +
|
||||
gsi::method ("p1", (const db::DPoint & (AnnotationRef::*) () const) &AnnotationRef::p1,
|
||||
gsi::method ("points", &AnnotationRef::points,
|
||||
"@brief Gets the points of the ruler\n"
|
||||
"A single-segmented ruler has two points. Rulers with more points "
|
||||
"have more segments correspondingly. Note that the point list may have one point "
|
||||
"only (single-point ruler) or may even be empty.\n"
|
||||
"\n"
|
||||
"Use \\points= to set the segment points. Use \\segments to get the number of "
|
||||
"segments and \\seg_p1 and \\seg_p2 to get the first and second point of one segment.\n"
|
||||
"\n"
|
||||
"Multi-segmented rulers have been introduced in version 0.28"
|
||||
) +
|
||||
gsi::method ("points=", &AnnotationRef::set_points, gsi::arg ("points"),
|
||||
"@brief Sets the points for a (potentially) multi-segmented ruler\n"
|
||||
"See \\points for a description of multi-segmented rulers. "
|
||||
"The list of points passed to this method is cleaned from duplicates before being "
|
||||
"stored inside the ruler.\n"
|
||||
"\n"
|
||||
"This method has been introduced in version 0.28."
|
||||
) +
|
||||
gsi::method ("segments", &AnnotationRef::segments,
|
||||
"@brief Gets the number of segments.\n"
|
||||
"This method returns the number of segments the ruler is made up. Even though the "
|
||||
"ruler can be one or even zero points, the number of segments is at least 1.\n"
|
||||
"\n"
|
||||
"This method has been introduced in version 0.28."
|
||||
) +
|
||||
gsi::method ("seg_p1", &AnnotationRef::seg_p1, gsi::arg ("segment_index"),
|
||||
"@brief Gets the first point of the given segment.\n"
|
||||
"The segment is indicated by the segment index which is a number between 0 and \\segments-1.\n"
|
||||
"\n"
|
||||
"This method has been introduced in version 0.28."
|
||||
) +
|
||||
gsi::method ("seg_p2", &AnnotationRef::seg_p2, gsi::arg ("segment_index"),
|
||||
"@brief Gets the second point of the given segment.\n"
|
||||
"The segment is indicated by the segment index which is a number between 0 and \\segments-1.\n"
|
||||
"The second point of a segment is also the first point of the following segment if there is one.\n"
|
||||
"\n"
|
||||
"This method has been introduced in version 0.28."
|
||||
) +
|
||||
gsi::method ("p1", (db::DPoint (AnnotationRef::*) () const) &AnnotationRef::p1,
|
||||
"@brief Gets the first point of the ruler or marker\n"
|
||||
"The points of the ruler or marker are always given in micron units in floating-point "
|
||||
"coordinates.\n"
|
||||
"\n"
|
||||
"This method is provided for backward compatibility. Starting with version 0.28, rulers can "
|
||||
"be multi-segmented. Use \\points or \\seg_p1 to retrieve the points of the ruler segments.\n"
|
||||
"\n"
|
||||
"@return The first point\n"
|
||||
) +
|
||||
gsi::method ("p2", (const db::DPoint & (AnnotationRef::*) () const) &AnnotationRef::p2,
|
||||
gsi::method ("p2", (db::DPoint (AnnotationRef::*) () const) &AnnotationRef::p2,
|
||||
"@brief Gets the second point of the ruler or marker\n"
|
||||
"The points of the ruler or marker are always given in micron units in floating-point "
|
||||
"coordinates.\n"
|
||||
"\n"
|
||||
"This method is provided for backward compatibility. Starting with version 0.28, rulers can "
|
||||
"be multi-segmented. Use \\points or \\seg_p1 to retrieve the points of the ruler segments.\n"
|
||||
"\n"
|
||||
"@return The second point\n"
|
||||
) +
|
||||
gsi::method ("p1=", (void (AnnotationRef::*) (const db::DPoint &)) &AnnotationRef::p1, gsi::arg ("point"),
|
||||
"@brief Sets the first point of the ruler or marker\n"
|
||||
"The points of the ruler or marker are always given in micron units in floating-point "
|
||||
"coordinates.\n"
|
||||
"\n"
|
||||
"This method is provided for backward compatibility. Starting with version 0.28, rulers can "
|
||||
"be multi-segmented. Use \\points= to specify the ruler segments.\n"
|
||||
) +
|
||||
gsi::method ("p2=", (void (AnnotationRef::*) (const db::DPoint &)) &AnnotationRef::p2, gsi::arg ("point"),
|
||||
"@brief Sets the second point of the ruler or marker\n"
|
||||
"The points of the ruler or marker are always given in micron units in floating-point "
|
||||
"coordinates.\n"
|
||||
"\n"
|
||||
"This method is provided for backward compatibility. Starting with version 0.28, rulers can "
|
||||
"be multi-segmented. Use \\points= to specify the ruler segments.\n"
|
||||
) +
|
||||
gsi::method ("box", &AnnotationRef::box,
|
||||
"@brief Gets the bounding box of the object (not including text)\n"
|
||||
|
|
@ -924,14 +1020,17 @@ gsi::Class<AnnotationRef> decl_Annotation (decl_BasicAnnotation, "lay", "Annotat
|
|||
"@brief Returns the angle constraint attribute\n"
|
||||
"See \\angle_constraint= for a more detailed description."
|
||||
) +
|
||||
gsi::method ("text_x", (std::string (AnnotationRef::*)() const) &AnnotationRef::text_x,
|
||||
"@brief Returns the formatted text for the x-axis label"
|
||||
gsi::method ("text_x", (std::string (AnnotationRef::*)(size_t index) const) &AnnotationRef::text_x, gsi::arg ("index", 0),
|
||||
"@brief Returns the formatted text for the x-axis label\n"
|
||||
"The index parameter indicates which segment to use (0 is the first one). It has been added in version 0.28.\n"
|
||||
) +
|
||||
gsi::method ("text_y", (std::string (AnnotationRef::*)() const) &AnnotationRef::text_y,
|
||||
"@brief Returns the formatted text for the y-axis label"
|
||||
gsi::method ("text_y", (std::string (AnnotationRef::*)(size_t index) const) &AnnotationRef::text_y, gsi::arg ("index", 0),
|
||||
"@brief Returns the formatted text for the y-axis label\n"
|
||||
"The index parameter indicates which segment to use (0 is the first one). It has been added in version 0.28.\n"
|
||||
) +
|
||||
gsi::method ("text", (std::string (AnnotationRef::*)() const) &AnnotationRef::text,
|
||||
"@brief Returns the formatted text for the main label"
|
||||
gsi::method ("text", (std::string (AnnotationRef::*)(size_t index) const) &AnnotationRef::text, gsi::arg ("index", 0),
|
||||
"@brief Returns the formatted text for the main label\n"
|
||||
"The index parameter indicates which segment to use (0 is the first one). It has been added in version 0.28.\n"
|
||||
) +
|
||||
gsi::method ("id", (int (AnnotationRef::*)() const) &AnnotationRef::id,
|
||||
"@brief Returns the annotation's ID"
|
||||
|
|
@ -953,6 +1052,12 @@ gsi::Class<AnnotationRef> decl_Annotation (decl_BasicAnnotation, "lay", "Annotat
|
|||
"\n"
|
||||
"This method was introduced in version 0.19."
|
||||
) +
|
||||
gsi::constructor ("from_s", &ant_from_s, gsi::arg ("s"),
|
||||
"@brief Creates a ruler from a string representation\n"
|
||||
"This function creates a ruler from the string returned by \\to_s.\n"
|
||||
"\n"
|
||||
"This method was introduced in version 0.28."
|
||||
) +
|
||||
gsi::method ("==", &AnnotationRef::operator==, gsi::arg ("other"),
|
||||
"@brief Equality operator\n"
|
||||
) +
|
||||
|
|
|
|||
|
|
@ -1366,10 +1366,38 @@ compute_area_and_perimeter_of_net_shapes (const db::hier_clusters<db::NetShape>
|
|||
perimeter = ap_collector.perimeter ();
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
class AntennaShapeGenerator
|
||||
: public PolygonSink
|
||||
{
|
||||
public:
|
||||
AntennaShapeGenerator (db::Layout *layout, db::Shapes &shapes, db::properties_id_type prop_id)
|
||||
: PolygonSink (), mp_layout (layout), mp_shapes (&shapes), m_prop_id (prop_id)
|
||||
{ }
|
||||
|
||||
virtual void put (const db::Polygon &polygon)
|
||||
{
|
||||
if (m_prop_id != 0) {
|
||||
mp_shapes->insert (db::PolygonRefWithProperties (db::PolygonRef (polygon, mp_layout->shape_repository ()), m_prop_id));
|
||||
} else {
|
||||
mp_shapes->insert (db::PolygonRef (polygon, mp_layout->shape_repository ()));
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
db::Layout *mp_layout;
|
||||
db::Shapes *mp_shapes;
|
||||
db::properties_id_type m_prop_id;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
static db::Point
|
||||
get_merged_shapes_of_net (const db::hier_clusters<db::NetShape> &clusters, db::cell_index_type ci, size_t cid, unsigned int layer_id, db::Shapes &shapes)
|
||||
get_merged_shapes_of_net (const db::hier_clusters<db::NetShape> &clusters, db::cell_index_type ci, size_t cid, unsigned int layer_id, db::Layout *layout, db::Shapes &shapes, db::properties_id_type prop_id)
|
||||
{
|
||||
db::Point ref;
|
||||
bool any_ref = false;
|
||||
db::EdgeProcessor ep;
|
||||
|
||||
// count vertices and reserve space
|
||||
|
|
@ -1386,7 +1414,10 @@ 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
|
||||
ref = (*e).p1 ();
|
||||
if (! any_ref && (*e).p1 () < ref) {
|
||||
ref = (*e).p1 ();
|
||||
any_ref = true;
|
||||
}
|
||||
ep.insert (pr, ++p);
|
||||
}
|
||||
} else {
|
||||
|
|
@ -1394,7 +1425,7 @@ get_merged_shapes_of_net (const db::hier_clusters<db::NetShape> &clusters, db::c
|
|||
}
|
||||
}
|
||||
|
||||
db::ShapeGenerator sg (shapes);
|
||||
db::AntennaShapeGenerator sg (layout, shapes, prop_id);
|
||||
db::PolygonGenerator pg (sg, false);
|
||||
db::SimpleMerge op;
|
||||
ep.process (pg, op);
|
||||
|
|
@ -1402,52 +1433,67 @@ get_merged_shapes_of_net (const db::hier_clusters<db::NetShape> &clusters, db::c
|
|||
return ref;
|
||||
}
|
||||
|
||||
static std::string
|
||||
create_antenna_msg (double agate, db::Polygon::area_type agate_int, double gate_area_factor, db::Polygon::perimeter_type pgate_int, double gate_perimeter_factor,
|
||||
double ametal, db::Polygon::area_type ametal_int, double metal_area_factor, db::Polygon::perimeter_type pmetal_int, double metal_perimeter_factor,
|
||||
const std::vector<std::pair<const db::Region *, double> > &diodes,
|
||||
const std::vector<db::Polygon::area_type> &adiodes_int,
|
||||
double r, double ratio, double dbu)
|
||||
static std::vector<std::pair<std::string, tl::Variant> >
|
||||
create_antenna_values (double agate, db::Polygon::area_type agate_int, double gate_area_factor, db::Polygon::perimeter_type pgate_int, double gate_perimeter_factor,
|
||||
double ametal, db::Polygon::area_type ametal_int, double metal_area_factor, db::Polygon::perimeter_type pmetal_int, double metal_perimeter_factor,
|
||||
const std::vector<std::pair<const db::Region *, double> > &diodes,
|
||||
const std::vector<db::Polygon::area_type> &adiodes_int,
|
||||
double r, double ratio, double dbu)
|
||||
{
|
||||
std::string msg;
|
||||
msg += tl::sprintf ("agate_eff: %.12g, ", agate);
|
||||
if (fabs (gate_area_factor) > 1e-6) {
|
||||
msg += tl::sprintf ("agate: %.12g, agate_factor: %.12g, ", agate_int * dbu * dbu, gate_area_factor);
|
||||
std::vector<std::pair<std::string, tl::Variant> > values;
|
||||
|
||||
if (fabs (gate_area_factor - 1.0) <= db::epsilon && fabs (gate_perimeter_factor) <= db::epsilon) {
|
||||
values.push_back (std::make_pair ("agate", agate));
|
||||
} else {
|
||||
if (fabs (gate_area_factor) > db::epsilon) {
|
||||
values.push_back (std::make_pair ("agate", agate_int * dbu * dbu));
|
||||
values.push_back (std::make_pair ("agate_factor", gate_area_factor));
|
||||
}
|
||||
if (fabs (gate_perimeter_factor) > db::epsilon) {
|
||||
values.push_back (std::make_pair ("pgate", pgate_int * dbu));
|
||||
values.push_back (std::make_pair ("pgate_factor", gate_perimeter_factor));
|
||||
}
|
||||
values.push_back (std::make_pair ("agate_eff", agate));
|
||||
}
|
||||
if (fabs (gate_perimeter_factor) > 1e-6) {
|
||||
msg += tl::sprintf ("pgate: %.12g, pgate_factor: %.12g, ", pgate_int * dbu * dbu, gate_perimeter_factor);
|
||||
}
|
||||
msg += tl::sprintf ("ametal_eff: %.12g, ", ametal);
|
||||
if (fabs (metal_area_factor) > 1e-6) {
|
||||
msg += tl::sprintf ("ametal: %.12g, ametal_factor: %.12g, ", ametal_int * dbu * dbu, metal_area_factor);
|
||||
}
|
||||
if (fabs (metal_perimeter_factor) > 1e-6) {
|
||||
msg += tl::sprintf ("pmetal: %.12g, pmetal_factor: %.12g, ", pmetal_int * dbu * dbu, metal_perimeter_factor);
|
||||
if (fabs (metal_area_factor - 1.0) <= db::epsilon && fabs (metal_perimeter_factor) <= db::epsilon) {
|
||||
values.push_back (std::make_pair ("ametal", ametal));
|
||||
} else {
|
||||
if (fabs (metal_area_factor) > db::epsilon) {
|
||||
values.push_back (std::make_pair ("ametal", ametal_int * dbu * dbu));
|
||||
values.push_back (std::make_pair ("ametal_factor", metal_area_factor));
|
||||
}
|
||||
if (fabs (metal_perimeter_factor) > db::epsilon) {
|
||||
values.push_back (std::make_pair ("pmetal", pmetal_int * dbu));
|
||||
values.push_back (std::make_pair ("pmetal_factor", metal_perimeter_factor));
|
||||
}
|
||||
values.push_back (std::make_pair ("ametal_eff", ametal));
|
||||
}
|
||||
if (! adiodes_int.empty ()) {
|
||||
msg += "adiodes: [";
|
||||
std::vector<tl::Variant> v;
|
||||
v.reserve (adiodes_int.size ());
|
||||
for (auto d = adiodes_int.begin (); d != adiodes_int.end (); ++d) {
|
||||
if (d != adiodes_int.begin ()) {
|
||||
msg += ", ";
|
||||
}
|
||||
msg += tl::sprintf ("%.12g", *d * dbu * dbu);
|
||||
v.push_back (*d * dbu * dbu);
|
||||
}
|
||||
msg += "], ";
|
||||
values.push_back (std::make_pair ("adiodes", tl::Variant (v)));
|
||||
}
|
||||
if (! diodes.empty ()) {
|
||||
msg += "diode_factors: [";
|
||||
std::vector<tl::Variant> v;
|
||||
v.reserve (diodes.size ());
|
||||
for (auto d = diodes.begin (); d != diodes.end (); ++d) {
|
||||
if (d != diodes.begin ()) {
|
||||
msg += ", ";
|
||||
}
|
||||
msg += tl::sprintf ("%.12g", d->second);
|
||||
v.push_back (d->second);
|
||||
}
|
||||
msg += "], ";
|
||||
values.push_back (std::make_pair ("diode_factors", tl::Variant (v)));
|
||||
}
|
||||
msg += tl::sprintf ("ratio: %.12g, ", ametal / agate);
|
||||
msg += tl::sprintf ("max_ratio_eff: %.12g, ", r);
|
||||
msg += tl::sprintf ("max_ratio: %.12g", ratio);
|
||||
return msg;
|
||||
values.push_back (std::make_pair ("ratio", ametal / agate));
|
||||
if (ratio > db::epsilon) {
|
||||
if (fabs (r / ratio - 1.0) < db::epsilon) {
|
||||
values.push_back (std::make_pair ("max_ratio", ratio));
|
||||
} else {
|
||||
values.push_back (std::make_pair ("max_ratio_eff", r));
|
||||
values.push_back (std::make_pair ("max_ratio", ratio));
|
||||
}
|
||||
}
|
||||
return values;
|
||||
}
|
||||
|
||||
db::Region LayoutToNetlist::antenna_check (const db::Region &gate, double gate_area_factor, double gate_perimeter_factor, const db::Region &metal, double metal_area_factor, double metal_perimeter_factor, double ratio, const std::vector<std::pair<const db::Region *, double> > &diodes, db::Texts *values)
|
||||
|
|
@ -1538,25 +1584,50 @@ db::Region LayoutToNetlist::antenna_check (const db::Region &gate, double gate_a
|
|||
}
|
||||
|
||||
if (tl::verbosity () >= 50) {
|
||||
tl::info << "cell [" << ly.cell_name (*cid) << "]: " <<
|
||||
create_antenna_msg (agate, agate_int, gate_area_factor, pgate_int, gate_perimeter_factor,
|
||||
ametal, ametal_int, metal_area_factor, pmetal_int, metal_perimeter_factor,
|
||||
diodes, adiodes_int, r, ratio, dbu);
|
||||
std::vector<std::pair<std::string, tl::Variant> > antenna_values =
|
||||
create_antenna_values (agate, agate_int, gate_area_factor, pgate_int, gate_perimeter_factor,
|
||||
ametal, ametal_int, metal_area_factor, pmetal_int, metal_perimeter_factor,
|
||||
diodes, adiodes_int, r, ratio, dbu);
|
||||
tl::info << "cell [" << ly.cell_name (*cid) << "]: ";
|
||||
for (auto v = antenna_values.begin (); v != antenna_values.end (); ++v) {
|
||||
tl::info << " " << v->first << ": " << v->second.to_string ();
|
||||
}
|
||||
}
|
||||
|
||||
if (ametal / agate > r + db::epsilon) {
|
||||
|
||||
db::Shapes &shapes = ly.cell (*cid).shapes (dl.layer ());
|
||||
db::Point ref = get_merged_shapes_of_net (m_net_clusters, *cid, *c, layer_of (metal), shapes);
|
||||
|
||||
std::vector<std::pair<std::string, tl::Variant> > antenna_values =
|
||||
create_antenna_values (agate, agate_int, gate_area_factor, pgate_int, gate_perimeter_factor,
|
||||
ametal, ametal_int, metal_area_factor, pmetal_int, metal_perimeter_factor,
|
||||
diodes, adiodes_int, r, ratio, dbu);
|
||||
|
||||
db::properties_id_type prop_id = 0;
|
||||
if (! values) {
|
||||
db::PropertiesRepository::properties_set ps;
|
||||
for (auto v = antenna_values.begin (); v != antenna_values.end (); ++v) {
|
||||
ps.insert (std::make_pair (ly.properties_repository ().prop_name_id (v->first), v->second));
|
||||
}
|
||||
prop_id = ly.properties_repository ().properties_id (ps);
|
||||
}
|
||||
|
||||
db::Point ref = get_merged_shapes_of_net (m_net_clusters, *cid, *c, layer_of (metal), &ly, shapes, prop_id);
|
||||
|
||||
if (values) {
|
||||
|
||||
// generate a data string with the details of the antenna computation (intentionally like JSON)
|
||||
std::string msg = create_antenna_msg (agate, agate_int, gate_area_factor, pgate_int, gate_perimeter_factor,
|
||||
ametal, ametal_int, metal_area_factor, pmetal_int, metal_perimeter_factor,
|
||||
diodes, adiodes_int, r, ratio, dbu);
|
||||
|
||||
db::Shapes &shapesv = ly.cell (*cid).shapes (dlv.layer ());
|
||||
|
||||
std::string msg;
|
||||
for (auto v = antenna_values.begin (); v != antenna_values.end (); ++v) {
|
||||
if (v != antenna_values.begin ()) {
|
||||
msg += ", ";
|
||||
}
|
||||
msg += v->first;
|
||||
msg += ": ";
|
||||
msg += v->second.to_string ();
|
||||
}
|
||||
|
||||
shapesv.insert (db::Text (msg, db::Trans (ref - db::Point ())));
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4370,6 +4370,17 @@ Class<db::Instance> decl_Instance ("db", "Instance",
|
|||
// ---------------------------------------------------------------
|
||||
// db::ParentInstRep binding (to "ParentInstArray")
|
||||
|
||||
static db::DCellInstArray
|
||||
dinst (const db::ParentInstRep *parent_inst)
|
||||
{
|
||||
const db::Instances *instances = parent_inst->child_inst ().instances ();
|
||||
if (! instances || ! instances->layout ()) {
|
||||
return db::DCellInstArray ();
|
||||
}
|
||||
|
||||
return cell_inst_array_defs<db::CellInstArray>::transform_array (parent_inst->inst (), db::CplxTrans (instances->layout ()->dbu ()));
|
||||
}
|
||||
|
||||
Class<db::ParentInstRep> decl_ParentInstArray ("db", "ParentInstArray",
|
||||
method ("parent_cell_index", &db::ParentInstRep::parent_cell_index,
|
||||
"@brief Gets the index of the parent cell\n"
|
||||
|
|
@ -4381,6 +4392,11 @@ Class<db::ParentInstRep> decl_ParentInstArray ("db", "ParentInstArray",
|
|||
) +
|
||||
method ("inst", &db::ParentInstRep::inst,
|
||||
"@brief Compute the inverse instance by which the parent is seen from the child\n"
|
||||
) +
|
||||
method_ext ("dinst", &dinst,
|
||||
"@brief Compute the inverse instance by which the parent is seen from the child in micrometer units\n"
|
||||
"\n"
|
||||
"This convenience method has been introduced in version 0.28."
|
||||
),
|
||||
"@brief A parent instance\n"
|
||||
"\n"
|
||||
|
|
|
|||
|
|
@ -295,6 +295,30 @@ Class<db::NetlistDeviceExtractor> decl_dbNetlistDeviceExtractor ("db", "DeviceEx
|
|||
"This class has been introduced in version 0.26."
|
||||
);
|
||||
|
||||
template <class Shape>
|
||||
static void
|
||||
define_terminal_by_names (GenericDeviceExtractor *extractor, db::Device *device, const std::string &terminal_name, const std::string &layer_name, const Shape &shape)
|
||||
{
|
||||
if (! extractor->device_class ()) {
|
||||
throw tl::Exception (tl::to_string (tr ("No device class registered yet")));
|
||||
}
|
||||
|
||||
size_t terminal_id = extractor->device_class ()->terminal_id_for_name (terminal_name);
|
||||
|
||||
size_t layer_id = std::numeric_limits<size_t>::max ();
|
||||
for (auto l = extractor->begin_layer_definitions (); l != extractor->end_layer_definitions (); ++l) {
|
||||
if (l->name == layer_name) {
|
||||
layer_id = l->index;
|
||||
}
|
||||
}
|
||||
|
||||
if (layer_id == std::numeric_limits<size_t>::max ()) {
|
||||
throw tl::Exception (tl::to_string (tr ("Not a valid layer name: ")) + layer_name);
|
||||
}
|
||||
|
||||
extractor->define_terminal (device, terminal_id, layer_id, shape);
|
||||
}
|
||||
|
||||
Class<GenericDeviceExtractor> decl_GenericDeviceExtractor (decl_dbNetlistDeviceExtractor, "db", "GenericDeviceExtractor",
|
||||
gsi::callback ("setup", &GenericDeviceExtractor::setup, &GenericDeviceExtractor::cb_setup,
|
||||
"@brief Sets up the extractor.\n"
|
||||
|
|
@ -392,6 +416,27 @@ Class<GenericDeviceExtractor> decl_GenericDeviceExtractor (decl_dbNetlistDeviceE
|
|||
"This version produces a point-like terminal. Note that the point is\n"
|
||||
"specified in database units.\n"
|
||||
) +
|
||||
gsi::method_ext ("define_terminal", &define_terminal_by_names<db::Polygon>,
|
||||
gsi::arg ("device"), gsi::arg ("terminal_name"), gsi::arg ("layer_name"), gsi::arg ("shape"),
|
||||
"@brief Defines a device terminal using names for terminal and layer.\n"
|
||||
"\n"
|
||||
"This convenience version of the ID-based \\define_terminal methods allows using names for terminal and layer.\n"
|
||||
"It has been introduced in version 0.28."
|
||||
) +
|
||||
gsi::method_ext ("define_terminal", &define_terminal_by_names<db::Box>,
|
||||
gsi::arg ("device"), gsi::arg ("terminal_name"), gsi::arg ("layer_name"), gsi::arg ("shape"),
|
||||
"@brief Defines a device terminal using names for terminal and layer.\n"
|
||||
"\n"
|
||||
"This convenience version of the ID-based \\define_terminal methods allows using names for terminal and layer.\n"
|
||||
"It has been introduced in version 0.28."
|
||||
) +
|
||||
gsi::method_ext ("define_terminal", &define_terminal_by_names<db::Point>,
|
||||
gsi::arg ("device"), gsi::arg ("terminal_name"), gsi::arg ("layer_name"), gsi::arg ("point"),
|
||||
"@brief Defines a device terminal using names for terminal and layer.\n"
|
||||
"\n"
|
||||
"This convenience version of the ID-based \\define_terminal methods allows using names for terminal and layer.\n"
|
||||
"It has been introduced in version 0.28."
|
||||
) +
|
||||
gsi::method ("dbu", &GenericDeviceExtractor::dbu,
|
||||
"@brief Gets the database unit\n"
|
||||
) +
|
||||
|
|
|
|||
|
|
@ -209,4 +209,27 @@
|
|||
subversion equivalent.
|
||||
</p>
|
||||
|
||||
<h2>Installation Hooks</h2>
|
||||
|
||||
<p>
|
||||
Scripts can register an event through <class_doc href="Application#on_salt_changed"/> which
|
||||
indicates that packages have been installed or uninstalled.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Packages itself can supply special scripts which are executed after a package was installed
|
||||
or before a package is uninstalled:
|
||||
</p>
|
||||
|
||||
<ul>
|
||||
<li><tt>_install.lym</tt>: if present, this script is executed after the package is installed.</li>
|
||||
<li><tt>_uninstall.lym</tt>: if present, this script is executed before the package is uninstalled.</li>
|
||||
</ul>
|
||||
|
||||
<p>
|
||||
Both scripts need to be stored in the same location as "grain.xml" and have to use
|
||||
"lym" format. This is the generic XML script format KLayout employs as an interpreter-agnostic
|
||||
script representation.
|
||||
</p>
|
||||
|
||||
</doc>
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@
|
|||
|
||||
<title>Doing Measurements</title>
|
||||
<keyword name="Rulers"/>
|
||||
<keyword name="Measure"/>
|
||||
|
||||
<p>
|
||||
A measurement can be performed by clicking on the ruler icon in the
|
||||
|
|
@ -23,6 +24,32 @@
|
|||
is attached perpendicular to the edge next to the initial point.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
You can mark a position with a single click by selecting the "Cross"
|
||||
ruler type. Clicking at a location will place such a ruler. The ruler
|
||||
shows the x and y coordinate.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The "Multi-Ruler" allows concatenating multiple rulers into a single
|
||||
object. Click and the first point to start such a ruler. Then click
|
||||
on more points to add new segments to the ruler. Each segment is shown
|
||||
as an individual ruler with tick marks and a length. Finish the sequence
|
||||
with a double-click.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The "Angle" ruler allows angle measurements. Three clicks are required
|
||||
to define a "V" like arrangement of two rulers. The angle enclosed by the two lines forming the "V"
|
||||
is shown in the ruler.
|
||||
<p>
|
||||
|
||||
<p>
|
||||
Another special ruler, the "Radius" ruler is also a three-click type.
|
||||
Specify three points to define a circle. The ruler shows the radius
|
||||
of this circle and the circle outline.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Rulers can be configured in manifold ways. Use "Rulers And Annotations Setup"
|
||||
in the "Edit" menu to open the ruler configuration dialog.
|
||||
|
|
@ -52,7 +79,7 @@
|
|||
|
||||
<p>
|
||||
Rulers can be moved by selecting "Move" mode with the speedbar buttons
|
||||
in the toolbar or "Move" from the "Mode" submenu in the "Edit" menu. Then
|
||||
in the toolbar or "Move" from the "Mode" sub-menu in the "Edit" menu. Then
|
||||
left-click and drag the ruler or the ruler end point that should be changed.
|
||||
</p>
|
||||
|
||||
|
|
|
|||
|
|
@ -76,6 +76,7 @@
|
|||
<li><b>X:</b> The horizontal extension of the ruler in micron units.</li>
|
||||
<li><b>Y:</b> The vertical extension of the ruler in micron units.</li>
|
||||
<li><b>A:</b> The area enclosed by the ruler (if it was a box) in square millimeters.</li>
|
||||
<li><b>G:</b> The angle enclosed by the first and last segment of the ruler (used for angle measurement rulers).</li>
|
||||
</ul>
|
||||
|
||||
</doc>
|
||||
|
|
|
|||
|
|
@ -61,7 +61,6 @@ InstPropertiesPage::InstPropertiesPage (edt::Service *service, db::Manager *mana
|
|||
for (edt::Service::obj_iterator s = service->selection ().begin (); s != service->selection ().end (); ++s) {
|
||||
m_selection_ptrs.push_back (s);
|
||||
}
|
||||
m_index = 0;
|
||||
m_prop_id = 0;
|
||||
mp_service->clear_highlights ();
|
||||
|
||||
|
|
@ -156,6 +155,10 @@ get_cell_or_pcell_ids_by_name (const db::Layout *layout, const std::string &name
|
|||
void
|
||||
InstPropertiesPage::browse_cell ()
|
||||
{
|
||||
if (m_indexes.empty ()) {
|
||||
return;
|
||||
}
|
||||
|
||||
BEGIN_PROTECTED
|
||||
|
||||
// find the layout the cell has to be looked up: that is either the layout of the current instance or
|
||||
|
|
@ -166,7 +169,7 @@ BEGIN_PROTECTED
|
|||
lib = lib_cbx->current_library ();
|
||||
layout = &lib->layout ();
|
||||
} else {
|
||||
edt::Service::obj_iterator pos = m_selection_ptrs [m_index];
|
||||
edt::Service::obj_iterator pos = m_selection_ptrs [m_indexes.front ()];
|
||||
const lay::CellView &cv = mp_service->view ()->cellview (pos->cv_index ());
|
||||
layout = &cv->layout ();
|
||||
}
|
||||
|
|
@ -207,8 +210,12 @@ END_PROTECTED
|
|||
void
|
||||
InstPropertiesPage::show_props ()
|
||||
{
|
||||
if (m_indexes.empty ()) {
|
||||
return;
|
||||
}
|
||||
|
||||
lay::UserPropertiesForm props_form (this);
|
||||
if (props_form.show (mp_service->view (), m_selection_ptrs [m_index]->cv_index (), m_prop_id)) {
|
||||
if (props_form.show (mp_service->view (), m_selection_ptrs [m_indexes.front ()]->cv_index (), m_prop_id)) {
|
||||
emit edited ();
|
||||
}
|
||||
}
|
||||
|
|
@ -226,43 +233,67 @@ InstPropertiesPage::display_mode_changed (bool)
|
|||
update ();
|
||||
}
|
||||
|
||||
void
|
||||
InstPropertiesPage::back ()
|
||||
size_t
|
||||
InstPropertiesPage::count () const
|
||||
{
|
||||
m_index = (unsigned int) m_selection_ptrs.size ();
|
||||
return m_selection_ptrs.size ();
|
||||
}
|
||||
|
||||
void
|
||||
InstPropertiesPage::front ()
|
||||
void
|
||||
InstPropertiesPage::select_entries (const std::vector<size_t> &entries)
|
||||
{
|
||||
m_index = 0;
|
||||
m_indexes = entries;
|
||||
}
|
||||
|
||||
bool
|
||||
InstPropertiesPage::at_begin () const
|
||||
std::string
|
||||
InstPropertiesPage::description (size_t entry) const
|
||||
{
|
||||
return (m_index == 0);
|
||||
std::string d;
|
||||
|
||||
edt::Service::obj_iterator pos = m_selection_ptrs [entry];
|
||||
if (! pos->is_cell_inst ()) {
|
||||
return d;
|
||||
}
|
||||
|
||||
const lay::CellView &cv = mp_service->view ()->cellview (pos->cv_index ());
|
||||
double dbu = cv->layout ().dbu ();
|
||||
|
||||
db::Layout *def_layout = &cv->layout ();
|
||||
db::cell_index_type def_cell_index = pos->back ().inst_ptr.cell_index ();
|
||||
std::pair<db::Library *, db::cell_index_type> dl = def_layout->defining_library (def_cell_index);
|
||||
if (dl.first) {
|
||||
def_layout = &dl.first->layout ();
|
||||
def_cell_index = dl.second;
|
||||
}
|
||||
|
||||
std::pair<bool, db::pcell_id_type> pci = def_layout->is_pcell_instance (def_cell_index);
|
||||
if (pci.first && def_layout->pcell_declaration (pci.second)) {
|
||||
d += def_layout->pcell_header (pci.second)->get_name ();
|
||||
} else {
|
||||
d += def_layout->cell_name (def_cell_index);
|
||||
}
|
||||
|
||||
db::ICplxTrans t (pos->back ().inst_ptr.complex_trans ());
|
||||
db::DCplxTrans dt = db::CplxTrans (dbu) * t * db::CplxTrans (dbu).inverted ();
|
||||
|
||||
db::Vector rowv, columnv;
|
||||
unsigned long rows, columns;
|
||||
if (pos->back ().inst_ptr.is_regular_array (rowv, columnv, rows, columns)) {
|
||||
d += tl::sprintf ("(%s; array %dx%d)", dt.to_string (true), rows, columns);
|
||||
} else {
|
||||
d += tl::sprintf ("(%s)", dt.to_string (true));
|
||||
}
|
||||
|
||||
return d;
|
||||
}
|
||||
|
||||
bool
|
||||
InstPropertiesPage::at_end () const
|
||||
std::string
|
||||
InstPropertiesPage::description () const
|
||||
{
|
||||
return (m_index == m_selection_ptrs.size ());
|
||||
return tl::to_string (tr ("Instances"));
|
||||
}
|
||||
|
||||
void
|
||||
InstPropertiesPage::operator-- ()
|
||||
{
|
||||
--m_index;
|
||||
}
|
||||
|
||||
void
|
||||
InstPropertiesPage::operator++ ()
|
||||
{
|
||||
++m_index;
|
||||
}
|
||||
|
||||
void
|
||||
void
|
||||
InstPropertiesPage::leave ()
|
||||
{
|
||||
mp_service->clear_highlights ();
|
||||
|
|
@ -271,10 +302,14 @@ InstPropertiesPage::leave ()
|
|||
void
|
||||
InstPropertiesPage::update ()
|
||||
{
|
||||
edt::Service::obj_iterator pos = m_selection_ptrs [m_index];
|
||||
if (m_indexes.empty ()) {
|
||||
return;
|
||||
}
|
||||
|
||||
edt::Service::obj_iterator pos = m_selection_ptrs [m_indexes.front ()];
|
||||
tl_assert (pos->is_cell_inst ());
|
||||
|
||||
mp_service->highlight (m_index);
|
||||
mp_service->highlight (m_indexes);
|
||||
|
||||
m_enable_cb_callback = false;
|
||||
dbu_cb->setChecked (mp_service->view ()->dbu_coordinates ());
|
||||
|
|
@ -382,7 +417,11 @@ InstPropertiesPage::update ()
|
|||
void
|
||||
InstPropertiesPage::show_cell ()
|
||||
{
|
||||
edt::Service::obj_iterator pos = m_selection_ptrs [m_index];
|
||||
if (m_indexes.empty ()) {
|
||||
return;
|
||||
}
|
||||
|
||||
edt::Service::obj_iterator pos = m_selection_ptrs [m_indexes.front ()];
|
||||
|
||||
lay::CellView::unspecific_cell_path_type path (mp_service->view ()->cellview (pos->cv_index ()).combined_unspecific_path ());
|
||||
for (lay::ObjectInstPath::iterator p = pos->begin (); p != pos->end (); ++p) {
|
||||
|
|
@ -395,8 +434,12 @@ InstPropertiesPage::show_cell ()
|
|||
void
|
||||
InstPropertiesPage::show_inst ()
|
||||
{
|
||||
if (m_indexes.empty ()) {
|
||||
return;
|
||||
}
|
||||
|
||||
InstantiationForm inst_form (this);
|
||||
inst_form.show (mp_service->view (), *m_selection_ptrs [m_index]);
|
||||
inst_form.show (mp_service->view (), *m_selection_ptrs [m_indexes.front ()]);
|
||||
}
|
||||
|
||||
bool
|
||||
|
|
@ -408,12 +451,14 @@ InstPropertiesPage::readonly ()
|
|||
ChangeApplicator *
|
||||
InstPropertiesPage::create_applicator (db::Cell & /*cell*/, const db::Instance & /*inst*/, double dbu)
|
||||
{
|
||||
tl_assert (! m_indexes.empty ());
|
||||
|
||||
bool has_error = false;
|
||||
bool has_pcell_error = false;
|
||||
|
||||
std::unique_ptr<CombinedChangeApplicator> appl (new CombinedChangeApplicator ());
|
||||
|
||||
edt::Service::obj_iterator pos = m_selection_ptrs [m_index];
|
||||
edt::Service::obj_iterator pos = m_selection_ptrs [m_indexes.front ()];
|
||||
const lay::CellView &cv = mp_service->view ()->cellview (pos->cv_index ());
|
||||
|
||||
bool du = dbu_cb->isChecked ();
|
||||
|
|
@ -707,13 +752,17 @@ InstPropertiesPage::recompute_selection_ptrs (const std::vector<lay::ObjectInstP
|
|||
void
|
||||
InstPropertiesPage::do_apply (bool current_only, bool relative)
|
||||
{
|
||||
if (m_indexes.empty ()) {
|
||||
return;
|
||||
}
|
||||
|
||||
lay::LayerState layer_state = mp_service->view ()->layer_snapshot ();
|
||||
unsigned int cv_index = m_selection_ptrs [m_index]->cv_index ();
|
||||
unsigned int cv_index = m_selection_ptrs [m_indexes.front ()]->cv_index ();
|
||||
|
||||
std::unique_ptr<ChangeApplicator> applicator;
|
||||
|
||||
{
|
||||
edt::Service::obj_iterator pos = m_selection_ptrs [m_index];
|
||||
edt::Service::obj_iterator pos = m_selection_ptrs [m_indexes.front ()];
|
||||
tl_assert (pos->is_cell_inst ());
|
||||
|
||||
const lay::CellView &cv = mp_service->view ()->cellview (pos->cv_index ());
|
||||
|
|
@ -741,7 +790,7 @@ InstPropertiesPage::do_apply (bool current_only, bool relative)
|
|||
// But it avoids issues with duplicate selections of the same instance which may happen when
|
||||
// an instance is selected multiple times through different hierarchy branches.
|
||||
|
||||
db::Instance current = m_selection_ptrs [m_index]->back ().inst_ptr;
|
||||
db::Instance current = m_selection_ptrs [m_indexes.front ()]->back ().inst_ptr;
|
||||
|
||||
std::vector<lay::ObjectInstPath> new_sel;
|
||||
new_sel.reserve (m_selection_ptrs.size ());
|
||||
|
|
@ -755,9 +804,10 @@ InstPropertiesPage::do_apply (bool current_only, bool relative)
|
|||
|
||||
try {
|
||||
|
||||
for (std::vector<edt::Service::obj_iterator>::const_iterator p = m_selection_ptrs.begin (); p != m_selection_ptrs.end (); ++p) {
|
||||
for (auto ii = m_indexes.begin (); ii != m_indexes.end (); ++ii) {
|
||||
|
||||
edt::Service::obj_iterator pos = *p;
|
||||
size_t index = *ii;
|
||||
edt::Service::obj_iterator pos = m_selection_ptrs [*ii];
|
||||
|
||||
// only update objects from the same layout - this is not practical limitation but saves a lot of effort for
|
||||
// managing different property id's etc.
|
||||
|
|
@ -790,8 +840,6 @@ InstPropertiesPage::do_apply (bool current_only, bool relative)
|
|||
|
||||
if (new_inst != pos->back ().inst_ptr) {
|
||||
|
||||
size_t index = p - m_selection_ptrs.begin ();
|
||||
|
||||
// change selection to new instance
|
||||
new_sel[index].back ().inst_ptr = new_inst;
|
||||
|
||||
|
|
@ -844,6 +892,10 @@ InstPropertiesPage::apply_to_all (bool relative)
|
|||
void
|
||||
InstPropertiesPage::update_pcell_parameters ()
|
||||
{
|
||||
if (m_indexes.empty ()) {
|
||||
return;
|
||||
}
|
||||
|
||||
db::Layout *layout;
|
||||
|
||||
// find the layout the cell has to be looked up: that is either the layout of the current instance or
|
||||
|
|
@ -854,7 +906,7 @@ InstPropertiesPage::update_pcell_parameters ()
|
|||
|
||||
} else {
|
||||
|
||||
edt::Service::obj_iterator pos = m_selection_ptrs [m_index];
|
||||
edt::Service::obj_iterator pos = m_selection_ptrs [m_indexes.front ()];
|
||||
const lay::CellView &cv = mp_service->view ()->cellview (pos->cv_index ());
|
||||
layout = &cv->layout ();
|
||||
|
||||
|
|
@ -878,7 +930,7 @@ InstPropertiesPage::update_pcell_parameters ()
|
|||
|
||||
std::vector<tl::Variant> parameters;
|
||||
|
||||
edt::Service::obj_iterator pos = m_selection_ptrs [m_index];
|
||||
edt::Service::obj_iterator pos = m_selection_ptrs [m_indexes.front ()];
|
||||
const lay::CellView &cv = mp_service->view ()->cellview (pos->cv_index ());
|
||||
db::Cell &cell = cv->layout ().cell (pos->cell_index ());
|
||||
std::pair<bool, db::pcell_id_type> pci = cell.is_pcell_instance (pos->back ().inst_ptr);
|
||||
|
|
|
|||
|
|
@ -47,12 +47,10 @@ public:
|
|||
InstPropertiesPage (edt::Service *service, db::Manager *manager, QWidget *parent);
|
||||
~InstPropertiesPage ();
|
||||
|
||||
virtual void back ();
|
||||
virtual void front ();
|
||||
virtual bool at_begin () const;
|
||||
virtual bool at_end () const;
|
||||
virtual void operator-- ();
|
||||
virtual void operator++ ();
|
||||
virtual size_t count () const;
|
||||
virtual void select_entries (const std::vector<size_t> &entries);
|
||||
virtual std::string description (size_t entry) const;
|
||||
virtual std::string description () const;
|
||||
virtual void leave ();
|
||||
|
||||
private:
|
||||
|
|
@ -61,7 +59,7 @@ private:
|
|||
|
||||
protected:
|
||||
std::vector<edt::Service::obj_iterator> m_selection_ptrs;
|
||||
unsigned int m_index;
|
||||
std::vector<size_t> m_indexes;
|
||||
edt::Service *mp_service;
|
||||
bool m_enable_cb_callback;
|
||||
db::properties_id_type m_prop_id;
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@
|
|||
#include "laySelector.h"
|
||||
#include "layFinder.h"
|
||||
#include "layLayerProperties.h"
|
||||
#include "laybasicConfig.h"
|
||||
#include "tlProgress.h"
|
||||
#include "edtPlugin.h"
|
||||
#include "edtMainService.h"
|
||||
|
|
|
|||
|
|
@ -43,15 +43,14 @@ namespace edt
|
|||
// -------------------------------------------------------------------------
|
||||
// ShapePropertiesPage implementation
|
||||
|
||||
ShapePropertiesPage::ShapePropertiesPage (edt::Service *service, db::Manager *manager, QWidget *parent)
|
||||
ShapePropertiesPage::ShapePropertiesPage (const std::string &description, edt::Service *service, db::Manager *manager, QWidget *parent)
|
||||
: lay::PropertiesPage (parent, manager, service),
|
||||
mp_service (service), m_enable_cb_callback (true)
|
||||
m_description (description), mp_service (service), m_enable_cb_callback (true)
|
||||
{
|
||||
m_selection_ptrs.reserve (service->selection ().size ());
|
||||
for (edt::Service::obj_iterator s = service->selection ().begin (); s != service->selection ().end (); ++s) {
|
||||
m_selection_ptrs.push_back (s);
|
||||
}
|
||||
m_index = 0;
|
||||
m_prop_id = 0;
|
||||
mp_service->clear_highlights ();
|
||||
}
|
||||
|
|
@ -73,43 +72,78 @@ ShapePropertiesPage::setup ()
|
|||
m_enable_cb_callback = true;
|
||||
}
|
||||
|
||||
void
|
||||
ShapePropertiesPage::back ()
|
||||
size_t
|
||||
ShapePropertiesPage::count () const
|
||||
{
|
||||
m_index = (unsigned int) m_selection_ptrs.size ();
|
||||
return m_selection_ptrs.size ();
|
||||
}
|
||||
|
||||
void
|
||||
ShapePropertiesPage::front ()
|
||||
void
|
||||
ShapePropertiesPage::select_entries (const std::vector<size_t> &entries)
|
||||
{
|
||||
m_index = 0;
|
||||
m_indexes = entries;
|
||||
}
|
||||
|
||||
bool
|
||||
ShapePropertiesPage::at_begin () const
|
||||
lay::LayoutViewBase *
|
||||
ShapePropertiesPage::view () const
|
||||
{
|
||||
return (m_index == 0);
|
||||
return mp_service->view ();
|
||||
}
|
||||
|
||||
bool
|
||||
ShapePropertiesPage::at_end () const
|
||||
const db::Shape &
|
||||
ShapePropertiesPage::shape (size_t entry) const
|
||||
{
|
||||
return (m_index == m_selection_ptrs.size ());
|
||||
return m_selection_ptrs [entry]->shape ();
|
||||
}
|
||||
|
||||
void
|
||||
ShapePropertiesPage::operator-- ()
|
||||
double
|
||||
ShapePropertiesPage::dbu (size_t entry) const
|
||||
{
|
||||
--m_index;
|
||||
unsigned int cv_index = m_selection_ptrs [entry]->cv_index ();
|
||||
return view ()->cellview (cv_index)->layout ().dbu ();
|
||||
}
|
||||
|
||||
void
|
||||
ShapePropertiesPage::operator++ ()
|
||||
std::string
|
||||
ShapePropertiesPage::description (size_t entry) const
|
||||
{
|
||||
++m_index;
|
||||
unsigned int cv_index = m_selection_ptrs [entry]->cv_index ();
|
||||
unsigned int layer = m_selection_ptrs [entry]->layer ();
|
||||
|
||||
if (view ()->cellview (cv_index).is_valid ()) {
|
||||
const db::LayerProperties &lp = view ()->cellview (cv_index)->layout ().get_properties (layer);
|
||||
if (view ()->cellviews () > 1) {
|
||||
return lp.to_string () + "@" + tl::to_string (cv_index + 1);
|
||||
} else {
|
||||
return lp.to_string ();
|
||||
}
|
||||
}
|
||||
|
||||
return std::string ();
|
||||
}
|
||||
|
||||
void
|
||||
QIcon
|
||||
ShapePropertiesPage::icon (size_t entry, int w, int h) const
|
||||
{
|
||||
int cv_index = m_selection_ptrs [entry]->cv_index ();
|
||||
int layer = m_selection_ptrs [entry]->layer ();
|
||||
|
||||
auto *view = mp_service->view ();
|
||||
for (auto lp = view->begin_layers (view->current_layer_list ()); ! lp.at_end (); ++lp) {
|
||||
const lay::LayerPropertiesNode *ln = lp.operator-> ();
|
||||
if (ln->cellview_index () == cv_index && ln->layer_index () == layer) {
|
||||
return QIcon (QPixmap::fromImage (view->icon_for_layer (lp, w, h).to_image ()));
|
||||
}
|
||||
}
|
||||
|
||||
return QIcon ();
|
||||
}
|
||||
std::string
|
||||
ShapePropertiesPage::description () const
|
||||
{
|
||||
return m_description;
|
||||
}
|
||||
|
||||
void
|
||||
ShapePropertiesPage::leave ()
|
||||
{
|
||||
mp_service->clear_highlights ();
|
||||
|
|
@ -130,8 +164,8 @@ ShapePropertiesPage::abs_trans () const
|
|||
db::ICplxTrans
|
||||
ShapePropertiesPage::trans () const
|
||||
{
|
||||
if (abs_trans ()) {
|
||||
return m_selection_ptrs[m_index]->trans ();
|
||||
if (abs_trans () && ! m_indexes.empty ()) {
|
||||
return m_selection_ptrs[m_indexes.front ()]->trans ();
|
||||
} else {
|
||||
return db::ICplxTrans ();
|
||||
}
|
||||
|
|
@ -154,7 +188,7 @@ END_PROTECTED
|
|||
void
|
||||
ShapePropertiesPage::update ()
|
||||
{
|
||||
mp_service->highlight (m_index);
|
||||
mp_service->highlight (m_indexes);
|
||||
|
||||
update_shape ();
|
||||
}
|
||||
|
|
@ -179,12 +213,16 @@ ShapePropertiesPage::recompute_selection_ptrs (const std::vector<lay::ObjectInst
|
|||
void
|
||||
ShapePropertiesPage::do_apply (bool current_only, bool relative)
|
||||
{
|
||||
if (m_indexes.empty ()) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::unique_ptr<ChangeApplicator> applicator;
|
||||
|
||||
unsigned int cv_index = m_selection_ptrs [m_index]->cv_index ();
|
||||
unsigned int cv_index = m_selection_ptrs [m_indexes.front ()]->cv_index ();
|
||||
|
||||
{
|
||||
edt::Service::obj_iterator pos = m_selection_ptrs [m_index];
|
||||
edt::Service::obj_iterator pos = m_selection_ptrs [m_indexes.front ()];
|
||||
tl_assert (! pos->is_cell_inst ());
|
||||
|
||||
const lay::CellView &cv = mp_service->view ()->cellview (pos->cv_index ());
|
||||
|
|
@ -213,7 +251,7 @@ ShapePropertiesPage::do_apply (bool current_only, bool relative)
|
|||
// But it avoids issues with duplicate selections of the same shape which may happen when
|
||||
// a shape is selected multiple times through different hierarchy branches.
|
||||
|
||||
db::Shape current = m_selection_ptrs [m_index]->shape ();
|
||||
db::Shape current = m_selection_ptrs [m_indexes.front ()]->shape ();
|
||||
|
||||
std::vector<lay::ObjectInstPath> new_sel;
|
||||
new_sel.reserve (m_selection_ptrs.size ());
|
||||
|
|
@ -227,11 +265,10 @@ ShapePropertiesPage::do_apply (bool current_only, bool relative)
|
|||
|
||||
try {
|
||||
|
||||
for (std::vector<edt::Service::obj_iterator>::const_iterator p = m_selection_ptrs.begin (); p != m_selection_ptrs.end (); ++p) {
|
||||
for (auto i = m_indexes.begin (); i != m_indexes.end (); ++i) {
|
||||
|
||||
size_t index = p - m_selection_ptrs.begin ();
|
||||
|
||||
edt::Service::obj_iterator pos = *p;
|
||||
size_t index = *i;
|
||||
edt::Service::obj_iterator pos = m_selection_ptrs [*i];
|
||||
|
||||
// only update objects from the same layout - this is not practical limitation but saves a lot of effort for
|
||||
// managing different property id's etc.
|
||||
|
|
@ -329,7 +366,11 @@ ShapePropertiesPage::apply_to_all (bool relative)
|
|||
void
|
||||
ShapePropertiesPage::update_shape ()
|
||||
{
|
||||
edt::Service::obj_iterator pos = m_selection_ptrs [m_index];
|
||||
if (m_indexes.empty ()) {
|
||||
return;
|
||||
}
|
||||
|
||||
edt::Service::obj_iterator pos = m_selection_ptrs [m_indexes.front ()];
|
||||
|
||||
const lay::CellView &cv = mp_service->view ()->cellview (pos->cv_index ());
|
||||
double dbu = cv->layout ().dbu ();
|
||||
|
|
@ -361,15 +402,23 @@ ShapePropertiesPage::update_shape ()
|
|||
void
|
||||
ShapePropertiesPage::show_inst ()
|
||||
{
|
||||
if (m_indexes.empty ()) {
|
||||
return;
|
||||
}
|
||||
|
||||
InstantiationForm inst_form (this);
|
||||
inst_form.show (mp_service->view (), *m_selection_ptrs [m_index]);
|
||||
inst_form.show (mp_service->view (), *m_selection_ptrs [m_indexes.front ()]);
|
||||
}
|
||||
|
||||
void
|
||||
ShapePropertiesPage::show_props ()
|
||||
{
|
||||
if (m_indexes.empty ()) {
|
||||
return;
|
||||
}
|
||||
|
||||
lay::UserPropertiesForm props_form (this);
|
||||
if (props_form.show (mp_service->view (), m_selection_ptrs [m_index]->cv_index (), m_prop_id)) {
|
||||
if (props_form.show (mp_service->view (), m_selection_ptrs [m_indexes.front ()]->cv_index (), m_prop_id)) {
|
||||
emit edited ();
|
||||
}
|
||||
}
|
||||
|
|
@ -384,7 +433,7 @@ ShapePropertiesPage::readonly ()
|
|||
// PolygonPropertiesPage implementation
|
||||
|
||||
PolygonPropertiesPage::PolygonPropertiesPage (edt::Service *service, db::Manager *manager, QWidget *parent)
|
||||
: ShapePropertiesPage (service, manager, parent), m_in_text_changed (false)
|
||||
: ShapePropertiesPage (tl::to_string (tr ("Polygons")), service, manager, parent), m_in_text_changed (false)
|
||||
{
|
||||
setupUi (this);
|
||||
setup ();
|
||||
|
|
@ -405,7 +454,34 @@ PolygonPropertiesPage::PolygonPropertiesPage (edt::Service *service, db::Manager
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
static size_t count_polygon_points (const db::Shape &sh)
|
||||
{
|
||||
size_t n = 0;
|
||||
for (auto pt = sh.begin_hull (); pt != sh.end_hull (); ++pt) {
|
||||
++n;
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
std::string
|
||||
PolygonPropertiesPage::description (size_t entry) const
|
||||
{
|
||||
const db::Shape &sh = shape (entry);
|
||||
|
||||
size_t npts = count_polygon_points (sh);
|
||||
if (sh.holes () == 0 && npts > 4) {
|
||||
return ShapePropertiesPage::description (entry) + " - " + tl::sprintf (tl::to_string (tr ("Polygon(%d points)")), npts);
|
||||
} else if (sh.holes () > 0) {
|
||||
return ShapePropertiesPage::description (entry) + " - " + tl::sprintf (tl::to_string (tr ("Polygon(%d points, %d holes)")), npts, sh.holes ());
|
||||
} else {
|
||||
db::Polygon poly;
|
||||
sh.polygon (poly);
|
||||
db::CplxTrans dbu_trans (dbu (entry));
|
||||
return ShapePropertiesPage::description (entry) + " - " + tl::sprintf (tl::to_string (tr ("Polygon%s")), (dbu_trans * poly).to_string ());
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
PolygonPropertiesPage::do_update (const db::Shape &shape, double dbu, const std::string &lname)
|
||||
{
|
||||
layer_lbl->setText (tl::to_qstring (lname));
|
||||
|
|
@ -536,7 +612,7 @@ PolygonPropertiesPage::create_applicator (db::Shapes & /*shapes*/, const db::Sha
|
|||
static bool s_coordinateMode = true;
|
||||
|
||||
BoxPropertiesPage::BoxPropertiesPage (edt::Service *service, db::Manager *manager, QWidget *parent)
|
||||
: ShapePropertiesPage (service, manager, parent),
|
||||
: ShapePropertiesPage (tl::to_string (tr ("Boxes")), service, manager, parent),
|
||||
m_recursion_sentinel (false), m_tab_index (0), m_dbu (1.0), m_lr_swapped (false), m_tb_swapped (false)
|
||||
{
|
||||
setupUi (this);
|
||||
|
|
@ -573,6 +649,14 @@ BoxPropertiesPage::BoxPropertiesPage (edt::Service *service, db::Manager *manage
|
|||
connect (prop_pb, SIGNAL (clicked ()), this, SLOT (show_props ()));
|
||||
}
|
||||
|
||||
std::string
|
||||
BoxPropertiesPage::description (size_t entry) const
|
||||
{
|
||||
const db::Shape &sh = shape (entry);
|
||||
db::CplxTrans dbu_trans (dbu (entry));
|
||||
return ShapePropertiesPage::description (entry) + " - " + tl::sprintf (tl::to_string (tr ("Box%s")), (dbu_trans * sh.box ()).to_string ());
|
||||
}
|
||||
|
||||
void
|
||||
BoxPropertiesPage::do_update (const db::Shape &shape, double dbu, const std::string &lname)
|
||||
{
|
||||
|
|
@ -773,7 +857,7 @@ BoxPropertiesPage::changed ()
|
|||
// TextPropertiesPage implementation
|
||||
|
||||
TextPropertiesPage::TextPropertiesPage (edt::Service *service, db::Manager *manager, QWidget *parent)
|
||||
: ShapePropertiesPage (service, manager, parent)
|
||||
: ShapePropertiesPage (tl::to_string (tr ("Texts")), service, manager, parent)
|
||||
{
|
||||
setupUi (this);
|
||||
setup ();
|
||||
|
|
@ -804,7 +888,17 @@ TextPropertiesPage::TextPropertiesPage (edt::Service *service, db::Manager *mana
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
std::string
|
||||
TextPropertiesPage::description (size_t entry) const
|
||||
{
|
||||
const db::Shape &sh = shape (entry);
|
||||
db::Text text;
|
||||
sh.text (text);
|
||||
db::CplxTrans dbu_trans (dbu (entry));
|
||||
return ShapePropertiesPage::description (entry) + " - " + tl::sprintf (tl::to_string (tr ("Text%s")), (dbu_trans * text).to_string ());
|
||||
}
|
||||
|
||||
void
|
||||
TextPropertiesPage::do_update (const db::Shape &shape, double dbu, const std::string &lname)
|
||||
{
|
||||
layer_lbl->setText (tl::to_qstring (lname));
|
||||
|
|
@ -907,7 +1001,7 @@ TextPropertiesPage::create_applicator (db::Shapes & /*shapes*/, const db::Shape
|
|||
// PathPropertiesPage implementation
|
||||
|
||||
PathPropertiesPage::PathPropertiesPage (edt::Service *service, db::Manager *manager, QWidget *parent)
|
||||
: ShapePropertiesPage (service, manager, parent), m_in_text_changed (false)
|
||||
: ShapePropertiesPage (tl::to_string (tr ("Paths")), service, manager, parent), m_in_text_changed (false)
|
||||
{
|
||||
setupUi (this);
|
||||
setup ();
|
||||
|
|
@ -928,6 +1022,34 @@ PathPropertiesPage::PathPropertiesPage (edt::Service *service, db::Manager *mana
|
|||
round_cb->setEnabled (false);
|
||||
}
|
||||
|
||||
static size_t count_path_points (const db::Shape &sh)
|
||||
{
|
||||
size_t n = 0;
|
||||
for (auto pt = sh.begin_point (); pt != sh.end_point (); ++pt) {
|
||||
++n;
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
static std::string path_description (const db::Shape &sh, double dbu)
|
||||
{
|
||||
size_t npts = count_path_points (sh);
|
||||
if (npts > 4) {
|
||||
return tl::sprintf (tl::to_string (tr ("Path(%d points, w=%.12g)")), npts, sh.path_width () * dbu);
|
||||
} else {
|
||||
db::CplxTrans dbu_trans (dbu);
|
||||
db::Path path;
|
||||
sh.path (path);
|
||||
return tl::sprintf (tl::to_string (tr ("Path%s")), (dbu_trans * path).to_string ());
|
||||
}
|
||||
}
|
||||
|
||||
std::string
|
||||
PathPropertiesPage::description (size_t entry) const
|
||||
{
|
||||
return ShapePropertiesPage::description (entry) + " - " + path_description (shape (entry), dbu (entry));
|
||||
}
|
||||
|
||||
void
|
||||
PathPropertiesPage::do_update (const db::Shape &shape, double dbu, const std::string &lname)
|
||||
{
|
||||
|
|
@ -974,7 +1096,7 @@ PathPropertiesPage::create_applicator (db::Shapes & /*shapes*/, const db::Shape
|
|||
// EditablePathPropertiesPage implementation
|
||||
|
||||
EditablePathPropertiesPage::EditablePathPropertiesPage (edt::Service *service, db::Manager *manager, QWidget *parent)
|
||||
: ShapePropertiesPage (service, manager, parent), m_in_text_changed (false)
|
||||
: ShapePropertiesPage (tl::to_string (tr ("Paths")), service, manager, parent), m_in_text_changed (false)
|
||||
{
|
||||
setupUi (this);
|
||||
setup ();
|
||||
|
|
@ -1026,6 +1148,12 @@ EditablePathPropertiesPage::text_changed ()
|
|||
m_in_text_changed = false;
|
||||
}
|
||||
|
||||
std::string
|
||||
EditablePathPropertiesPage::description (size_t entry) const
|
||||
{
|
||||
return ShapePropertiesPage::description (entry) + " - " + path_description (shape (entry), dbu (entry));
|
||||
}
|
||||
|
||||
void
|
||||
EditablePathPropertiesPage::do_update (const db::Shape &shape, double dbu, const std::string &lname)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -46,15 +46,14 @@ class ShapePropertiesPage
|
|||
Q_OBJECT
|
||||
|
||||
public:
|
||||
ShapePropertiesPage (edt::Service *service, db::Manager *manager, QWidget *parent);
|
||||
ShapePropertiesPage (const std::string &description, edt::Service *service, db::Manager *manager, QWidget *parent);
|
||||
~ShapePropertiesPage ();
|
||||
|
||||
virtual void back ();
|
||||
virtual void front ();
|
||||
virtual bool at_begin () const;
|
||||
virtual bool at_end () const;
|
||||
virtual void operator-- ();
|
||||
virtual void operator++ ();
|
||||
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 void leave ();
|
||||
|
||||
protected:
|
||||
|
|
@ -69,8 +68,9 @@ private:
|
|||
void recompute_selection_ptrs (const std::vector<lay::ObjectInstPath> &new_sel);
|
||||
|
||||
protected:
|
||||
std::string m_description;
|
||||
std::vector<edt::Service::obj_iterator> m_selection_ptrs;
|
||||
unsigned int m_index;
|
||||
std::vector<size_t> m_indexes;
|
||||
edt::Service *mp_service;
|
||||
bool m_enable_cb_callback;
|
||||
db::properties_id_type m_prop_id;
|
||||
|
|
@ -83,6 +83,9 @@ protected:
|
|||
bool abs_trans () const;
|
||||
db::ICplxTrans trans () const;
|
||||
void setup ();
|
||||
lay::LayoutViewBase *view () const;
|
||||
const db::Shape &shape (size_t entry) const;
|
||||
double dbu (size_t entry) const;
|
||||
|
||||
public slots:
|
||||
void show_inst ();
|
||||
|
|
@ -101,6 +104,7 @@ Q_OBJECT
|
|||
public:
|
||||
PolygonPropertiesPage (edt::Service *service, db::Manager *manager, QWidget *parent);
|
||||
|
||||
virtual std::string description (size_t entry) const;
|
||||
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);
|
||||
|
||||
|
|
@ -124,6 +128,7 @@ Q_OBJECT
|
|||
public:
|
||||
BoxPropertiesPage (edt::Service *service, db::Manager *manager, QWidget *parent);
|
||||
|
||||
virtual std::string description (size_t entry) const;
|
||||
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);
|
||||
|
||||
|
|
@ -153,6 +158,7 @@ Q_OBJECT
|
|||
public:
|
||||
TextPropertiesPage (edt::Service *service, db::Manager *manager, QWidget *parent);
|
||||
|
||||
virtual std::string description (size_t entry) const;
|
||||
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);
|
||||
|
||||
|
|
@ -170,6 +176,7 @@ Q_OBJECT
|
|||
public:
|
||||
PathPropertiesPage (edt::Service *service, db::Manager *manager, QWidget *parent);
|
||||
|
||||
virtual std::string description (size_t entry) const;
|
||||
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);
|
||||
|
||||
|
|
@ -190,6 +197,7 @@ Q_OBJECT
|
|||
public:
|
||||
EditablePathPropertiesPage (edt::Service *service, db::Manager *manager, QWidget *parent);
|
||||
|
||||
virtual std::string description (size_t entry) const;
|
||||
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);
|
||||
|
||||
|
|
|
|||
|
|
@ -77,6 +77,7 @@ Service::Service (db::Manager *manager, lay::LayoutViewBase *view, db::ShapeIter
|
|||
m_hier_copy_mode (-1),
|
||||
m_indicate_secondary_selection (false),
|
||||
m_seq (0),
|
||||
m_highlights_selected (false),
|
||||
dm_selection_to_view (this, &edt::Service::do_selection_to_view)
|
||||
{
|
||||
mp_view->geom_changed_event.add (this, &edt::Service::selection_to_view);
|
||||
|
|
@ -97,6 +98,7 @@ Service::Service (db::Manager *manager, lay::LayoutViewBase *view)
|
|||
m_hier_copy_mode (-1),
|
||||
m_indicate_secondary_selection (false),
|
||||
m_seq (0),
|
||||
m_highlights_selected (false),
|
||||
dm_selection_to_view (this, &edt::Service::do_selection_to_view)
|
||||
{
|
||||
mp_view->geom_changed_event.add (this, &edt::Service::selection_to_view);
|
||||
|
|
@ -271,28 +273,36 @@ Service::configure (const std::string &name, const std::string &value)
|
|||
void
|
||||
Service::clear_highlights ()
|
||||
{
|
||||
for (std::vector<lay::ViewObject *>::iterator r = m_markers.begin (); r != m_markers.end (); ++r) {
|
||||
(*r)->visible (false);
|
||||
}
|
||||
m_highlights_selected = true;
|
||||
m_selected_highlights.clear ();
|
||||
apply_highlights ();
|
||||
}
|
||||
|
||||
void
|
||||
Service::restore_highlights ()
|
||||
{
|
||||
for (std::vector<lay::ViewObject *>::iterator r = m_markers.begin (); r != m_markers.end (); ++r) {
|
||||
(*r)->visible (true);
|
||||
}
|
||||
m_highlights_selected = false;
|
||||
m_selected_highlights.clear ();
|
||||
apply_highlights ();
|
||||
}
|
||||
|
||||
void
|
||||
Service::highlight (unsigned int n)
|
||||
void
|
||||
Service::highlight (const std::vector<size_t> &n)
|
||||
{
|
||||
m_highlights_selected = true;
|
||||
m_selected_highlights = std::set<size_t> (n.begin (), n.end ());
|
||||
apply_highlights ();
|
||||
}
|
||||
|
||||
void
|
||||
Service::apply_highlights ()
|
||||
{
|
||||
for (std::vector<lay::ViewObject *>::iterator r = m_markers.begin (); r != m_markers.end (); ++r) {
|
||||
(*r)->visible (n-- == 0);
|
||||
(*r)->visible (! m_highlights_selected || m_selected_highlights.find (r - m_markers.begin ()) != m_selected_highlights.end ());
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
void
|
||||
Service::cut ()
|
||||
{
|
||||
if (has_selection () && view ()->is_editable ()) {
|
||||
|
|
@ -1597,6 +1607,8 @@ Service::do_selection_to_view ()
|
|||
}
|
||||
|
||||
}
|
||||
|
||||
apply_highlights ();
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
|||
|
|
@ -105,10 +105,10 @@ public:
|
|||
*/
|
||||
void restore_highlights ();
|
||||
|
||||
/**
|
||||
* @brief Highlight a certain object
|
||||
/**
|
||||
* @brief Highlights a group of objects
|
||||
*/
|
||||
void highlight (unsigned int n);
|
||||
void highlight (const std::vector<size_t> &n);
|
||||
|
||||
/**
|
||||
* @brief "delete" operation
|
||||
|
|
@ -616,6 +616,10 @@ private:
|
|||
bool m_indicate_secondary_selection;
|
||||
unsigned long m_seq;
|
||||
|
||||
// selective highlights
|
||||
bool m_highlights_selected;
|
||||
std::set<size_t> m_selected_highlights;
|
||||
|
||||
// Deferred method to update the selection
|
||||
tl::DeferredMethod<edt::Service> dm_selection_to_view;
|
||||
|
||||
|
|
@ -646,6 +650,11 @@ private:
|
|||
*/
|
||||
void display_status (bool transient);
|
||||
|
||||
/**
|
||||
* @brief Apply highlight selection
|
||||
*/
|
||||
void apply_highlights ();
|
||||
|
||||
private:
|
||||
void copy_selected (unsigned int inst_mode);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -381,10 +381,12 @@ PolygonService::PolygonService (db::Manager *manager, lay::LayoutViewBase *view)
|
|||
}
|
||||
|
||||
#if defined(HAVE_QT)
|
||||
lay::PropertiesPage *
|
||||
PolygonService::properties_page (db::Manager *manager, QWidget *parent)
|
||||
std::vector<lay::PropertiesPage *>
|
||||
PolygonService::properties_pages (db::Manager *manager, QWidget *parent)
|
||||
{
|
||||
return new edt::PolygonPropertiesPage (this, manager, parent);
|
||||
std::vector<lay::PropertiesPage *> pages;
|
||||
pages.push_back (new edt::PolygonPropertiesPage (this, manager, parent));
|
||||
return pages;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
@ -712,10 +714,12 @@ BoxService::BoxService (db::Manager *manager, lay::LayoutViewBase *view)
|
|||
}
|
||||
|
||||
#if defined(HAVE_QT)
|
||||
lay::PropertiesPage *
|
||||
BoxService::properties_page (db::Manager *manager, QWidget *parent)
|
||||
std::vector<lay::PropertiesPage *>
|
||||
BoxService::properties_pages (db::Manager *manager, QWidget *parent)
|
||||
{
|
||||
return new edt::BoxPropertiesPage (this, manager, parent);
|
||||
std::vector<lay::PropertiesPage *> pages;
|
||||
pages.push_back (new edt::BoxPropertiesPage (this, manager, parent));
|
||||
return pages;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
@ -812,10 +816,12 @@ TextService::~TextService ()
|
|||
}
|
||||
|
||||
#if defined(HAVE_QT)
|
||||
lay::PropertiesPage *
|
||||
TextService::properties_page (db::Manager *manager, QWidget *parent)
|
||||
std::vector<lay::PropertiesPage *>
|
||||
TextService::properties_pages (db::Manager *manager, QWidget *parent)
|
||||
{
|
||||
return new edt::TextPropertiesPage (this, manager, parent);
|
||||
std::vector<lay::PropertiesPage *> pages;
|
||||
pages.push_back (new edt::TextPropertiesPage (this, manager, parent));
|
||||
return pages;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
@ -1004,14 +1010,16 @@ PathService::~PathService ()
|
|||
}
|
||||
|
||||
#if defined(HAVE_QT)
|
||||
lay::PropertiesPage *
|
||||
PathService::properties_page (db::Manager *manager, QWidget *parent)
|
||||
std::vector<lay::PropertiesPage *>
|
||||
PathService::properties_pages (db::Manager *manager, QWidget *parent)
|
||||
{
|
||||
std::vector<lay::PropertiesPage *> pages;
|
||||
if (view ()->is_editable ()) {
|
||||
return new edt::EditablePathPropertiesPage (this, manager, parent);
|
||||
pages.push_back (new edt::EditablePathPropertiesPage (this, manager, parent));
|
||||
} else {
|
||||
return new edt::PathPropertiesPage (this, manager, parent);
|
||||
pages.push_back (new edt::PathPropertiesPage (this, manager, parent));
|
||||
}
|
||||
return pages;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
@ -1246,10 +1254,12 @@ InstService::InstService (db::Manager *manager, lay::LayoutViewBase *view)
|
|||
}
|
||||
|
||||
#if defined(HAVE_QT)
|
||||
lay::PropertiesPage *
|
||||
InstService::properties_page (db::Manager *manager, QWidget *parent)
|
||||
std::vector<lay::PropertiesPage *>
|
||||
InstService::properties_pages (db::Manager *manager, QWidget *parent)
|
||||
{
|
||||
return new edt::InstPropertiesPage (this, manager, parent);
|
||||
std::vector<lay::PropertiesPage *> pages;
|
||||
pages.push_back (new edt::InstPropertiesPage (this, manager, parent));
|
||||
return pages;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
|
|||
|
|
@ -90,7 +90,7 @@ public:
|
|||
PolygonService (db::Manager *manager, lay::LayoutViewBase *view);
|
||||
|
||||
#if defined(HAVE_QT)
|
||||
virtual lay::PropertiesPage *properties_page (db::Manager *manager, QWidget *parent);
|
||||
virtual std::vector<lay::PropertiesPage *> properties_pages (db::Manager *manager, QWidget *parent);
|
||||
#endif
|
||||
virtual void do_delete ();
|
||||
virtual void do_begin_edit (const db::DPoint &p);
|
||||
|
|
@ -123,7 +123,7 @@ public:
|
|||
BoxService (db::Manager *manager, lay::LayoutViewBase *view);
|
||||
|
||||
#if defined(HAVE_QT)
|
||||
virtual lay::PropertiesPage *properties_page (db::Manager *manager, QWidget *parent);
|
||||
virtual std::vector<lay::PropertiesPage *> properties_pages (db::Manager *manager, QWidget *parent);
|
||||
#endif
|
||||
virtual void do_begin_edit (const db::DPoint &p);
|
||||
virtual void do_mouse_move (const db::DPoint &p);
|
||||
|
|
@ -151,7 +151,7 @@ public:
|
|||
~TextService ();
|
||||
|
||||
#if defined(HAVE_QT)
|
||||
virtual lay::PropertiesPage *properties_page (db::Manager *manager, QWidget *parent);
|
||||
virtual std::vector<lay::PropertiesPage *> properties_pages (db::Manager *manager, QWidget *parent);
|
||||
#endif
|
||||
virtual void do_begin_edit (const db::DPoint &p);
|
||||
virtual void do_mouse_transform (const db::DPoint &p, db::DFTrans trans);
|
||||
|
|
@ -185,7 +185,7 @@ public:
|
|||
~PathService ();
|
||||
|
||||
#if defined(HAVE_QT)
|
||||
virtual lay::PropertiesPage *properties_page (db::Manager *manager, QWidget *parent);
|
||||
virtual std::vector<lay::PropertiesPage *> properties_pages (db::Manager *manager, QWidget *parent);
|
||||
#endif
|
||||
virtual void do_begin_edit (const db::DPoint &p);
|
||||
virtual void do_mouse_move (const db::DPoint &p);
|
||||
|
|
@ -223,7 +223,7 @@ public:
|
|||
InstService (db::Manager *manager, lay::LayoutViewBase *view);
|
||||
|
||||
#if defined(HAVE_QT)
|
||||
virtual lay::PropertiesPage *properties_page (db::Manager *manager, QWidget *parent);
|
||||
virtual std::vector<lay::PropertiesPage *> properties_pages (db::Manager *manager, QWidget *parent);
|
||||
#endif
|
||||
virtual void do_begin_edit (const db::DPoint &p);
|
||||
virtual void do_mouse_move_inactive (const db::DPoint &p);
|
||||
|
|
|
|||
|
|
@ -52,6 +52,8 @@
|
|||
<file alias="clear_edit_16px@2x.png">images/clear_edit_16px@2x.png</file>
|
||||
<file alias="clearbreakpoints_16px.png">images/clearbreakpoints_16px.png</file>
|
||||
<file alias="clearbreakpoints_16px@2x.png">images/clearbreakpoints_16px@2x.png</file>
|
||||
<file alias="clone_16px.png">images/clone_16px.png</file>
|
||||
<file alias="clone_16px@2x.png">images/clone_16px@2x.png</file>
|
||||
<file alias="cm_add_24px.png">images/cm_add_24px.png</file>
|
||||
<file alias="cm_add_24px@2x.png">images/cm_add_24px@2x.png</file>
|
||||
<file alias="cm_diff_24px.png">images/cm_diff_24px.png</file>
|
||||
|
|
@ -115,6 +117,7 @@
|
|||
<file alias="left_16px.png">images/left_16px.png</file>
|
||||
<file alias="left_16px@2x.png">images/left_16px@2x.png</file>
|
||||
<file alias="logo.png">images/logo.png</file>
|
||||
<file alias="logo@2x.png">images/logo@2x.png</file>
|
||||
<file alias="lt_31px.png">images/lt_31px.png</file>
|
||||
<file alias="lt_31px@2x.png">images/lt_31px@2x.png</file>
|
||||
<file alias="m0_24px.png">images/m0_24px.png</file>
|
||||
|
|
|
|||
Binary file not shown.
|
After Width: | Height: | Size: 411 B |
Binary file not shown.
|
After Width: | Height: | Size: 673 B |
Binary file not shown.
|
Before Width: | Height: | Size: 71 KiB After Width: | Height: | Size: 57 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 174 KiB |
|
|
@ -0,0 +1,93 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
width="16"
|
||||
height="16"
|
||||
viewBox="0 0 4.2333332 4.2333335"
|
||||
version="1.1"
|
||||
id="svg1011"
|
||||
inkscape:version="1.1.2 (0a00cf5339, 2022-02-04)"
|
||||
sodipodi:docname="clone_16px.svg"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<sodipodi:namedview
|
||||
id="namedview1013"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
inkscape:document-units="px"
|
||||
showgrid="true"
|
||||
units="px"
|
||||
inkscape:snap-nodes="true"
|
||||
inkscape:snap-bbox="true"
|
||||
inkscape:bbox-nodes="true"
|
||||
inkscape:snap-others="false"
|
||||
inkscape:zoom="34.576923"
|
||||
inkscape:cx="2.6173526"
|
||||
inkscape:cy="10.006674"
|
||||
inkscape:window-width="1846"
|
||||
inkscape:window-height="1016"
|
||||
inkscape:window-x="74"
|
||||
inkscape:window-y="27"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="layer1"
|
||||
width="16px">
|
||||
<inkscape:grid
|
||||
type="xygrid"
|
||||
id="grid1074"
|
||||
spacingx="0.13229167"
|
||||
spacingy="0.13229167"
|
||||
empspacing="2" />
|
||||
</sodipodi:namedview>
|
||||
<defs
|
||||
id="defs1008">
|
||||
<linearGradient
|
||||
id="linearGradient3600">
|
||||
<stop
|
||||
style="stop-color:#ff9f3f;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop3602" />
|
||||
<stop
|
||||
style="stop-color:#ffffff;stop-opacity:1;"
|
||||
offset="1"
|
||||
id="stop3604" />
|
||||
</linearGradient>
|
||||
</defs>
|
||||
<g
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1">
|
||||
<path
|
||||
style="fill:none;fill-rule:evenodd;stroke:#fdfdfd;stroke-width:0.79375;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.5"
|
||||
d="M 0.92604171,2.3812501 V 1.9843751 H 1.9843751 V 0.92604171 h 0.79375 V 1.9843751 h 1.0583333 v 0.79375 H 2.7781251 v 1.0583333 h -0.79375 V 2.7781251 H 0.92604171 Z"
|
||||
id="path828" />
|
||||
<path
|
||||
style="fill:#808080;fill-opacity:1;fill-rule:evenodd;stroke:#808080;stroke-width:0.264583;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="M 0.92604171,2.3812501 V 1.9843751 H 1.9843751 V 0.92604171 h 0.79375 V 1.9843751 h 1.0583333 v 0.79375 H 2.7781251 v 1.0583333 h -0.79375 V 2.7781251 H 0.92604171 Z"
|
||||
id="path830" />
|
||||
<path
|
||||
style="fill:none;fill-rule:evenodd;stroke:#fdfdfd;stroke-width:0.79375;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.5"
|
||||
d="M 0.39687504,1.8520834 V 1.4552084 H 1.4552084 V 0.39687504 h 0.79375 V 1.4552084 h 1.0583333 v 0.79375 H 2.2489584 v 1.0583333 h -0.79375 V 2.2489584 H 0.39687504 Z"
|
||||
id="path3331" />
|
||||
<rect
|
||||
style="fill:none;stroke:#865b26;stroke-width:0;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
|
||||
id="rect3596"
|
||||
width="4.2333326"
|
||||
height="4.2333331"
|
||||
x="3.3333333e-07"
|
||||
y="3.3333333e-07"
|
||||
inkscape:export-filename="/home/matthias/klayout/master/src/lay/lay/images/back.png"
|
||||
inkscape:export-xdpi="27.093315"
|
||||
inkscape:export-ydpi="27.093315" />
|
||||
<path
|
||||
style="fill:#404040;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.264583;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="M 0.39687504,1.8520834 V 1.4552084 H 1.4552084 V 0.39687504 h 0.79375 V 1.4552084 h 1.0583333 v 0.79375 H 2.2489584 v 1.0583333 h -0.79375 V 2.2489584 H 0.39687504 Z"
|
||||
id="path2830" />
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 3.8 KiB |
|
|
@ -44,7 +44,7 @@ PropertiesPage::PropertiesPage (img::Service *service, db::Manager *manager, QWi
|
|||
: lay::PropertiesPage (parent, manager, service), mp_service (service), mp_direct_image (0)
|
||||
{
|
||||
mp_service->get_selection (m_selection);
|
||||
m_pos = m_selection.begin ();
|
||||
m_index = 0;
|
||||
|
||||
mp_service->clear_highlights ();
|
||||
|
||||
|
|
@ -107,10 +107,12 @@ PropertiesPage::init ()
|
|||
|
||||
colors->set_color (std::make_pair (QColor (), QColor ()));
|
||||
colors->setEnabled (false);
|
||||
value_le->setEnabled (false);
|
||||
|
||||
connect (browse_pb, SIGNAL (clicked ()), this, SLOT (browse ()));
|
||||
connect (colors, SIGNAL (color_changed (std::pair<QColor, QColor>)), false_color_control, SLOT (set_current_color (std::pair<QColor, QColor>)));
|
||||
connect (false_color_control, SIGNAL (selection_changed (std::pair<QColor, QColor>)), colors, SLOT (set_color (std::pair<QColor, QColor>)));
|
||||
connect (false_color_control, SIGNAL (selection_changed (std::pair<QColor, QColor>)), this, SLOT (color_mapping_changed ()));
|
||||
connect (false_color_control, SIGNAL (color_mapping_changed ()), this, SLOT (color_mapping_changed ()));
|
||||
|
||||
connect (brightness_slider, SIGNAL (valueChanged (int)), this, SLOT (brightness_slider_changed (int)));
|
||||
|
|
@ -154,44 +156,40 @@ PropertiesPage::invalidate ()
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
PropertiesPage::back ()
|
||||
size_t
|
||||
PropertiesPage::count () const
|
||||
{
|
||||
m_pos = m_selection.end ();
|
||||
return m_selection.size ();
|
||||
}
|
||||
|
||||
void
|
||||
PropertiesPage::select_entries (const std::vector<size_t> &entries)
|
||||
{
|
||||
tl_assert (entries.size () == 1);
|
||||
m_index = entries.front ();
|
||||
invalidate ();
|
||||
}
|
||||
|
||||
void
|
||||
PropertiesPage::front ()
|
||||
std::string
|
||||
PropertiesPage::description (size_t entry) const
|
||||
{
|
||||
m_pos = m_selection.begin ();
|
||||
invalidate ();
|
||||
const img::Object *obj = dynamic_cast <const img::Object *> (m_selection [entry]->ptr ());
|
||||
if (! obj) {
|
||||
return std::string ("nil");
|
||||
}
|
||||
|
||||
std::string d = tl::to_string (tr ("Image"));
|
||||
if (! obj->filename ().empty ()) {
|
||||
d += "[" + tl::filename (obj->filename ()) + "]";
|
||||
}
|
||||
d += tl::sprintf ("(%dx%d)", obj->width (), obj->height ());
|
||||
return d;
|
||||
}
|
||||
|
||||
bool
|
||||
PropertiesPage::at_begin () const
|
||||
std::string
|
||||
PropertiesPage::description () const
|
||||
{
|
||||
return (m_pos == m_selection.begin ());
|
||||
}
|
||||
|
||||
bool
|
||||
PropertiesPage::at_end () const
|
||||
{
|
||||
return (m_pos == m_selection.end ());
|
||||
}
|
||||
|
||||
void
|
||||
PropertiesPage::operator-- ()
|
||||
{
|
||||
--m_pos;
|
||||
invalidate ();
|
||||
}
|
||||
|
||||
void
|
||||
PropertiesPage::operator++ ()
|
||||
{
|
||||
++m_pos;
|
||||
invalidate ();
|
||||
return tl::to_string (tr ("Images"));
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -378,11 +376,11 @@ PropertiesPage::update ()
|
|||
|
||||
if (mp_service) {
|
||||
|
||||
mp_service->highlight (std::distance (m_selection.begin (), m_pos));
|
||||
mp_service->highlight (m_index);
|
||||
|
||||
// create a local copy in which we can apply modifications
|
||||
if (! mp_direct_image) {
|
||||
const img::Object *image = dynamic_cast <const img::Object *> ((*m_pos)->ptr ());
|
||||
const img::Object *image = dynamic_cast <const img::Object *> (m_selection [m_index]->ptr ());
|
||||
mp_direct_image = new img::Object (*image);
|
||||
}
|
||||
|
||||
|
|
@ -908,7 +906,7 @@ PropertiesPage::apply ()
|
|||
mp_direct_image->set_data_mapping (dm);
|
||||
|
||||
if (mp_service) {
|
||||
mp_service->change_image (*m_pos, *mp_direct_image);
|
||||
mp_service->change_image (m_selection [m_index], *mp_direct_image);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -50,12 +50,10 @@ public:
|
|||
PropertiesPage (QWidget *parent);
|
||||
~PropertiesPage ();
|
||||
|
||||
virtual void back ();
|
||||
virtual void front ();
|
||||
virtual bool at_begin () const;
|
||||
virtual bool at_end () const;
|
||||
virtual void operator-- ();
|
||||
virtual void operator++ ();
|
||||
virtual size_t count () const;
|
||||
virtual void select_entries (const std::vector<size_t> &entries);
|
||||
virtual std::string description (size_t entry) const;
|
||||
virtual std::string description () const;
|
||||
virtual void update ();
|
||||
virtual void leave ();
|
||||
virtual bool readonly ();
|
||||
|
|
@ -91,7 +89,7 @@ private slots:
|
|||
|
||||
private:
|
||||
std::vector <img::Service::obj_iterator> m_selection;
|
||||
std::vector <img::Service::obj_iterator>::iterator m_pos;
|
||||
size_t m_index;
|
||||
img::Service *mp_service;
|
||||
img::Object *mp_direct_image;
|
||||
bool m_no_signals;
|
||||
|
|
|
|||
|
|
@ -1377,10 +1377,12 @@ Service::display_status (bool transient)
|
|||
}
|
||||
|
||||
#if defined(HAVE_QT)
|
||||
lay::PropertiesPage *
|
||||
Service::properties_page (db::Manager *manager, QWidget *parent)
|
||||
std::vector<lay::PropertiesPage *>
|
||||
Service::properties_pages (db::Manager *manager, QWidget *parent)
|
||||
{
|
||||
return new img::PropertiesPage (this, manager, parent);
|
||||
std::vector<lay::PropertiesPage *> pages;
|
||||
pages.push_back (new img::PropertiesPage (this, manager, parent));
|
||||
return pages;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
|
|||
|
|
@ -373,7 +373,7 @@ public:
|
|||
/**
|
||||
* @brief Create the properties page
|
||||
*/
|
||||
virtual lay::PropertiesPage *properties_page (db::Manager *manager, QWidget *parent);
|
||||
virtual std::vector<lay::PropertiesPage *> properties_pages (db::Manager *manager, QWidget *parent);
|
||||
#endif
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -63,8 +63,8 @@ TwoColorWidget::TwoColorWidget (QWidget *parent)
|
|||
mp_lock->setIconSize (QSize (16, 16));
|
||||
|
||||
QIcon icon;
|
||||
icon.addFile (":/locked_16.png", QSize (), QIcon::Normal, QIcon::On);
|
||||
icon.addFile (":/unlocked_16.png", QSize (), QIcon::Normal, QIcon::Off);
|
||||
icon.addFile (":/locked_16px.png", QSize (), QIcon::Normal, QIcon::On);
|
||||
icon.addFile (":/unlocked_16px.png", QSize (), QIcon::Normal, QIcon::Off);
|
||||
mp_lock->setIcon (icon);
|
||||
|
||||
connect (mp_left, SIGNAL (color_changed (QColor)), this, SLOT (lcolor_changed (QColor)));
|
||||
|
|
|
|||
|
|
@ -137,7 +137,7 @@
|
|||
<string/>
|
||||
</property>
|
||||
<property name="pixmap">
|
||||
<pixmap resource="../../icons/icons.qrc">:/logo@2x.png</pixmap>
|
||||
<pixmap resource="../../icons/icons.qrc">:/logo.png</pixmap>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
|
|
|
|||
|
|
@ -171,7 +171,7 @@ p, li { white-space: pre-wrap; }
|
|||
</property>
|
||||
<property name="icon">
|
||||
<iconset>
|
||||
<normaloff>:/run.png</normaloff>:/run.png</iconset>
|
||||
<normaloff>:/run_16px.png</normaloff>:/run_16px.png</iconset>
|
||||
</property>
|
||||
<property name="autoDefault">
|
||||
<bool>true</bool>
|
||||
|
|
@ -280,7 +280,7 @@ p, li { white-space: pre-wrap; }
|
|||
</property>
|
||||
<property name="icon">
|
||||
<iconset>
|
||||
<normaloff>:/run.png</normaloff>:/run.png</iconset>
|
||||
<normaloff>:/run_16px.png</normaloff>:/run_16px.png</iconset>
|
||||
</property>
|
||||
<property name="autoDefault">
|
||||
<bool>true</bool>
|
||||
|
|
@ -454,7 +454,7 @@ p, li { white-space: pre-wrap; }
|
|||
</property>
|
||||
<property name="icon">
|
||||
<iconset>
|
||||
<normaloff>:/run.png</normaloff>:/run.png</iconset>
|
||||
<normaloff>:/run_16px.png</normaloff>:/run_16px.png</iconset>
|
||||
</property>
|
||||
<property name="autoDefault">
|
||||
<bool>true</bool>
|
||||
|
|
@ -642,7 +642,7 @@ p, li { white-space: pre-wrap; }
|
|||
</property>
|
||||
<property name="icon">
|
||||
<iconset>
|
||||
<normaloff>:/run.png</normaloff>:/run.png</iconset>
|
||||
<normaloff>:/run_16px.png</normaloff>:/run_16px.png</iconset>
|
||||
</property>
|
||||
<property name="autoDefault">
|
||||
<bool>true</bool>
|
||||
|
|
|
|||
|
|
@ -108,6 +108,9 @@
|
|||
</property>
|
||||
<item>
|
||||
<widget class="QToolButton" name="add_pb">
|
||||
<property name="toolTip">
|
||||
<string>Add technology</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>...</string>
|
||||
</property>
|
||||
|
|
@ -116,12 +119,15 @@
|
|||
<normaloff>:/add_16px.png</normaloff>:/add_16px.png</iconset>
|
||||
</property>
|
||||
<property name="autoRaise">
|
||||
<bool>true</bool>
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="delete_pb">
|
||||
<property name="toolTip">
|
||||
<string>Delete technology</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>...</string>
|
||||
</property>
|
||||
|
|
@ -130,33 +136,37 @@
|
|||
<normaloff>:/clear_16px.png</normaloff>:/clear_16px.png</iconset>
|
||||
</property>
|
||||
<property name="autoRaise">
|
||||
<bool>true</bool>
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer>
|
||||
<widget class="QToolButton" name="rename_pb">
|
||||
<property name="toolTip">
|
||||
<string>Rename technology</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Rename</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../../icons/icons.qrc">
|
||||
<normaloff>:/rename_16px@2x.png</normaloff>:/rename_16px@2x.png</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::Expanding</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>141</width>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="rename_pb">
|
||||
<property name="text">
|
||||
<string>Rename</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@
|
|||
#include "layMainWindow.h"
|
||||
#include "laySignalHandler.h"
|
||||
#include "gsiDecl.h"
|
||||
#include "gsiSignals.h"
|
||||
#include "tlArch.h"
|
||||
|
||||
#if defined(HAVE_QTBINDINGS)
|
||||
|
|
@ -243,6 +244,14 @@ static gsi::Methods application_methods ()
|
|||
"\n"
|
||||
"There is exactly one instance of the application. This instance can be obtained with this "
|
||||
"method."
|
||||
) +
|
||||
event<C> ("on_salt_changed", &C::salt_changed_event,
|
||||
"@brief This event is triggered when the package status changes.\n"
|
||||
"\n"
|
||||
"Register to this event if you are interested in package changes - i.e. installation or removal of packages or "
|
||||
"package updates.\n"
|
||||
"\n"
|
||||
"This event has been introduced in version 0.28."
|
||||
)
|
||||
;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -672,6 +672,8 @@ ApplicationBase::init_app ()
|
|||
}
|
||||
}
|
||||
|
||||
sc->salt_changed_event.add (this, &ApplicationBase::salt_changed);
|
||||
|
||||
}
|
||||
|
||||
if (tc) {
|
||||
|
|
@ -852,6 +854,14 @@ ApplicationBase::add_macro_category (const std::string &name, const std::string
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
ApplicationBase::salt_changed ()
|
||||
{
|
||||
BEGIN_PROTECTED_SILENT
|
||||
salt_changed_event ();
|
||||
END_PROTECTED_SILENT
|
||||
}
|
||||
|
||||
ApplicationBase::~ApplicationBase ()
|
||||
{
|
||||
tl::set_ui_exception_handlers (0, 0, 0);
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@
|
|||
|
||||
#include "layCommon.h"
|
||||
#include "layBusy.h"
|
||||
#include "tlEvents.h"
|
||||
|
||||
#include <QApplication>
|
||||
#include <QEventLoop>
|
||||
|
|
@ -76,7 +77,7 @@ class LayoutView;
|
|||
* and one for the GUI version (derived from QApplication).
|
||||
*/
|
||||
class LAY_PUBLIC ApplicationBase
|
||||
: public gsi::ObjectBase
|
||||
: public gsi::ObjectBase, public tl::Object
|
||||
{
|
||||
public:
|
||||
/**
|
||||
|
|
@ -313,6 +314,11 @@ public:
|
|||
*/
|
||||
void init_app ();
|
||||
|
||||
/**
|
||||
* @brief An event indicating that the package collection has changed
|
||||
*/
|
||||
tl::Event salt_changed_event;
|
||||
|
||||
/**
|
||||
* @brief Gets the QApplication object
|
||||
* This method will return non-null only if a GUI-enabled application is present.
|
||||
|
|
@ -376,6 +382,8 @@ private:
|
|||
// in order to maintain a valid MainWindow reference for ruby scripts and Ruby's GC all the time.
|
||||
gsi::Interpreter *mp_ruby_interpreter;
|
||||
gsi::Interpreter *mp_python_interpreter;
|
||||
|
||||
void salt_changed ();
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@
|
|||
#include "tlLog.h"
|
||||
#include "tlInternational.h"
|
||||
#include "tlWebDAV.h"
|
||||
#include "lymMacro.h"
|
||||
|
||||
#include <QFileInfo>
|
||||
#include <QDir>
|
||||
|
|
@ -281,6 +282,21 @@ Salt::remove_grain (const SaltGrain &grain)
|
|||
|
||||
QString name = tl::to_qstring (grain.name ());
|
||||
tl::info << QObject::tr ("Removing package '%1' ..").arg (name);
|
||||
|
||||
// Execute "_uninstall.lym" if it exists
|
||||
try {
|
||||
QFile uninstall_lym (QDir (tl::to_qstring (grain.path ())).absoluteFilePath (tl::to_qstring ("_uninstall.lym")));
|
||||
if (uninstall_lym.exists ()) {
|
||||
lym::Macro uninstall;
|
||||
uninstall.load_from (tl::to_string (uninstall_lym.fileName ()));
|
||||
uninstall.set_file_path (tl::to_string (uninstall_lym.fileName ()));
|
||||
uninstall.run ();
|
||||
}
|
||||
} catch (tl::Exception &ex) {
|
||||
// Errors in the uninstallation script are only logged, but do not prevent uninstallation
|
||||
tl::error << ex.msg ();
|
||||
}
|
||||
|
||||
bool res = remove_from_collection (m_root, grain.name ());
|
||||
if (res) {
|
||||
tl::info << QObject::tr ("Package '%1' removed.").arg (name);
|
||||
|
|
@ -493,10 +509,25 @@ Salt::create_grain (const SaltGrain &templ, SaltGrain &target, double timeout, t
|
|||
|
||||
if (res) {
|
||||
|
||||
tl::info << QObject::tr ("Package '%1' installed").arg (tl::to_qstring (target.name ()));
|
||||
target.set_installed_time (QDateTime::currentDateTime ());
|
||||
target.save ();
|
||||
|
||||
// Execute "_install.lym" if it exists
|
||||
try {
|
||||
QFile install_lym (QDir (tl::to_qstring (target.path ())).absoluteFilePath (tl::to_qstring ("_install.lym")));
|
||||
if (install_lym.exists ()) {
|
||||
lym::Macro install;
|
||||
install.load_from (tl::to_string (install_lym.fileName ()));
|
||||
install.set_file_path (tl::to_string (install_lym.fileName ()));
|
||||
install.run ();
|
||||
}
|
||||
} catch (tl::Exception &ex) {
|
||||
// Errors in the installation script are only logged, but do not prevent installation
|
||||
tl::error << ex.msg ();
|
||||
}
|
||||
|
||||
tl::info << QObject::tr ("Package '%1' installed").arg (tl::to_qstring (target.name ()));
|
||||
|
||||
// NOTE: this is a bit brute force .. we could as well try to insert the new grain into the existing structure
|
||||
refresh ();
|
||||
|
||||
|
|
|
|||
|
|
@ -58,13 +58,13 @@ SaltController::initialized (lay::Dispatcher * /*root*/)
|
|||
connect (m_file_watcher, SIGNAL (fileRemoved (const QString &)), this, SLOT (file_watcher_triggered ()));
|
||||
}
|
||||
|
||||
connect (&m_salt, SIGNAL (collections_changed ()), this, SIGNAL (salt_changed ()));
|
||||
connect (&m_salt, SIGNAL (collections_changed ()), this, SLOT (emit_salt_changed ()));
|
||||
}
|
||||
|
||||
void
|
||||
SaltController::uninitialize (lay::Dispatcher * /*root*/)
|
||||
{
|
||||
disconnect (&m_salt, SIGNAL (collections_changed ()), this, SIGNAL (salt_changed ()));
|
||||
disconnect (&m_salt, SIGNAL (collections_changed ()), this, SLOT (emit_salt_changed ()));
|
||||
|
||||
if (m_file_watcher) {
|
||||
disconnect (m_file_watcher, SIGNAL (fileChanged (const QString &)), this, SLOT (file_watcher_triggered ()));
|
||||
|
|
@ -168,7 +168,7 @@ void
|
|||
SaltController::sync_files ()
|
||||
{
|
||||
tl::log << tl::to_string (tr ("Detected file system change in packages - updating"));
|
||||
emit salt_changed ();
|
||||
emit_salt_changed ();
|
||||
}
|
||||
|
||||
bool
|
||||
|
|
@ -242,6 +242,13 @@ SaltController::file_watcher_triggered ()
|
|||
dm_sync_files ();
|
||||
}
|
||||
|
||||
void
|
||||
SaltController::emit_salt_changed ()
|
||||
{
|
||||
salt_changed_event ();
|
||||
emit salt_changed ();
|
||||
}
|
||||
|
||||
void
|
||||
SaltController::set_salt_mine_url (const std::string &url)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@
|
|||
#include "laySalt.h"
|
||||
#include "tlFileSystemWatcher.h"
|
||||
#include "tlDeferredExecution.h"
|
||||
#include "tlEvents.h"
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
|
@ -171,6 +172,11 @@ public:
|
|||
return m_salt;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Event-style version of "salt_changed"
|
||||
*/
|
||||
tl::Event salt_changed_event;
|
||||
|
||||
/**
|
||||
* @brief Gets the singleton instance for this object
|
||||
*/
|
||||
|
|
@ -182,6 +188,11 @@ private slots:
|
|||
*/
|
||||
void file_watcher_triggered ();
|
||||
|
||||
/**
|
||||
* @brief Emits a salt_changed event + signal
|
||||
*/
|
||||
void emit_salt_changed ();
|
||||
|
||||
signals:
|
||||
/**
|
||||
* @brief This signal is emitted if the salt changed
|
||||
|
|
|
|||
|
|
@ -35,7 +35,13 @@ ViewWidgetStack::ViewWidgetStack (QWidget *parent, const char *name)
|
|||
|
||||
mp_bglabel = new QLabel (this);
|
||||
mp_bglabel->setAutoFillBackground (true);
|
||||
mp_bglabel->setText (QObject::tr ("<html><body><p><img src=\":/logo.png\"/></p><p>Use File/Open to open a layout</p></body></html>"));
|
||||
std::string logo = "logo.png";
|
||||
#if QT_VERSION >= 0x50000
|
||||
if (devicePixelRatio () >= 2.0) {
|
||||
logo = "logo@2x.png";
|
||||
}
|
||||
#endif
|
||||
mp_bglabel->setText (QObject::tr ("<html><body><p><img src=\":/%1\" width=\"256\" height=\"256\"/></p><p>Use File/Open to open a layout</p></body></html>").arg (tl::to_qstring (logo)));
|
||||
mp_bglabel->setAlignment (Qt::AlignVCenter | Qt::AlignHCenter);
|
||||
mp_bglabel->show ();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1603,6 +1603,17 @@ LAYBASIC_PUBLIC Class<lay::LayoutViewBase> decl_LayoutViewBase ("lay", "LayoutVi
|
|||
"Returns an array of \\LayerPropertiesIterator objects pointing to the currently selected layers. "
|
||||
"If no layer view is selected currently, an empty array is returned.\n"
|
||||
) +
|
||||
gsi::method ("icon_for_layer", &lay::LayoutViewBase::icon_for_layer, gsi::arg ("iter"), gsi::arg ("w"), gsi::arg ("h"), gsi::arg ("dpr"), gsi::arg ("di_off", 0), gsi::arg ("no_state", false),
|
||||
"@brief Creates an icon pixmap for the given layer.\n"
|
||||
"\n"
|
||||
"The icon will have size w times h pixels multiplied by the device pixel ratio (dpr). The dpr is "
|
||||
"The number of physical pixels per logical pixels on high-DPI displays.\n"
|
||||
"\n"
|
||||
"'di_off' will shift the dither pattern by the given number of (physical) pixels. "
|
||||
"If 'no_state' is true, the icon will not reflect visibility or validity states but rather the display style.\n"
|
||||
"\n"
|
||||
"This method has been introduced in version 0.28."
|
||||
) +
|
||||
gsi::event ("on_active_cellview_changed", static_cast<tl::Event (lay::LayoutViewBase::*)> (&lay::LayoutViewBase::active_cellview_changed_event),
|
||||
"@brief An event indicating that the active cellview has changed\n"
|
||||
"\n"
|
||||
|
|
@ -1631,6 +1642,14 @@ LAYBASIC_PUBLIC Class<lay::LayoutViewBase> decl_LayoutViewBase ("lay", "LayoutVi
|
|||
"Before version 0.25 this event was based on the observer pattern obsolete now. The corresponding methods "
|
||||
"(add_cellview_observer/remove_cellview_observer) have been removed in 0.25.\n"
|
||||
) +
|
||||
gsi::event ("on_apply_technology", static_cast<tl::event<int> (lay::LayoutViewBase::*)> (&lay::LayoutViewBase::apply_technology_event), gsi::arg ("cellview_index"),
|
||||
"@brief An event indicating that a cellview has requested a new technology\n"
|
||||
"\n"
|
||||
"If the technology of a cellview is changed, this event is triggered.\n"
|
||||
"The integer parameter of this event will indicate the cellview that has changed.\n"
|
||||
"\n"
|
||||
"This event has been introduced in version 0.28.\n"
|
||||
) +
|
||||
gsi::event ("on_file_open", static_cast<tl::Event (lay::LayoutViewBase::*)> (&lay::LayoutViewBase::file_open_event),
|
||||
"@brief An event indicating that a file was opened\n"
|
||||
"\n"
|
||||
|
|
|
|||
|
|
@ -311,15 +311,22 @@ render_scanline_cross (const uint32_t *dp, unsigned int ds, const lay::Bitmap *p
|
|||
return;
|
||||
}
|
||||
|
||||
if (pixels > 15) {
|
||||
pixels = 15;
|
||||
// NOTE: hardcoded bar/width ratio for crosses.
|
||||
unsigned int lw = std::max (std::min ((unsigned int) 6, pixels / 9), (unsigned int) 1);
|
||||
|
||||
const int max_pixels = 31;
|
||||
if (pixels > max_pixels) {
|
||||
pixels = max_pixels;
|
||||
}
|
||||
|
||||
const uint32_t *dm = dp;
|
||||
unsigned int px1 = (pixels - 1) / 2;
|
||||
unsigned int px2 = (pixels - 1) - px1;
|
||||
|
||||
const uint32_t *ps[16];
|
||||
unsigned int spx1 = (lw - 1) / 2;
|
||||
unsigned int spx2 = (lw - 1) - spx1;
|
||||
|
||||
const uint32_t *ps[max_pixels + 1];
|
||||
for (unsigned int p = 0; p < pixels; ++p) {
|
||||
if (y + p < px1) {
|
||||
ps[p] = pbitmap->scanline (0);
|
||||
|
|
@ -330,56 +337,94 @@ render_scanline_cross (const uint32_t *dp, unsigned int ds, const lay::Bitmap *p
|
|||
}
|
||||
}
|
||||
|
||||
uint32_t d, dd = 0, dn;
|
||||
dn = *(ps[px1]++);
|
||||
uint32_t *dpp = data;
|
||||
for (unsigned int i = (w + lay::wordlen - 1) / lay::wordlen; i > 0; --i) {
|
||||
*dpp++ = 0;
|
||||
}
|
||||
|
||||
unsigned int x = w;
|
||||
while (true) {
|
||||
for (unsigned int o = 0; o < pixels; ++o) {
|
||||
|
||||
d = dn;
|
||||
dpp = data;
|
||||
|
||||
dn = 0;
|
||||
if (x > lay::wordlen) {
|
||||
dn = *(ps[px1]++);
|
||||
}
|
||||
|
||||
uint32_t d0 = d;
|
||||
if (d0 != 0) {
|
||||
for (unsigned int p = 1; p <= px1; ++p) {
|
||||
d |= (d0 >> p);
|
||||
}
|
||||
for (unsigned int p = 1; p <= px2; ++p) {
|
||||
d |= (d0 << p);
|
||||
}
|
||||
}
|
||||
if (dn != 0) {
|
||||
for (unsigned int p = 1; p <= px1; ++p) {
|
||||
d |= (dn << (32 - p));
|
||||
}
|
||||
}
|
||||
if (dd != 0) {
|
||||
for (unsigned int p = 1; p <= px2; ++p) {
|
||||
d |= (dd >> (32 - p));
|
||||
}
|
||||
}
|
||||
for (unsigned int p = 0; p < px1; ++p) {
|
||||
d |= *(ps[p]++);
|
||||
}
|
||||
for (unsigned int p = px1 + 1; p < pixels; ++p) {
|
||||
d |= *(ps[p]++);
|
||||
}
|
||||
|
||||
dd = d0;
|
||||
|
||||
*data++ = d & *dm++;
|
||||
if (dm == dp + ds) {
|
||||
dm = dp;
|
||||
}
|
||||
|
||||
if (x > lay::wordlen) {
|
||||
x -= lay::wordlen;
|
||||
unsigned int bpx1 = 0, bpx2 = 0;
|
||||
if (o >= px1 - spx1 && o <= px1 + spx2) {
|
||||
bpx1 = px1;
|
||||
bpx2 = px2;
|
||||
} else {
|
||||
break;
|
||||
bpx1 = spx1;
|
||||
bpx2 = spx2;
|
||||
}
|
||||
|
||||
if (bpx1 > 0 || bpx2 > 0) {
|
||||
|
||||
uint32_t d, dd = 0, dn;
|
||||
dn = *(ps[o]++);
|
||||
|
||||
unsigned int x = w;
|
||||
while (true) {
|
||||
|
||||
d = dn;
|
||||
|
||||
dn = 0;
|
||||
if (x > lay::wordlen) {
|
||||
dn = *(ps[o]++);
|
||||
}
|
||||
|
||||
uint32_t d0 = d;
|
||||
if (d0 != 0) {
|
||||
for (unsigned int p = 1; p <= bpx1; ++p) {
|
||||
d |= (d0 >> p);
|
||||
}
|
||||
for (unsigned int p = 1; p <= bpx2; ++p) {
|
||||
d |= (d0 << p);
|
||||
}
|
||||
}
|
||||
if (dn != 0) {
|
||||
for (unsigned int p = 1; p <= bpx1; ++p) {
|
||||
d |= (dn << (32 - p));
|
||||
}
|
||||
}
|
||||
if (dd != 0) {
|
||||
for (unsigned int p = 1; p <= bpx2; ++p) {
|
||||
d |= (dd >> (32 - p));
|
||||
}
|
||||
}
|
||||
|
||||
dd = d0;
|
||||
|
||||
*dpp++ |= d & *dm++;
|
||||
if (dm == dp + ds) {
|
||||
dm = dp;
|
||||
}
|
||||
|
||||
if (x > lay::wordlen) {
|
||||
x -= lay::wordlen;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
unsigned int x = w;
|
||||
while (true) {
|
||||
|
||||
uint32_t d = *(ps[o]++);
|
||||
|
||||
*dpp++ |= d & *dm++;
|
||||
if (dm == dp + ds) {
|
||||
dm = dp;
|
||||
}
|
||||
|
||||
if (x > lay::wordlen) {
|
||||
x -= lay::wordlen;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -368,9 +368,9 @@ public:
|
|||
* by the caller. The return value is 0 if the Editable object does
|
||||
* not support a properties page.
|
||||
*/
|
||||
virtual lay::PropertiesPage *properties_page (db::Manager * /*manager*/, QWidget * /*parent*/)
|
||||
virtual std::vector<lay::PropertiesPage *> properties_pages (db::Manager * /*manager*/, QWidget * /*parent*/)
|
||||
{
|
||||
return 0;
|
||||
return std::vector<lay::PropertiesPage *> ();
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
|
|||
|
|
@ -160,7 +160,7 @@ protected:
|
|||
ops[0] = lay::ViewOp (cursor_color (canvas), lay::ViewOp::Copy, solid_style, 0, 0, lay::ViewOp::Rect, lw, 0);
|
||||
lay::CanvasPlane *arrow_plane = canvas.plane (ops);
|
||||
|
||||
ops[0] = lay::ViewOp (cursor_color (canvas), lay::ViewOp::Copy, m_solid ? solid_style : dashed_style, 1, 0, lay::ViewOp::Rect, lw, 0);
|
||||
ops[0] = lay::ViewOp (cursor_color (canvas), lay::ViewOp::Copy, m_solid ? solid_style : dashed_style, 0, 0, lay::ViewOp::Rect, lw, 0);
|
||||
lay::CanvasPlane *edge_plane = canvas.plane (ops);
|
||||
|
||||
lay::Renderer &r = canvas.renderer ();
|
||||
|
|
|
|||
|
|
@ -131,137 +131,6 @@ std::string ImageCacheEntry::to_string () const
|
|||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
static void
|
||||
blowup (const tl::PixelBuffer &src, tl::PixelBuffer &dest, unsigned int os)
|
||||
{
|
||||
unsigned int ymax = src.height ();
|
||||
unsigned int xmax = src.width ();
|
||||
|
||||
for (unsigned int y = 0; y < ymax; ++y) {
|
||||
for (unsigned int i = 0; i < os; ++i) {
|
||||
const uint32_t *psrc = (const uint32_t *) src.scan_line (y);
|
||||
uint32_t *pdest = (uint32_t *) dest.scan_line (y * os + i);
|
||||
for (unsigned int x = 0; x < xmax; ++x) {
|
||||
for (unsigned int j = 0; j < os; ++j) {
|
||||
*pdest++ = *psrc;
|
||||
}
|
||||
++psrc;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
subsample (const tl::PixelBuffer &src, tl::PixelBuffer &dest, unsigned int os, double g)
|
||||
{
|
||||
// TODO: this is probably not compatible with the endianess of SPARC ..
|
||||
|
||||
// LUT's for combining the RGB channels
|
||||
|
||||
// forward transformation table
|
||||
unsigned short lut1[256];
|
||||
for (unsigned int i = 0; i < 256; ++i) {
|
||||
double f = (65536 / (os * os)) - 1;
|
||||
lut1[i] = (unsigned short)std::min (f, std::max (0.0, floor (0.5 + pow (i / 255.0, g) * f)));
|
||||
}
|
||||
|
||||
// backward transformation table
|
||||
unsigned char lut2[65536];
|
||||
for (unsigned int i = 0; i < 65536; ++i) {
|
||||
double f = os * os * ((65536 / (os * os)) - 1);
|
||||
lut2[i] = (unsigned char)std::min (255.0, std::max (0.0, floor (0.5 + pow (i / f, 1.0 / g) * 255.0)));
|
||||
}
|
||||
|
||||
// LUT's for alpha channel
|
||||
|
||||
// forward transformation table
|
||||
unsigned short luta1[256];
|
||||
for (unsigned int i = 0; i < 256; ++i) {
|
||||
double f = (65536 / (os * os)) - 1;
|
||||
luta1[i] = (unsigned short)std::min (f, std::max (0.0, floor (0.5 + (i / 255.0) * f)));
|
||||
}
|
||||
|
||||
// backward transformation table
|
||||
unsigned char luta2[65536];
|
||||
for (unsigned int i = 0; i < 65536; ++i) {
|
||||
double f = os * os * ((65536 / (os * os)) - 1);
|
||||
luta2[i] = (unsigned char)std::min (255.0, std::max (0.0, floor (0.5 + (i / f) * 255.0)));
|
||||
}
|
||||
|
||||
unsigned int ymax = dest.height ();
|
||||
unsigned int xmax = dest.width ();
|
||||
|
||||
unsigned short *buffer = new unsigned short[xmax * 4];
|
||||
|
||||
for (unsigned int y = 0; y < ymax; ++y) {
|
||||
|
||||
{
|
||||
|
||||
const unsigned char *psrc = (const unsigned char *) src.scan_line (y * os);
|
||||
unsigned short *pdest = buffer;
|
||||
|
||||
for (unsigned int x = 0; x < xmax; ++x) {
|
||||
|
||||
pdest[0] = lut1[psrc[0]];
|
||||
pdest[1] = lut1[psrc[1]];
|
||||
pdest[2] = lut1[psrc[2]];
|
||||
pdest[3] = luta1[psrc[3]];
|
||||
psrc += 4;
|
||||
|
||||
for (unsigned int j = os; j > 1; j--) {
|
||||
pdest[0] += lut1[psrc[0]];
|
||||
pdest[1] += lut1[psrc[1]];
|
||||
pdest[2] += lut1[psrc[2]];
|
||||
pdest[3] += luta1[psrc[3]];
|
||||
psrc += 4;
|
||||
}
|
||||
|
||||
pdest += 4;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
for (unsigned int i = 1; i < os; ++i) {
|
||||
|
||||
const unsigned char *psrc = (const unsigned char *) src.scan_line (y * os + i);
|
||||
unsigned short *pdest = buffer;
|
||||
|
||||
for (unsigned int x = 0; x < xmax; ++x) {
|
||||
|
||||
for (unsigned int j = os; j > 0; j--) {
|
||||
pdest[0] += lut1[psrc[0]];
|
||||
pdest[1] += lut1[psrc[1]];
|
||||
pdest[2] += lut1[psrc[2]];
|
||||
pdest[3] += luta1[psrc[3]];
|
||||
psrc += 4;
|
||||
}
|
||||
|
||||
pdest += 4;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
{
|
||||
|
||||
unsigned char *pdest = (unsigned char *) dest.scan_line (y);
|
||||
const unsigned short *psrc = buffer;
|
||||
|
||||
for (unsigned int x = 0; x < xmax; ++x) {
|
||||
*pdest++ = lut2[*psrc++];
|
||||
*pdest++ = lut2[*psrc++];
|
||||
*pdest++ = lut2[*psrc++];
|
||||
*pdest++ = luta2[*psrc++];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
delete[] buffer;
|
||||
}
|
||||
|
||||
void
|
||||
invert (unsigned char *data, unsigned int width, unsigned int height)
|
||||
{
|
||||
|
|
@ -281,6 +150,7 @@ LayoutCanvas::LayoutCanvas (lay::LayoutViewBase *view)
|
|||
mp_image_fg (0),
|
||||
m_background (0), m_foreground (0), m_active (0),
|
||||
m_oversampling (1),
|
||||
m_hrm (false),
|
||||
m_need_redraw (false),
|
||||
m_redraw_clearing (false),
|
||||
m_redraw_force_update (true),
|
||||
|
|
@ -328,19 +198,15 @@ LayoutCanvas::~LayoutCanvas ()
|
|||
clear_fg_bitmaps ();
|
||||
}
|
||||
|
||||
#if defined(HAVE_QT) && QT_VERSION >= 0x050000
|
||||
double
|
||||
LayoutCanvas::dpr ()
|
||||
LayoutCanvas::resolution () const
|
||||
{
|
||||
return widget () ? widget ()->devicePixelRatio () : 1.0;
|
||||
if (m_hrm) {
|
||||
return 1.0 / m_oversampling;
|
||||
} else {
|
||||
return 1.0 / (m_oversampling * dpr ());
|
||||
}
|
||||
}
|
||||
#else
|
||||
double
|
||||
LayoutCanvas::dpr ()
|
||||
{
|
||||
return 1.0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_QT)
|
||||
void
|
||||
|
|
@ -407,6 +273,26 @@ LayoutCanvas::set_oversampling (unsigned int os)
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
LayoutCanvas::set_highres_mode (bool hrm)
|
||||
{
|
||||
if (hrm != m_hrm) {
|
||||
m_image_cache.clear ();
|
||||
m_hrm = hrm;
|
||||
do_redraw_all ();
|
||||
}
|
||||
}
|
||||
|
||||
double
|
||||
LayoutCanvas::dpr () const
|
||||
{
|
||||
#if defined(HAVE_QT) && QT_VERSION >= 0x50000
|
||||
return widget () ? widget ()->devicePixelRatio () : 1.0;
|
||||
#else
|
||||
return 1.0;
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
LayoutCanvas::set_colors (tl::Color background, tl::Color foreground, tl::Color active)
|
||||
{
|
||||
|
|
@ -477,7 +363,7 @@ LayoutCanvas::prepare_drawing ()
|
|||
{
|
||||
if (m_need_redraw) {
|
||||
|
||||
BitmapViewObjectCanvas::set_size (m_viewport_l.width (), m_viewport_l.height (), 1.0 / double (m_oversampling * dpr ()));
|
||||
BitmapViewObjectCanvas::set_size (m_viewport_l.width (), m_viewport_l.height (), resolution ());
|
||||
|
||||
if (! mp_image ||
|
||||
(unsigned int) mp_image->width () != m_viewport_l.width () ||
|
||||
|
|
@ -513,7 +399,7 @@ LayoutCanvas::prepare_drawing ()
|
|||
++c;
|
||||
}
|
||||
|
||||
mp_redraw_thread->commit (m_layers, m_viewport_l, 1.0 / double (m_oversampling * dpr ()));
|
||||
mp_redraw_thread->commit (m_layers, m_viewport_l, resolution ());
|
||||
|
||||
if (tl::verbosity () >= 20) {
|
||||
tl::info << "Restored image from cache";
|
||||
|
|
@ -563,7 +449,7 @@ LayoutCanvas::prepare_drawing ()
|
|||
}
|
||||
|
||||
if (m_redraw_clearing) {
|
||||
mp_redraw_thread->start (mp_view->synchronous () ? 0 : mp_view->drawing_workers (), m_layers, m_viewport_l, 1.0 / double (m_oversampling * dpr ()), m_redraw_force_update);
|
||||
mp_redraw_thread->start (mp_view->synchronous () ? 0 : mp_view->drawing_workers (), m_layers, m_viewport_l, resolution (), m_redraw_force_update);
|
||||
} else {
|
||||
mp_redraw_thread->restart (m_need_redraw_layer);
|
||||
}
|
||||
|
|
@ -634,7 +520,7 @@ LayoutCanvas::paint_event ()
|
|||
}
|
||||
|
||||
// render the main bitmaps
|
||||
to_image (scaled_view_ops (m_oversampling * dpr ()), dither_pattern (), line_styles (), m_oversampling * dpr (), background_color (), foreground_color (), active_color (), this, *mp_image, m_viewport_l.width (), m_viewport_l.height ());
|
||||
to_image (scaled_view_ops (1.0 / resolution ()), dither_pattern (), line_styles (), 1.0 / resolution (), background_color (), foreground_color (), active_color (), this, *mp_image, m_viewport_l.width (), m_viewport_l.height ());
|
||||
|
||||
if (mp_image_fg) {
|
||||
delete mp_image_fg;
|
||||
|
|
@ -664,7 +550,7 @@ LayoutCanvas::paint_event ()
|
|||
if (fg_bitmaps () > 0) {
|
||||
|
||||
tl::PixelBuffer full_image (*mp_image);
|
||||
bitmaps_to_image (fg_view_op_vector (), fg_bitmap_vector (), dither_pattern (), line_styles (), m_oversampling * dpr (), &full_image, m_viewport_l.width (), m_viewport_l.height (), false, &m_mutex);
|
||||
bitmaps_to_image (fg_view_op_vector (), fg_bitmap_vector (), dither_pattern (), line_styles (), 1.0 / resolution (), &full_image, m_viewport_l.width (), m_viewport_l.height (), false, &m_mutex);
|
||||
|
||||
// render the foreground parts ..
|
||||
if (m_oversampling == 1) {
|
||||
|
|
@ -672,7 +558,7 @@ LayoutCanvas::paint_event ()
|
|||
} else {
|
||||
tl::PixelBuffer subsampled_image (m_viewport.width (), m_viewport.height ());
|
||||
subsampled_image.set_transparent (mp_image->transparent ());
|
||||
subsample (full_image, subsampled_image, m_oversampling, m_gamma);
|
||||
full_image.subsample (subsampled_image, m_oversampling, m_gamma);
|
||||
*mp_image_fg = subsampled_image;
|
||||
}
|
||||
|
||||
|
|
@ -684,7 +570,7 @@ LayoutCanvas::paint_event ()
|
|||
|
||||
tl::PixelBuffer subsampled_image (m_viewport.width (), m_viewport.height ());
|
||||
subsampled_image.set_transparent (mp_image->transparent ());
|
||||
subsample (*mp_image, subsampled_image, m_oversampling, m_gamma);
|
||||
mp_image->subsample (subsampled_image, m_oversampling, m_gamma);
|
||||
*mp_image_fg = subsampled_image;
|
||||
|
||||
}
|
||||
|
|
@ -711,7 +597,7 @@ LayoutCanvas::paint_event ()
|
|||
full_image.set_transparent (true);
|
||||
full_image.fill (0);
|
||||
|
||||
bitmaps_to_image (fg_view_op_vector (), fg_bitmap_vector (), dither_pattern (), line_styles (), m_oversampling * dpr (), &full_image, m_viewport_l.width (), m_viewport_l.height (), false, &m_mutex);
|
||||
bitmaps_to_image (fg_view_op_vector (), fg_bitmap_vector (), dither_pattern (), line_styles (), 1.0 / resolution (), &full_image, m_viewport_l.width (), m_viewport_l.height (), false, &m_mutex);
|
||||
|
||||
// render the foreground parts ..
|
||||
if (m_oversampling == 1) {
|
||||
|
|
@ -723,7 +609,7 @@ LayoutCanvas::paint_event ()
|
|||
} else {
|
||||
tl::PixelBuffer subsampled_image (m_viewport.width (), m_viewport.height ());
|
||||
subsampled_image.set_transparent (true);
|
||||
subsample (full_image, subsampled_image, m_oversampling, m_gamma);
|
||||
full_image.subsample (subsampled_image, m_oversampling, m_gamma);
|
||||
QImage img = subsampled_image.to_image ();
|
||||
#if QT_VERSION >= 0x050000
|
||||
img.setDevicePixelRatio (dpr ());
|
||||
|
|
@ -799,9 +685,9 @@ public:
|
|||
{
|
||||
if (mp_image_l) {
|
||||
unsigned int os = mp_image_l->width () / width;
|
||||
blowup (*mp_image, *mp_image_l, os);
|
||||
mp_image->blowup (*mp_image_l, os);
|
||||
bitmaps_to_image (fg_view_op_vector (), fg_bitmap_vector (), dp, ls, 1.0 / resolution (), mp_image_l, mp_image_l->width (), mp_image_l->height (), false, 0);
|
||||
subsample (*mp_image_l, *mp_image, os, m_gamma);
|
||||
mp_image_l->subsample (*mp_image, os, m_gamma);
|
||||
} else {
|
||||
bitmaps_to_image (fg_view_op_vector (), fg_bitmap_vector (), dp, ls, 1.0 / resolution (), mp_image, width, height, false, 0);
|
||||
}
|
||||
|
|
@ -812,7 +698,7 @@ public:
|
|||
{
|
||||
if (mp_image_l && mp_image->width () > 0) {
|
||||
unsigned int os = mp_image_l->width () / mp_image->width ();
|
||||
subsample (*mp_image_l, *mp_image, os, m_gamma);
|
||||
mp_image_l->subsample (*mp_image, os, m_gamma);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -986,13 +872,13 @@ LayoutCanvas::screenshot ()
|
|||
tl::PixelBuffer img (m_viewport.width (), m_viewport.height ());
|
||||
img.fill (m_background);
|
||||
|
||||
DetachedViewObjectCanvas vo_canvas (background_color (), foreground_color (), active_color (), m_viewport_l.width (), m_viewport_l.height (), 1.0 / double (m_oversampling * dpr ()), &img);
|
||||
DetachedViewObjectCanvas vo_canvas (background_color (), foreground_color (), active_color (), m_viewport_l.width (), m_viewport_l.height (), resolution (), &img);
|
||||
|
||||
// and paint the background objects. It uses "img" to paint on.
|
||||
do_render_bg (m_viewport_l, vo_canvas);
|
||||
|
||||
// paint the layout bitmaps
|
||||
to_image (scaled_view_ops (m_oversampling * dpr ()), dither_pattern (), line_styles (), m_oversampling * dpr (), background_color (), foreground_color (), active_color (), this, *vo_canvas.bg_image (), m_viewport_l.width (), m_viewport_l.height ());
|
||||
to_image (scaled_view_ops (1.0 / resolution ()), dither_pattern (), line_styles (), 1.0 / resolution (), background_color (), foreground_color (), active_color (), this, *vo_canvas.bg_image (), m_viewport_l.width (), m_viewport_l.height ());
|
||||
|
||||
// subsample current image to provide the background for the foreground objects
|
||||
vo_canvas.make_background ();
|
||||
|
|
|
|||
|
|
@ -256,6 +256,32 @@ public:
|
|||
*/
|
||||
void set_oversampling (unsigned int os);
|
||||
|
||||
/**
|
||||
* @brief Gets the oversampling factor
|
||||
*/
|
||||
unsigned int oversampling () const
|
||||
{
|
||||
return m_oversampling;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set high resolution mode (utilize full DPI on high-DPI displays)
|
||||
*/
|
||||
void set_highres_mode (bool hrm);
|
||||
|
||||
/**
|
||||
* @brief Gets the high resolution mode flag
|
||||
*/
|
||||
bool highres_mode () const
|
||||
{
|
||||
return m_hrm;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the default device pixel ratio for this canvas
|
||||
*/
|
||||
double dpr () const;
|
||||
|
||||
/**
|
||||
* @brief Sets the depth of the image cache
|
||||
*/
|
||||
|
|
@ -380,6 +406,7 @@ private:
|
|||
lay::LineStyles m_line_styles;
|
||||
std::map<unsigned int, std::vector <lay::ViewOp> > m_scaled_view_ops;
|
||||
unsigned int m_oversampling;
|
||||
bool m_hrm;
|
||||
double m_gamma;
|
||||
|
||||
bool m_need_redraw;
|
||||
|
|
@ -417,7 +444,7 @@ private:
|
|||
void do_redraw_all (bool force_redraw = true);
|
||||
|
||||
void prepare_drawing ();
|
||||
double dpr ();
|
||||
virtual double resolution () const;
|
||||
|
||||
const std::vector<ViewOp> &scaled_view_ops (unsigned int lw);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -36,6 +36,7 @@
|
|||
#include "tlExceptions.h"
|
||||
#include "tlDeferredExecution.h"
|
||||
#include "layLayoutViewBase.h"
|
||||
#include "layBitmapsToImage.h"
|
||||
#include "layViewOp.h"
|
||||
#include "layViewObject.h"
|
||||
#include "layConverters.h"
|
||||
|
|
@ -780,6 +781,13 @@ LayoutViewBase::configure (const std::string &name, const std::string &value)
|
|||
mp_canvas->set_oversampling (os);
|
||||
return true;
|
||||
|
||||
} else if (name == cfg_highres_mode) {
|
||||
|
||||
bool hrm = false;
|
||||
tl::from_string (value, hrm);
|
||||
mp_canvas->set_highres_mode (hrm);
|
||||
return true;
|
||||
|
||||
} else if (name == cfg_image_cache_size) {
|
||||
|
||||
int sz = 0;
|
||||
|
|
@ -1520,6 +1528,185 @@ LayoutViewBase::set_selected_layers (const std::vector<lay::LayerPropertiesConst
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief A helper function to create an image from a single bitmap
|
||||
*/
|
||||
static void
|
||||
single_bitmap_to_image (const lay::ViewOp &view_op, lay::Bitmap &bitmap,
|
||||
tl::PixelBuffer *pimage, const lay::DitherPattern &dither_pattern, const lay::LineStyles &line_styles,
|
||||
double dpr, unsigned int width, unsigned int height)
|
||||
{
|
||||
std::vector <lay::ViewOp> view_ops;
|
||||
view_ops.push_back (view_op);
|
||||
|
||||
std::vector <lay::Bitmap *> pbitmaps;
|
||||
pbitmaps.push_back (&bitmap);
|
||||
|
||||
lay::bitmaps_to_image (view_ops, pbitmaps, dither_pattern, line_styles, dpr, pimage, width, height, false, 0);
|
||||
}
|
||||
|
||||
tl::PixelBuffer
|
||||
LayoutViewBase::icon_for_layer (const LayerPropertiesConstIterator &iter, unsigned int w, unsigned int h, double dpr, unsigned int di_off, bool no_state)
|
||||
{
|
||||
if (dpr < 0.0) {
|
||||
dpr = canvas ()->dpr ();
|
||||
}
|
||||
|
||||
int oversampling = canvas () ? canvas ()->oversampling () : 1;
|
||||
double gamma = 2.0;
|
||||
|
||||
bool hrm = canvas () ? canvas ()->highres_mode () : false;
|
||||
double dpr_drawing = oversampling * (hrm ? 1.0 : dpr);
|
||||
|
||||
h = std::max ((unsigned int) 16, h) * oversampling * dpr + 0.5;
|
||||
w = std::max ((unsigned int) 16, w) * oversampling * dpr + 0.5;
|
||||
|
||||
tl::color_t def_color = 0x808080;
|
||||
tl::color_t fill_color = iter->has_fill_color (true) ? iter->eff_fill_color (true) : def_color;
|
||||
tl::color_t frame_color = iter->has_frame_color (true) ? iter->eff_frame_color (true) : def_color;
|
||||
|
||||
tl::PixelBuffer image (w, h);
|
||||
image.set_transparent (true);
|
||||
image.fill (background_color ().rgb ());
|
||||
|
||||
// upper scanline is a dummy one
|
||||
tl::color_t *sl0 = (uint32_t *) image.scan_line (0);
|
||||
for (size_t i = 0; i < w; ++i) {
|
||||
*sl0++ = 0;
|
||||
}
|
||||
|
||||
lay::Bitmap fill (w, h, 1.0);
|
||||
lay::Bitmap frame (w, h, 1.0);
|
||||
lay::Bitmap text (w, h, 1.0);
|
||||
lay::Bitmap vertex (w, h, 1.0);
|
||||
|
||||
unsigned int wp = w - 1;
|
||||
|
||||
if (! no_state && ! iter->visible (true)) {
|
||||
|
||||
wp = w / 4;
|
||||
|
||||
// Show the arrow if it is invisible also locally.
|
||||
if (! iter->visible (false)) {
|
||||
|
||||
unsigned int aw = h / 4;
|
||||
unsigned int ap = w / 2 - 1;
|
||||
for (unsigned int i = 0; i <= aw; ++i) {
|
||||
text.fill (h / 2 - 1 - i, ap, ap + aw - i + 1);
|
||||
text.fill (h / 2 - 1 + i, ap, ap + aw - i + 1);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (! no_state && no_stipples ()) {
|
||||
// Show a partial stipple pattern only for "no stipple" mode
|
||||
for (unsigned int i = 1; i < h - 2; ++i) {
|
||||
fill.fill (i, w - 1 - w / 4, w);
|
||||
}
|
||||
} else {
|
||||
for (unsigned int i = 1; i < h - 2; ++i) {
|
||||
fill.fill (i, w - 1 - wp, w);
|
||||
}
|
||||
}
|
||||
|
||||
int lw = iter->width (true);
|
||||
if (lw < 0) {
|
||||
// default line width is 0 for parents and 1 for leafs
|
||||
lw = iter->has_children () ? 0 : 1;
|
||||
}
|
||||
lw = lw * dpr_drawing + 0.5;
|
||||
|
||||
int p0 = lw / 2;
|
||||
p0 = std::max (0, std::min (int (w / 4 - 1), p0));
|
||||
|
||||
int p1 = (lw - 1) / 2;
|
||||
p1 = std::max (0, std::min (int (w / 4 - 1), p1));
|
||||
|
||||
int p0x = p0, p1x = p1;
|
||||
unsigned int ddx = 0;
|
||||
unsigned int ddy = h - 2 - p1 - p0;
|
||||
if (iter->xfill (true)) {
|
||||
ddx = wp - p0 - p1 - 1;
|
||||
}
|
||||
unsigned int d = ddx / 2;
|
||||
|
||||
frame.fill (p0, w - 1 - (wp - p1), w);
|
||||
frame.fill (h - 2 - p1, w - 1 - (wp - p1), w);
|
||||
|
||||
for (unsigned int i = p0; i < h - 2; ++i) {
|
||||
|
||||
frame.fill (i, w - 1 - p0, w - p0);
|
||||
frame.fill (i, w - 1 - (wp - p1), w - (wp - p1));
|
||||
frame.fill (i, w - 1 - p0x, w - p0x);
|
||||
frame.fill (i, w - 1 - (wp - p1x), w - (wp - p1x));
|
||||
|
||||
while (d < ddx) {
|
||||
d += ddy;
|
||||
frame.fill (i, w - 1 - p0x, w - p0x);
|
||||
frame.fill (i, w - 1 - (wp - p1x), w - (wp - p1x));
|
||||
++p0x;
|
||||
++p1x;
|
||||
}
|
||||
|
||||
if (d >= ddx) {
|
||||
d -= ddx;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (! no_state && ! iter->valid (true)) {
|
||||
|
||||
unsigned int bp = w - 1 - ((w * 7) / 8 - 1);
|
||||
unsigned int be = bp + h / 2;
|
||||
unsigned int bw = h / 4 - 1;
|
||||
unsigned int by = h / 2 - 1;
|
||||
|
||||
for (unsigned int i = 0; i < bw + 2; ++i) {
|
||||
fill.clear (by - i, bp - 1, be);
|
||||
fill.clear (by + i, bp - 1, be);
|
||||
}
|
||||
|
||||
for (unsigned int i = 0; i < bw; ++i) {
|
||||
text.fill (by - i, bp + bw - i - 1, bp + bw - i + 1);
|
||||
text.fill (by - i - 1, bp + bw - i - 1, bp + bw - i + 1);
|
||||
text.fill (by - i, bp + bw + i, bp + bw + i + 2);
|
||||
text.fill (by - i - 1, bp + bw + i, bp + bw + i + 2);
|
||||
text.fill (by + i, bp + bw - i - 1, bp + bw - i + 1);
|
||||
text.fill (by + i + 1, bp + bw - i - 1, bp + bw - i + 1);
|
||||
text.fill (by + i, bp + bw + i, bp + bw + i + 2);
|
||||
text.fill (by + i + 1, bp + bw + i, bp + bw + i + 2);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
vertex.fill (h / 2 - 1, w - 1 - wp / 2, w - wp / 2);
|
||||
|
||||
lay::ViewOp::Mode mode = lay::ViewOp::Copy;
|
||||
|
||||
// create fill
|
||||
single_bitmap_to_image (lay::ViewOp (fill_color, mode, 0, iter->eff_dither_pattern (true), di_off), fill, &image, dither_pattern (), line_styles (), dpr_drawing, w, h);
|
||||
// create frame
|
||||
if (lw == 0) {
|
||||
single_bitmap_to_image (lay::ViewOp (frame_color, mode, 0 /*solid line*/, 2 /*dotted*/, 0), frame, &image, dither_pattern (), line_styles (), dpr_drawing, w, h);
|
||||
} else {
|
||||
single_bitmap_to_image (lay::ViewOp (frame_color, mode, iter->eff_line_style (true), 0, 0, lay::ViewOp::Rect, lw), frame, &image, dither_pattern (), line_styles (), dpr_drawing, w, h);
|
||||
}
|
||||
// create text
|
||||
single_bitmap_to_image (lay::ViewOp (frame_color, mode, 0, 0, 0), text, &image, dither_pattern (), line_styles (), dpr_drawing, w, h);
|
||||
// create vertex
|
||||
single_bitmap_to_image (lay::ViewOp (frame_color, mode, 0, 0, 0, lay::ViewOp::Cross, iter->marked (true) ? int (9 * dpr_drawing + 0.5) : 0), vertex, &image, dither_pattern (), line_styles (), dpr_drawing, w, h);
|
||||
|
||||
if (oversampling > 1) {
|
||||
tl::PixelBuffer subsampled (image.width () / oversampling, image.height () / oversampling);
|
||||
image.subsample (subsampled, oversampling, gamma);
|
||||
return subsampled;
|
||||
} else {
|
||||
return image;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
LayoutViewBase::merge_dither_pattern (lay::LayerPropertiesList &props)
|
||||
{
|
||||
|
|
@ -2314,6 +2501,8 @@ LayoutViewBase::signal_apply_technology (lay::LayoutHandle *layout_handle)
|
|||
|
||||
}
|
||||
|
||||
apply_technology_event (int (i));
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -581,6 +581,18 @@ public:
|
|||
*/
|
||||
virtual std::vector<lay::LayerPropertiesConstIterator> selected_layers () const;
|
||||
|
||||
/**
|
||||
* @brief Gets a pixmap representing the given layer
|
||||
*
|
||||
* @param iter indicates the layer
|
||||
* @param w The width in logical pixels of the generated pixmap (will be multiplied by dpr)
|
||||
* @param h The height in logical pixels of the generated pixmap (will be multiplied by dpr)
|
||||
* @param dpr The device pixel ratio (number of image pixes per logical pixel) - negative values mean auto-detect
|
||||
* @param di_off The dither pattern offset (used for animation)
|
||||
* @param no_state If true, the state will not be indicated
|
||||
*/
|
||||
tl::PixelBuffer icon_for_layer (const lay::LayerPropertiesConstIterator &iter, unsigned int w, unsigned int h, double dpr = -1.0, unsigned int di_off = 0, bool no_state = false);
|
||||
|
||||
/**
|
||||
* @brief Sets the layers that are selected in the layer browser
|
||||
*/
|
||||
|
|
@ -677,6 +689,14 @@ public:
|
|||
*/
|
||||
tl::event<int> cellview_changed_event;
|
||||
|
||||
/**
|
||||
* @brief A event signalling that one cellview has requested a new technology
|
||||
*
|
||||
* This event is triggered if a cellview has requested a new technology.
|
||||
* The argument is the index of the cellview that received the new technology.
|
||||
*/
|
||||
tl::event<int> apply_technology_event;
|
||||
|
||||
/**
|
||||
* @brief An event signalling that a file has been loaded.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -107,6 +107,7 @@ public:
|
|||
options.push_back (std::pair<std::string, std::string> (cfg_drop_small_cells_value, "10"));
|
||||
options.push_back (std::pair<std::string, std::string> (cfg_array_border_instances, "false"));
|
||||
options.push_back (std::pair<std::string, std::string> (cfg_bitmap_oversampling, "1"));
|
||||
options.push_back (std::pair<std::string, std::string> (cfg_highres_mode, "false"));
|
||||
options.push_back (std::pair<std::string, std::string> (cfg_image_cache_size, "1"));
|
||||
options.push_back (std::pair<std::string, std::string> (cfg_default_font_size, "0"));
|
||||
options.push_back (std::pair<std::string, std::string> (cfg_color_palette, lay::ColorPalette ().to_string ()));
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@
|
|||
#include "layEditable.h"
|
||||
|
||||
#include <QFrame>
|
||||
#include <QIcon>
|
||||
|
||||
namespace db
|
||||
{
|
||||
|
|
@ -69,80 +70,54 @@ public:
|
|||
virtual ~PropertiesPage ();
|
||||
|
||||
/**
|
||||
* @brief Move the current pointer to the end of the selected objects list
|
||||
*
|
||||
* Must be implemented by the Editable function and must set the
|
||||
* selected object pointer to past-the-end of the list. at_end () must
|
||||
* return true after this.
|
||||
* @brief Gets the number of entries represented by this page
|
||||
*/
|
||||
virtual void back () = 0;
|
||||
virtual size_t count () const = 0;
|
||||
|
||||
/**
|
||||
* @brief A helper function for the dialog that additionally reports
|
||||
* if there are any elements in the selection
|
||||
* @brief Selects the entries with the given indexes
|
||||
*
|
||||
* If multiple indexes are selected, the properties page shows
|
||||
* all items with different values as "leave as is". Items with
|
||||
* same value are shown with the given value.
|
||||
*/
|
||||
bool back_checked ()
|
||||
virtual void select_entries (const std::vector<size_t> &entries) = 0;
|
||||
|
||||
/**
|
||||
* @brief Convenience function to select a specific entry
|
||||
*/
|
||||
void select_entry (size_t entry)
|
||||
{
|
||||
back ();
|
||||
return ! at_begin ();
|
||||
std::vector<size_t> entries;
|
||||
entries.push_back (entry);
|
||||
select_entries (entries);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Move the current pointer to the beginning of the selected objects list
|
||||
*
|
||||
* Must be implemented by the Editable function and must set the
|
||||
* selected object pointer to the beginning of the list. at_begin () must
|
||||
* return true after this.
|
||||
* This method must return true, if there are any elements in the selection
|
||||
* - i.e. operator++ () will be successful afterwards.
|
||||
* @brief Gets a description text for the nth entry
|
||||
*/
|
||||
virtual void front () = 0;
|
||||
virtual std::string description (size_t entry) const = 0;
|
||||
|
||||
/**
|
||||
* @brief A helper function for the dialog that additionally reports
|
||||
* if there are any elements in the selection
|
||||
* @brief Gets the icon for the nth entry
|
||||
*/
|
||||
bool front_checked ()
|
||||
virtual QIcon icon (size_t /*entry*/, int /*w*/, int /*h*/) const
|
||||
{
|
||||
front ();
|
||||
return ! at_end ();
|
||||
return QIcon ();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Tell if the current object references the first one
|
||||
*
|
||||
* Must be implemented by the Editable function and must return
|
||||
* true if the current object is the first one - i.e. if an
|
||||
* operator-- would render the status invalid.
|
||||
* If no object is referenced, this method and at_end () must return true.
|
||||
* @brief Gets a description text for the whole group
|
||||
*/
|
||||
virtual bool at_begin () const = 0;
|
||||
virtual std::string description () const = 0;
|
||||
|
||||
/**
|
||||
* @brief Tell if the current object references past the last one
|
||||
*
|
||||
* If the current object pointer is past the end of the selected
|
||||
* object space,
|
||||
* @brief Gets the icon associated with the whole group
|
||||
*/
|
||||
virtual bool at_end () const = 0;
|
||||
|
||||
/**
|
||||
* @brief Step one element back
|
||||
*
|
||||
* This method is supposed to move the current pointer one position
|
||||
* back. If at_begin () was true before, the result may be unpredictable.
|
||||
* The dialog will call update () to update the display accordingly.
|
||||
*/
|
||||
virtual void operator-- () = 0;
|
||||
|
||||
/**
|
||||
* @brief Advance one element
|
||||
*
|
||||
* This method is supposed to move the current pointer one position
|
||||
* forward. If at_end () was true before, the result may be unpredictable.
|
||||
* The dialog will call update () to update the display accordingly.
|
||||
*/
|
||||
virtual void operator++ () = 0;
|
||||
virtual QIcon icon (int /*w*/, int /*h*/) const
|
||||
{
|
||||
return QIcon ();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Update the display
|
||||
|
|
@ -176,7 +151,7 @@ public:
|
|||
/**
|
||||
* @brief Apply any changes to the current object
|
||||
*
|
||||
* Apply any changes to the current object. If nothing was
|
||||
* Apply any changes to the current objects. If nothing was
|
||||
* changed, the object may be left untouched.
|
||||
* The dialog will start a transaction on the manager object.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -966,7 +966,7 @@ public:
|
|||
/**
|
||||
* @brief Gets the QWidget representing this canvas visually in Qt
|
||||
*/
|
||||
QWidget *widget ()
|
||||
QWidget *widget () const
|
||||
{
|
||||
return mp_widget;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -120,6 +120,7 @@ static const std::string cfg_reader_options_show_always ("reader-options-show-al
|
|||
static const std::string cfg_tip_window_hidden ("tip-window-hidden");
|
||||
|
||||
static const std::string cfg_bitmap_oversampling ("bitmap-oversampling");
|
||||
static const std::string cfg_highres_mode ("highres-mode");
|
||||
static const std::string cfg_image_cache_size ("image-cache-size");
|
||||
static const std::string cfg_default_font_size ("default-font-size");
|
||||
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>791</width>
|
||||
<height>385</height>
|
||||
<height>403</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
|
|
@ -32,7 +32,7 @@
|
|||
<item>
|
||||
<widget class="QGroupBox" name="groupBox">
|
||||
<property name="title">
|
||||
<string>Oversampling</string>
|
||||
<string>Display Quality</string>
|
||||
</property>
|
||||
<layout class="QGridLayout">
|
||||
<property name="leftMargin">
|
||||
|
|
@ -53,7 +53,14 @@
|
|||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>Use oversampling: </string>
|
||||
<string>Oversampling mode</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0" colspan="3">
|
||||
<widget class="QLabel" name="label_5">
|
||||
<property name="text">
|
||||
<string>High resolution mode utilizes the full pixel density on high-DPI displays. Features may look small but rich in details.</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
|
|
@ -99,6 +106,13 @@
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0" colspan="3">
|
||||
<widget class="QCheckBox" name="highres_mode">
|
||||
<property name="text">
|
||||
<string>High resolution mode enabled</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
|
|
|
|||
|
|
@ -63,7 +63,7 @@
|
|||
</property>
|
||||
<property name="icon">
|
||||
<iconset>
|
||||
<normaloff>:/run.png</normaloff>:/run.png</iconset>
|
||||
<normaloff>:/run_16px.png</normaloff>:/run_16px.png</iconset>
|
||||
</property>
|
||||
<property name="shortcut">
|
||||
<string>F5</string>
|
||||
|
|
|
|||
|
|
@ -135,7 +135,7 @@
|
|||
</property>
|
||||
<property name="icon">
|
||||
<iconset>
|
||||
<normaloff>:/run.png</normaloff>:/run.png</iconset>
|
||||
<normaloff>:/run_16px.png</normaloff>:/run_16px.png</iconset>
|
||||
</property>
|
||||
<property name="shortcut">
|
||||
<string>F5</string>
|
||||
|
|
|
|||
|
|
@ -6,43 +6,59 @@
|
|||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>601</width>
|
||||
<height>391</height>
|
||||
<width>828</width>
|
||||
<height>567</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Object Properties</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout">
|
||||
<property name="spacing">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>9</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>9</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>9</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>9</number>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QFrame" name="content_frame">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>1</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::StyledPanel</enum>
|
||||
</property>
|
||||
<property name="frameShadow">
|
||||
<enum>QFrame::Raised</enum>
|
||||
<widget class="QSplitter" name="splitter">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<widget class="QTreeView" name="tree">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="selectionMode">
|
||||
<enum>QAbstractItemView::ExtendedSelection</enum>
|
||||
</property>
|
||||
<property name="iconSize">
|
||||
<size>
|
||||
<width>16</width>
|
||||
<height>16</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="uniformRowHeights">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<attribute name="headerVisible">
|
||||
<bool>false</bool>
|
||||
</attribute>
|
||||
<attribute name="headerStretchLastSection">
|
||||
<bool>false</bool>
|
||||
</attribute>
|
||||
</widget>
|
||||
<widget class="QFrame" name="content_frame">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::StyledPanel</enum>
|
||||
</property>
|
||||
<property name="frameShadow">
|
||||
<enum>QFrame::Raised</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
|
|
|
|||
|
|
@ -208,6 +208,8 @@ LayerControlPanel::LayerControlPanel (lay::LayoutViewBase *view, db::Manager *ma
|
|||
m_hidden_flags_need_update (true),
|
||||
m_in_update (false),
|
||||
m_phase (0),
|
||||
m_oversampling (1),
|
||||
m_hrm (false),
|
||||
m_do_update_content_dm (this, &LayerControlPanel::do_update_content),
|
||||
m_no_stipples (false)
|
||||
{
|
||||
|
|
@ -1712,6 +1714,24 @@ LayerControlPanel::set_phase (int phase)
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
LayerControlPanel::set_highres_mode (bool hrm)
|
||||
{
|
||||
if (m_hrm != hrm) {
|
||||
m_hrm = hrm;
|
||||
m_do_update_content_dm ();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
LayerControlPanel::set_oversampling (int os)
|
||||
{
|
||||
if (m_oversampling != os) {
|
||||
m_oversampling = os;
|
||||
m_do_update_content_dm ();
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
set_hidden_flags_rec (LayerTreeModel *model, QTreeView *tree_view, const QModelIndex &parent)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -208,6 +208,16 @@ public:
|
|||
*/
|
||||
void set_phase (int phase);
|
||||
|
||||
/**
|
||||
* @brief Sets highres mode
|
||||
*/
|
||||
void set_highres_mode (bool hrm);
|
||||
|
||||
/**
|
||||
* @brief Sets oversampling mode
|
||||
*/
|
||||
void set_oversampling (int os);
|
||||
|
||||
/**
|
||||
* @brief Tell, if the model has been updated already (true) or if it is still under construction (false)
|
||||
*/
|
||||
|
|
@ -347,6 +357,8 @@ private:
|
|||
bool m_in_update;
|
||||
std::vector<size_t> m_new_sel;
|
||||
int m_phase;
|
||||
int m_oversampling;
|
||||
bool m_hrm;
|
||||
tl::DeferredMethod<LayerControlPanel> m_do_update_content_dm;
|
||||
std::set<unsigned int> m_expanded;
|
||||
bool m_no_stipples;
|
||||
|
|
|
|||
|
|
@ -24,7 +24,6 @@
|
|||
|
||||
#include "layLayerTreeModel.h"
|
||||
#include "layLayoutViewBase.h"
|
||||
#include "layBitmapsToImage.h"
|
||||
#include "dbLayoutUtils.h"
|
||||
#include "tlLog.h"
|
||||
#include "tlTimer.h"
|
||||
|
|
@ -182,7 +181,8 @@ EmptyWithinViewCache::determine_empty_layers (const db::Layout *layout, unsigned
|
|||
LayerTreeModel::LayerTreeModel (QWidget *parent, lay::LayoutViewBase *view)
|
||||
: QAbstractItemModel (parent),
|
||||
mp_parent (parent), mp_view (view), m_filter_mode (false), m_id_start (0), m_id_end (0),
|
||||
m_phase ((unsigned int) -1), m_test_shapes_in_view (false), m_hide_empty_layers (false)
|
||||
m_phase ((unsigned int) -1),
|
||||
m_test_shapes_in_view (false), m_hide_empty_layers (false)
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
|
@ -620,170 +620,11 @@ LayerTreeModel::empty_within_view_predicate (const QModelIndex &index) const
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief A helper function to create an image from a single bitmap
|
||||
*/
|
||||
static void
|
||||
single_bitmap_to_image (const lay::ViewOp &view_op, lay::Bitmap &bitmap,
|
||||
tl::PixelBuffer *pimage, const lay::DitherPattern &dither_pattern, const lay::LineStyles &line_styles,
|
||||
double dpr, unsigned int width, unsigned int height)
|
||||
{
|
||||
std::vector <lay::ViewOp> view_ops;
|
||||
view_ops.push_back (view_op);
|
||||
|
||||
std::vector <lay::Bitmap *> pbitmaps;
|
||||
pbitmaps.push_back (&bitmap);
|
||||
|
||||
lay::bitmaps_to_image (view_ops, pbitmaps, dither_pattern, line_styles, dpr, pimage, width, height, false, 0);
|
||||
}
|
||||
|
||||
LAYUI_PUBLIC
|
||||
QIcon
|
||||
LayerTreeModel::icon_for_layer (const lay::LayerPropertiesConstIterator &iter, lay::LayoutViewBase *view, unsigned int w, unsigned int h, double dpr, unsigned int di_off, bool no_state)
|
||||
{
|
||||
h = std::max ((unsigned int) 16, h) * dpr + 0.5;
|
||||
w = std::max ((unsigned int) 16, w) * dpr + 0.5;
|
||||
|
||||
tl::color_t def_color = 0x808080;
|
||||
tl::color_t fill_color = iter->has_fill_color (true) ? iter->eff_fill_color (true) : def_color;
|
||||
tl::color_t frame_color = iter->has_frame_color (true) ? iter->eff_frame_color (true) : def_color;
|
||||
|
||||
tl::PixelBuffer image (w, h);
|
||||
image.set_transparent (true);
|
||||
image.fill (view->background_color ().rgb ());
|
||||
|
||||
// upper scanline is a dummy one
|
||||
uint32_t *sl0 = (uint32_t *) image.scan_line (0);
|
||||
uint32_t transparent = QColor (Qt::transparent).rgba ();
|
||||
for (size_t i = 0; i < w; ++i) {
|
||||
*sl0++ = transparent;
|
||||
}
|
||||
|
||||
// TODO: adjust the resolution according to the oversampling mode
|
||||
lay::Bitmap fill (w, h, 1.0);
|
||||
lay::Bitmap frame (w, h, 1.0);
|
||||
lay::Bitmap text (w, h, 1.0);
|
||||
lay::Bitmap vertex (w, h, 1.0);
|
||||
|
||||
unsigned int wp = w - 1;
|
||||
|
||||
if (! no_state && ! iter->visible (true)) {
|
||||
|
||||
wp = w / 4;
|
||||
|
||||
// Show the arrow if it is invisible also locally.
|
||||
if (! iter->visible (false)) {
|
||||
|
||||
unsigned int aw = h / 4;
|
||||
unsigned int ap = w / 2 - 1;
|
||||
for (unsigned int i = 0; i <= aw; ++i) {
|
||||
text.fill (h / 2 - 1 - i, ap, ap + aw - i + 1);
|
||||
text.fill (h / 2 - 1 + i, ap, ap + aw - i + 1);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (! no_state && view->no_stipples ()) {
|
||||
// Show a partial stipple pattern only for "no stipple" mode
|
||||
for (unsigned int i = 1; i < h - 2; ++i) {
|
||||
fill.fill (i, w - 1 - w / 4, w);
|
||||
}
|
||||
} else {
|
||||
for (unsigned int i = 1; i < h - 2; ++i) {
|
||||
fill.fill (i, w - 1 - wp, w);
|
||||
}
|
||||
}
|
||||
|
||||
int lw = iter->width (true);
|
||||
if (lw < 0) {
|
||||
// default line width is 0 for parents and 1 for leafs
|
||||
lw = iter->has_children () ? 0 : 1;
|
||||
}
|
||||
lw = lw * dpr + 0.5;
|
||||
|
||||
int p0 = lw / 2;
|
||||
p0 = std::max (0, std::min (int (w / 4 - 1), p0));
|
||||
|
||||
int p1 = (lw - 1) / 2;
|
||||
p1 = std::max (0, std::min (int (w / 4 - 1), p1));
|
||||
|
||||
int p0x = p0, p1x = p1;
|
||||
unsigned int ddx = 0;
|
||||
unsigned int ddy = h - 2 - p1 - p0;
|
||||
if (iter->xfill (true)) {
|
||||
ddx = wp - p0 - p1 - 1;
|
||||
}
|
||||
unsigned int d = ddx / 2;
|
||||
|
||||
frame.fill (p0, w - 1 - (wp - p1), w);
|
||||
frame.fill (h - 2 - p1, w - 1 - (wp - p1), w);
|
||||
|
||||
for (unsigned int i = p0; i < h - 2; ++i) {
|
||||
|
||||
frame.fill (i, w - 1 - p0, w - p0);
|
||||
frame.fill (i, w - 1 - (wp - p1), w - (wp - p1));
|
||||
frame.fill (i, w - 1 - p0x, w - p0x);
|
||||
frame.fill (i, w - 1 - (wp - p1x), w - (wp - p1x));
|
||||
|
||||
while (d < ddx) {
|
||||
d += ddy;
|
||||
frame.fill (i, w - 1 - p0x, w - p0x);
|
||||
frame.fill (i, w - 1 - (wp - p1x), w - (wp - p1x));
|
||||
++p0x;
|
||||
++p1x;
|
||||
}
|
||||
|
||||
if (d >= ddx) {
|
||||
d -= ddx;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (! no_state && ! iter->valid (true)) {
|
||||
|
||||
unsigned int bp = w - 1 - ((w * 7) / 8 - 1);
|
||||
unsigned int be = bp + h / 2;
|
||||
unsigned int bw = h / 4 - 1;
|
||||
unsigned int by = h / 2 - 1;
|
||||
|
||||
for (unsigned int i = 0; i < bw + 2; ++i) {
|
||||
fill.clear (by - i, bp - 1, be);
|
||||
fill.clear (by + i, bp - 1, be);
|
||||
}
|
||||
|
||||
for (unsigned int i = 0; i < bw; ++i) {
|
||||
text.fill (by - i, bp + bw - i - 1, bp + bw - i + 1);
|
||||
text.fill (by - i - 1, bp + bw - i - 1, bp + bw - i + 1);
|
||||
text.fill (by - i, bp + bw + i, bp + bw + i + 2);
|
||||
text.fill (by - i - 1, bp + bw + i, bp + bw + i + 2);
|
||||
text.fill (by + i, bp + bw - i - 1, bp + bw - i + 1);
|
||||
text.fill (by + i + 1, bp + bw - i - 1, bp + bw - i + 1);
|
||||
text.fill (by + i, bp + bw + i, bp + bw + i + 2);
|
||||
text.fill (by + i + 1, bp + bw + i, bp + bw + i + 2);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
vertex.fill (h / 2 - 1, w - 1 - wp / 2, w - wp / 2);
|
||||
|
||||
lay::ViewOp::Mode mode = lay::ViewOp::Copy;
|
||||
|
||||
// create fill
|
||||
single_bitmap_to_image (lay::ViewOp (fill_color, mode, 0, iter->eff_dither_pattern (true), di_off), fill, &image, view->dither_pattern (), view->line_styles (), dpr, w, h);
|
||||
// create frame
|
||||
if (lw == 0) {
|
||||
single_bitmap_to_image (lay::ViewOp (frame_color, mode, 0 /*solid line*/, 2 /*dotted*/, 0), frame, &image, view->dither_pattern (), view->line_styles (), dpr, w, h);
|
||||
} else {
|
||||
single_bitmap_to_image (lay::ViewOp (frame_color, mode, iter->eff_line_style (true), 0, 0, lay::ViewOp::Rect, lw), frame, &image, view->dither_pattern (), view->line_styles (), dpr, w, h);
|
||||
}
|
||||
// create text
|
||||
single_bitmap_to_image (lay::ViewOp (frame_color, mode, 0, 0, 0), text, &image, view->dither_pattern (), view->line_styles (), dpr, w, h);
|
||||
// create vertex
|
||||
single_bitmap_to_image (lay::ViewOp (frame_color, mode, 0, 0, 0, lay::ViewOp::Cross, iter->marked (true) ? 9/*mark size*/ : 0), vertex, &image, view->dither_pattern (), view->line_styles (), dpr, w, h);
|
||||
|
||||
QPixmap pixmap = QPixmap::fromImage (image.to_image ());
|
||||
QImage img = view->icon_for_layer (iter, w, h, dpr, di_off, no_state).to_image_copy ();
|
||||
QPixmap pixmap = QPixmap::fromImage (std::move (img));
|
||||
#if QT_VERSION >= 0x050000
|
||||
pixmap.setDevicePixelRatio (dpr);
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -123,17 +123,17 @@ public:
|
|||
QModelIndex index (lay::LayerPropertiesConstIterator iter, int column) const;
|
||||
|
||||
/**
|
||||
* @brief Convert a QModelIndex to an iterator
|
||||
* @brief Converts a QModelIndex to an iterator
|
||||
*/
|
||||
lay::LayerPropertiesConstIterator iterator (const QModelIndex &index) const;
|
||||
|
||||
/**
|
||||
* @brief Get a flag indicating that an entry is hidden
|
||||
* @brief Gets a flag indicating that an entry is hidden
|
||||
*/
|
||||
bool is_hidden (const QModelIndex &index) const;
|
||||
|
||||
/**
|
||||
* @brief Set the animation phase
|
||||
* @brief Sets the animation phase
|
||||
*/
|
||||
void set_phase (unsigned int ph);
|
||||
|
||||
|
|
|
|||
|
|
@ -888,10 +888,10 @@ LayoutViewConfigPage4::update ()
|
|||
#endif
|
||||
|
||||
QPainter painter (&img);
|
||||
painter.setPen (QPen (palette ().color (QPalette::Active, QPalette::Text), 1.0 / dpr));
|
||||
painter.setBrush (QBrush (color));
|
||||
QRectF r (0, 0, w - painter.pen ().widthF (), h - painter.pen ().widthF ());
|
||||
painter.drawRect (r);
|
||||
QRectF r (0.0, 0.0, w, h);
|
||||
painter.fillRect (r, QBrush (palette ().color (QPalette::Active, QPalette::ButtonText)));
|
||||
r = QRectF (1.0, 1.0, w - 2.0, h - 2.0);
|
||||
painter.fillRect (r, QBrush (color));
|
||||
painter.setFont (font ());
|
||||
painter.setPen (QPen (text_color));
|
||||
painter.drawText (r, Qt::AlignHCenter | Qt::AlignVCenter | Qt::TextSingleLine, text);
|
||||
|
|
@ -1476,6 +1476,10 @@ LayoutViewConfigPage7::setup (lay::Dispatcher *root)
|
|||
root->config_get (cfg_bitmap_oversampling, oversampling);
|
||||
mp_ui->oversampling->setCurrentIndex (oversampling - 1);
|
||||
|
||||
bool highres_mode = false;
|
||||
root->config_get (cfg_highres_mode, highres_mode);
|
||||
mp_ui->highres_mode->setChecked (highres_mode);
|
||||
|
||||
int default_font_size = 0;
|
||||
root->config_get (cfg_default_font_size, default_font_size);
|
||||
mp_ui->default_font_size->setCurrentIndex (default_font_size);
|
||||
|
|
@ -1499,6 +1503,7 @@ void
|
|||
LayoutViewConfigPage7::commit (lay::Dispatcher *root)
|
||||
{
|
||||
root->config_set (cfg_bitmap_oversampling, mp_ui->oversampling->currentIndex () + 1);
|
||||
root->config_set (cfg_highres_mode, mp_ui->highres_mode->isChecked ());
|
||||
root->config_set (cfg_default_font_size, mp_ui->default_font_size->currentIndex ());
|
||||
root->config_set (cfg_global_trans, db::DCplxTrans (db::DFTrans (mp_ui->global_trans->currentIndex ())).to_string ());
|
||||
root->config_set (cfg_initial_hier_depth, mp_ui->def_depth->value ());
|
||||
|
|
|
|||
|
|
@ -32,91 +32,222 @@
|
|||
#include "ui_PropertiesDialog.h"
|
||||
|
||||
#include <QStackedLayout>
|
||||
#include <QAbstractItemModel>
|
||||
#include <QModelIndex>
|
||||
|
||||
namespace lay
|
||||
{
|
||||
|
||||
#if QT_VERSION >= 0x50000
|
||||
typedef qint64 tree_id_type;
|
||||
#else
|
||||
typedef qint32 tree_id_type;
|
||||
#endif
|
||||
|
||||
// ----------------------------------------------------------------------------------------------------------
|
||||
// PropertiesTreeModel definition and implementation
|
||||
|
||||
class PropertiesTreeModel
|
||||
: public QAbstractItemModel
|
||||
{
|
||||
public:
|
||||
PropertiesTreeModel (PropertiesDialog *dialog, int icon_width, int icon_height)
|
||||
: QAbstractItemModel (dialog), mp_dialog (dialog), m_icon_width (icon_width), m_icon_height (icon_height)
|
||||
{ }
|
||||
|
||||
int columnCount (const QModelIndex &) const
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
QVariant data (const QModelIndex &index, int role) const
|
||||
{
|
||||
if (role == Qt::DisplayRole) {
|
||||
if (tree_id_type (index.internalId ()) < tree_id_type (mp_dialog->properties_pages ().size ())) {
|
||||
return tl::to_qstring (mp_dialog->properties_pages () [index.internalId ()]->description (index.row ()));
|
||||
} else if (index.row () < int (mp_dialog->properties_pages ().size ())) {
|
||||
return tl::to_qstring (mp_dialog->properties_pages () [index.row ()]->description ());
|
||||
}
|
||||
} else if (role == Qt::DecorationRole) {
|
||||
QIcon icon;
|
||||
if (tree_id_type (index.internalId ()) < tree_id_type (mp_dialog->properties_pages ().size ())) {
|
||||
icon = mp_dialog->properties_pages () [index.internalId ()]->icon (index.row (), m_icon_width, m_icon_height);
|
||||
} else if (index.row () < int (mp_dialog->properties_pages ().size ())) {
|
||||
icon = mp_dialog->properties_pages () [index.row ()]->icon (m_icon_width, m_icon_height);
|
||||
}
|
||||
if (! icon.isNull ()) {
|
||||
return QVariant (icon);
|
||||
}
|
||||
}
|
||||
return QVariant ();
|
||||
}
|
||||
|
||||
Qt::ItemFlags flags (const QModelIndex &index) const
|
||||
{
|
||||
Qt::ItemFlags f = QAbstractItemModel::flags (index);
|
||||
if (tree_id_type (index.internalId ()) >= tree_id_type (mp_dialog->properties_pages ().size ()) && ! mp_dialog->properties_pages () [index.row ()]->can_apply_to_all ()) {
|
||||
f &= ~Qt::ItemIsSelectable;
|
||||
}
|
||||
return f;
|
||||
}
|
||||
|
||||
bool hasChildren (const QModelIndex &parent) const
|
||||
{
|
||||
return (! parent.isValid () || tree_id_type (parent.internalId ()) >= tree_id_type (mp_dialog->properties_pages ().size ()));
|
||||
}
|
||||
|
||||
QModelIndex index (int row, int column, const QModelIndex &parent) const
|
||||
{
|
||||
if (! parent.isValid ()) {
|
||||
return createIndex (row, column, tree_id_type (mp_dialog->properties_pages ().size ()));
|
||||
} else {
|
||||
return createIndex (row, column, tree_id_type (parent.row ()));
|
||||
}
|
||||
}
|
||||
|
||||
QModelIndex parent (const QModelIndex &child) const
|
||||
{
|
||||
if (tree_id_type (child.internalId ()) < tree_id_type (mp_dialog->properties_pages ().size ())) {
|
||||
return createIndex (int (child.internalId ()), child.column (), tree_id_type (mp_dialog->properties_pages ().size ()));
|
||||
} else {
|
||||
return QModelIndex ();
|
||||
}
|
||||
}
|
||||
|
||||
int rowCount (const QModelIndex &parent) const
|
||||
{
|
||||
if (! hasChildren (parent)) {
|
||||
return 0;
|
||||
} else if (parent.isValid ()) {
|
||||
return int (mp_dialog->properties_pages () [parent.row ()]->count ());
|
||||
} else {
|
||||
return int (mp_dialog->properties_pages ().size ());
|
||||
}
|
||||
}
|
||||
|
||||
int page_index (const QModelIndex &index)
|
||||
{
|
||||
return int (index.internalId ());
|
||||
}
|
||||
|
||||
int object_index (const QModelIndex &index)
|
||||
{
|
||||
return int (index.row ());
|
||||
}
|
||||
|
||||
QModelIndex index_for (int page_index, int object_index)
|
||||
{
|
||||
if (page_index < 0) {
|
||||
return QModelIndex ();
|
||||
} else {
|
||||
return createIndex (object_index, 0, tree_id_type (page_index));
|
||||
}
|
||||
}
|
||||
|
||||
QModelIndex index_for (int page_index)
|
||||
{
|
||||
if (page_index < 0) {
|
||||
return QModelIndex ();
|
||||
} else {
|
||||
return createIndex (page_index, 0, tree_id_type (mp_dialog->properties_pages ().size ()));
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
PropertiesDialog *mp_dialog;
|
||||
int m_icon_width, m_icon_height;
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------------------------------------
|
||||
// PropertiesDialog
|
||||
|
||||
PropertiesDialog::PropertiesDialog (QWidget * /*parent*/, db::Manager *manager, lay::Editables *editables)
|
||||
: QDialog (0 /*parent*/),
|
||||
mp_manager (manager), mp_editables (editables), m_index (-1), m_auto_applied (false), m_transaction_id (0)
|
||||
mp_manager (manager),
|
||||
mp_editables (editables),
|
||||
m_index (0), m_prev_index (-1),
|
||||
m_auto_applied (false),
|
||||
m_transaction_id (0),
|
||||
m_signals_enabled (true)
|
||||
{
|
||||
mp_ui = new Ui::PropertiesDialog ();
|
||||
|
||||
setObjectName (QString::fromUtf8 ("properties_dialog"));
|
||||
mp_ui->setupUi (this);
|
||||
mp_tree_model = 0;
|
||||
|
||||
mp_editables->enable_edits (false);
|
||||
|
||||
mp_stack = new QStackedLayout;
|
||||
|
||||
for (lay::Editables::iterator e = mp_editables->begin (); e != mp_editables->end (); ++e) {
|
||||
mp_properties_pages.push_back (e->properties_page (mp_manager, mp_ui->content_frame));
|
||||
if (mp_properties_pages.back ()) {
|
||||
mp_stack->addWidget (mp_properties_pages.back ());
|
||||
connect (mp_properties_pages.back (), SIGNAL (edited ()), this, SLOT (apply ()));
|
||||
auto pp = e->properties_pages (mp_manager, mp_ui->content_frame);
|
||||
for (auto p = pp.begin (); p != pp.end (); ++p) {
|
||||
if ((*p)->count () == 0) {
|
||||
delete *p;
|
||||
} else {
|
||||
mp_properties_pages.push_back (*p);
|
||||
}
|
||||
}
|
||||
}
|
||||
for (size_t i = 0; i < mp_properties_pages.size (); ++i) {
|
||||
mp_stack->addWidget (mp_properties_pages [i]);
|
||||
connect (mp_properties_pages [i], SIGNAL (edited ()), this, SLOT (apply ()));
|
||||
}
|
||||
|
||||
// Necessary to maintain the page order for UI regression testing of 0.18 vs. 0.19 (because tl::Collection has changed to order) ..
|
||||
std::reverse (mp_properties_pages.begin (), mp_properties_pages.end ());
|
||||
|
||||
// Add a label as a dummy
|
||||
QLabel *dummy = new QLabel (QObject::tr ("No object with properties to display"), mp_ui->content_frame);
|
||||
dummy->setAlignment (Qt::AlignHCenter | Qt::AlignVCenter);
|
||||
mp_stack->addWidget (dummy);
|
||||
mp_none = new QLabel (QObject::tr ("No object with properties to display"), mp_ui->content_frame);
|
||||
mp_none->setAlignment (Qt::AlignHCenter | Qt::AlignVCenter);
|
||||
mp_stack->addWidget (mp_none);
|
||||
|
||||
mp_ui->content_frame->setLayout (mp_stack);
|
||||
|
||||
// disable the apply button for first ..
|
||||
mp_ui->apply_to_all_cbx->setEnabled (false);
|
||||
mp_ui->relative_cbx->setEnabled (false);
|
||||
mp_ui->ok_button->setEnabled (false);
|
||||
|
||||
// as a proposal, the start button can be enabled in most cases
|
||||
mp_ui->prev_button->setEnabled (true);
|
||||
|
||||
// count the total number of objects
|
||||
m_objects = mp_editables->selection_size ();
|
||||
m_current_object = 0;
|
||||
|
||||
// look for next usable editable
|
||||
if (m_index >= int (mp_properties_pages.size ())) {
|
||||
m_index = -1;
|
||||
} else {
|
||||
m_object_indexes.push_back (0);
|
||||
}
|
||||
|
||||
update_title ();
|
||||
|
||||
// look for next usable editable
|
||||
while (m_index < int (mp_properties_pages.size ()) &&
|
||||
(m_index < 0 || mp_properties_pages [m_index] == 0 || mp_properties_pages [m_index]->at_end ())) {
|
||||
++m_index;
|
||||
}
|
||||
|
||||
mp_ui->prev_button->setEnabled (false);
|
||||
|
||||
// if at end disable the "Next" button and return (this may only happen at the first call)
|
||||
if (m_index >= int (mp_properties_pages.size ())) {
|
||||
|
||||
mp_ui->next_button->setEnabled (false);
|
||||
mp_stack->setCurrentWidget (dummy);
|
||||
mp_ui->apply_to_all_cbx->setEnabled (false);
|
||||
mp_ui->apply_to_all_cbx->setChecked (false);
|
||||
mp_ui->relative_cbx->setEnabled (false);
|
||||
mp_ui->relative_cbx->setChecked (false);
|
||||
mp_ui->ok_button->setEnabled (false);
|
||||
|
||||
} else {
|
||||
|
||||
mp_ui->next_button->setEnabled (any_next ());
|
||||
mp_properties_pages [m_index]->update ();
|
||||
mp_stack->setCurrentWidget (mp_properties_pages [m_index]);
|
||||
mp_ui->apply_to_all_cbx->setEnabled (! mp_properties_pages [m_index]->readonly () && mp_properties_pages [m_index]->can_apply_to_all ());
|
||||
mp_ui->apply_to_all_cbx->setChecked (false);
|
||||
mp_ui->relative_cbx->setEnabled (mp_ui->apply_to_all_cbx->isEnabled () && mp_ui->apply_to_all_cbx->isChecked ());
|
||||
mp_ui->relative_cbx->setChecked (true);
|
||||
mp_ui->ok_button->setEnabled (! mp_properties_pages [m_index]->readonly ());
|
||||
mp_tree_model = new PropertiesTreeModel (this, mp_ui->tree->iconSize ().width (), mp_ui->tree->iconSize ().height ());
|
||||
mp_ui->tree->setModel (mp_tree_model);
|
||||
#if QT_VERSION >= 0x50000
|
||||
mp_ui->tree->header()->setSectionResizeMode (QHeaderView::ResizeToContents);
|
||||
#else
|
||||
mp_ui->tree->header()->setResizeMode (QHeaderView::ResizeToContents);
|
||||
#endif
|
||||
mp_ui->tree->expandAll ();
|
||||
|
||||
if (mp_properties_pages.empty ()) {
|
||||
mp_ui->tree->hide ();
|
||||
}
|
||||
|
||||
m_signals_enabled = false;
|
||||
mp_ui->tree->setCurrentIndex (mp_tree_model->index_for (m_index, 0));
|
||||
m_signals_enabled = true;
|
||||
|
||||
update_controls ();
|
||||
|
||||
mp_ui->apply_to_all_cbx->setChecked (false);
|
||||
mp_ui->relative_cbx->setChecked (true);
|
||||
|
||||
connect (mp_ui->ok_button, SIGNAL (clicked ()), this, SLOT (ok_pressed ()));
|
||||
connect (mp_ui->cancel_button, SIGNAL (clicked ()), this, SLOT (cancel_pressed ()));
|
||||
connect (mp_ui->prev_button, SIGNAL (clicked ()), this, SLOT (prev_pressed ()));
|
||||
connect (mp_ui->next_button, SIGNAL (clicked ()), this, SLOT (next_pressed ()));
|
||||
connect (mp_ui->apply_to_all_cbx, SIGNAL (clicked ()), this, SLOT (apply_to_all_pressed ()));
|
||||
connect (mp_ui->tree->selectionModel (), SIGNAL (currentChanged (const QModelIndex &, const QModelIndex &)), this, SLOT (current_index_changed (const QModelIndex &, const QModelIndex &)));
|
||||
connect (mp_ui->tree->selectionModel (), SIGNAL (selectionChanged(const QItemSelection &, const QItemSelection &)), this, SLOT (selection_changed ()));
|
||||
}
|
||||
|
||||
PropertiesDialog::~PropertiesDialog ()
|
||||
|
|
@ -138,11 +269,147 @@ PropertiesDialog::disconnect ()
|
|||
mp_properties_pages.clear ();
|
||||
}
|
||||
|
||||
void
|
||||
PropertiesDialog::apply_to_all_pressed ()
|
||||
{
|
||||
m_signals_enabled = false;
|
||||
if (mp_ui->apply_to_all_cbx->isChecked ()) {
|
||||
mp_ui->tree->setCurrentIndex (mp_tree_model->index_for (m_index));
|
||||
} else if (! m_object_indexes.empty ()) {
|
||||
mp_ui->tree->setCurrentIndex (mp_tree_model->index_for (m_index, int (m_object_indexes.front ())));
|
||||
}
|
||||
m_signals_enabled = true;
|
||||
}
|
||||
|
||||
void
|
||||
PropertiesDialog::selection_changed ()
|
||||
{
|
||||
current_index_changed (mp_ui->tree->currentIndex (), QModelIndex ());
|
||||
}
|
||||
|
||||
void
|
||||
PropertiesDialog::current_index_changed (const QModelIndex &index, const QModelIndex & /*previous*/)
|
||||
{
|
||||
if (! m_signals_enabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_object_indexes.clear ();
|
||||
|
||||
if (! index.isValid ()) {
|
||||
|
||||
m_index = -1;
|
||||
|
||||
} else {
|
||||
|
||||
if (mp_tree_model->parent (index).isValid ()) {
|
||||
|
||||
m_index = mp_tree_model->page_index (index);
|
||||
|
||||
if (mp_properties_pages [m_index]->can_apply_to_all ()) {
|
||||
|
||||
m_object_indexes.push_back (size_t (mp_tree_model->object_index (index)));
|
||||
|
||||
auto selection = mp_ui->tree->selectionModel ()->selectedIndexes ();
|
||||
for (auto i = selection.begin (); i != selection.end (); ++i) {
|
||||
if (mp_tree_model->parent (*i).isValid () && mp_tree_model->page_index (*i) == m_index) {
|
||||
int oi = mp_tree_model->object_index (*i);
|
||||
if (oi != int (m_object_indexes.front ())) {
|
||||
m_object_indexes.push_back (size_t (oi));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
m_object_indexes.push_back (size_t (mp_tree_model->object_index (index)));
|
||||
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
m_index = index.row ();
|
||||
mp_ui->apply_to_all_cbx->setChecked (mp_properties_pages [m_index]->can_apply_to_all ());
|
||||
|
||||
if (mp_properties_pages [m_index]->can_apply_to_all ()) {
|
||||
|
||||
for (size_t oi = 0; oi < mp_properties_pages [m_index]->count (); ++oi) {
|
||||
m_object_indexes.push_back (oi);
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
m_object_indexes.push_back (size_t (mp_tree_model->object_index (index)));
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (! m_object_indexes.empty ()) {
|
||||
m_current_object = 0;
|
||||
for (int i = 0; i < m_index; ++i) {
|
||||
m_current_object += mp_properties_pages [i]->count ();
|
||||
}
|
||||
m_current_object += int (m_object_indexes.front ());
|
||||
} else {
|
||||
m_current_object = -1;
|
||||
}
|
||||
|
||||
update_title ();
|
||||
update_controls ();
|
||||
}
|
||||
|
||||
void
|
||||
PropertiesDialog::update_controls ()
|
||||
{
|
||||
if (m_prev_index >= 0 && m_index != m_prev_index) {
|
||||
if (m_prev_index >= 0 && m_prev_index < int (mp_properties_pages.size ())) {
|
||||
mp_properties_pages [m_prev_index]->leave ();
|
||||
}
|
||||
}
|
||||
m_prev_index = m_index;
|
||||
|
||||
mp_ui->apply_to_all_cbx->setChecked (m_object_indexes.size () > 1);
|
||||
|
||||
if (m_index < 0) {
|
||||
|
||||
mp_stack->setCurrentWidget (mp_none);
|
||||
|
||||
mp_ui->prev_button->setEnabled (false);
|
||||
mp_ui->next_button->setEnabled (false);
|
||||
mp_ui->apply_to_all_cbx->setEnabled (false);
|
||||
mp_ui->relative_cbx->setEnabled (false);
|
||||
mp_ui->ok_button->setEnabled (false);
|
||||
mp_ui->tree->setEnabled (false);
|
||||
|
||||
} else {
|
||||
|
||||
mp_stack->setCurrentWidget (mp_properties_pages [m_index]);
|
||||
|
||||
mp_ui->prev_button->setEnabled (any_prev ());
|
||||
mp_ui->next_button->setEnabled (any_next ());
|
||||
mp_ui->apply_to_all_cbx->setEnabled (! mp_properties_pages [m_index]->readonly () && mp_properties_pages [m_index]->can_apply_to_all ());
|
||||
mp_ui->relative_cbx->setEnabled (mp_ui->apply_to_all_cbx->isEnabled () && mp_ui->apply_to_all_cbx->isChecked ());
|
||||
mp_ui->ok_button->setEnabled (! mp_properties_pages [m_index]->readonly ());
|
||||
mp_ui->tree->setEnabled (true);
|
||||
|
||||
mp_properties_pages [m_index]->select_entries (m_object_indexes);
|
||||
mp_properties_pages [m_index]->update ();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
PropertiesDialog::next_pressed ()
|
||||
{
|
||||
BEGIN_PROTECTED
|
||||
|
||||
if (m_object_indexes.empty ()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (! mp_properties_pages [m_index]->readonly ()) {
|
||||
db::Transaction t (mp_manager, tl::to_string (QObject::tr ("Apply changes")), m_transaction_id);
|
||||
mp_properties_pages [m_index]->apply ();
|
||||
|
|
@ -152,32 +419,32 @@ BEGIN_PROTECTED
|
|||
}
|
||||
|
||||
// advance the current entry
|
||||
++(*mp_properties_pages [m_index]);
|
||||
int object_index = int (m_object_indexes.front ());
|
||||
++object_index;
|
||||
|
||||
// look for next usable editable if at end
|
||||
if (mp_properties_pages [m_index]->at_end ()) {
|
||||
mp_properties_pages [m_index]->leave ();
|
||||
if (object_index >= int (mp_properties_pages [m_index]->count ())) {
|
||||
|
||||
++m_index;
|
||||
while (m_index < int (mp_properties_pages.size ()) &&
|
||||
(mp_properties_pages [m_index] == 0 || ! mp_properties_pages [m_index]->front_checked ())) {
|
||||
++m_index;
|
||||
}
|
||||
object_index = 0;
|
||||
|
||||
// because we checked that there are any further elements, this should not happen:
|
||||
if (m_index >= int (mp_properties_pages.size ())) {
|
||||
return;
|
||||
}
|
||||
mp_stack->setCurrentWidget (mp_properties_pages [m_index]);
|
||||
|
||||
}
|
||||
|
||||
m_object_indexes.clear ();
|
||||
m_object_indexes.push_back (object_index);
|
||||
|
||||
++m_current_object;
|
||||
update_title ();
|
||||
|
||||
mp_ui->prev_button->setEnabled (true);
|
||||
mp_ui->next_button->setEnabled (any_next ());
|
||||
mp_ui->apply_to_all_cbx->setEnabled (! mp_properties_pages [m_index]->readonly () && mp_properties_pages [m_index]->can_apply_to_all ());
|
||||
mp_ui->relative_cbx->setEnabled (mp_ui->apply_to_all_cbx->isEnabled () && mp_ui->apply_to_all_cbx->isChecked ());
|
||||
mp_ui->ok_button->setEnabled (! mp_properties_pages [m_index]->readonly ());
|
||||
mp_properties_pages [m_index]->update ();
|
||||
update_controls ();
|
||||
m_signals_enabled = false;
|
||||
mp_ui->tree->setCurrentIndex (mp_tree_model->index_for (m_index, object_index));
|
||||
m_signals_enabled = true;
|
||||
|
||||
END_PROTECTED
|
||||
}
|
||||
|
|
@ -187,6 +454,10 @@ PropertiesDialog::prev_pressed ()
|
|||
{
|
||||
BEGIN_PROTECTED
|
||||
|
||||
if (m_object_indexes.empty ()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (! mp_properties_pages [m_index]->readonly ()) {
|
||||
db::Transaction t (mp_manager, tl::to_string (QObject::tr ("Apply changes")), m_transaction_id);
|
||||
mp_properties_pages [m_index]->apply ();
|
||||
|
|
@ -195,35 +466,35 @@ BEGIN_PROTECTED
|
|||
}
|
||||
}
|
||||
|
||||
if (mp_properties_pages [m_index]->at_begin ()) {
|
||||
// advance the current entry
|
||||
int object_index = int (m_object_indexes.front ());
|
||||
if (object_index == 0) {
|
||||
|
||||
// look for last usable editable if at end
|
||||
mp_properties_pages [m_index]->leave ();
|
||||
--m_index;
|
||||
while (m_index >= 0 &&
|
||||
(mp_properties_pages [m_index] == 0 || ! mp_properties_pages [m_index]->back_checked ())) {
|
||||
--m_index;
|
||||
}
|
||||
|
||||
// because we checked that there are any further elements, this should not happen:
|
||||
if (m_index < 0) {
|
||||
return;
|
||||
}
|
||||
mp_stack->setCurrentWidget (mp_properties_pages [m_index]);
|
||||
|
||||
|
||||
object_index = mp_properties_pages [m_index]->count ();
|
||||
|
||||
}
|
||||
|
||||
// decrement the current entry
|
||||
--(*mp_properties_pages [m_index]);
|
||||
--object_index;
|
||||
|
||||
m_object_indexes.clear ();
|
||||
m_object_indexes.push_back (object_index);
|
||||
|
||||
--m_current_object;
|
||||
update_title ();
|
||||
|
||||
mp_ui->next_button->setEnabled (true);
|
||||
mp_ui->prev_button->setEnabled (any_prev ());
|
||||
mp_ui->apply_to_all_cbx->setEnabled (! mp_properties_pages [m_index]->readonly () && mp_properties_pages [m_index]->can_apply_to_all ());
|
||||
mp_ui->relative_cbx->setEnabled (mp_ui->apply_to_all_cbx->isEnabled () && mp_ui->apply_to_all_cbx->isChecked ());
|
||||
mp_ui->ok_button->setEnabled (! mp_properties_pages [m_index]->readonly ());
|
||||
mp_properties_pages [m_index]->update ();
|
||||
update_controls ();
|
||||
m_signals_enabled = false;
|
||||
mp_ui->tree->setCurrentIndex (mp_tree_model->index_for (m_index, object_index));
|
||||
m_signals_enabled = true;
|
||||
|
||||
END_PROTECTED
|
||||
}
|
||||
|
|
@ -231,40 +502,39 @@ END_PROTECTED
|
|||
void
|
||||
PropertiesDialog::update_title ()
|
||||
{
|
||||
setWindowTitle (tl::to_qstring (tl::to_string (QObject::tr ("Object Properties - ")) + tl::to_string (m_current_object + 1) + tl::to_string (QObject::tr (" of ")) + tl::to_string (m_objects)));
|
||||
if (m_index < 0) {
|
||||
setWindowTitle (QObject::tr ("Object Properties"));
|
||||
} else {
|
||||
setWindowTitle (tl::to_qstring (tl::to_string (QObject::tr ("Object Properties - ")) + tl::to_string (m_current_object + 1) + tl::to_string (QObject::tr (" of ")) + tl::to_string (m_objects)));
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
PropertiesDialog::any_next () const
|
||||
{
|
||||
// test-advance
|
||||
if (m_object_indexes.empty ()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int index = m_index;
|
||||
++(*mp_properties_pages [index]);
|
||||
if (mp_properties_pages [index]->at_end ()) {
|
||||
if (m_object_indexes.front () + 1 >= mp_properties_pages [index]->count ()) {
|
||||
++index;
|
||||
while (index < int (mp_properties_pages.size ()) &&
|
||||
(mp_properties_pages [index] == 0 || ! mp_properties_pages [index]->front_checked ())) {
|
||||
++index;
|
||||
}
|
||||
}
|
||||
|
||||
// return true, if not at end
|
||||
bool ret = (index < int (mp_properties_pages.size ()));
|
||||
--(*mp_properties_pages [m_index]);
|
||||
return ret;
|
||||
return (index < int (mp_properties_pages.size ()));
|
||||
}
|
||||
|
||||
bool
|
||||
PropertiesDialog::any_prev () const
|
||||
{
|
||||
// test-decrement
|
||||
if (m_object_indexes.empty ()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int index = m_index;
|
||||
if (mp_properties_pages [index]->at_begin ()) {
|
||||
if (m_object_indexes.front () == 0) {
|
||||
--index;
|
||||
while (index >= 0 &&
|
||||
(mp_properties_pages [index] == 0 || ! mp_properties_pages [index]->back_checked ())) {
|
||||
--index;
|
||||
}
|
||||
}
|
||||
|
||||
// return true, if not at the beginning
|
||||
|
|
|
|||
|
|
@ -54,6 +54,7 @@ class Editable;
|
|||
class Editables;
|
||||
class PropertiesPage;
|
||||
class MainWindow;
|
||||
class PropertiesTreeModel;
|
||||
|
||||
/**
|
||||
* @brief The properties dialog
|
||||
|
|
@ -80,20 +81,28 @@ public:
|
|||
~PropertiesDialog ();
|
||||
|
||||
private:
|
||||
friend class PropertiesTreeModel;
|
||||
|
||||
std::vector<lay::PropertiesPage *> mp_properties_pages;
|
||||
db::Manager *mp_manager;
|
||||
lay::Editables *mp_editables;
|
||||
int m_index;
|
||||
int m_index, m_prev_index;
|
||||
std::vector<size_t> m_object_indexes;
|
||||
QStackedLayout *mp_stack;
|
||||
QLabel *mp_none;
|
||||
lay::MainWindow *mp_mw;
|
||||
size_t m_objects, m_current_object;
|
||||
bool m_auto_applied;
|
||||
db::Manager::transaction_id_t m_transaction_id;
|
||||
PropertiesTreeModel *mp_tree_model;
|
||||
bool m_signals_enabled;
|
||||
|
||||
const std::vector<lay::PropertiesPage *> &properties_pages () { return mp_properties_pages; }
|
||||
void disconnect ();
|
||||
bool any_prev () const;
|
||||
bool any_next () const;
|
||||
void update_title ();
|
||||
void update_controls ();
|
||||
|
||||
public slots:
|
||||
void apply ();
|
||||
|
|
@ -101,6 +110,9 @@ public slots:
|
|||
void prev_pressed ();
|
||||
void cancel_pressed ();
|
||||
void ok_pressed ();
|
||||
void apply_to_all_pressed ();
|
||||
void current_index_changed (const QModelIndex &index, const QModelIndex &previous);
|
||||
void selection_changed ();
|
||||
|
||||
protected:
|
||||
void reject ();
|
||||
|
|
|
|||
|
|
@ -860,6 +860,40 @@ const char *color_icon =
|
|||
"xxxxE44ExxD33Dxxxx"
|
||||
"xxxxxeexxxxddxxxxx";
|
||||
|
||||
const char *color_icon_2x =
|
||||
"xxxxxxxxxxaaaaxxxxxxxxbbbbxxxxxxxxxx"
|
||||
"xxxxxxxxxA0000AxxxxxxB1111Bxxxxxxxxx"
|
||||
"xxxxxxxxA000000AxxxxB111111Bxxxxxxxx"
|
||||
"xxxxxxxA00000000AxxB11111111Bxxxxxxx"
|
||||
"xxxxxxa0000000000ab1111111111bxxxxxx"
|
||||
"xxxxxxa0000000000ab1111111111bxxxxxx"
|
||||
"xxxxxxa0000000000ab1111111111bxxxxxx"
|
||||
"xxxxxxa0000000000ab1111111111bxxxxxx"
|
||||
"xxxxxxxA00000000AxxB11111111Bxxxxxxx"
|
||||
"xxxxxxxxA000000AxxxxB111111Bxxxxxxxx"
|
||||
"xxxxffffxA0000AxxxxxxB1111Bxccccxxxx"
|
||||
"xxxF5555FxaaaaxxxxxxxxbbbbxC2222Cxxx"
|
||||
"xxF555555FxxxxxxxxxxxxxxxxC222222Cxx"
|
||||
"xF55555555FxxxxxxxxxxxxxxC22222222Cx"
|
||||
"f5555555555fxxxxxxxxxxxxc2222222222c"
|
||||
"f5555555555fxxxxxxxxxxxxc2222222222c"
|
||||
"f5555555555fxxxxxxxxxxxxc2222222222c"
|
||||
"f5555555555fxxxxxxxxxxxxc2222222222c"
|
||||
"xF55555555FxxxxxxxxxxxxxxC22222222Cx"
|
||||
"xxF555555FxxxxxxxxxxxxxxxxC222222Cxx"
|
||||
"xxxF5555FxeeeexxxxxxxxddddxC2222Cxxx"
|
||||
"xxxxffffxE4444ExxxxxxD3333Dxccccxxxx"
|
||||
"xxxxxxxxE444444ExxxxD333333Dxxxxxxxx"
|
||||
"xxxxxxxE44444444ExxD33333333Dxxxxxxx"
|
||||
"xxxxxxe4444444444ed3333333333dxxxxxx"
|
||||
"xxxxxxe4444444444ed3333333333dxxxxxx"
|
||||
"xxxxxxe4444444444ed3333333333dxxxxxx"
|
||||
"xxxxxxe4444444444ed3333333333dxxxxxx"
|
||||
"xxxxxxxE44444444ExxD33333333Dxxxxxxx"
|
||||
"xxxxxxxxE444444ExxxxD333333Dxxxxxxxx"
|
||||
"xxxxxxxxxE4444ExxxxxxD3333Dxxxxxxxxx"
|
||||
"xxxxxxxxxxeeeexxxxxxxxddddxxxxxxxxxx";
|
||||
|
||||
void
|
||||
ColorButton::build_color_menu (QMenu *menu, QObject *receiver, const char *browse_slot, const char *selected_slot)
|
||||
{
|
||||
|
|
@ -898,10 +932,18 @@ ColorButton::build_color_menu (QMenu *menu, QObject *receiver, const char *brows
|
|||
codes.insert (std::make_pair ('A' + j, c));
|
||||
}
|
||||
|
||||
QImage icon (18, 16, QImage::Format_ARGB32);
|
||||
const char *cp = color_icon;
|
||||
for (int y = 0; y < 16; ++y) {
|
||||
for (int x = 0; x < 18; ++x) {
|
||||
int dpr = 1;
|
||||
#if QT_VERSION >= 0x50000
|
||||
dpr = (menu->devicePixelRatio () >= 2.0) ? 2 : 1;
|
||||
#endif
|
||||
|
||||
QImage icon (18 * dpr, 16 * dpr, QImage::Format_ARGB32);
|
||||
#if QT_VERSION >= 0x50000
|
||||
icon.setDevicePixelRatio (menu->devicePixelRatio ());
|
||||
#endif
|
||||
const char *cp = dpr > 1 ? color_icon_2x : color_icon;
|
||||
for (int y = 0; y < icon.height (); ++y) {
|
||||
for (int x = 0; x < icon.width (); ++x) {
|
||||
icon.setPixel (x, y, codes [*cp].rgba ());
|
||||
++cp;
|
||||
}
|
||||
|
|
@ -915,6 +957,9 @@ ColorButton::build_color_menu (QMenu *menu, QObject *receiver, const char *brows
|
|||
std::string name = tl::sprintf ("#%d", i + 1);
|
||||
|
||||
QPixmap icon (16, 16);
|
||||
#if QT_VERSION >= 0x50000
|
||||
icon.setDevicePixelRatio (menu->devicePixelRatio ());
|
||||
#endif
|
||||
icon.fill (color);
|
||||
|
||||
submenu->addAction (QIcon (icon), tl::to_qstring (name), receiver, selected_slot)->setData (QVariant (color));
|
||||
|
|
@ -949,7 +994,16 @@ ColorButton::set_color_internal (QColor c)
|
|||
|
||||
QPushButton::setIconSize (QSize (rt.width (), rt.height ()));
|
||||
|
||||
QPixmap pixmap (rt.width (), rt.height ());
|
||||
#if QT_VERSION >= 0x050000
|
||||
double dpr = devicePixelRatio ();
|
||||
#else
|
||||
double dpr = 1.0;
|
||||
#endif
|
||||
|
||||
QPixmap pixmap (rt.width () * dpr, rt.height () * dpr);
|
||||
#if QT_VERSION >= 0x50000
|
||||
pixmap.setDevicePixelRatio (dpr);
|
||||
#endif
|
||||
pixmap.fill (QColor (0, 0, 0, 0));
|
||||
|
||||
QColor text_color = palette ().color (QPalette::Active, QPalette::Text);
|
||||
|
|
@ -959,13 +1013,13 @@ ColorButton::set_color_internal (QColor c)
|
|||
if (! m_color.isValid ()) {
|
||||
|
||||
pxpainter.setFont (font ());
|
||||
QRect r (0, 0, pixmap.width () - 1, pixmap.height () - 1);
|
||||
QRectF r (0, 0, rt.width () - pxpainter.pen ().widthF (), rt.height () - pxpainter.pen ().widthF ());
|
||||
pxpainter.drawText (r, Qt::AlignHCenter | Qt::AlignVCenter | Qt::TextSingleLine, QObject::tr ("Auto"));
|
||||
|
||||
} else {
|
||||
|
||||
pxpainter.setBrush (QBrush (c));
|
||||
QRect r (0, 0, pixmap.width () - 1, pixmap.height () - 1);
|
||||
QRectF r (0, 0, rt.width () - pxpainter.pen ().widthF (), rt.height () - pxpainter.pen ().widthF ());
|
||||
pxpainter.drawRect (r);
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@
|
|||
#include "rdbMarkerBrowserDialog.h"
|
||||
#include "rdb.h"
|
||||
#include "rdbReader.h"
|
||||
#include "rdbUtils.h"
|
||||
#include "tlProgress.h"
|
||||
#include "layLayoutViewBase.h"
|
||||
#include "tlExceptions.h"
|
||||
|
|
@ -790,11 +791,7 @@ MarkerBrowserDialog::scan_layer ()
|
|||
|
||||
for (db::ShapeIterator shape = cell.shapes ((*l)->layer_index ()).begin (db::ShapeIterator::All); ! shape.at_end (); ++shape) {
|
||||
|
||||
std::unique_ptr<rdb::ValueBase> value (rdb::ValueBase::create_from_shape (*shape, db::CplxTrans (layout.dbu ())));
|
||||
if (value.get ()) {
|
||||
rdb::Item *item = rdb->create_item (rdb_cell->id (), cat->id ());
|
||||
item->values ().add (value.release ());
|
||||
}
|
||||
rdb::create_item_from_shape (rdb.get (), rdb_cell->id (), cat->id (), db::CplxTrans (layout.dbu ()), *shape);
|
||||
|
||||
++progress;
|
||||
|
||||
|
|
@ -869,11 +866,7 @@ MarkerBrowserDialog::scan_layer_flat ()
|
|||
db::RecursiveShapeIterator shape (layout, *cv.cell (), (*l)->layer_index ());
|
||||
while (! shape.at_end ()) {
|
||||
|
||||
std::unique_ptr<rdb::ValueBase> value (rdb::ValueBase::create_from_shape (*shape, db::CplxTrans (layout.dbu ()) * shape.trans ()));
|
||||
if (value.get ()) {
|
||||
rdb::Item *item = rdb->create_item (rdb_top_cell->id (), cat->id ());
|
||||
item->values ().add (value.release ());
|
||||
}
|
||||
rdb::create_item_from_shape (rdb.get (), rdb_top_cell->id (), cat->id (), db::CplxTrans (layout.dbu ()) * shape.trans (), *shape);
|
||||
|
||||
++progress;
|
||||
++shape;
|
||||
|
|
|
|||
|
|
@ -584,10 +584,15 @@ LayoutView::show_properties ()
|
|||
}
|
||||
|
||||
// re-create a new properties dialog
|
||||
QByteArray geom;
|
||||
if (mp_properties_dialog) {
|
||||
geom = mp_properties_dialog->saveGeometry ();
|
||||
delete mp_properties_dialog.data ();
|
||||
}
|
||||
mp_properties_dialog = new lay::PropertiesDialog (widget (), manager (), this);
|
||||
if (! geom.isEmpty ()) {
|
||||
mp_properties_dialog->restoreGeometry (geom);
|
||||
}
|
||||
|
||||
// if launched from a dialog, do not use "show" as this blocks user interaction
|
||||
if (QApplication::activeModalWidget ()) {
|
||||
|
|
@ -731,6 +736,24 @@ LayoutView::update_menu (lay::LayoutView *view, lay::AbstractMenu &menu)
|
|||
bool
|
||||
LayoutView::configure (const std::string &name, const std::string &value)
|
||||
{
|
||||
if (name == cfg_bitmap_oversampling) {
|
||||
|
||||
int os = 1;
|
||||
tl::from_string (value, os);
|
||||
if (mp_control_panel) {
|
||||
mp_control_panel->set_oversampling (os);
|
||||
}
|
||||
|
||||
} else if (name == cfg_highres_mode) {
|
||||
|
||||
bool hrm = false;
|
||||
tl::from_string (value, hrm);
|
||||
if (mp_control_panel) {
|
||||
mp_control_panel->set_highres_mode (hrm);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (LayoutViewBase::configure (name, value)) {
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -182,9 +182,9 @@ NetTracerLayerExpressionInfo::compile (const std::string &s)
|
|||
}
|
||||
|
||||
NetTracerLayerExpression *
|
||||
NetTracerLayerExpressionInfo::get_expr (const db::LayerProperties &lp, const db::Layout &layout, const NetTracerTechnologyComponent &tech, const std::set<std::string> &used_symbols) const
|
||||
NetTracerLayerExpressionInfo::get_expr (const db::LayerProperties &lp, const db::Layout &layout, const NetTracerConnectivity &tech, const std::set<std::string> &used_symbols) const
|
||||
{
|
||||
for (NetTracerTechnologyComponent::const_symbol_iterator s = tech.begin_symbols (); s != tech.end_symbols (); ++s) {
|
||||
for (NetTracerConnectivity::const_symbol_iterator s = tech.begin_symbols (); s != tech.end_symbols (); ++s) {
|
||||
if (s->symbol ().log_equal (lp)) {
|
||||
std::set<std::string> us = used_symbols;
|
||||
if (! us.insert (s->symbol ().to_string ()).second) {
|
||||
|
|
@ -204,14 +204,14 @@ NetTracerLayerExpressionInfo::get_expr (const db::LayerProperties &lp, const db:
|
|||
}
|
||||
|
||||
NetTracerLayerExpression *
|
||||
NetTracerLayerExpressionInfo::get (const db::Layout &layout, const NetTracerTechnologyComponent &tech) const
|
||||
NetTracerLayerExpressionInfo::get (const db::Layout &layout, const NetTracerConnectivity &tech) const
|
||||
{
|
||||
std::set<std::string> us;
|
||||
return get (layout, tech, us);
|
||||
}
|
||||
|
||||
NetTracerLayerExpression *
|
||||
NetTracerLayerExpressionInfo::get (const db::Layout &layout, const NetTracerTechnologyComponent &tech, const std::set<std::string> &used_symbols) const
|
||||
NetTracerLayerExpressionInfo::get (const db::Layout &layout, const NetTracerConnectivity &tech, const std::set<std::string> &used_symbols) const
|
||||
{
|
||||
NetTracerLayerExpression *e = 0;
|
||||
|
||||
|
|
@ -252,7 +252,7 @@ NetTracerConnectionInfo::NetTracerConnectionInfo (const NetTracerLayerExpression
|
|||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
static int get_layer_id (const NetTracerLayerExpressionInfo &e, const db::Layout &layout, const NetTracerTechnologyComponent &tech, NetTracerData *data)
|
||||
static int get_layer_id (const NetTracerLayerExpressionInfo &e, const db::Layout &layout, const NetTracerConnectivity &tech, NetTracerData *data)
|
||||
{
|
||||
std::unique_ptr<NetTracerLayerExpression> expr_in (NetTracerLayerExpressionInfo::compile (e.to_string ()).get (layout, tech));
|
||||
int l = expr_in->alias_for ();
|
||||
|
|
@ -266,7 +266,7 @@ static int get_layer_id (const NetTracerLayerExpressionInfo &e, const db::Layout
|
|||
}
|
||||
|
||||
NetTracerConnection
|
||||
NetTracerConnectionInfo::get (const db::Layout &layout, const NetTracerTechnologyComponent &tech, NetTracerData &data) const
|
||||
NetTracerConnectionInfo::get (const db::Layout &layout, const NetTracerConnectivity &tech, NetTracerData &data) const
|
||||
{
|
||||
int la = get_layer_id (m_la, layout, tech, &data);
|
||||
int lb = get_layer_id (m_lb, layout, tech, &data);
|
||||
|
|
@ -490,30 +490,40 @@ NetTracerNet::define_layer (unsigned int l, const db::LayerProperties &lp, const
|
|||
|
||||
NetTracerTechnologyComponent::NetTracerTechnologyComponent ()
|
||||
: db::TechnologyComponent (net_tracer_component_name (), tl::to_string (tr ("Connectivity")))
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------------
|
||||
// NetTracerConnectivity implementation
|
||||
|
||||
NetTracerConnectivity::NetTracerConnectivity ()
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
NetTracerTechnologyComponent::NetTracerTechnologyComponent (const NetTracerTechnologyComponent &d)
|
||||
: db::TechnologyComponent (net_tracer_component_name (), tl::to_string (tr ("Connectivity")))
|
||||
NetTracerConnectivity::NetTracerConnectivity (const NetTracerConnectivity &d)
|
||||
{
|
||||
m_connections = d.m_connections;
|
||||
m_symbols = d.m_symbols;
|
||||
operator= (d);
|
||||
}
|
||||
|
||||
NetTracerTechnologyComponent &NetTracerTechnologyComponent::operator= (const NetTracerTechnologyComponent &d)
|
||||
NetTracerConnectivity &NetTracerConnectivity::operator= (const NetTracerConnectivity &d)
|
||||
{
|
||||
m_connections = d.m_connections;
|
||||
m_symbols = d.m_symbols;
|
||||
if (this != &d) {
|
||||
m_connections = d.m_connections;
|
||||
m_symbols = d.m_symbols;
|
||||
m_name = d.m_name;
|
||||
m_description = d.m_description;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
NetTracerData
|
||||
NetTracerTechnologyComponent::get_tracer_data (const db::Layout &layout) const
|
||||
NetTracerConnectivity::get_tracer_data (const db::Layout &layout) const
|
||||
{
|
||||
// test run on the expressions to verify their syntax
|
||||
int n = 1;
|
||||
for (NetTracerTechnologyComponent::const_iterator c = begin (); c != end (); ++c, ++n) {
|
||||
for (NetTracerConnectivity::const_iterator c = begin (); c != end (); ++c, ++n) {
|
||||
if (c->layer_a ().to_string ().empty ()) {
|
||||
throw tl::Exception (tl::to_string (tr ("Missing first layer specification on connectivity specification #%d")), n);
|
||||
}
|
||||
|
|
@ -523,7 +533,7 @@ NetTracerTechnologyComponent::get_tracer_data (const db::Layout &layout) const
|
|||
}
|
||||
|
||||
n = 1;
|
||||
for (NetTracerTechnologyComponent::const_symbol_iterator s = begin_symbols (); s != end_symbols (); ++s, ++n) {
|
||||
for (NetTracerConnectivity::const_symbol_iterator s = begin_symbols (); s != end_symbols (); ++s, ++n) {
|
||||
if (s->symbol ().to_string ().empty ()) {
|
||||
throw tl::Exception (tl::to_string (tr ("Missing symbol name on symbol specification #%d")), n);
|
||||
}
|
||||
|
|
@ -540,12 +550,12 @@ NetTracerTechnologyComponent::get_tracer_data (const db::Layout &layout) const
|
|||
NetTracerData data;
|
||||
|
||||
// register a logical layer for each original one as alias and one for each expression with a new ID
|
||||
for (db::NetTracerTechnologyComponent::const_symbol_iterator s = begin_symbols (); s != end_symbols (); ++s) {
|
||||
for (db::NetTracerConnectivity::const_symbol_iterator s = begin_symbols (); s != end_symbols (); ++s) {
|
||||
db::NetTracerLayerExpression *expr = db::NetTracerLayerExpressionInfo::compile (s->expression ()).get (layout, *this);
|
||||
data.register_logical_layer (expr, s->symbol ().to_string ().c_str ());
|
||||
}
|
||||
|
||||
for (db::NetTracerTechnologyComponent::const_iterator c = begin (); c != end (); ++c) {
|
||||
for (db::NetTracerConnectivity::const_iterator c = begin (); c != end (); ++c) {
|
||||
data.add_connection (c->get (layout, *this, data));
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@
|
|||
namespace db
|
||||
{
|
||||
|
||||
class NetTracerTechnologyComponent;
|
||||
class NetTracerConnectivity;
|
||||
|
||||
DB_PLUGIN_PUBLIC std::string net_tracer_component_name ();
|
||||
|
||||
|
|
@ -57,7 +57,7 @@ public:
|
|||
return m_expression;
|
||||
}
|
||||
|
||||
NetTracerLayerExpression *get (const db::Layout &layout, const NetTracerTechnologyComponent &tech) const;
|
||||
NetTracerLayerExpression *get (const db::Layout &layout, const NetTracerConnectivity &tech) const;
|
||||
|
||||
private:
|
||||
std::string m_expression;
|
||||
|
|
@ -70,8 +70,8 @@ private:
|
|||
static NetTracerLayerExpressionInfo parse_mult (tl::Extractor &ex);
|
||||
static NetTracerLayerExpressionInfo parse_atomic (tl::Extractor &ex);
|
||||
|
||||
NetTracerLayerExpression *get (const db::Layout &layout, const NetTracerTechnologyComponent &tech, const std::set<std::string> &used_symbols) const;
|
||||
NetTracerLayerExpression *get_expr (const db::LayerProperties &lp, const db::Layout &layout, const NetTracerTechnologyComponent &tech, const std::set<std::string> &used_symbols) const;
|
||||
NetTracerLayerExpression *get (const db::Layout &layout, const NetTracerConnectivity &tech, const std::set<std::string> &used_symbols) const;
|
||||
NetTracerLayerExpression *get_expr (const db::LayerProperties &lp, const db::Layout &layout, const NetTracerConnectivity &tech, const std::set<std::string> &used_symbols) const;
|
||||
};
|
||||
|
||||
class DB_PLUGIN_PUBLIC NetTracerConnectionInfo
|
||||
|
|
@ -81,7 +81,7 @@ public:
|
|||
NetTracerConnectionInfo (const NetTracerLayerExpressionInfo &la, const NetTracerLayerExpressionInfo &lb);
|
||||
NetTracerConnectionInfo (const NetTracerLayerExpressionInfo &la, const NetTracerLayerExpressionInfo &via, const NetTracerLayerExpressionInfo &lb);
|
||||
|
||||
NetTracerConnection get (const db::Layout &layout, const NetTracerTechnologyComponent &tech, NetTracerData &data) const;
|
||||
NetTracerConnection get (const db::Layout &layout, const NetTracerConnectivity &tech, NetTracerData &data) const;
|
||||
|
||||
std::string to_string () const;
|
||||
void parse (tl::Extractor &ex);
|
||||
|
|
@ -357,8 +357,7 @@ private:
|
|||
void define_layer (unsigned int l, const db::LayerProperties &lp, const db::LayerProperties &lp_representative);
|
||||
};
|
||||
|
||||
class DB_PLUGIN_PUBLIC NetTracerTechnologyComponent
|
||||
: public db::TechnologyComponent
|
||||
class DB_PLUGIN_PUBLIC NetTracerConnectivity
|
||||
{
|
||||
public:
|
||||
typedef std::vector<NetTracerConnectionInfo>::const_iterator const_iterator;
|
||||
|
|
@ -366,9 +365,29 @@ public:
|
|||
typedef std::vector<NetTracerSymbolInfo>::const_iterator const_symbol_iterator;
|
||||
typedef std::vector<NetTracerSymbolInfo>::iterator symbol_iterator;
|
||||
|
||||
NetTracerTechnologyComponent ();
|
||||
NetTracerTechnologyComponent (const NetTracerTechnologyComponent &d);
|
||||
NetTracerTechnologyComponent &operator= (const NetTracerTechnologyComponent &d);
|
||||
NetTracerConnectivity ();
|
||||
NetTracerConnectivity (const NetTracerConnectivity &d);
|
||||
NetTracerConnectivity &operator= (const NetTracerConnectivity &d);
|
||||
|
||||
const std::string &name () const
|
||||
{
|
||||
return m_name;
|
||||
}
|
||||
|
||||
void set_name (const std::string &n)
|
||||
{
|
||||
m_name = n;
|
||||
}
|
||||
|
||||
const std::string &description () const
|
||||
{
|
||||
return m_description;
|
||||
}
|
||||
|
||||
void set_description (const std::string &d)
|
||||
{
|
||||
m_description = d;
|
||||
}
|
||||
|
||||
const_iterator begin () const
|
||||
{
|
||||
|
|
@ -416,6 +435,16 @@ public:
|
|||
m_symbols.clear ();
|
||||
}
|
||||
|
||||
void clear_connections ()
|
||||
{
|
||||
m_connections.clear ();
|
||||
}
|
||||
|
||||
void clear_symbols ()
|
||||
{
|
||||
m_symbols.clear ();
|
||||
}
|
||||
|
||||
void erase (iterator p)
|
||||
{
|
||||
m_connections.erase (p);
|
||||
|
|
@ -458,14 +487,73 @@ public:
|
|||
|
||||
NetTracerData get_tracer_data (const db::Layout &layout) const;
|
||||
|
||||
db::TechnologyComponent *clone () const
|
||||
private:
|
||||
std::vector<NetTracerConnectionInfo> m_connections;
|
||||
std::vector<NetTracerSymbolInfo> m_symbols;
|
||||
std::string m_name, m_description;
|
||||
};
|
||||
|
||||
class DB_PLUGIN_PUBLIC NetTracerTechnologyComponent
|
||||
: public db::TechnologyComponent
|
||||
{
|
||||
public:
|
||||
typedef std::vector<NetTracerConnectivity>::const_iterator const_iterator;
|
||||
typedef std::vector<NetTracerConnectivity>::iterator iterator;
|
||||
|
||||
NetTracerTechnologyComponent ();
|
||||
|
||||
size_t size () const
|
||||
{
|
||||
return m_connectivity.size ();
|
||||
}
|
||||
|
||||
void push_back (const db::NetTracerConnectivity &c)
|
||||
{
|
||||
m_connectivity.push_back (c);
|
||||
}
|
||||
|
||||
void clear ()
|
||||
{
|
||||
m_connectivity.clear ();
|
||||
}
|
||||
|
||||
void erase (iterator i)
|
||||
{
|
||||
m_connectivity.erase (i);
|
||||
}
|
||||
|
||||
void insert (iterator i, const db::NetTracerConnectivity &c)
|
||||
{
|
||||
m_connectivity.insert (i, c);
|
||||
}
|
||||
|
||||
const_iterator begin () const
|
||||
{
|
||||
return m_connectivity.begin ();
|
||||
}
|
||||
|
||||
const_iterator end () const
|
||||
{
|
||||
return m_connectivity.end ();
|
||||
}
|
||||
|
||||
iterator begin ()
|
||||
{
|
||||
return m_connectivity.begin ();
|
||||
}
|
||||
|
||||
iterator end ()
|
||||
{
|
||||
return m_connectivity.end ();
|
||||
}
|
||||
|
||||
db::NetTracerTechnologyComponent *clone () const
|
||||
{
|
||||
return new NetTracerTechnologyComponent (*this);
|
||||
}
|
||||
|
||||
private:
|
||||
std::vector<NetTracerConnectionInfo> m_connections;
|
||||
std::vector<NetTracerSymbolInfo> m_symbols;
|
||||
std::vector<NetTracerConnectivity> m_connectivity;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -65,6 +65,101 @@ namespace tl
|
|||
};
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
static const db::NetTracerConnectivity *
|
||||
get_default (const db::NetTracerTechnologyComponent &tc)
|
||||
{
|
||||
for (auto d = tc.begin (); d != tc.end (); ++d) {
|
||||
if (d->name ().empty ()) {
|
||||
return d.operator-> ();
|
||||
}
|
||||
}
|
||||
|
||||
if (tc.begin () != tc.end ()) {
|
||||
return tc.begin ().operator-> ();
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
template <class Value>
|
||||
struct FallbackXMLWriteAdaptor
|
||||
{
|
||||
FallbackXMLWriteAdaptor (void (db::NetTracerConnectivity::*member) (const Value &), void (db::NetTracerConnectivity::*clear) ())
|
||||
: mp_member (member), mp_clear (clear), mp_stack (0)
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
void operator () (db::NetTracerTechnologyComponent &owner, tl::XMLReaderState &reader) const
|
||||
{
|
||||
if (! mp_stack) {
|
||||
mp_stack = const_cast<db::NetTracerConnectivity *> (get_default (owner));
|
||||
if (! mp_stack) {
|
||||
owner.push_back (db::NetTracerConnectivity ());
|
||||
mp_stack = (owner.end () - 1).operator-> ();
|
||||
}
|
||||
(mp_stack->*mp_clear) ();
|
||||
}
|
||||
|
||||
tl::XMLObjTag<Value> tag;
|
||||
(mp_stack->*mp_member) (*reader.back (tag));
|
||||
}
|
||||
|
||||
private:
|
||||
void (db::NetTracerConnectivity::*mp_member) (const Value &);
|
||||
void (db::NetTracerConnectivity::*mp_clear) ();
|
||||
mutable db::NetTracerConnectivity *mp_stack;
|
||||
};
|
||||
|
||||
template <class Value, class Iter>
|
||||
struct FallbackXMLReadAdaptor
|
||||
{
|
||||
typedef tl::pass_by_ref_tag tag;
|
||||
|
||||
FallbackXMLReadAdaptor (Iter (db::NetTracerConnectivity::*begin) () const, Iter (db::NetTracerConnectivity::*end) () const)
|
||||
: mp_begin (begin), mp_end (end)
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
Value operator () () const
|
||||
{
|
||||
return *m_iter;
|
||||
}
|
||||
|
||||
bool at_end () const
|
||||
{
|
||||
return m_iter == m_end;
|
||||
}
|
||||
|
||||
void start (const db::NetTracerTechnologyComponent &parent)
|
||||
{
|
||||
const db::NetTracerConnectivity *tn = get_default (parent);
|
||||
if (! tn) {
|
||||
m_iter = Iter ();
|
||||
m_end = Iter ();
|
||||
} else {
|
||||
m_iter = (tn->*mp_begin) ();
|
||||
m_end = (tn->*mp_end) ();
|
||||
}
|
||||
}
|
||||
|
||||
void next ()
|
||||
{
|
||||
++m_iter;
|
||||
}
|
||||
|
||||
private:
|
||||
Iter (db::NetTracerConnectivity::*mp_begin) () const;
|
||||
Iter (db::NetTracerConnectivity::*mp_end) () const;
|
||||
Iter m_iter, m_end;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
namespace db
|
||||
{
|
||||
|
||||
|
|
@ -86,8 +181,20 @@ public:
|
|||
virtual tl::XMLElementBase *xml_element () const
|
||||
{
|
||||
return new db::TechnologyComponentXMLElement<NetTracerTechnologyComponent> (net_tracer_component_name (),
|
||||
tl::make_member ((NetTracerTechnologyComponent::const_iterator (NetTracerTechnologyComponent::*) () const) &NetTracerTechnologyComponent::begin, (NetTracerTechnologyComponent::const_iterator (NetTracerTechnologyComponent::*) () const) &NetTracerTechnologyComponent::end, &NetTracerTechnologyComponent::add, "connection") +
|
||||
tl::make_member ((NetTracerTechnologyComponent::const_symbol_iterator (NetTracerTechnologyComponent::*) () const) &NetTracerTechnologyComponent::begin_symbols, (NetTracerTechnologyComponent::const_symbol_iterator (NetTracerTechnologyComponent::*) () const) &NetTracerTechnologyComponent::end_symbols, &NetTracerTechnologyComponent::add_symbol, "symbols")
|
||||
// 0.28 definitions
|
||||
tl::make_element ((NetTracerTechnologyComponent::const_iterator (NetTracerTechnologyComponent::*) () const) &NetTracerTechnologyComponent::begin, (NetTracerTechnologyComponent::const_iterator (NetTracerTechnologyComponent::*) () const) &NetTracerTechnologyComponent::end, (void (NetTracerTechnologyComponent::*) (const NetTracerConnectivity &)) &NetTracerTechnologyComponent::push_back, "stack",
|
||||
tl::make_member (&NetTracerConnectivity::name, &NetTracerConnectivity::set_name, "name") +
|
||||
tl::make_member (&NetTracerConnectivity::description, &NetTracerConnectivity::set_description, "description") +
|
||||
tl::make_member ((NetTracerConnectivity::const_iterator (NetTracerConnectivity::*) () const) &NetTracerConnectivity::begin, (NetTracerConnectivity::const_iterator (NetTracerConnectivity::*) () const) &NetTracerConnectivity::end, &NetTracerConnectivity::add, "connection") +
|
||||
tl::make_member ((NetTracerConnectivity::const_symbol_iterator (NetTracerConnectivity::*) () const) &NetTracerConnectivity::begin_symbols, (NetTracerConnectivity::const_symbol_iterator (NetTracerConnectivity::*) () const) &NetTracerConnectivity::end_symbols, &NetTracerConnectivity::add_symbol, "symbols")
|
||||
) +
|
||||
// Fallback readers for migrating pre-0.28 setups to 0.28 and backward compatibility
|
||||
tl::XMLMember<NetTracerConnectionInfo, NetTracerTechnologyComponent, FallbackXMLReadAdaptor <NetTracerConnectionInfo, NetTracerConnectivity::const_iterator>, FallbackXMLWriteAdaptor <NetTracerConnectionInfo>, tl::XMLStdConverter <NetTracerConnectionInfo> > (
|
||||
FallbackXMLReadAdaptor <NetTracerConnectionInfo, NetTracerConnectivity::const_iterator> (&NetTracerConnectivity::begin, &NetTracerConnectivity::end),
|
||||
FallbackXMLWriteAdaptor <NetTracerConnectionInfo> (&NetTracerConnectivity::add, &NetTracerConnectivity::clear_connections), "connection") +
|
||||
tl::XMLMember<NetTracerSymbolInfo, NetTracerTechnologyComponent, FallbackXMLReadAdaptor <NetTracerSymbolInfo, NetTracerConnectivity::const_symbol_iterator>, FallbackXMLWriteAdaptor <NetTracerSymbolInfo>, tl::XMLStdConverter <NetTracerSymbolInfo> > (
|
||||
FallbackXMLReadAdaptor <NetTracerSymbolInfo, NetTracerConnectivity::const_symbol_iterator> (&NetTracerConnectivity::begin_symbols, &NetTracerConnectivity::end_symbols),
|
||||
FallbackXMLWriteAdaptor <NetTracerSymbolInfo> (&NetTracerConnectivity::add_symbol, &NetTracerConnectivity::clear_symbols), "symbols")
|
||||
);
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -32,14 +32,14 @@ namespace gsi
|
|||
// -----------------------------------------------------------------------------------
|
||||
// GSI binding
|
||||
|
||||
static void def_connection2 (db::NetTracerTechnologyComponent *tech, const std::string &la, const std::string &lb)
|
||||
static void def_connection2 (db::NetTracerConnectivity *tech, const std::string &la, const std::string &lb)
|
||||
{
|
||||
db::NetTracerLayerExpressionInfo la_info = db::NetTracerLayerExpressionInfo::compile (la);
|
||||
db::NetTracerLayerExpressionInfo lb_info = db::NetTracerLayerExpressionInfo::compile (lb);
|
||||
tech->add (db::NetTracerConnectionInfo (la_info, lb_info));
|
||||
}
|
||||
|
||||
static void def_connection3 (db::NetTracerTechnologyComponent *tech, const std::string &la, const std::string &via, const std::string &lb)
|
||||
static void def_connection3 (db::NetTracerConnectivity *tech, const std::string &la, const std::string &via, const std::string &lb)
|
||||
{
|
||||
db::NetTracerLayerExpressionInfo la_info = db::NetTracerLayerExpressionInfo::compile (la);
|
||||
db::NetTracerLayerExpressionInfo via_info = db::NetTracerLayerExpressionInfo::compile (via);
|
||||
|
|
@ -47,14 +47,26 @@ static void def_connection3 (db::NetTracerTechnologyComponent *tech, const std::
|
|||
tech->add (db::NetTracerConnectionInfo (la_info, via_info, lb_info));
|
||||
}
|
||||
|
||||
static void def_symbol (db::NetTracerTechnologyComponent *tech, const std::string &name, const std::string &expr)
|
||||
static void def_symbol (db::NetTracerConnectivity *tech, const std::string &name, const std::string &expr)
|
||||
{
|
||||
tech->add_symbol (db::NetTracerSymbolInfo (db::LayerProperties (name), expr));
|
||||
}
|
||||
|
||||
gsi::Class<db::TechnologyComponent> &decl_dbTechnologyComponent ();
|
||||
|
||||
gsi::Class<db::NetTracerTechnologyComponent> decl_NetTracerTechnology (decl_dbTechnologyComponent (), "db", "NetTracerTechnology",
|
||||
gsi::Class<db::NetTracerConnectivity> decl_NetTracerConnectivity ("db", "NetTracerConnectivity",
|
||||
gsi::method ("name", &db::NetTracerConnectivity::name,
|
||||
"@brief Gets the name of the connectivty definition\n"
|
||||
"The name is an optional string defining the formal name for this definition.\n"
|
||||
) +
|
||||
gsi::method ("name=", &db::NetTracerConnectivity::set_name, gsi::arg ("n"),
|
||||
"@brief Sets the name of the connectivty definition\n"
|
||||
) +
|
||||
gsi::method ("description", &db::NetTracerConnectivity::description,
|
||||
"@brief Gets the description text of the connectivty definition\n"
|
||||
"The description is an optional string giving a human-readable description for this definition."
|
||||
) +
|
||||
gsi::method ("description=", &db::NetTracerConnectivity::set_description, gsi::arg ("d"),
|
||||
"@brief Sets the description of the connectivty definition\n"
|
||||
) +
|
||||
gsi::method_ext ("connection", &def_connection2, gsi::arg("a"), gsi::arg("b"),
|
||||
"@brief Defines a connection between two materials\n"
|
||||
"See the class description for details about this method."
|
||||
|
|
@ -68,7 +80,7 @@ gsi::Class<db::NetTracerTechnologyComponent> decl_NetTracerTechnology (decl_dbTe
|
|||
"Defines a sub-expression to be used in further symbols or material expressions. "
|
||||
"For the detailed notation of the expression see the description of the net tracer feature."
|
||||
),
|
||||
"@brief A technology description for the net tracer\n"
|
||||
"@brief A connectivity description for the net tracer\n"
|
||||
"\n"
|
||||
"This object represents the technology description for the net tracer (represented by the \\NetTracer class).\n"
|
||||
"A technology description basically consists of connection declarations.\n"
|
||||
|
|
@ -83,16 +95,17 @@ gsi::Class<db::NetTracerTechnologyComponent> decl_NetTracerTechnology (decl_dbTe
|
|||
"\n"
|
||||
"For details about the expressions see the description of the net tracer feature.\n"
|
||||
"\n"
|
||||
"This class has been introduced in version 0.25.\n"
|
||||
"This class has been introduced in version 0.28 and replaces the 'NetTracerTechnology' class which "
|
||||
"has been generalized.\n"
|
||||
);
|
||||
|
||||
static void trace1 (db::NetTracer *net_tracer, const db::NetTracerTechnologyComponent &tech, const db::Layout &layout, const db::Cell &cell, const db::Point &start_point, unsigned int start_layer)
|
||||
static void trace1 (db::NetTracer *net_tracer, const db::NetTracerConnectivity &tech, const db::Layout &layout, const db::Cell &cell, const db::Point &start_point, unsigned int start_layer)
|
||||
{
|
||||
db::NetTracerData tracer_data = tech.get_tracer_data (layout);
|
||||
net_tracer->trace (layout, cell, start_point, start_layer, tracer_data);
|
||||
}
|
||||
|
||||
static void trace2 (db::NetTracer *net_tracer, const db::NetTracerTechnologyComponent &tech, const db::Layout &layout, const db::Cell &cell, const db::Point &start_point, unsigned int start_layer, const db::Point &stop_point, unsigned int stop_layer)
|
||||
static void trace2 (db::NetTracer *net_tracer, const db::NetTracerConnectivity &tech, const db::Layout &layout, const db::Cell &cell, const db::Point &start_point, unsigned int start_layer, const db::Point &stop_point, unsigned int stop_layer)
|
||||
{
|
||||
db::NetTracerData tracer_data = tech.get_tracer_data (layout);
|
||||
net_tracer->trace (layout, cell, start_point, start_layer, stop_point, stop_layer, tracer_data);
|
||||
|
|
@ -106,7 +119,31 @@ static db::NetTracerData get_tracer_data_from_tech (const std::string &tech_name
|
|||
const db::NetTracerTechnologyComponent *tech_component = dynamic_cast <const db::NetTracerTechnologyComponent *> (tech->component_by_name (db::net_tracer_component_name ()));
|
||||
tl_assert (tech_component != 0);
|
||||
|
||||
return tech_component->get_tracer_data (layout);
|
||||
if (tech_component->size () < 1) {
|
||||
throw tl::Exception (tl::to_string (tr ("No connectivity setup exists for technology '%s'")), tech_name);
|
||||
}
|
||||
if (tech_component->size () > 1) {
|
||||
throw tl::Exception (tl::to_string (tr ("Multiple connectivity setups exist for technology '%s' - specify a name")), tech_name);
|
||||
}
|
||||
|
||||
return tech_component->begin ()->get_tracer_data (layout);
|
||||
}
|
||||
|
||||
static db::NetTracerData get_tracer_data_from_tech (const std::string &tech_name, const std::string &name, const db::Layout &layout)
|
||||
{
|
||||
const db::Technology *tech = db::Technologies::instance ()->technology_by_name (tech_name);
|
||||
tl_assert (tech != 0);
|
||||
|
||||
const db::NetTracerTechnologyComponent *tech_component = dynamic_cast <const db::NetTracerTechnologyComponent *> (tech->component_by_name (db::net_tracer_component_name ()));
|
||||
tl_assert (tech_component != 0);
|
||||
|
||||
for (auto t = tech_component->begin (); t != tech_component->end (); ++t) {
|
||||
if (t->name () == name) {
|
||||
return t->get_tracer_data (layout);
|
||||
}
|
||||
}
|
||||
|
||||
throw tl::Exception (tl::to_string (tr ("No connectivity setup exists with name '%s' for technology '%s'")), name, tech_name);
|
||||
}
|
||||
|
||||
static void trace1_tn (db::NetTracer *net_tracer, const std::string &tech, const db::Layout &layout, const db::Cell &cell, const db::Point &start_point, unsigned int start_layer)
|
||||
|
|
@ -115,12 +152,24 @@ static void trace1_tn (db::NetTracer *net_tracer, const std::string &tech, const
|
|||
net_tracer->trace (layout, cell, start_point, start_layer, tracer_data);
|
||||
}
|
||||
|
||||
static void trace1_tn2 (db::NetTracer *net_tracer, const std::string &tech, const std::string &name, const db::Layout &layout, const db::Cell &cell, const db::Point &start_point, unsigned int start_layer)
|
||||
{
|
||||
db::NetTracerData tracer_data = get_tracer_data_from_tech (tech, name, layout);
|
||||
net_tracer->trace (layout, cell, start_point, start_layer, tracer_data);
|
||||
}
|
||||
|
||||
static void trace2_tn (db::NetTracer *net_tracer, const std::string &tech, const db::Layout &layout, const db::Cell &cell, const db::Point &start_point, unsigned int start_layer, const db::Point &stop_point, unsigned int stop_layer)
|
||||
{
|
||||
db::NetTracerData tracer_data = get_tracer_data_from_tech (tech, layout);
|
||||
net_tracer->trace (layout, cell, start_point, start_layer, stop_point, stop_layer, tracer_data);
|
||||
}
|
||||
|
||||
static void trace2_tn2 (db::NetTracer *net_tracer, const std::string &tech, const std::string &name, const db::Layout &layout, const db::Cell &cell, const db::Point &start_point, unsigned int start_layer, const db::Point &stop_point, unsigned int stop_layer)
|
||||
{
|
||||
db::NetTracerData tracer_data = get_tracer_data_from_tech (tech, name, layout);
|
||||
net_tracer->trace (layout, cell, start_point, start_layer, stop_point, stop_layer, tracer_data);
|
||||
}
|
||||
|
||||
gsi::Class<db::NetTracerShape> decl_NetElement ("db", "NetElement",
|
||||
gsi::method ("trans", &db::NetTracerShape::trans,
|
||||
"@brief Gets the transformation to apply for rendering the shape in the original top cell\n"
|
||||
|
|
@ -178,7 +227,7 @@ gsi::Class<db::NetTracer> decl_NetTracer ("db", "NetTracer",
|
|||
"A path extraction version is provided as well which will extract one (the presumably shortest) path between two "
|
||||
"points.\n"
|
||||
"\n"
|
||||
"@param tech The technology definition\n"
|
||||
"@param tech The connectivity definition\n"
|
||||
"@param layout The layout on which to run the extraction\n"
|
||||
"@param cell The cell on which to run the extraction (child cells will be included)\n"
|
||||
"@param start_point The start point from which to start extraction of the net\n"
|
||||
|
|
@ -194,7 +243,7 @@ gsi::Class<db::NetTracer> decl_NetTracer ("db", "NetTracer",
|
|||
"\n"
|
||||
"This version runs a path extraction and will deliver elements forming one path leading from the start to the end point.\n"
|
||||
"\n"
|
||||
"@param tech The technology definition\n"
|
||||
"@param tech The connectivity definition\n"
|
||||
"@param layout The layout on which to run the extraction\n"
|
||||
"@param cell The cell on which to run the extraction (child cells will be included)\n"
|
||||
"@param start_point The start point from which to start extraction of the net\n"
|
||||
|
|
@ -205,13 +254,31 @@ gsi::Class<db::NetTracer> decl_NetTracer ("db", "NetTracer",
|
|||
gsi::method_ext ("trace", &trace1_tn, gsi::arg ("tech"), gsi::arg ("layout"), gsi::arg ("cell"), gsi::arg ("start_point"), gsi::arg ("start_layer"),
|
||||
"@brief Runs a net extraction taking a predefined technology\n"
|
||||
"This method behaves identical as the version with a technology object, except that it will look for a technology "
|
||||
"with the given name to obtain the extraction setup."
|
||||
"with the given name to obtain the extraction setup.\n"
|
||||
"The technology is looked up by technology name. A version of this method exists where it is possible "
|
||||
"to specify the name of the particular connectivity to use in case there are multiple definitions available."
|
||||
) +
|
||||
gsi::method_ext ("trace", &trace1_tn2, gsi::arg ("tech"), gsi::arg ("connectivity_name"), gsi::arg ("layout"), gsi::arg ("cell"), gsi::arg ("start_point"), gsi::arg ("start_layer"),
|
||||
"@brief Runs a net extraction taking a predefined technology\n"
|
||||
"This method behaves identical as the version with a technology object, except that it will look for a technology "
|
||||
"with the given name to obtain the extraction setup. "
|
||||
"This version allows specifying the name of the connecvitiy setup.\n"
|
||||
"\n"
|
||||
"This method variant has been introduced in version 0.28."
|
||||
) +
|
||||
gsi::method_ext ("trace", &trace2_tn, gsi::arg ("tech"), gsi::arg ("layout"), gsi::arg ("cell"), gsi::arg ("start_point"), gsi::arg ("start_layer"), gsi::arg ("stop_point"), gsi::arg ("stop_layer"),
|
||||
"@brief Runs a path extraction taking a predefined technology\n"
|
||||
"This method behaves identical as the version with a technology object, except that it will look for a technology "
|
||||
"with the given name to obtain the extraction setup."
|
||||
) +
|
||||
gsi::method_ext ("trace", &trace2_tn2, gsi::arg ("tech"), gsi::arg ("connectivity_name"), gsi::arg ("layout"), gsi::arg ("cell"), gsi::arg ("start_point"), gsi::arg ("start_layer"), gsi::arg ("stop_point"), gsi::arg ("stop_layer"),
|
||||
"@brief Runs a path extraction taking a predefined technology\n"
|
||||
"This method behaves identical as the version with a technology object, except that it will look for a technology "
|
||||
"with the given name to obtain the extraction setup."
|
||||
"This version allows specifying the name of the connecvitiy setup.\n"
|
||||
"\n"
|
||||
"This method variant has been introduced in version 0.28."
|
||||
) +
|
||||
gsi::iterator ("each_element", &db::NetTracer::begin, &db::NetTracer::end,
|
||||
"@brief Iterates over the elements found during extraction\n"
|
||||
"The elements are available only after the extraction has been performed."
|
||||
|
|
@ -267,7 +334,7 @@ gsi::Class<db::NetTracer> decl_NetTracer ("db", "NetTracer",
|
|||
"\n"
|
||||
"tracer = RBA::NetTracer::new\n"
|
||||
"\n"
|
||||
"tech = RBA::NetTracerTechnology::new\n"
|
||||
"tech = RBA::NetTracerConnectivity::new\n"
|
||||
"tech.connection(\"1/0\", \"2/0\", \"3/0\")\n"
|
||||
"\n"
|
||||
"tracer.trace(tech, ly, ly.top_cell, RBA::Point::new(7000, 1500), ly.find_layer(1, 0))\n"
|
||||
|
|
@ -277,7 +344,7 @@ gsi::Class<db::NetTracer> decl_NetTracer ("db", "NetTracer",
|
|||
"end\n"
|
||||
"@/code\n"
|
||||
"\n"
|
||||
"This class has been introduced in version 0.25."
|
||||
"This class has been introduced in version 0.25. With version 0.28, the \\NetTracerConnectivity class replaces the 'NetTracerTechnology' class."
|
||||
);
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,343 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>NetTracerConnectivityEditor</class>
|
||||
<widget class="QWidget" name="NetTracerConnectivityEditor">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>572</width>
|
||||
<height>449</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Form</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout">
|
||||
<property name="spacing">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="margin" stdset="0">
|
||||
<number>9</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QSplitter" name="splitter">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<widget class="QFrame" name="frame_6">
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::NoFrame</enum>
|
||||
</property>
|
||||
<property name="frameShadow">
|
||||
<enum>QFrame::Raised</enum>
|
||||
</property>
|
||||
<layout class="QVBoxLayout">
|
||||
<property name="spacing">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="margin" stdset="0">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QFrame" name="frame_2">
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::NoFrame</enum>
|
||||
</property>
|
||||
<property name="frameShadow">
|
||||
<enum>QFrame::Raised</enum>
|
||||
</property>
|
||||
<layout class="QHBoxLayout">
|
||||
<property name="spacing">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="margin" stdset="0">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLabel" name="help_label">
|
||||
<property name="text">
|
||||
<string><html>Connectivity (<a href="int:/about/connectivity.xml">See here for details</a>)</html></string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QFrame" name="frame_5">
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::NoFrame</enum>
|
||||
</property>
|
||||
<property name="frameShadow">
|
||||
<enum>QFrame::Raised</enum>
|
||||
</property>
|
||||
<layout class="QGridLayout">
|
||||
<property name="margin" stdset="0">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="spacing">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item row="3" column="1">
|
||||
<widget class="QToolButton" name="move_conductor_down_pb">
|
||||
<property name="text">
|
||||
<string>...</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../../../../icons/icons.qrc">
|
||||
<normaloff>:/down_16px.png</normaloff>:/down_16px.png</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QToolButton" name="del_conductor_pb">
|
||||
<property name="text">
|
||||
<string>...</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../../../../icons/icons.qrc">
|
||||
<normaloff>:/del_16px.png</normaloff>:/del_16px.png</iconset>
|
||||
</property>
|
||||
<property name="shortcut">
|
||||
<string>Del</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0" rowspan="5">
|
||||
<widget class="QTableWidget" name="connectivity_table">
|
||||
<property name="editTriggers">
|
||||
<set>QAbstractItemView::AllEditTriggers</set>
|
||||
</property>
|
||||
<property name="alternatingRowColors">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="selectionBehavior">
|
||||
<enum>QAbstractItemView::SelectRows</enum>
|
||||
</property>
|
||||
<property name="columnCount">
|
||||
<number>3</number>
|
||||
</property>
|
||||
<column/>
|
||||
<column/>
|
||||
<column/>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QToolButton" name="add_conductor_pb">
|
||||
<property name="text">
|
||||
<string>...</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../../../../icons/icons.qrc">
|
||||
<normaloff>:/add_16px.png</normaloff>:/add_16px.png</iconset>
|
||||
</property>
|
||||
<property name="shortcut">
|
||||
<string>Return</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
<spacer>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>131</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QToolButton" name="move_conductor_up_pb">
|
||||
<property name="text">
|
||||
<string>...</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../../../../icons/icons.qrc">
|
||||
<normaloff>:/up_16px.png</normaloff>:/up_16px.png</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QFrame" name="frame_4">
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::NoFrame</enum>
|
||||
</property>
|
||||
<property name="frameShadow">
|
||||
<enum>QFrame::Raised</enum>
|
||||
</property>
|
||||
<layout class="QVBoxLayout">
|
||||
<property name="spacing">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="margin" stdset="0">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QFrame" name="frame_3">
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::NoFrame</enum>
|
||||
</property>
|
||||
<property name="frameShadow">
|
||||
<enum>QFrame::Raised</enum>
|
||||
</property>
|
||||
<layout class="QHBoxLayout">
|
||||
<property name="spacing">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="margin" stdset="0">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLabel" name="symbol_help_label">
|
||||
<property name="text">
|
||||
<string><html>Computed and symbolic layers (<a href="int:/about/symbolic_layers.xml">See here for details</a>)</html></string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QFrame" name="frame">
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::NoFrame</enum>
|
||||
</property>
|
||||
<property name="frameShadow">
|
||||
<enum>QFrame::Raised</enum>
|
||||
</property>
|
||||
<layout class="QGridLayout">
|
||||
<property name="margin" stdset="0">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="spacing">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item row="3" column="1">
|
||||
<widget class="QToolButton" name="move_symbol_down_pb">
|
||||
<property name="text">
|
||||
<string>...</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../../../../icons/icons.qrc">
|
||||
<normaloff>:/down_16px.png</normaloff>:/down_16px.png</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QToolButton" name="del_symbol_pb">
|
||||
<property name="text">
|
||||
<string>...</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../../../../icons/icons.qrc">
|
||||
<normaloff>:/del_16px.png</normaloff>:/del_16px.png</iconset>
|
||||
</property>
|
||||
<property name="shortcut">
|
||||
<string>Del</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0" rowspan="5">
|
||||
<widget class="QTableWidget" name="symbol_table">
|
||||
<property name="editTriggers">
|
||||
<set>QAbstractItemView::AllEditTriggers</set>
|
||||
</property>
|
||||
<property name="alternatingRowColors">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="selectionBehavior">
|
||||
<enum>QAbstractItemView::SelectRows</enum>
|
||||
</property>
|
||||
<property name="columnCount">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<column/>
|
||||
<column/>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QToolButton" name="add_symbol_pb">
|
||||
<property name="text">
|
||||
<string>...</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../../../../icons/icons.qrc">
|
||||
<normaloff>:/add_16px.png</normaloff>:/add_16px.png</iconset>
|
||||
</property>
|
||||
<property name="shortcut">
|
||||
<string>Return</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
<spacer>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>131</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QToolButton" name="move_symbol_up_pb">
|
||||
<property name="text">
|
||||
<string>...</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../../../../icons/icons.qrc">
|
||||
<normaloff>:/up_16px.png</normaloff>:/up_16px.png</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources>
|
||||
<include location="../../../../icons/icons.qrc"/>
|
||||
</resources>
|
||||
<connections/>
|
||||
</ui>
|
||||
|
|
@ -29,24 +29,14 @@
|
|||
<property name="spacing">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item row="3" column="0" rowspan="2" colspan="8">
|
||||
<item row="3" column="0" rowspan="2" colspan="9">
|
||||
<widget class="Line" name="line">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="0" rowspan="2">
|
||||
<widget class="QPushButton" name="configure_pb">
|
||||
<property name="text">
|
||||
<string>Configure</string>
|
||||
</property>
|
||||
<property name="autoDefault">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0" colspan="8">
|
||||
<item row="1" column="0" colspan="9">
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Minimum">
|
||||
|
|
@ -67,7 +57,7 @@ Select one or multiple nets and choose "Export" to export the selected
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="7">
|
||||
<item row="2" column="8">
|
||||
<widget class="QFrame" name="frame">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
|
|
@ -196,60 +186,7 @@ Select one or multiple nets and choose "Export" to export the selected
|
|||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="2">
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::Fixed</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>5</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="5" column="3" rowspan="2">
|
||||
<widget class="QLabel" name="label_5">
|
||||
<property name="text">
|
||||
<string>Trace depth:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="7" rowspan="2">
|
||||
<widget class="QPushButton" name="close_pb">
|
||||
<property name="text">
|
||||
<string>Close</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="6" rowspan="2">
|
||||
<widget class="QLabel" name="tech_info_label">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>1</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="1" rowspan="2">
|
||||
<widget class="QPushButton" name="stack_pb">
|
||||
<property name="text">
|
||||
<string>Layer Stack</string>
|
||||
</property>
|
||||
<property name="autoDefault">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0" colspan="7">
|
||||
<item row="2" column="0" colspan="8">
|
||||
<widget class="QSplitter" name="splitter">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
|
||||
|
|
@ -332,7 +269,6 @@ Select one or multiple nets and choose "Export" to export the selected
|
|||
<property name="font">
|
||||
<font>
|
||||
<pointsize>12</pointsize>
|
||||
<weight>75</weight>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
|
|
@ -477,7 +413,23 @@ p, li { white-space: pre-wrap; }
|
|||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0" colspan="8">
|
||||
<item row="5" column="3">
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::Fixed</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>5</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="0" column="0" colspan="9">
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Minimum">
|
||||
|
|
@ -488,7 +440,6 @@ p, li { white-space: pre-wrap; }
|
|||
<property name="font">
|
||||
<font>
|
||||
<pointsize>12</pointsize>
|
||||
<weight>75</weight>
|
||||
<italic>false</italic>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
|
|
@ -498,14 +449,54 @@ p, li { white-space: pre-wrap; }
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="5" rowspan="2">
|
||||
<item row="5" column="2">
|
||||
<widget class="QComboBox" name="stack_selector">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Ignored">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="sizeAdjustPolicy">
|
||||
<enum>QComboBox::AdjustToContents</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="1">
|
||||
<widget class="QPushButton" name="stack_pb">
|
||||
<property name="text">
|
||||
<string>Layer Stack</string>
|
||||
</property>
|
||||
<property name="autoDefault">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="0">
|
||||
<widget class="QPushButton" name="configure_pb">
|
||||
<property name="text">
|
||||
<string>Configure</string>
|
||||
</property>
|
||||
<property name="autoDefault">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="8">
|
||||
<widget class="QPushButton" name="close_pb">
|
||||
<property name="text">
|
||||
<string>Close</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="6">
|
||||
<widget class="QLabel" name="label_6">
|
||||
<property name="text">
|
||||
<string>shapes</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="4" rowspan="2">
|
||||
<item row="5" column="5">
|
||||
<widget class="QLineEdit" name="depth_le">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
|
|
@ -521,6 +512,26 @@ p, li { white-space: pre-wrap; }
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="4">
|
||||
<widget class="QLabel" name="label_5">
|
||||
<property name="text">
|
||||
<string>Trace depth:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="7">
|
||||
<widget class="QLabel" name="tech_info_label">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>1</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
|
|
|
|||
|
|
@ -1,7 +1,8 @@
|
|||
<ui version="4.0" >
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>NetTracerTechComponentEditor</class>
|
||||
<widget class="QWidget" name="NetTracerTechComponentEditor" >
|
||||
<property name="geometry" >
|
||||
<widget class="QWidget" name="NetTracerTechComponentEditor">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
|
|
@ -9,324 +10,265 @@
|
|||
<height>449</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle" >
|
||||
<property name="windowTitle">
|
||||
<string>Form</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" >
|
||||
<property name="margin" >
|
||||
<number>9</number>
|
||||
</property>
|
||||
<property name="spacing" >
|
||||
<number>6</number>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<item>
|
||||
<widget class="QSplitter" name="splitter" >
|
||||
<property name="orientation" >
|
||||
<enum>Qt::Vertical</enum>
|
||||
<widget class="QSplitter" name="splitter">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<widget class="QFrame" name="frame_6" >
|
||||
<property name="frameShape" >
|
||||
<widget class="QFrame" name="frame_5">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::NoFrame</enum>
|
||||
</property>
|
||||
<property name="frameShadow" >
|
||||
<property name="frameShadow">
|
||||
<enum>QFrame::Raised</enum>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" >
|
||||
<property name="margin" >
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="spacing" >
|
||||
<number>6</number>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QFrame" name="frame_2" >
|
||||
<property name="frameShape" >
|
||||
<enum>QFrame::NoFrame</enum>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item row="4" column="5">
|
||||
<widget class="QToolButton" name="move_down_pb">
|
||||
<property name="toolTip">
|
||||
<string>Move selected stacks up</string>
|
||||
</property>
|
||||
<property name="frameShadow" >
|
||||
<enum>QFrame::Raised</enum>
|
||||
<property name="text">
|
||||
<string>...</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../../../../icons/icons.qrc">
|
||||
<normaloff>:/down_16px.png</normaloff>:/down_16px.png</iconset>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" >
|
||||
<property name="margin" >
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="spacing" >
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLabel" name="help_label" >
|
||||
<property name="text" >
|
||||
<string><html>Connectivity (<a href="int:/about/connectivity.xml">See here for details</a>)</html></string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer>
|
||||
<property name="orientation" >
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" >
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QFrame" name="frame_5" >
|
||||
<property name="frameShape" >
|
||||
<item row="4" column="0" colspan="2">
|
||||
<widget class="QToolButton" name="add_pb">
|
||||
<property name="toolTip">
|
||||
<string>Add new stack</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>...</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../../../../icons/icons.qrc">
|
||||
<normaloff>:/add_16px.png</normaloff>:/add_16px.png</iconset>
|
||||
</property>
|
||||
<property name="shortcut">
|
||||
<string>Return</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1" colspan="6">
|
||||
<widget class="QFrame" name="frame_2">
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::NoFrame</enum>
|
||||
</property>
|
||||
<property name="frameShadow" >
|
||||
<property name="frameShadow">
|
||||
<enum>QFrame::Raised</enum>
|
||||
</property>
|
||||
<layout class="QGridLayout" >
|
||||
<property name="margin" >
|
||||
<number>0</number>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0" rowspan="2" colspan="7">
|
||||
<widget class="QTreeWidget" name="stack_tree">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>1</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="contextMenuPolicy">
|
||||
<enum>Qt::ActionsContextMenu</enum>
|
||||
</property>
|
||||
<property name="selectionMode">
|
||||
<enum>QAbstractItemView::ExtendedSelection</enum>
|
||||
</property>
|
||||
<property name="rootIsDecorated">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="allColumnsShowFocus">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Name</string>
|
||||
</property>
|
||||
<property name="spacing" >
|
||||
<number>6</number>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Description</string>
|
||||
</property>
|
||||
<item row="3" column="1" >
|
||||
<widget class="QToolButton" name="move_conductor_down_pb" >
|
||||
<property name="text" >
|
||||
<string>...</string>
|
||||
</property>
|
||||
<property name="icon" >
|
||||
<iconset resource="layResources.qrc" >:/down_16px.png</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1" >
|
||||
<widget class="QToolButton" name="del_conductor_pb" >
|
||||
<property name="text" >
|
||||
<string>...</string>
|
||||
</property>
|
||||
<property name="icon" >
|
||||
<iconset resource="layResources.qrc" >:/del_16px.png</iconset>
|
||||
</property>
|
||||
<property name="shortcut" >
|
||||
<string>Del</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item rowspan="5" row="0" column="0" >
|
||||
<widget class="QTableWidget" name="connectivity_table" >
|
||||
<property name="editTriggers" >
|
||||
<set>QAbstractItemView::AllEditTriggers</set>
|
||||
</property>
|
||||
<property name="alternatingRowColors" >
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="selectionBehavior" >
|
||||
<enum>QAbstractItemView::SelectRows</enum>
|
||||
</property>
|
||||
<property name="columnCount" >
|
||||
<number>3</number>
|
||||
</property>
|
||||
<column/>
|
||||
<column/>
|
||||
<column/>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1" >
|
||||
<widget class="QToolButton" name="add_conductor_pb" >
|
||||
<property name="text" >
|
||||
<string>...</string>
|
||||
</property>
|
||||
<property name="icon" >
|
||||
<iconset resource="layResources.qrc" >:/add_16px.png</iconset>
|
||||
</property>
|
||||
<property name="shortcut" >
|
||||
<string>Return</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1" >
|
||||
<spacer>
|
||||
<property name="orientation" >
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" >
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>131</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="2" column="1" >
|
||||
<widget class="QToolButton" name="move_conductor_up_pb" >
|
||||
<property name="text" >
|
||||
<string>...</string>
|
||||
</property>
|
||||
<property name="icon" >
|
||||
<iconset resource="layResources.qrc" >:/up_16px.png</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</column>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="3">
|
||||
<widget class="QToolButton" name="del_pb">
|
||||
<property name="toolTip">
|
||||
<string>Remove selected stacks</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>...</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../../../../icons/icons.qrc">
|
||||
<normaloff>:/del_16px.png</normaloff>:/del_16px.png</iconset>
|
||||
</property>
|
||||
<property name="shortcut">
|
||||
<string>Del</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="4">
|
||||
<widget class="QToolButton" name="move_up_pb">
|
||||
<property name="toolTip">
|
||||
<string>Move selected stacks down</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>...</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../../../../icons/icons.qrc">
|
||||
<normaloff>:/up_16px.png</normaloff>:/up_16px.png</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0" colspan="7">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="font">
|
||||
<font>
|
||||
<italic>true</italic>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Double-click to edit text</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="6">
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>157</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="0" column="0" colspan="7">
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>Technology Stacks</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="2">
|
||||
<widget class="QToolButton" name="clone_pb">
|
||||
<property name="toolTip">
|
||||
<string>Clone current stack</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>...</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../../../../icons/icons.qrc">
|
||||
<normaloff>:/clone_16px.png</normaloff>:/clone_16px.png</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QFrame" name="frame_4" >
|
||||
<property name="frameShape" >
|
||||
<widget class="QFrame" name="frame">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>1</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::NoFrame</enum>
|
||||
</property>
|
||||
<property name="frameShadow" >
|
||||
<property name="frameShadow">
|
||||
<enum>QFrame::Raised</enum>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" >
|
||||
<property name="margin" >
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="spacing" >
|
||||
<number>6</number>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QFrame" name="frame_3" >
|
||||
<property name="frameShape" >
|
||||
<enum>QFrame::NoFrame</enum>
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="text">
|
||||
<string>Connectivity</string>
|
||||
</property>
|
||||
<property name="frameShadow" >
|
||||
<enum>QFrame::Raised</enum>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" >
|
||||
<property name="margin" >
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="spacing" >
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLabel" name="symbol_help_label" >
|
||||
<property name="text" >
|
||||
<string><html>Computed and symbolic layers (<a href="int:/about/symbolic_layers.xml">See here for details</a>)</html></string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer>
|
||||
<property name="orientation" >
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" >
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QFrame" name="frame" >
|
||||
<property name="frameShape" >
|
||||
<enum>QFrame::NoFrame</enum>
|
||||
<widget class="lay::NetTracerConnectivityEditor" name="connectivity_editor_widget" native="true">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>1</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="frameShadow" >
|
||||
<enum>QFrame::Raised</enum>
|
||||
</property>
|
||||
<layout class="QGridLayout" >
|
||||
<property name="margin" >
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="spacing" >
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item row="3" column="1" >
|
||||
<widget class="QToolButton" name="move_symbol_down_pb" >
|
||||
<property name="text" >
|
||||
<string>...</string>
|
||||
</property>
|
||||
<property name="icon" >
|
||||
<iconset resource="layResources.qrc" >:/down_16px.png</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1" >
|
||||
<widget class="QToolButton" name="del_symbol_pb" >
|
||||
<property name="text" >
|
||||
<string>...</string>
|
||||
</property>
|
||||
<property name="icon" >
|
||||
<iconset resource="layResources.qrc" >:/del_16px.png</iconset>
|
||||
</property>
|
||||
<property name="shortcut" >
|
||||
<string>Del</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item rowspan="5" row="0" column="0" >
|
||||
<widget class="QTableWidget" name="symbol_table" >
|
||||
<property name="editTriggers" >
|
||||
<set>QAbstractItemView::AllEditTriggers</set>
|
||||
</property>
|
||||
<property name="alternatingRowColors" >
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="selectionBehavior" >
|
||||
<enum>QAbstractItemView::SelectRows</enum>
|
||||
</property>
|
||||
<property name="columnCount" >
|
||||
<number>2</number>
|
||||
</property>
|
||||
<column/>
|
||||
<column/>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1" >
|
||||
<widget class="QToolButton" name="add_symbol_pb" >
|
||||
<property name="text" >
|
||||
<string>...</string>
|
||||
</property>
|
||||
<property name="icon" >
|
||||
<iconset resource="layResources.qrc" >:/add_16px.png</iconset>
|
||||
</property>
|
||||
<property name="shortcut" >
|
||||
<string>Return</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1" >
|
||||
<spacer>
|
||||
<property name="orientation" >
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" >
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>131</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="2" column="1" >
|
||||
<widget class="QToolButton" name="move_symbol_up_pb" >
|
||||
<property name="text" >
|
||||
<string>...</string>
|
||||
</property>
|
||||
<property name="icon" >
|
||||
<iconset resource="layResources.qrc" >:/up_16px.png</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>lay::NetTracerConnectivityEditor</class>
|
||||
<extends>QWidget</extends>
|
||||
<header>layNetTracerConnectivityEditor.h</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources>
|
||||
<include location="../../../../icons/icons.qrc"/>
|
||||
</resources>
|
||||
<connections/>
|
||||
</ui>
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@
|
|||
*/
|
||||
|
||||
|
||||
#include "layNetTracerIO.h"
|
||||
#include "layNetTracerConnectivityEditor.h"
|
||||
#include "layNetTracerConfig.h"
|
||||
|
||||
#include "layConfigurationDialog.h"
|
||||
|
|
@ -56,7 +56,7 @@ class NetTracerConnectivityColumnDelegate
|
|||
: public QItemDelegate
|
||||
{
|
||||
public:
|
||||
NetTracerConnectivityColumnDelegate (QWidget *parent, db::NetTracerTechnologyComponent *data)
|
||||
NetTracerConnectivityColumnDelegate (QWidget *parent, db::NetTracerConnectivity *data)
|
||||
: QItemDelegate (parent), mp_data (data)
|
||||
{
|
||||
// .. nothing yet ..
|
||||
|
|
@ -148,7 +148,7 @@ public:
|
|||
}
|
||||
|
||||
private:
|
||||
db::NetTracerTechnologyComponent *mp_data;
|
||||
db::NetTracerConnectivity *mp_data;
|
||||
};
|
||||
|
||||
// -----------------------------------------------------------------------------------------
|
||||
|
|
@ -158,7 +158,7 @@ class NetTracerConnectivitySymbolColumnDelegate
|
|||
: public QItemDelegate
|
||||
{
|
||||
public:
|
||||
NetTracerConnectivitySymbolColumnDelegate (QWidget *parent, db::NetTracerTechnologyComponent *data)
|
||||
NetTracerConnectivitySymbolColumnDelegate (QWidget *parent, db::NetTracerConnectivity *data)
|
||||
: QItemDelegate (parent), mp_data (data)
|
||||
{
|
||||
// .. nothing yet ..
|
||||
|
|
@ -262,16 +262,16 @@ public:
|
|||
}
|
||||
|
||||
private:
|
||||
db::NetTracerTechnologyComponent *mp_data;
|
||||
db::NetTracerConnectivity *mp_data;
|
||||
};
|
||||
|
||||
// -----------------------------------------------------------------------------------
|
||||
// NetTracerTechComponentEditor implementation
|
||||
|
||||
NetTracerTechComponentEditor::NetTracerTechComponentEditor (QWidget *parent)
|
||||
: TechnologyComponentEditor (parent)
|
||||
NetTracerConnectivityEditor::NetTracerConnectivityEditor (QWidget *parent)
|
||||
: QWidget (parent)
|
||||
{
|
||||
Ui::NetTracerTechComponentEditor::setupUi (this);
|
||||
Ui::NetTracerConnectivityEditor::setupUi (this);
|
||||
|
||||
connect (add_conductor_pb, SIGNAL (clicked ()), this, SLOT (add_clicked ()));
|
||||
connect (del_conductor_pb, SIGNAL (clicked ()), this, SLOT (del_clicked ()));
|
||||
|
|
@ -293,26 +293,20 @@ NetTracerTechComponentEditor::NetTracerTechComponentEditor (QWidget *parent)
|
|||
symbol_table->verticalHeader ()->hide ();
|
||||
}
|
||||
|
||||
void
|
||||
NetTracerTechComponentEditor::commit ()
|
||||
void
|
||||
NetTracerConnectivityEditor::get_connectivity (db::NetTracerConnectivity &data)
|
||||
{
|
||||
db::NetTracerTechnologyComponent *data = dynamic_cast <db::NetTracerTechnologyComponent *> (tech_component ());
|
||||
if (! data) {
|
||||
return;
|
||||
}
|
||||
|
||||
*data = m_data;
|
||||
std::string name = data.name ();
|
||||
std::string description = data.description ();
|
||||
data = m_data;
|
||||
data.set_name (name);
|
||||
data.set_description (description);
|
||||
}
|
||||
|
||||
void
|
||||
NetTracerTechComponentEditor::setup ()
|
||||
NetTracerConnectivityEditor::set_connectivity (const db::NetTracerConnectivity &data)
|
||||
{
|
||||
db::NetTracerTechnologyComponent *data = dynamic_cast <db::NetTracerTechnologyComponent *> (tech_component ());
|
||||
if (! data) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_data = *data;
|
||||
m_data = data;
|
||||
|
||||
for (int c = 0; c < 3; ++c) {
|
||||
if (connectivity_table->itemDelegateForColumn (c) != 0) {
|
||||
|
|
@ -332,7 +326,7 @@ NetTracerTechComponentEditor::setup ()
|
|||
}
|
||||
|
||||
void
|
||||
NetTracerTechComponentEditor::add_clicked ()
|
||||
NetTracerConnectivityEditor::add_clicked ()
|
||||
{
|
||||
// removes focus from the tree view - commits the data
|
||||
add_conductor_pb->setFocus ();
|
||||
|
|
@ -351,7 +345,7 @@ NetTracerTechComponentEditor::add_clicked ()
|
|||
}
|
||||
|
||||
void
|
||||
NetTracerTechComponentEditor::del_clicked ()
|
||||
NetTracerConnectivityEditor::del_clicked ()
|
||||
{
|
||||
// removes focus from the tree view - commits the data
|
||||
del_conductor_pb->setFocus ();
|
||||
|
|
@ -374,7 +368,7 @@ NetTracerTechComponentEditor::del_clicked ()
|
|||
}
|
||||
|
||||
void
|
||||
NetTracerTechComponentEditor::move_up_clicked ()
|
||||
NetTracerConnectivityEditor::move_up_clicked ()
|
||||
{
|
||||
// removes focus from the tree view - commits the data
|
||||
move_conductor_up_pb->setFocus ();
|
||||
|
|
@ -391,7 +385,7 @@ NetTracerTechComponentEditor::move_up_clicked ()
|
|||
connectivity_table->setCurrentIndex (QModelIndex ());
|
||||
|
||||
int n = 0;
|
||||
for (db::NetTracerTechnologyComponent::iterator l = m_data.begin (); l != m_data.end (); ++l, ++n) {
|
||||
for (db::NetTracerConnectivity::iterator l = m_data.begin (); l != m_data.end (); ++l, ++n) {
|
||||
if (selected_rows.find (n + 1) != selected_rows.end () && selected_rows.find (n) == selected_rows.end ()) {
|
||||
std::swap (m_data.begin () [n + 1], m_data.begin () [n]);
|
||||
selected_rows.erase (n + 1);
|
||||
|
|
@ -415,7 +409,7 @@ NetTracerTechComponentEditor::move_up_clicked ()
|
|||
}
|
||||
|
||||
void
|
||||
NetTracerTechComponentEditor::move_down_clicked ()
|
||||
NetTracerConnectivityEditor::move_down_clicked ()
|
||||
{
|
||||
// removes focus from the tree view - commits the data
|
||||
move_conductor_down_pb->setFocus ();
|
||||
|
|
@ -432,7 +426,7 @@ NetTracerTechComponentEditor::move_down_clicked ()
|
|||
connectivity_table->setCurrentIndex (QModelIndex ());
|
||||
|
||||
int n = int (m_data.size ());
|
||||
for (db::NetTracerTechnologyComponent::iterator l = m_data.end (); l != m_data.begin (); ) {
|
||||
for (db::NetTracerConnectivity::iterator l = m_data.end (); l != m_data.begin (); ) {
|
||||
--l;
|
||||
--n;
|
||||
if (selected_rows.find (n - 1) != selected_rows.end () && selected_rows.find (n) == selected_rows.end ()) {
|
||||
|
|
@ -458,7 +452,7 @@ NetTracerTechComponentEditor::move_down_clicked ()
|
|||
}
|
||||
|
||||
void
|
||||
NetTracerTechComponentEditor::symbol_add_clicked ()
|
||||
NetTracerConnectivityEditor::symbol_add_clicked ()
|
||||
{
|
||||
// removes focus from the tree view - commits the data
|
||||
add_symbol_pb->setFocus ();
|
||||
|
|
@ -477,7 +471,7 @@ NetTracerTechComponentEditor::symbol_add_clicked ()
|
|||
}
|
||||
|
||||
void
|
||||
NetTracerTechComponentEditor::symbol_del_clicked ()
|
||||
NetTracerConnectivityEditor::symbol_del_clicked ()
|
||||
{
|
||||
// removes focus from the tree view - commits the data
|
||||
del_symbol_pb->setFocus ();
|
||||
|
|
@ -500,7 +494,7 @@ NetTracerTechComponentEditor::symbol_del_clicked ()
|
|||
}
|
||||
|
||||
void
|
||||
NetTracerTechComponentEditor::symbol_move_up_clicked ()
|
||||
NetTracerConnectivityEditor::symbol_move_up_clicked ()
|
||||
{
|
||||
// removes focus from the tree view - commits the data
|
||||
move_symbol_up_pb->setFocus ();
|
||||
|
|
@ -517,7 +511,7 @@ NetTracerTechComponentEditor::symbol_move_up_clicked ()
|
|||
symbol_table->setCurrentIndex (QModelIndex ());
|
||||
|
||||
int n = 0;
|
||||
for (db::NetTracerTechnologyComponent::symbol_iterator l = m_data.begin_symbols (); l != m_data.end_symbols (); ++l, ++n) {
|
||||
for (db::NetTracerConnectivity::symbol_iterator l = m_data.begin_symbols (); l != m_data.end_symbols (); ++l, ++n) {
|
||||
if (selected_rows.find (n + 1) != selected_rows.end () && selected_rows.find (n) == selected_rows.end ()) {
|
||||
std::swap (m_data.begin_symbols () [n + 1], m_data.begin_symbols () [n]);
|
||||
selected_rows.erase (n + 1);
|
||||
|
|
@ -541,7 +535,7 @@ NetTracerTechComponentEditor::symbol_move_up_clicked ()
|
|||
}
|
||||
|
||||
void
|
||||
NetTracerTechComponentEditor::symbol_move_down_clicked ()
|
||||
NetTracerConnectivityEditor::symbol_move_down_clicked ()
|
||||
{
|
||||
// removes focus from the tree view - commits the data
|
||||
move_symbol_down_pb->setFocus ();
|
||||
|
|
@ -558,7 +552,7 @@ NetTracerTechComponentEditor::symbol_move_down_clicked ()
|
|||
symbol_table->setCurrentIndex (QModelIndex ());
|
||||
|
||||
int n = int (m_data.symbols ());
|
||||
for (db::NetTracerTechnologyComponent::symbol_iterator l = m_data.end_symbols (); l != m_data.begin_symbols (); ) {
|
||||
for (db::NetTracerConnectivity::symbol_iterator l = m_data.end_symbols (); l != m_data.begin_symbols (); ) {
|
||||
--l;
|
||||
--n;
|
||||
if (selected_rows.find (n - 1) != selected_rows.end () && selected_rows.find (n) == selected_rows.end ()) {
|
||||
|
|
@ -584,7 +578,7 @@ NetTracerTechComponentEditor::symbol_move_down_clicked ()
|
|||
}
|
||||
|
||||
void
|
||||
NetTracerTechComponentEditor::update ()
|
||||
NetTracerConnectivityEditor::update ()
|
||||
{
|
||||
QStringList labels;
|
||||
int n;
|
||||
|
|
@ -600,7 +594,7 @@ NetTracerTechComponentEditor::update ()
|
|||
connectivity_table->setHorizontalHeaderLabels (labels);
|
||||
|
||||
n = 0;
|
||||
for (db::NetTracerTechnologyComponent::iterator l = m_data.begin (); l != m_data.end (); ++l, ++n) {
|
||||
for (db::NetTracerConnectivity::iterator l = m_data.begin (); l != m_data.end (); ++l, ++n) {
|
||||
|
||||
for (int c = 0; c < 3; ++c) {
|
||||
|
||||
|
|
@ -652,7 +646,7 @@ NetTracerTechComponentEditor::update ()
|
|||
symbol_table->setHorizontalHeaderLabels (labels);
|
||||
|
||||
n = 0;
|
||||
for (db::NetTracerTechnologyComponent::symbol_iterator l = m_data.begin_symbols (); l != m_data.end_symbols (); ++l, ++n) {
|
||||
for (db::NetTracerConnectivity::symbol_iterator l = m_data.begin_symbols (); l != m_data.end_symbols (); ++l, ++n) {
|
||||
|
||||
for (int c = 0; c < 2; ++c) {
|
||||
|
||||
|
|
@ -0,0 +1,82 @@
|
|||
|
||||
/*
|
||||
|
||||
KLayout Layout Viewer
|
||||
Copyright (C) 2006-2022 Matthias Koefferlein
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#ifndef HDR_layNetTracerConnectivityEditor
|
||||
#define HDR_layNetTracerConnectivityEditor
|
||||
|
||||
#include "ui_NetTracerConnectivityEditor.h"
|
||||
|
||||
#include "dbNetTracer.h"
|
||||
#include "dbNetTracerIO.h"
|
||||
#include "dbTechnology.h"
|
||||
|
||||
#include "layNetTracerConfig.h"
|
||||
#include "layBrowser.h"
|
||||
#include "layPlugin.h"
|
||||
#include "layViewObject.h"
|
||||
#include "layMarker.h"
|
||||
#include "layTechnology.h"
|
||||
|
||||
#include "tlObject.h"
|
||||
|
||||
namespace db
|
||||
{
|
||||
class NetTracerConnectivity;
|
||||
}
|
||||
|
||||
namespace lay
|
||||
{
|
||||
|
||||
class NetTracerConnectivityEditor
|
||||
: public QWidget,
|
||||
public Ui::NetTracerConnectivityEditor
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
NetTracerConnectivityEditor (QWidget *parent);
|
||||
|
||||
void set_connectivity (const db::NetTracerConnectivity &data);
|
||||
void get_connectivity (db::NetTracerConnectivity &);
|
||||
|
||||
public slots:
|
||||
void add_clicked ();
|
||||
void del_clicked ();
|
||||
void move_up_clicked ();
|
||||
void move_down_clicked ();
|
||||
void symbol_add_clicked ();
|
||||
void symbol_del_clicked ();
|
||||
void symbol_move_up_clicked ();
|
||||
void symbol_move_down_clicked ();
|
||||
|
||||
private:
|
||||
db::NetTracerConnectivity m_data;
|
||||
|
||||
void update ();
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
|
@ -92,7 +92,9 @@ NetTracerDialog::NetTracerDialog (lay::Dispatcher *root, LayoutViewBase *view)
|
|||
|
||||
view->layer_list_changed_event.add (this, &NetTracerDialog::layer_list_changed);
|
||||
|
||||
attach_events ();
|
||||
update_info ();
|
||||
update_list_of_stacks ();
|
||||
}
|
||||
|
||||
NetTracerDialog::~NetTracerDialog ()
|
||||
|
|
@ -101,6 +103,69 @@ NetTracerDialog::~NetTracerDialog ()
|
|||
clear_nets ();
|
||||
}
|
||||
|
||||
void
|
||||
NetTracerDialog::attach_events ()
|
||||
{
|
||||
detach_from_all_events ();
|
||||
|
||||
mp_view->layer_list_changed_event.add (this, &NetTracerDialog::layer_list_changed);
|
||||
|
||||
db::Technologies::instance ()->technology_changed_event.add (this, &NetTracerDialog::update_list_of_stacks_with_technology);
|
||||
db::Technologies::instance ()->technologies_changed_event.add (this, &NetTracerDialog::update_list_of_stacks);
|
||||
|
||||
mp_view->cellviews_changed_event.add (this, &NetTracerDialog::update_list_of_stacks);
|
||||
mp_view->apply_technology_event.add (this, &NetTracerDialog::update_list_of_stacks_with_cellview);
|
||||
}
|
||||
|
||||
void
|
||||
NetTracerDialog::update_list_of_stacks_with_technology (db::Technology *)
|
||||
{
|
||||
update_list_of_stacks ();
|
||||
}
|
||||
|
||||
void
|
||||
NetTracerDialog::update_list_of_stacks_with_cellview (int)
|
||||
{
|
||||
update_list_of_stacks ();
|
||||
}
|
||||
|
||||
void
|
||||
NetTracerDialog::update_list_of_stacks ()
|
||||
{
|
||||
QString current_name = stack_selector->currentText ();
|
||||
|
||||
std::set<QString> names;
|
||||
for (unsigned int cvi = 0; cvi < mp_view->cellviews (); ++cvi) {
|
||||
const db::Technology *tech = mp_view->cellview (cvi)->technology ();
|
||||
if (tech) {
|
||||
const db::NetTracerTechnologyComponent *tech_component = dynamic_cast <const db::NetTracerTechnologyComponent *> (tech->component_by_name (db::net_tracer_component_name ()));
|
||||
if (tech_component) {
|
||||
for (auto d = tech_component->begin (); d != tech_component->end (); ++d) {
|
||||
names.insert (tl::to_qstring (d->name ()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
stack_selector->clear ();
|
||||
|
||||
int current_index = 0;
|
||||
int i = 0;
|
||||
for (auto n = names.begin (); n != names.end (); ++n, ++i) {
|
||||
if (n->isEmpty ()) {
|
||||
stack_selector->addItem (tr ("(default)"), QVariant (*n));
|
||||
} else {
|
||||
stack_selector->addItem (*n, QVariant (*n));
|
||||
}
|
||||
if (*n == current_name) {
|
||||
current_index = i;
|
||||
}
|
||||
}
|
||||
|
||||
stack_selector->setVisible (stack_selector->count () >= 2);
|
||||
stack_selector->setCurrentIndex (current_index);
|
||||
}
|
||||
|
||||
void
|
||||
NetTracerDialog::clear_nets ()
|
||||
{
|
||||
|
|
@ -290,14 +355,27 @@ NetTracerDialog::get_net_tracer_setup (const lay::CellView &cv, db::NetTracerDat
|
|||
if (! tech) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const db::NetTracerTechnologyComponent *tech_component = dynamic_cast <const db::NetTracerTechnologyComponent *> (tech->component_by_name (db::net_tracer_component_name ()));
|
||||
if (! tech_component) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Set up the net tracer environment
|
||||
data = tech_component->get_tracer_data (cv->layout ());
|
||||
std::string stack_name = tl::to_string (stack_selector->itemData (stack_selector->currentIndex ()).toString ());
|
||||
|
||||
const db::NetTracerConnectivity *connectivity = 0;
|
||||
for (auto d = tech_component->begin (); d != tech_component->end () && ! connectivity; ++d) {
|
||||
if (d->name () == stack_name) {
|
||||
connectivity = d.operator-> ();
|
||||
}
|
||||
}
|
||||
|
||||
if (! connectivity) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Set up the net tracer environment
|
||||
data = connectivity->get_tracer_data (cv->layout ());
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -545,6 +623,7 @@ NetTracerDialog::configure (const std::string &name, const std::string &value)
|
|||
update_highlights ();
|
||||
adjust_view ();
|
||||
update_info ();
|
||||
update_list_of_stacks ();
|
||||
}
|
||||
|
||||
return taken;
|
||||
|
|
@ -1243,6 +1322,7 @@ BEGIN_PROTECTED
|
|||
lay::TechComponentSetupDialog dialog (this, &tech, db::net_tracer_component_name ());
|
||||
if (dialog.exec ()) {
|
||||
*db::Technologies::instance ()->technology_by_name (tech.name ()) = tech;
|
||||
update_list_of_stacks ();
|
||||
}
|
||||
|
||||
END_PROTECTED
|
||||
|
|
|
|||
|
|
@ -112,6 +112,11 @@ private:
|
|||
|
||||
void commit ();
|
||||
size_t get_trace_depth ();
|
||||
void attach_events ();
|
||||
void update_list_of_stacks_with_technology (db::Technology *);
|
||||
void update_list_of_stacks_with_cellview (int);
|
||||
void update_list_of_stacks ();
|
||||
|
||||
void update_highlights ();
|
||||
void adjust_view ();
|
||||
void clear_markers ();
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@
|
|||
|
||||
#include "dbNetTracerIO.h"
|
||||
|
||||
#include "layNetTracerIO.h"
|
||||
#include "layNetTracerTechComponentEditor.h"
|
||||
#include "layNetTracerDialog.h"
|
||||
#include "layNetTracerConfig.h"
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,424 @@
|
|||
|
||||
/*
|
||||
|
||||
KLayout Layout Viewer
|
||||
Copyright (C) 2006-2022 Matthias Koefferlein
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
*/
|
||||
|
||||
|
||||
#include "layNetTracerTechComponentEditor.h"
|
||||
#include "layNetTracerConfig.h"
|
||||
|
||||
#include "layConfigurationDialog.h"
|
||||
#include "laybasicConfig.h"
|
||||
#include "layConverters.h"
|
||||
#include "layFinder.h"
|
||||
#include "layLayoutView.h"
|
||||
#include "layTechSetupDialog.h"
|
||||
#include "layFileDialog.h"
|
||||
#include "layQtTools.h"
|
||||
#include "tlExceptions.h"
|
||||
#include "tlXMLWriter.h"
|
||||
#include "tlUtils.h"
|
||||
#include "gsiDecl.h"
|
||||
|
||||
#include <QMessageBox>
|
||||
#include <QInputDialog>
|
||||
#include <QItemDelegate>
|
||||
#include <QHeaderView>
|
||||
#include <QPainter>
|
||||
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
|
||||
namespace lay
|
||||
{
|
||||
|
||||
// -----------------------------------------------------------------------------------------
|
||||
// NetTracerTechComponentColumnDelegate definition and implementation
|
||||
|
||||
class NetTracerTechComponentColumnDelegate
|
||||
: public QItemDelegate
|
||||
{
|
||||
public:
|
||||
NetTracerTechComponentColumnDelegate (QWidget *parent, db::NetTracerTechnologyComponent *data)
|
||||
: QItemDelegate (parent), mp_data (data)
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
QWidget *createEditor (QWidget *parent, const QStyleOptionViewItem & /*option*/, const QModelIndex & /*index*/) const
|
||||
{
|
||||
return new QLineEdit (parent);
|
||||
}
|
||||
|
||||
void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex & /*index*/) const
|
||||
{
|
||||
editor->setGeometry(option.rect);
|
||||
}
|
||||
|
||||
void setEditorData (QWidget *widget, const QModelIndex &index) const
|
||||
{
|
||||
QLineEdit *editor = dynamic_cast<QLineEdit *> (widget);
|
||||
if (editor) {
|
||||
int n = index.model ()->data (index, Qt::UserRole).toInt ();
|
||||
if (mp_data->size () > size_t (n)) {
|
||||
if (index.column () == 0) {
|
||||
std::string name = mp_data->begin () [n].name ();
|
||||
editor->setText (tl::to_qstring (name));
|
||||
editor->setPlaceholderText (tr ("(default)"));
|
||||
} else if (index.column () == 1) {
|
||||
editor->setText (tl::to_qstring (mp_data->begin () [n].description ()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void setModelData (QWidget *widget, QAbstractItemModel *model, const QModelIndex &index) const
|
||||
{
|
||||
QLineEdit *editor = dynamic_cast<QLineEdit *> (widget);
|
||||
if (editor) {
|
||||
|
||||
int n = model->data (index, Qt::UserRole).toInt ();
|
||||
if (mp_data->size () > size_t (n)) {
|
||||
|
||||
std::string text = tl::to_string (editor->text ());
|
||||
if (index.column () == 0 && text.empty ()) {
|
||||
model->setData (index, QVariant (tr ("(default)")), Qt::DisplayRole);
|
||||
} else {
|
||||
model->setData (index, QVariant (tl::to_qstring (text)), Qt::DisplayRole);
|
||||
}
|
||||
|
||||
if (index.column () == 0) {
|
||||
mp_data->begin () [n].set_name (text);
|
||||
} else if (index.column () == 1) {
|
||||
mp_data->begin () [n].set_description (text);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
QSize sizeHint (const QStyleOptionViewItem &option, const QModelIndex &index) const
|
||||
{
|
||||
QWidget *editor = createEditor (0, option, index);
|
||||
QSize size = editor->sizeHint ();
|
||||
delete editor;
|
||||
return size - QSize (2, 2);
|
||||
}
|
||||
|
||||
private:
|
||||
db::NetTracerTechnologyComponent *mp_data;
|
||||
};
|
||||
|
||||
// -----------------------------------------------------------------------------------
|
||||
// NetTracerTechComponentEditor implementation
|
||||
|
||||
NetTracerTechComponentEditor::NetTracerTechComponentEditor (QWidget *parent)
|
||||
: TechnologyComponentEditor (parent)
|
||||
{
|
||||
Ui::NetTracerTechComponentEditor::setupUi (this);
|
||||
|
||||
QAction *action;
|
||||
action = new QAction (QObject::tr ("Add Stack"), this);
|
||||
connect (action, SIGNAL (triggered ()), this, SLOT (add_clicked ()));
|
||||
stack_tree->addAction (action);
|
||||
action = new QAction (QObject::tr ("Delete Selected Stacks"), this);
|
||||
connect (action, SIGNAL (triggered ()), this, SLOT (delete_clicked ()));
|
||||
stack_tree->addAction (action);
|
||||
action = new QAction (QObject::tr ("Duplicate Stack"), this);
|
||||
connect (action, SIGNAL (triggered ()), this, SLOT (clone_clicked ()));
|
||||
stack_tree->addAction (action);
|
||||
|
||||
connect (add_pb, SIGNAL (clicked ()), this, SLOT (add_clicked ()));
|
||||
connect (del_pb, SIGNAL (clicked ()), this, SLOT (del_clicked ()));
|
||||
connect (clone_pb, SIGNAL (clicked ()), this, SLOT (clone_clicked ()));
|
||||
connect (move_up_pb, SIGNAL (clicked ()), this, SLOT (move_up_clicked ()));
|
||||
connect (move_down_pb, SIGNAL (clicked ()), this, SLOT (move_down_clicked ()));
|
||||
|
||||
stack_tree->header ()->setHighlightSections (false);
|
||||
stack_tree->header ()->setStretchLastSection (true);
|
||||
|
||||
connect (stack_tree, SIGNAL (currentItemChanged(QTreeWidgetItem *, QTreeWidgetItem *)), this, SLOT (current_item_changed(QTreeWidgetItem *, QTreeWidgetItem *)));
|
||||
}
|
||||
|
||||
void
|
||||
NetTracerTechComponentEditor::commit ()
|
||||
{
|
||||
db::NetTracerTechnologyComponent *data = dynamic_cast <db::NetTracerTechnologyComponent *> (tech_component ());
|
||||
if (! data) {
|
||||
return;
|
||||
}
|
||||
|
||||
commit_current ();
|
||||
*data = m_data;
|
||||
}
|
||||
|
||||
void
|
||||
NetTracerTechComponentEditor::setup ()
|
||||
{
|
||||
db::NetTracerTechnologyComponent *data = dynamic_cast <db::NetTracerTechnologyComponent *> (tech_component ());
|
||||
if (! data) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_data = *data;
|
||||
|
||||
if (m_data.size () == 0) {
|
||||
m_data.push_back (db::NetTracerConnectivity ());
|
||||
}
|
||||
|
||||
stack_tree->setItemDelegateForColumn (0, new NetTracerTechComponentColumnDelegate (stack_tree, &m_data));
|
||||
stack_tree->setItemDelegateForColumn (1, new NetTracerTechComponentColumnDelegate (stack_tree, &m_data));
|
||||
|
||||
update ();
|
||||
|
||||
if (stack_tree->topLevelItemCount () > 0) {
|
||||
stack_tree->setCurrentItem (stack_tree->topLevelItem (0));
|
||||
}
|
||||
current_item_changed (stack_tree->currentItem (), 0);
|
||||
}
|
||||
|
||||
void
|
||||
NetTracerTechComponentEditor::current_item_changed (QTreeWidgetItem *current, QTreeWidgetItem *previous)
|
||||
{
|
||||
commit_current (previous);
|
||||
|
||||
int row = current ? stack_tree->indexOfTopLevelItem (current) : -1;
|
||||
if (row < 0 || row >= int (m_data.size ())) {
|
||||
connectivity_editor_widget->set_connectivity (db::NetTracerConnectivity ());
|
||||
connectivity_editor_widget->hide ();
|
||||
} else {
|
||||
connectivity_editor_widget->set_connectivity (m_data.begin ()[row]);
|
||||
connectivity_editor_widget->show ();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
NetTracerTechComponentEditor::commit_current ()
|
||||
{
|
||||
commit_current (stack_tree->currentItem ());
|
||||
}
|
||||
|
||||
void
|
||||
NetTracerTechComponentEditor::commit_current (QTreeWidgetItem *current)
|
||||
{
|
||||
int row = current ? stack_tree->indexOfTopLevelItem (current) : -1;
|
||||
if (row >= 0 && row < int (m_data.size ())) {
|
||||
connectivity_editor_widget->get_connectivity (m_data.begin () [row]);
|
||||
}
|
||||
}
|
||||
|
||||
static std::string
|
||||
new_name (const db::NetTracerTechnologyComponent &data)
|
||||
{
|
||||
for (int i = 1; ; ++i) {
|
||||
std::string n = "STACK" + tl::to_string (i);
|
||||
bool found = false;
|
||||
for (auto d = data.begin (); d != data.end () && ! found; ++d) {
|
||||
found = (d->name () == n);
|
||||
}
|
||||
if (! found) {
|
||||
return n;
|
||||
}
|
||||
}
|
||||
|
||||
return std::string ();
|
||||
}
|
||||
|
||||
void
|
||||
NetTracerTechComponentEditor::clone_clicked ()
|
||||
{
|
||||
// removes focus from the tree view - commits the data
|
||||
add_pb->setFocus ();
|
||||
commit_current ();
|
||||
|
||||
int row = stack_tree->currentItem () ? stack_tree->indexOfTopLevelItem (stack_tree->currentItem ()) : -1;
|
||||
if (row < 0) {
|
||||
m_data.push_back (db::NetTracerConnectivity ());
|
||||
row = int (m_data.size () - 1);
|
||||
} else {
|
||||
row += 1;
|
||||
m_data.insert (m_data.begin () + row, db::NetTracerConnectivity ());
|
||||
m_data.begin ()[row] = m_data.begin ()[row - 1];
|
||||
}
|
||||
|
||||
m_data.begin ()[row].set_name (new_name (m_data));
|
||||
|
||||
update ();
|
||||
stack_tree->setCurrentItem (stack_tree->topLevelItem (row));
|
||||
}
|
||||
|
||||
void
|
||||
NetTracerTechComponentEditor::add_clicked ()
|
||||
{
|
||||
// removes focus from the tree view - commits the data
|
||||
add_pb->setFocus ();
|
||||
commit_current ();
|
||||
|
||||
int row = stack_tree->currentItem () ? stack_tree->indexOfTopLevelItem (stack_tree->currentItem ()) : -1;
|
||||
if (row < 0) {
|
||||
m_data.push_back (db::NetTracerConnectivity ());
|
||||
row = int (m_data.size () - 1);
|
||||
} else {
|
||||
row += 1;
|
||||
m_data.insert (m_data.begin () + row, db::NetTracerConnectivity ());
|
||||
}
|
||||
|
||||
m_data.begin ()[row].set_name (new_name (m_data));
|
||||
|
||||
update ();
|
||||
stack_tree->setCurrentItem (stack_tree->topLevelItem (row));
|
||||
}
|
||||
|
||||
void
|
||||
NetTracerTechComponentEditor::del_clicked ()
|
||||
{
|
||||
// removes focus from the tree view - commits the data
|
||||
del_pb->setFocus ();
|
||||
commit_current ();
|
||||
|
||||
std::set<int> selected_rows;
|
||||
QModelIndexList selected_indices = stack_tree->selectionModel ()->selectedIndexes ();
|
||||
for (auto i = selected_indices.begin (); i != selected_indices.end (); ++i) {
|
||||
selected_rows.insert (i->row ());
|
||||
}
|
||||
|
||||
int offset = 0;
|
||||
for (std::set<int>::const_iterator r = selected_rows.begin (); r != selected_rows.end (); ++r) {
|
||||
m_data.erase (m_data.begin () + (*r - offset));
|
||||
++offset;
|
||||
}
|
||||
|
||||
update ();
|
||||
stack_tree->setCurrentItem (0);
|
||||
}
|
||||
|
||||
void
|
||||
NetTracerTechComponentEditor::move_up_clicked ()
|
||||
{
|
||||
// removes focus from the tree view - commits the data
|
||||
move_up_pb->setFocus ();
|
||||
commit_current ();
|
||||
|
||||
std::set<int> selected_rows;
|
||||
QModelIndexList selected_indices = stack_tree->selectionModel ()->selectedIndexes ();
|
||||
for (auto i = selected_indices.begin (); i != selected_indices.end (); ++i) {
|
||||
selected_rows.insert (i->row ());
|
||||
}
|
||||
|
||||
QTreeWidgetItem *current = stack_tree->currentItem ();
|
||||
int n_current = current ? current->data (0, Qt::UserRole).toInt () : -1;
|
||||
|
||||
stack_tree->setCurrentIndex (QModelIndex ());
|
||||
|
||||
int n = 0;
|
||||
for (db::NetTracerTechnologyComponent::iterator l = m_data.begin (); l != m_data.end (); ++l, ++n) {
|
||||
if (selected_rows.find (n + 1) != selected_rows.end () && selected_rows.find (n) == selected_rows.end ()) {
|
||||
std::swap (m_data.begin () [n + 1], m_data.begin () [n]);
|
||||
selected_rows.erase (n + 1);
|
||||
selected_rows.insert (n);
|
||||
if (n_current == n + 1) {
|
||||
n_current = n;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
update ();
|
||||
|
||||
// select the new items
|
||||
for (std::set <int>::const_iterator s = selected_rows.begin (); s != selected_rows.end (); ++s) {
|
||||
stack_tree->topLevelItem (*s)->setSelected (true);
|
||||
}
|
||||
if (n_current >= 0) {
|
||||
stack_tree->setCurrentItem (stack_tree->topLevelItem (n_current), 0, QItemSelectionModel::Current);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
NetTracerTechComponentEditor::move_down_clicked ()
|
||||
{
|
||||
// removes focus from the tree view - commits the data
|
||||
move_down_pb->setFocus ();
|
||||
commit_current ();
|
||||
|
||||
std::set<int> selected_rows;
|
||||
QModelIndexList selected_indices = stack_tree->selectionModel ()->selectedIndexes ();
|
||||
for (auto i = selected_indices.begin (); i != selected_indices.end (); ++i) {
|
||||
selected_rows.insert (i->row ());
|
||||
}
|
||||
|
||||
QTreeWidgetItem *current = stack_tree->currentItem ();
|
||||
int n_current = current ? current->data (0, Qt::UserRole).toInt () : -1;
|
||||
|
||||
stack_tree->setCurrentIndex (QModelIndex ());
|
||||
|
||||
int n = int (m_data.size ());
|
||||
for (db::NetTracerTechnologyComponent::iterator l = m_data.end (); l != m_data.begin (); ) {
|
||||
--l;
|
||||
--n;
|
||||
if (selected_rows.find (n - 1) != selected_rows.end () && selected_rows.find (n) == selected_rows.end ()) {
|
||||
std::swap (m_data.begin () [n - 1], m_data.begin () [n]);
|
||||
selected_rows.erase (n - 1);
|
||||
selected_rows.insert (n);
|
||||
if (n_current == n - 1) {
|
||||
n_current = n;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
update ();
|
||||
|
||||
// select the new items
|
||||
for (std::set <int>::const_iterator s = selected_rows.begin (); s != selected_rows.end (); ++s) {
|
||||
stack_tree->topLevelItem (*s)->setSelected (true);
|
||||
}
|
||||
if (n_current >= 0) {
|
||||
stack_tree->setCurrentItem (stack_tree->topLevelItem (n_current), 0, QItemSelectionModel::Current);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
NetTracerTechComponentEditor::update ()
|
||||
{
|
||||
stack_tree->clear ();
|
||||
stack_tree->clearSelection ();
|
||||
|
||||
int n = 0;
|
||||
for (db::NetTracerTechnologyComponent::iterator l = m_data.begin (); l != m_data.end (); ++l, ++n) {
|
||||
|
||||
QTreeWidgetItem *item = new QTreeWidgetItem (stack_tree);
|
||||
item->setFlags (item->flags () | Qt::ItemIsEditable);
|
||||
|
||||
std::string name = l->name ();
|
||||
if (name.empty ()) {
|
||||
item->setData (0, Qt::DisplayRole, QVariant (tr ("(default)")));
|
||||
} else {
|
||||
item->setData (0, Qt::DisplayRole, QVariant (tl::to_qstring (name)));
|
||||
}
|
||||
item->setData (0, Qt::UserRole, QVariant (n));
|
||||
|
||||
item->setData (1, Qt::DisplayRole, QVariant (tl::to_qstring (l->description ())));
|
||||
item->setData (1, Qt::UserRole, QVariant (n));
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -22,8 +22,8 @@
|
|||
|
||||
|
||||
|
||||
#ifndef HDR_layNetTracerIO
|
||||
#define HDR_layNetTracerIO
|
||||
#ifndef HDR_layNetTracerTechComponentEditor
|
||||
#define HDR_layNetTracerTechComponentEditor
|
||||
|
||||
#include "ui_NetTracerTechComponentEditor.h"
|
||||
|
||||
|
|
@ -48,8 +48,6 @@ namespace db
|
|||
namespace lay
|
||||
{
|
||||
|
||||
class FileDialog;
|
||||
|
||||
class NetTracerTechComponentEditor
|
||||
: public lay::TechnologyComponentEditor,
|
||||
public Ui::NetTracerTechComponentEditor
|
||||
|
|
@ -64,18 +62,18 @@ public:
|
|||
|
||||
public slots:
|
||||
void add_clicked ();
|
||||
void clone_clicked ();
|
||||
void del_clicked ();
|
||||
void move_up_clicked ();
|
||||
void move_down_clicked ();
|
||||
void symbol_add_clicked ();
|
||||
void symbol_del_clicked ();
|
||||
void symbol_move_up_clicked ();
|
||||
void symbol_move_down_clicked ();
|
||||
void current_item_changed (QTreeWidgetItem *current, QTreeWidgetItem *previous);
|
||||
|
||||
private:
|
||||
db::NetTracerTechnologyComponent m_data;
|
||||
|
||||
void update ();
|
||||
void commit_current (QTreeWidgetItem *current);
|
||||
void commit_current ();
|
||||
};
|
||||
|
||||
}
|
||||
|
|
@ -14,17 +14,20 @@ LIBS += -L$$DESTDIR/../db_plugins -lnet_tracer
|
|||
|
||||
HEADERS = \
|
||||
layNetTracerConfig.h \
|
||||
layNetTracerConnectivityEditor.h \
|
||||
layNetTracerDialog.h \
|
||||
layNetTracerIO.h \
|
||||
layNetTracerTechComponentEditor.h
|
||||
|
||||
SOURCES = \
|
||||
layNetTracerConfig.cc \
|
||||
layNetTracerConnectivityEditor.cc \
|
||||
layNetTracerDialog.cc \
|
||||
layNetTracerPlugin.cc \
|
||||
layNetTracerIO.cc \
|
||||
layNetTracerTechComponentEditor.cc
|
||||
|
||||
FORMS = \
|
||||
NetTracerConfigPage.ui \
|
||||
NetTracerConnectivityEditor.ui \
|
||||
NetTracerDialog.ui \
|
||||
NetTracerTechComponentEditor.ui \
|
||||
|
||||
|
|
|
|||
|
|
@ -76,21 +76,21 @@ static db::NetTracerShape find_shape (const db::Layout &layout, const db::Cell &
|
|||
}
|
||||
#endif
|
||||
|
||||
static db::NetTracerNet trace (db::NetTracer &tracer, const db::Layout &layout, const db::Cell &cell, const db::NetTracerTechnologyComponent &tc, unsigned int l_start, const db::Point &p_start)
|
||||
static db::NetTracerNet trace (db::NetTracer &tracer, const db::Layout &layout, const db::Cell &cell, const db::NetTracerConnectivity &tc, unsigned int l_start, const db::Point &p_start)
|
||||
{
|
||||
db::NetTracerData tracer_data = tc.get_tracer_data (layout);
|
||||
tracer.trace (layout, cell, p_start, l_start, tracer_data);
|
||||
return db::NetTracerNet (tracer, db::ICplxTrans (), layout, cell.cell_index (), std::string (), std::string (), tracer_data);
|
||||
}
|
||||
|
||||
static db::NetTracerNet trace (db::NetTracer &tracer, const db::Layout &layout, const db::Cell &cell, const db::NetTracerTechnologyComponent &tc, unsigned int l_start, const db::Point &p_start, unsigned int l_stop, const db::Point &p_stop)
|
||||
static db::NetTracerNet trace (db::NetTracer &tracer, const db::Layout &layout, const db::Cell &cell, const db::NetTracerConnectivity &tc, unsigned int l_start, const db::Point &p_start, unsigned int l_stop, const db::Point &p_stop)
|
||||
{
|
||||
db::NetTracerData tracer_data = tc.get_tracer_data (layout);
|
||||
tracer.trace (layout, cell, p_start, l_start, p_stop, l_stop, tracer_data);
|
||||
return db::NetTracerNet (tracer, db::ICplxTrans (), layout, cell.cell_index (), std::string (), std::string (), tracer_data);
|
||||
}
|
||||
|
||||
void run_test (tl::TestBase *_this, const std::string &file, const db::NetTracerTechnologyComponent &tc, const db::LayerProperties &lp_start, const db::Point &p_start, const std::string &file_au, const char *net_name = 0, size_t depth = 0)
|
||||
void run_test (tl::TestBase *_this, const std::string &file, const db::NetTracerConnectivity &tc, const db::LayerProperties &lp_start, const db::Point &p_start, const std::string &file_au, const char *net_name = 0, size_t depth = 0)
|
||||
{
|
||||
db::Manager m (false);
|
||||
|
||||
|
|
@ -130,7 +130,7 @@ void run_test (tl::TestBase *_this, const std::string &file, const db::NetTracer
|
|||
db::compare_layouts (_this, layout_net, fn, db::WriteOAS);
|
||||
}
|
||||
|
||||
void run_test2 (tl::TestBase *_this, const std::string &file, const db::NetTracerTechnologyComponent &tc, const db::LayerProperties &lp_start, const db::Point &p_start, const db::LayerProperties &lp_stop, const db::Point &p_stop, const std::string &file_au, const char *net_name = 0)
|
||||
void run_test2 (tl::TestBase *_this, const std::string &file, const db::NetTracerConnectivity &tc, const db::LayerProperties &lp_start, const db::Point &p_start, const db::LayerProperties &lp_stop, const db::Point &p_stop, const std::string &file_au, const char *net_name = 0)
|
||||
{
|
||||
db::Manager m (false);
|
||||
|
||||
|
|
@ -169,7 +169,7 @@ TEST(1)
|
|||
std::string file = "t1.oas.gz";
|
||||
std::string file_au = "t1_net.oas.gz";
|
||||
|
||||
db::NetTracerTechnologyComponent tc;
|
||||
db::NetTracerConnectivity tc;
|
||||
tc.add (connection ("1/0", "2/0", "3/0"));
|
||||
|
||||
run_test (_this, file, tc, db::LayerProperties (1, 0), db::Point (7000, 1500), file_au, "THE_NAME");
|
||||
|
|
@ -180,7 +180,7 @@ TEST(1b)
|
|||
std::string file = "t1.oas.gz";
|
||||
std::string file_au = "t1b_net.oas.gz";
|
||||
|
||||
db::NetTracerTechnologyComponent tc;
|
||||
db::NetTracerConnectivity tc;
|
||||
tc.add (connection ("1/0", "2/0", "3/0"));
|
||||
|
||||
// point is off net ...
|
||||
|
|
@ -192,7 +192,7 @@ TEST(1c)
|
|||
std::string file = "t1.oas.gz";
|
||||
std::string file_au = "t1_net.oas.gz";
|
||||
|
||||
db::NetTracerTechnologyComponent tc;
|
||||
db::NetTracerConnectivity tc;
|
||||
tc.add_symbol (symbol ("a", "1/0"));
|
||||
tc.add_symbol (symbol ("c", "cc"));
|
||||
tc.add_symbol (symbol ("cc", "3/0"));
|
||||
|
|
@ -206,7 +206,7 @@ TEST(1d)
|
|||
std::string file = "t1.oas.gz";
|
||||
std::string file_au = "t1d_net.oas.gz";
|
||||
|
||||
db::NetTracerTechnologyComponent tc;
|
||||
db::NetTracerConnectivity tc;
|
||||
tc.add (connection ("1/0", "10/0", "11/0"));
|
||||
|
||||
// some layers are non-existing
|
||||
|
|
@ -218,7 +218,7 @@ TEST(2)
|
|||
std::string file = "t2.oas.gz";
|
||||
std::string file_au = "t2_net.oas.gz";
|
||||
|
||||
db::NetTracerTechnologyComponent tc;
|
||||
db::NetTracerConnectivity tc;
|
||||
tc.add (connection ("1/0", "2/0", "3/0"));
|
||||
|
||||
run_test2 (_this, file, tc, db::LayerProperties (1, 0), db::Point (7000, 1500), db::LayerProperties (3, 0), db::Point (4000, -20000), file_au, "THE_NAME");
|
||||
|
|
@ -229,7 +229,7 @@ TEST(3)
|
|||
std::string file = "t3.oas.gz";
|
||||
std::string file_au = "t3_net.oas.gz";
|
||||
|
||||
db::NetTracerTechnologyComponent tc;
|
||||
db::NetTracerConnectivity tc;
|
||||
tc.add (connection ("1/0", "2/0", "3/0"));
|
||||
|
||||
std::string msg;
|
||||
|
|
@ -246,7 +246,7 @@ TEST(4)
|
|||
std::string file = "t4.oas.gz";
|
||||
std::string file_au = "t4_net.oas.gz";
|
||||
|
||||
db::NetTracerTechnologyComponent tc;
|
||||
db::NetTracerConnectivity tc;
|
||||
tc.add (connection ("1/0", "2/0", "3/0"));
|
||||
|
||||
run_test (_this, file, tc, db::LayerProperties (1, 0), db::Point (7000, 1500), file_au, "");
|
||||
|
|
@ -257,7 +257,7 @@ TEST(4b)
|
|||
std::string file = "t4.oas.gz";
|
||||
std::string file_au = "t4b_net.oas.gz";
|
||||
|
||||
db::NetTracerTechnologyComponent tc;
|
||||
db::NetTracerConnectivity tc;
|
||||
tc.add (connection ("1/0", "3/0"));
|
||||
|
||||
run_test (_this, file, tc, db::LayerProperties (1, 0), db::Point (7000, 1500), file_au, "THE_NAME");
|
||||
|
|
@ -268,7 +268,7 @@ TEST(5)
|
|||
std::string file = "t5.oas.gz";
|
||||
std::string file_au = "t5_net.oas.gz";
|
||||
|
||||
db::NetTracerTechnologyComponent tc;
|
||||
db::NetTracerConnectivity tc;
|
||||
tc.add (connection ("1/0*10/0", "2/0", "3/0"));
|
||||
|
||||
run_test (_this, file, tc, db::LayerProperties (1, 0), db::Point (7000, 1500), file_au, "THE_NAME");
|
||||
|
|
@ -279,7 +279,7 @@ TEST(5b)
|
|||
std::string file = "t5.oas.gz";
|
||||
std::string file_au = "t5b_net.oas.gz";
|
||||
|
||||
db::NetTracerTechnologyComponent tc;
|
||||
db::NetTracerConnectivity tc;
|
||||
tc.add (connection ("1/0", "2/0*10/0", "3/0"));
|
||||
|
||||
run_test (_this, file, tc, db::LayerProperties (1, 0), db::Point (7000, 1500), file_au, "THE_NAME");
|
||||
|
|
@ -290,7 +290,7 @@ TEST(5c)
|
|||
std::string file = "t5.oas.gz";
|
||||
std::string file_au = "t5c_net.oas.gz";
|
||||
|
||||
db::NetTracerTechnologyComponent tc;
|
||||
db::NetTracerConnectivity tc;
|
||||
tc.add (connection ("1/0", "2/0-11/0", "3/0"));
|
||||
|
||||
run_test (_this, file, tc, db::LayerProperties (1, 0), db::Point (7000, 1500), file_au, "");
|
||||
|
|
@ -301,7 +301,7 @@ TEST(5d)
|
|||
std::string file = "t5.oas.gz";
|
||||
std::string file_au = "t5d_net.oas.gz";
|
||||
|
||||
db::NetTracerTechnologyComponent tc;
|
||||
db::NetTracerConnectivity tc;
|
||||
tc.add (connection ("1/0-12/0", "2/0", "3/0-12/0"));
|
||||
|
||||
run_test (_this, file, tc, db::LayerProperties (1, 0), db::Point (7000, 1500), file_au, "THE_NAME");
|
||||
|
|
@ -312,7 +312,7 @@ TEST(5e)
|
|||
std::string file = "t5.oas.gz";
|
||||
std::string file_au = "t5e_net.oas.gz";
|
||||
|
||||
db::NetTracerTechnologyComponent tc;
|
||||
db::NetTracerConnectivity tc;
|
||||
tc.add (connection ("1/0-12/0", "2/0", "3/0-12/0"));
|
||||
|
||||
run_test (_this, file, tc, db::LayerProperties (1, 0), db::Point (7000, 1500), file_au, "THE_NAME");
|
||||
|
|
@ -323,7 +323,7 @@ TEST(5f)
|
|||
std::string file = "t5.oas.gz";
|
||||
std::string file_au = "t5f_net.oas.gz";
|
||||
|
||||
db::NetTracerTechnologyComponent tc;
|
||||
db::NetTracerConnectivity tc;
|
||||
tc.add_symbol (symbol ("x", "3-14"));
|
||||
tc.add (connection ("10-13", "x"));
|
||||
tc.add (connection ("x", "2", "1+13"));
|
||||
|
|
@ -336,7 +336,7 @@ TEST(6)
|
|||
std::string file = "t6.oas.gz";
|
||||
std::string file_au = "t6_net.oas.gz";
|
||||
|
||||
db::NetTracerTechnologyComponent tc;
|
||||
db::NetTracerConnectivity tc;
|
||||
tc.add (connection ("1-10", "2", "3"));
|
||||
tc.add (connection ("3", "4", "5"));
|
||||
|
||||
|
|
@ -348,7 +348,7 @@ TEST(6b)
|
|||
std::string file = "t6.oas.gz";
|
||||
std::string file_au = "t6b_net.oas.gz";
|
||||
|
||||
db::NetTracerTechnologyComponent tc;
|
||||
db::NetTracerConnectivity tc;
|
||||
tc.add (connection ("1-10", "2", "3"));
|
||||
tc.add (connection ("3", "4", "5"));
|
||||
|
||||
|
|
@ -360,7 +360,7 @@ TEST(7)
|
|||
std::string file = "t7.oas.gz";
|
||||
std::string file_au = "t7_net.oas.gz";
|
||||
|
||||
db::NetTracerTechnologyComponent tc;
|
||||
db::NetTracerConnectivity tc;
|
||||
tc.add (connection ("15", "14", "2-7"));
|
||||
tc.add (connection ("15", "14", "7"));
|
||||
|
||||
|
|
@ -373,7 +373,7 @@ TEST(8)
|
|||
std::string file = "t8.oas.gz";
|
||||
std::string file_au = "t8_net.oas.gz";
|
||||
|
||||
db::NetTracerTechnologyComponent tc;
|
||||
db::NetTracerConnectivity tc;
|
||||
tc.add (connection ("15", "14", "7"));
|
||||
|
||||
run_test (_this, file, tc, db::LayerProperties (15, 0), db::Point (4000, 10000), file_au, "");
|
||||
|
|
@ -384,7 +384,7 @@ TEST(9)
|
|||
std::string file = "t9.oas.gz";
|
||||
std::string file_au = "t9_net.oas.gz";
|
||||
|
||||
db::NetTracerTechnologyComponent tc;
|
||||
db::NetTracerConnectivity tc;
|
||||
tc.add_symbol (symbol ("a", "8-12"));
|
||||
tc.add_symbol (symbol ("b", "a+7"));
|
||||
tc.add_symbol (symbol ("c", "15*26"));
|
||||
|
|
|
|||
|
|
@ -50,7 +50,7 @@ static db::NetTracerSymbolInfo symbol (const std::string &s, const std::string &
|
|||
return db::NetTracerSymbolInfo (s, e);
|
||||
}
|
||||
|
||||
void run_test (tl::TestBase *_this, const std::string &file, const db::NetTracerTechnologyComponent &tc, const std::string &file_au)
|
||||
void run_test (tl::TestBase *_this, const std::string &file, const db::NetTracerConnectivity &tc, const std::string &file_au)
|
||||
{
|
||||
db::Manager m (false);
|
||||
|
||||
|
|
@ -93,7 +93,7 @@ TEST(1)
|
|||
std::string file = "t1.oas.gz";
|
||||
std::string file_au = "t1_all_nets.oas.gz";
|
||||
|
||||
db::NetTracerTechnologyComponent tc;
|
||||
db::NetTracerConnectivity tc;
|
||||
tc.add (connection ("1/0", "2/0", "3/0"));
|
||||
|
||||
run_test (_this, file, tc, file_au);
|
||||
|
|
@ -104,7 +104,7 @@ TEST(1c)
|
|||
std::string file = "t1.oas.gz";
|
||||
std::string file_au = "t1_all_nets.oas.gz";
|
||||
|
||||
db::NetTracerTechnologyComponent tc;
|
||||
db::NetTracerConnectivity tc;
|
||||
tc.add_symbol (symbol ("a", "1/0"));
|
||||
tc.add_symbol (symbol ("c", "cc"));
|
||||
tc.add_symbol (symbol ("cc", "3/0"));
|
||||
|
|
@ -118,7 +118,7 @@ TEST(1d)
|
|||
std::string file = "t1.oas.gz";
|
||||
std::string file_au = "t1d_all_nets.oas.gz";
|
||||
|
||||
db::NetTracerTechnologyComponent tc;
|
||||
db::NetTracerConnectivity tc;
|
||||
tc.add (connection ("1/0", "10/0", "11/0"));
|
||||
|
||||
// some layers are non-existing
|
||||
|
|
@ -130,7 +130,7 @@ TEST(4)
|
|||
std::string file = "t4.oas.gz";
|
||||
std::string file_au = "t4_all_nets.oas.gz";
|
||||
|
||||
db::NetTracerTechnologyComponent tc;
|
||||
db::NetTracerConnectivity tc;
|
||||
tc.add (connection ("1/0", "2/0", "3/0"));
|
||||
|
||||
run_test (_this, file, tc, file_au);
|
||||
|
|
@ -141,7 +141,7 @@ TEST(4b)
|
|||
std::string file = "t4.oas.gz";
|
||||
std::string file_au = "t4b_all_nets.oas.gz";
|
||||
|
||||
db::NetTracerTechnologyComponent tc;
|
||||
db::NetTracerConnectivity tc;
|
||||
tc.add (connection ("1/0", "3/0"));
|
||||
|
||||
run_test (_this, file, tc, file_au);
|
||||
|
|
@ -152,7 +152,7 @@ TEST(5)
|
|||
std::string file = "t5.oas.gz";
|
||||
std::string file_au = "t5_all_nets.oas.gz";
|
||||
|
||||
db::NetTracerTechnologyComponent tc;
|
||||
db::NetTracerConnectivity tc;
|
||||
tc.add (connection ("1/0*10/0", "2/0", "3/0"));
|
||||
|
||||
run_test (_this, file, tc, file_au);
|
||||
|
|
@ -163,7 +163,7 @@ TEST(5b)
|
|||
std::string file = "t5.oas.gz";
|
||||
std::string file_au = "t5b_all_nets.oas.gz";
|
||||
|
||||
db::NetTracerTechnologyComponent tc;
|
||||
db::NetTracerConnectivity tc;
|
||||
tc.add (connection ("1/0", "2/0*10/0", "3/0"));
|
||||
|
||||
run_test (_this, file, tc, file_au);
|
||||
|
|
@ -174,7 +174,7 @@ TEST(5c)
|
|||
std::string file = "t5.oas.gz";
|
||||
std::string file_au = "t5c_all_nets.oas.gz";
|
||||
|
||||
db::NetTracerTechnologyComponent tc;
|
||||
db::NetTracerConnectivity tc;
|
||||
tc.add (connection ("1/0", "2/0-11/0", "3/0"));
|
||||
|
||||
run_test (_this, file, tc, file_au);
|
||||
|
|
@ -185,7 +185,7 @@ TEST(5d)
|
|||
std::string file = "t5.oas.gz";
|
||||
std::string file_au = "t5d_all_nets.oas.gz";
|
||||
|
||||
db::NetTracerTechnologyComponent tc;
|
||||
db::NetTracerConnectivity tc;
|
||||
tc.add (connection ("1/0-12/0", "2/0", "3/0-12/0"));
|
||||
|
||||
run_test (_this, file, tc, file_au);
|
||||
|
|
@ -196,7 +196,7 @@ TEST(5f)
|
|||
std::string file = "t5.oas.gz";
|
||||
std::string file_au = "t5f_all_nets.oas.gz";
|
||||
|
||||
db::NetTracerTechnologyComponent tc;
|
||||
db::NetTracerConnectivity tc;
|
||||
tc.add_symbol (symbol ("x", "3-14"));
|
||||
tc.add (connection ("10-13", "x"));
|
||||
tc.add (connection ("x", "2", "1+13"));
|
||||
|
|
@ -209,7 +209,7 @@ TEST(6)
|
|||
std::string file = "t6.oas.gz";
|
||||
std::string file_au = "t6_all_nets.oas.gz";
|
||||
|
||||
db::NetTracerTechnologyComponent tc;
|
||||
db::NetTracerConnectivity tc;
|
||||
tc.add (connection ("1-10", "2", "3"));
|
||||
tc.add (connection ("3", "4", "5"));
|
||||
|
||||
|
|
@ -221,7 +221,7 @@ TEST(7)
|
|||
std::string file = "t7.oas.gz";
|
||||
std::string file_au = "t7_all_nets.oas.gz";
|
||||
|
||||
db::NetTracerTechnologyComponent tc;
|
||||
db::NetTracerConnectivity tc;
|
||||
tc.add (connection ("15", "14", "2-7"));
|
||||
tc.add (connection ("15", "14", "7"));
|
||||
|
||||
|
|
|
|||
|
|
@ -71,8 +71,8 @@
|
|||
<string>...</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../../../../lay/lay/layResources.qrc">
|
||||
<normaloff>:/run.png</normaloff>:/run.png</iconset>
|
||||
<iconset resource="../../../../icons/icons.qrc">
|
||||
<normaloff>:/run_16px.png</normaloff>:/run_16px.png</iconset>
|
||||
</property>
|
||||
<property name="autoRaise">
|
||||
<bool>true</bool>
|
||||
|
|
@ -260,7 +260,7 @@
|
|||
<string>...</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../../../../lay/lay/layResources.qrc">
|
||||
<iconset resource="../../../../icons/icons.qrc">
|
||||
<normaloff>:/fit_left_24px.png</normaloff>:/fit_left_24px.png</iconset>
|
||||
</property>
|
||||
<property name="iconSize">
|
||||
|
|
@ -280,7 +280,7 @@
|
|||
<string>...</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../../../../lay/lay/layResources.qrc">
|
||||
<iconset resource="../../../../icons/icons.qrc">
|
||||
<normaloff>:/fit_front_24px.png</normaloff>:/fit_front_24px.png</iconset>
|
||||
</property>
|
||||
<property name="iconSize">
|
||||
|
|
@ -300,7 +300,7 @@
|
|||
<string>...</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../../../../lay/lay/layResources.qrc">
|
||||
<iconset resource="../../../../icons/icons.qrc">
|
||||
<normaloff>:/fit_right_24px.png</normaloff>:/fit_right_24px.png</iconset>
|
||||
</property>
|
||||
<property name="iconSize">
|
||||
|
|
@ -320,7 +320,7 @@
|
|||
<string>...</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../../../../lay/lay/layResources.qrc">
|
||||
<iconset resource="../../../../icons/icons.qrc">
|
||||
<normaloff>:/fit_back_24px.png</normaloff>:/fit_back_24px.png</iconset>
|
||||
</property>
|
||||
<property name="iconSize">
|
||||
|
|
@ -340,7 +340,7 @@
|
|||
<string>...</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../../../../lay/lay/layResources.qrc">
|
||||
<iconset resource="../../../../icons/icons.qrc">
|
||||
<normaloff>:/fit_top_24px.png</normaloff>:/fit_top_24px.png</iconset>
|
||||
</property>
|
||||
<property name="iconSize">
|
||||
|
|
@ -360,7 +360,7 @@
|
|||
<string>...</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../../../../lay/lay/layResources.qrc">
|
||||
<iconset resource="../../../../icons/icons.qrc">
|
||||
<normaloff>:/fit_bottom_24px.png</normaloff>:/fit_bottom_24px.png</iconset>
|
||||
</property>
|
||||
<property name="iconSize">
|
||||
|
|
@ -628,7 +628,7 @@ See here for more information: <a href="int:/about/25d_view.xml">
|
|||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources>
|
||||
<include location="../../../../lay/lay/layResources.qrc"/>
|
||||
<include location="../../../../icons/icons.qrc"/>
|
||||
</resources>
|
||||
<connections>
|
||||
<connection>
|
||||
|
|
|
|||
|
|
@ -248,42 +248,38 @@ ItemRefUnwrappingIterator category_items_end (const rdb::Category *cat)
|
|||
return cat->database ()->items_by_category (cat->id ()).second;
|
||||
}
|
||||
|
||||
static void scan_layer1 (rdb::Category *cat, const db::Layout &layout, unsigned int layer)
|
||||
static void scan_layer (rdb::Category *cat, const db::Layout &layout, unsigned int layer, const db::Cell *from_cell, int levels, bool with_properties)
|
||||
{
|
||||
rdb::scan_layer (cat, layout, layer);
|
||||
rdb::scan_layer (cat, layout, layer, from_cell, levels, with_properties);
|
||||
}
|
||||
|
||||
static void scan_layer2 (rdb::Category *cat, const db::Layout &layout, unsigned int layer, const db::Cell *from_cell)
|
||||
static void scan_shapes (rdb::Category *cat, const db::RecursiveShapeIterator &iter, bool flat, bool with_properties)
|
||||
{
|
||||
rdb::scan_layer (cat, layout, layer, from_cell);
|
||||
rdb::scan_layer (cat, iter, flat, with_properties);
|
||||
}
|
||||
|
||||
static void scan_layer3 (rdb::Category *cat, const db::Layout &layout, unsigned int layer, const db::Cell *from_cell, int levels)
|
||||
{
|
||||
rdb::scan_layer (cat, layout, layer, from_cell, levels);
|
||||
}
|
||||
|
||||
static void scan_shapes (rdb::Category *cat, const db::RecursiveShapeIterator &iter, bool flat)
|
||||
{
|
||||
rdb::scan_layer (cat, iter, flat);
|
||||
}
|
||||
|
||||
static void scan_region (rdb::Category *cat, rdb::Cell *cell, const db::CplxTrans &trans, const db::Region ®ion, bool flat)
|
||||
static void scan_region (rdb::Category *cat, rdb::Cell *cell, const db::CplxTrans &trans, const db::Region ®ion, bool flat, bool with_properties)
|
||||
{
|
||||
std::pair<db::RecursiveShapeIterator, db::ICplxTrans> it = region.begin_iter ();
|
||||
rdb::scan_layer (cat, cell, trans * it.second, it.first, flat);
|
||||
rdb::scan_layer (cat, cell, trans * it.second, it.first, flat, with_properties);
|
||||
}
|
||||
|
||||
static void scan_edges (rdb::Category *cat, rdb::Cell *cell, const db::CplxTrans &trans, const db::Edges &edges, bool flat)
|
||||
static void scan_edges (rdb::Category *cat, rdb::Cell *cell, const db::CplxTrans &trans, const db::Edges &edges, bool flat, bool with_properties)
|
||||
{
|
||||
std::pair<db::RecursiveShapeIterator, db::ICplxTrans> it = edges.begin_iter ();
|
||||
rdb::scan_layer (cat, cell, trans * it.second, it.first, flat);
|
||||
rdb::scan_layer (cat, cell, trans * it.second, it.first, flat, with_properties);
|
||||
}
|
||||
|
||||
static void scan_edge_pairs (rdb::Category *cat, rdb::Cell *cell, const db::CplxTrans &trans, const db::EdgePairs &edge_pairs, bool flat)
|
||||
static void scan_edge_pairs (rdb::Category *cat, rdb::Cell *cell, const db::CplxTrans &trans, const db::EdgePairs &edge_pairs, bool flat, bool with_properties)
|
||||
{
|
||||
std::pair<db::RecursiveShapeIterator, db::ICplxTrans> it = edge_pairs.begin_iter ();
|
||||
rdb::scan_layer (cat, cell, trans * it.second, it.first, flat);
|
||||
rdb::scan_layer (cat, cell, trans * it.second, it.first, flat, with_properties);
|
||||
}
|
||||
|
||||
static void scan_texts (rdb::Category *cat, rdb::Cell *cell, const db::CplxTrans &trans, const db::Texts &texts, bool flat, bool with_properties)
|
||||
{
|
||||
std::pair<db::RecursiveShapeIterator, db::ICplxTrans> it = texts.begin_iter ();
|
||||
rdb::scan_layer (cat, cell, trans * it.second, it.first, flat, with_properties);
|
||||
}
|
||||
|
||||
Class<rdb::Category> decl_RdbCategory ("rdb", "RdbCategory",
|
||||
|
|
@ -303,7 +299,7 @@ Class<rdb::Category> decl_RdbCategory ("rdb", "RdbCategory",
|
|||
"\n"
|
||||
"This method has been introduced in version 0.23."
|
||||
) +
|
||||
gsi::method_ext ("scan_shapes", &scan_shapes, gsi::arg ("iter"), gsi::arg ("flat", false),
|
||||
gsi::method_ext ("scan_shapes", &scan_shapes, gsi::arg ("iter"), gsi::arg ("flat", false), gsi::arg ("with_properties", true),
|
||||
"@brief Scans the polygon or edge shapes from the shape iterator into the category\n"
|
||||
"Creates RDB items for each polygon or edge shape read from the iterator and puts them into this category.\n"
|
||||
"A similar, but lower-level method is \\ReportDatabase#create_items with a \\RecursiveShapeIterator argument.\n"
|
||||
|
|
@ -311,9 +307,11 @@ Class<rdb::Category> decl_RdbCategory ("rdb", "RdbCategory",
|
|||
"if the \\flat argument is false. In this case, the hierarchy the recursive shape iterator traverses is "
|
||||
"copied into the report database using sample references.\n"
|
||||
"\n"
|
||||
"This method has been introduced in version 0.23. The flat mode argument has been added in version 0.26.\n"
|
||||
"If 'with_properties' is true, user properties will be turned into tagged values as well.\n"
|
||||
"\n"
|
||||
"This method has been introduced in version 0.23. The flat mode argument has been added in version 0.26. The 'with_properties' argument has been added in version 0.28.\n"
|
||||
) +
|
||||
gsi::method_ext ("scan_collection", &scan_region, gsi::arg ("cell"), gsi::arg ("trans"), gsi::arg ("region"), gsi::arg ("flat", false),
|
||||
gsi::method_ext ("scan_collection", &scan_region, gsi::arg ("cell"), gsi::arg ("trans"), gsi::arg ("region"), gsi::arg ("flat", false), gsi::arg ("with_properties", true),
|
||||
"@brief Turns the given region into a hierarchical or flat report database\n"
|
||||
"The exact behavior depends on the nature of the region. If the region is a hierarchical (original or deep) region "
|
||||
"and the 'flat' argument is false, this method will produce a hierarchical report database in the given category. "
|
||||
|
|
@ -325,44 +323,38 @@ Class<rdb::Category> decl_RdbCategory ("rdb", "RdbCategory",
|
|||
"\n"
|
||||
"The transformation argument needs to supply the dbu-to-micron transformation.\n"
|
||||
"\n"
|
||||
"This method has been introduced in version 0.26.\n"
|
||||
"If 'with_properties' is true, user properties will be turned into tagged values as well.\n"
|
||||
"\n"
|
||||
"This method has been introduced in version 0.26. The 'with_properties' argument has been added in version 0.28.\n"
|
||||
) +
|
||||
gsi::method_ext ("scan_collection", &scan_edges, gsi::arg ("cell"), gsi::arg ("trans"), gsi::arg ("edges"), gsi::arg ("flat", false),
|
||||
gsi::method_ext ("scan_collection", &scan_edges, gsi::arg ("cell"), gsi::arg ("trans"), gsi::arg ("edges"), gsi::arg ("flat", false), gsi::arg ("with_properties", true),
|
||||
"@brief Turns the given edge collection into a hierarchical or flat report database\n"
|
||||
"This a another flavour of \\scan_collection accepting an edge collection.\n"
|
||||
"\n"
|
||||
"This method has been introduced in version 0.26.\n"
|
||||
"This method has been introduced in version 0.26. The 'with_properties' argument has been added in version 0.28.\n"
|
||||
) +
|
||||
gsi::method_ext ("scan_collection", &scan_edge_pairs, gsi::arg ("cell"), gsi::arg ("trans"), gsi::arg ("edge_pairs"), gsi::arg ("flat", false),
|
||||
gsi::method_ext ("scan_collection", &scan_edge_pairs, gsi::arg ("cell"), gsi::arg ("trans"), gsi::arg ("edge_pairs"), gsi::arg ("flat", false), gsi::arg ("with_properties", true),
|
||||
"@brief Turns the given edge pair collection into a hierarchical or flat report database\n"
|
||||
"This a another flavour of \\scan_collection accepting an edge pair collection.\n"
|
||||
"\n"
|
||||
"This method has been introduced in version 0.26.\n"
|
||||
"This method has been introduced in version 0.26. The 'with_properties' argument has been added in version 0.28.\n"
|
||||
) +
|
||||
gsi::method_ext ("scan_layer", &scan_layer1, gsi::arg ("layout"), gsi::arg ("layer"),
|
||||
"@brief Scans a layer from a layout into this category\n"
|
||||
"Creates RDB items for each polygon or edge shape read from the each cell in the layout on the given layer and puts them into this category.\n"
|
||||
"New cells will be generated for every cell encountered in the layout.\n"
|
||||
"Other settings like database unit, description, top cell etc. are not made in the RDB.\n"
|
||||
gsi::method_ext ("scan_collection", &scan_texts, gsi::arg ("cell"), gsi::arg ("trans"), gsi::arg ("texts"), gsi::arg ("flat", false), gsi::arg ("with_properties", true),
|
||||
"@brief Turns the given edge pair collection into a hierarchical or flat report database\n"
|
||||
"This a another flavour of \\scan_collection accepting a text collection.\n"
|
||||
"\n"
|
||||
"This method has been introduced in version 0.23.\n"
|
||||
"This method has been introduced in version 0.28.\n"
|
||||
) +
|
||||
gsi::method_ext ("scan_layer", &scan_layer2, gsi::arg ("layout"), gsi::arg ("layer"), gsi::arg ("cell"),
|
||||
"@brief Scans a layer from a layout into this category, starting with a given cell\n"
|
||||
"Creates RDB items for each polygon or edge shape read from the cell and it's children in the layout on the given layer and puts them into this category.\n"
|
||||
"New cells will be generated when required.\n"
|
||||
"Other settings like database unit, description, top cell etc. are not made in the RDB.\n"
|
||||
"\n"
|
||||
"This method has been introduced in version 0.23.\n"
|
||||
) +
|
||||
gsi::method_ext ("scan_layer", &scan_layer3, gsi::arg ("layout"), gsi::arg ("layer"), gsi::arg ("cell"), gsi::arg ("levels"),
|
||||
gsi::method_ext ("scan_layer", &scan_layer, gsi::arg ("layout"), gsi::arg ("layer"), gsi::arg ("cell", (const db::Cell *) 0, "nil"), gsi::arg ("levels", -1), gsi::arg ("with_properties", true),
|
||||
"@brief Scans a layer from a layout into this category, starting with a given cell and a depth specification\n"
|
||||
"Creates RDB items for each polygon or edge shape read from the cell and it's children in the layout on the given layer and puts them into this category.\n"
|
||||
"New cells will be generated when required.\n"
|
||||
"\"levels\" is the number of hierarchy levels to take the child cells from. 0 means to use only \"cell\" and don't descend, -1 means \"all levels\".\n"
|
||||
"Other settings like database unit, description, top cell etc. are not made in the RDB.\n"
|
||||
"\n"
|
||||
"This method has been introduced in version 0.23.\n"
|
||||
"If 'with_properties' is true, user properties will be turned into tagged values as well.\n"
|
||||
"\n"
|
||||
"This method has been introduced in version 0.23. The 'with_properties' argument has been added in version 0.28.\n"
|
||||
) +
|
||||
gsi::method ("name", &rdb::Category::name,
|
||||
"@brief Gets the category name\n"
|
||||
|
|
@ -1209,7 +1201,7 @@ Class<rdb::Database> decl_ReportDatabase ("rdb", "ReportDatabase",
|
|||
"\n"
|
||||
"This convenience method has been added in version 0.25.\n"
|
||||
) +
|
||||
gsi::method_ext ("create_items", &rdb::create_items_from_iterator, gsi::arg ("cell_id"), gsi::arg ("category_id"), gsi::arg ("iter"),
|
||||
gsi::method_ext ("create_items", &rdb::create_items_from_iterator, gsi::arg ("cell_id"), gsi::arg ("category_id"), gsi::arg ("iter"), gsi::arg ("with_properties", true),
|
||||
"@brief Creates new items from a shape iterator\n"
|
||||
"This method takes the shapes from the given iterator and produces items from them.\n"
|
||||
"It accepts various kind of shapes, such as texts, polygons, boxes and paths and "
|
||||
|
|
@ -1217,41 +1209,44 @@ Class<rdb::Database> decl_ReportDatabase ("rdb", "ReportDatabase",
|
|||
"A similar method, which is intended for production of polygon or edge error layers and also provides hierarchical database "
|
||||
"construction is \\RdbCategory#scan_shapes.\n"
|
||||
"\n"
|
||||
"This method has been introduced in version 0.25.3.\n"
|
||||
"This method has been introduced in version 0.25.3. The 'with_properties' argument has been added in version 0.28.\n"
|
||||
"\n"
|
||||
"@param cell_id The ID of the cell to which the item is associated\n"
|
||||
"@param category_id The ID of the category to which the item is associated\n"
|
||||
"@param iter The iterator (a \\RecursiveShapeIterator object) from which to take the items\n"
|
||||
"@param with_properties If true, user properties will be turned into tagged values as well\n"
|
||||
) +
|
||||
gsi::method_ext ("create_item", &rdb::create_item_from_shape, gsi::arg ("cell_id"), gsi::arg ("category_id"), gsi::arg ("trans"), gsi::arg ("shape"),
|
||||
gsi::method_ext ("create_item", &rdb::create_item_from_shape, gsi::arg ("cell_id"), gsi::arg ("category_id"), gsi::arg ("trans"), gsi::arg ("shape"), gsi::arg ("with_properties", true),
|
||||
"@brief Creates a new item from a single shape\n"
|
||||
"This method produces an item from the given shape.\n"
|
||||
"It accepts various kind of shapes, such as texts, polygons, boxes and paths and "
|
||||
"converts them to a corresponding item. The transformation argument can be used to "
|
||||
"supply the transformation that applies the database unit for example.\n"
|
||||
"\n"
|
||||
"This method has been introduced in version 0.25.3.\n"
|
||||
"This method has been introduced in version 0.25.3. The 'with_properties' argument has been added in version 0.28.\n"
|
||||
"\n"
|
||||
"@param cell_id The ID of the cell to which the item is associated\n"
|
||||
"@param category_id The ID of the category to which the item is associated\n"
|
||||
"@param shape The shape to take the geometrical object from\n"
|
||||
"@param trans The transformation to apply\n"
|
||||
"@param with_properties If true, user properties will be turned into tagged values as well\n"
|
||||
) +
|
||||
gsi::method_ext ("create_items", &rdb::create_items_from_shapes, gsi::arg ("cell_id"), gsi::arg ("category_id"), gsi::arg ("trans"), gsi::arg ("shapes"),
|
||||
gsi::method_ext ("create_items", &rdb::create_items_from_shapes, gsi::arg ("cell_id"), gsi::arg ("category_id"), gsi::arg ("trans"), gsi::arg ("shapes"), gsi::arg ("with_properties", true),
|
||||
"@brief Creates new items from a shape container\n"
|
||||
"This method takes the shapes from the given container and produces items from them.\n"
|
||||
"It accepts various kind of shapes, such as texts, polygons, boxes and paths and "
|
||||
"converts them to corresponding items. The transformation argument can be used to "
|
||||
"supply the transformation that applies the database unit for example.\n"
|
||||
"\n"
|
||||
"This method has been introduced in version 0.25.3.\n"
|
||||
"This method has been introduced in version 0.25.3. The 'with_properties' argument has been added in version 0.28.\n"
|
||||
"\n"
|
||||
"@param cell_id The ID of the cell to which the item is associated\n"
|
||||
"@param category_id The ID of the category to which the item is associated\n"
|
||||
"@param shapes The shape container from which to take the items\n"
|
||||
"@param trans The transformation to apply\n"
|
||||
"@param with_properties If true, user properties will be turned into tagged values as well\n"
|
||||
) +
|
||||
gsi::method_ext ("create_items", &rdb::create_items_from_region, gsi::arg ("cell_id"), gsi::arg ("category_id"), gsi::arg ("trans"), gsi::arg ("region"),
|
||||
gsi::method_ext ("#create_items", &rdb::create_items_from_region, gsi::arg ("cell_id"), gsi::arg ("category_id"), gsi::arg ("trans"), gsi::arg ("region"),
|
||||
"@brief Creates new polygon items for the given cell/category combination\n"
|
||||
"For each polygon in the region a single item will be created. The value of the item will be this "
|
||||
"polygon.\n"
|
||||
|
|
@ -1262,14 +1257,14 @@ Class<rdb::Database> decl_ReportDatabase ("rdb", "ReportDatabase",
|
|||
"\\RdbCategory#scan_collection is a similar method which also supports construction of "
|
||||
"hierarchical databases from deep regions.\n"
|
||||
"\n"
|
||||
"This method has been introduced in version 0.23.\n"
|
||||
"This method has been introduced in version 0.23. It has been deprecated in favor of \\RdbCategory#scan_collection in version 0.28.\n"
|
||||
"\n"
|
||||
"@param cell_id The ID of the cell to which the item is associated\n"
|
||||
"@param category_id The ID of the category to which the item is associated\n"
|
||||
"@param trans The transformation to apply\n"
|
||||
"@param region The region (a \\Region object) containing the polygons for which to create items\n"
|
||||
) +
|
||||
gsi::method_ext ("create_items", &rdb::create_items_from_edges, gsi::arg ("cell_id"), gsi::arg ("category_id"), gsi::arg ("trans"), gsi::arg ("edges"),
|
||||
gsi::method_ext ("#create_items", &rdb::create_items_from_edges, gsi::arg ("cell_id"), gsi::arg ("category_id"), gsi::arg ("trans"), gsi::arg ("edges"),
|
||||
"@brief Creates new edge items for the given cell/category combination\n"
|
||||
"For each edge a single item will be created. The value of the item will be this "
|
||||
"edge.\n"
|
||||
|
|
@ -1280,14 +1275,14 @@ Class<rdb::Database> decl_ReportDatabase ("rdb", "ReportDatabase",
|
|||
"\\RdbCategory#scan_collection is a similar method which also supports construction of "
|
||||
"hierarchical databases from deep edge collections.\n"
|
||||
"\n"
|
||||
"This method has been introduced in version 0.23.\n"
|
||||
"This method has been introduced in version 0.23. It has been deprecated in favor of \\RdbCategory#scan_collection in version 0.28.\n"
|
||||
"\n"
|
||||
"@param cell_id The ID of the cell to which the item is associated\n"
|
||||
"@param category_id The ID of the category to which the item is associated\n"
|
||||
"@param trans The transformation to apply\n"
|
||||
"@param edges The list of edges (an \\Edges object) for which the items are created\n"
|
||||
) +
|
||||
gsi::method_ext ("create_items", &rdb::create_items_from_edge_pairs, gsi::arg ("cell_id"), gsi::arg ("category_id"), gsi::arg ("trans"), gsi::arg ("edge_pairs"),
|
||||
gsi::method_ext ("#create_items", &rdb::create_items_from_edge_pairs, gsi::arg ("cell_id"), gsi::arg ("category_id"), gsi::arg ("trans"), gsi::arg ("edge_pairs"),
|
||||
"@brief Creates new edge pair items for the given cell/category combination\n"
|
||||
"For each edge pair a single item will be created. The value of the item will be this "
|
||||
"edge pair.\n"
|
||||
|
|
@ -1298,7 +1293,7 @@ Class<rdb::Database> decl_ReportDatabase ("rdb", "ReportDatabase",
|
|||
"\\RdbCategory#scan_collection is a similar method which also supports construction of "
|
||||
"hierarchical databases from deep edge pair collections.\n"
|
||||
"\n"
|
||||
"This method has been introduced in version 0.23.\n"
|
||||
"This method has been introduced in version 0.23. It has been deprecated in favor of \\RdbCategory#scan_collection in version 0.28.\n"
|
||||
"\n"
|
||||
"@param cell_id The ID of the cell to which the item is associated\n"
|
||||
"@param category_id The ID of the category to which the item is associated\n"
|
||||
|
|
|
|||
|
|
@ -860,9 +860,11 @@ public:
|
|||
* @brief Add a value in a generic way
|
||||
*/
|
||||
template <class V>
|
||||
void add_value (const V &v)
|
||||
ValueBase *add_value (const V &v, id_type tag_id = 0)
|
||||
{
|
||||
values ().add (new Value<V> (v));
|
||||
ValueBase *value = new Value<V> (v);
|
||||
values ().add (value, tag_id);
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ namespace rdb
|
|||
{
|
||||
|
||||
void
|
||||
scan_layer (rdb::Category *cat, const db::Layout &layout, unsigned int layer, const db::Cell *from, int levels)
|
||||
scan_layer (rdb::Category *cat, const db::Layout &layout, unsigned int layer, const db::Cell *from, int levels, bool with_properties)
|
||||
{
|
||||
rdb::Database *rdb = cat->database ();
|
||||
if (! rdb) {
|
||||
|
|
@ -78,7 +78,7 @@ scan_layer (rdb::Category *cat, const db::Layout &layout, unsigned int layer, co
|
|||
|
||||
}
|
||||
|
||||
create_items_from_shapes (rdb, rdb_cell->id (), cat->id (), db::CplxTrans (layout.dbu ()), cell.shapes (layer));
|
||||
create_items_from_shapes (rdb, rdb_cell->id (), cat->id (), db::CplxTrans (layout.dbu ()), cell.shapes (layer), with_properties);
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -92,8 +92,8 @@ class CreateItemsRecursiveReceiver
|
|||
: public db::RecursiveShapeReceiver
|
||||
{
|
||||
public:
|
||||
CreateItemsRecursiveReceiver (rdb::Category *cat, const db::CplxTrans &trans, rdb::Cell *cell)
|
||||
: mp_cat (cat), mp_rdb (cat->database ()), m_trans (trans), mp_rdb_cell (cell)
|
||||
CreateItemsRecursiveReceiver (rdb::Category *cat, const db::CplxTrans &trans, rdb::Cell *cell, bool with_properties)
|
||||
: mp_cat (cat), mp_rdb (cat->database ()), m_trans (trans), mp_rdb_cell (cell), m_with_properties (with_properties)
|
||||
{
|
||||
// just in case the iterator is non-hierarchical
|
||||
if (cell) {
|
||||
|
|
@ -159,7 +159,7 @@ public:
|
|||
virtual void shape (const db::RecursiveShapeIterator * /*iter*/, const db::Shape &shape, const db::ICplxTrans & /*always_apply*/, const db::ICplxTrans & /*trans*/, const db::Box & /*region*/, const box_tree_type * /*complex_region*/)
|
||||
{
|
||||
tl_assert (! m_cell_stack.empty ());
|
||||
create_item_from_shape (mp_rdb, m_cell_stack.back ()->id (), mp_cat->id (), m_trans, shape);
|
||||
create_item_from_shape (mp_rdb, m_cell_stack.back ()->id (), mp_cat->id (), m_trans, shape, m_with_properties);
|
||||
}
|
||||
|
||||
public:
|
||||
|
|
@ -169,6 +169,7 @@ public:
|
|||
std::map<db::cell_index_type, const rdb::Cell *> m_id_to_cell;
|
||||
db::CplxTrans m_trans;
|
||||
rdb::Cell *mp_rdb_cell;
|
||||
bool m_with_properties;
|
||||
|
||||
const rdb::Cell *cell_for_id (const db::Layout *layout, db::cell_index_type ci)
|
||||
{
|
||||
|
|
@ -187,8 +188,8 @@ class CreateItemsFlatReceiver
|
|||
: public db::RecursiveShapeReceiver
|
||||
{
|
||||
public:
|
||||
CreateItemsFlatReceiver (rdb::Category *cat, const db::CplxTrans &trans, rdb::Cell *cell)
|
||||
: mp_cat (cat), mp_rdb (cat->database ()), m_trans (trans), mp_rdb_cell (cell)
|
||||
CreateItemsFlatReceiver (rdb::Category *cat, const db::CplxTrans &trans, rdb::Cell *cell, bool with_properties)
|
||||
: mp_cat (cat), mp_rdb (cat->database ()), m_trans (trans), mp_rdb_cell (cell), m_with_properties (with_properties)
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
|
@ -211,7 +212,7 @@ public:
|
|||
|
||||
virtual void shape (const db::RecursiveShapeIterator * /*iter*/, const db::Shape &shape, const db::ICplxTrans & /*always_apply*/, const db::ICplxTrans &trans, const db::Box & /*region*/, const box_tree_type * /*complex_region*/)
|
||||
{
|
||||
create_item_from_shape (mp_rdb, mp_rdb_cell->id (), mp_cat->id (), m_trans * trans, shape);
|
||||
create_item_from_shape (mp_rdb, mp_rdb_cell->id (), mp_cat->id (), m_trans * trans, shape, m_with_properties);
|
||||
}
|
||||
|
||||
public:
|
||||
|
|
@ -219,23 +220,24 @@ public:
|
|||
rdb::Database *mp_rdb;
|
||||
db::CplxTrans m_trans;
|
||||
const rdb::Cell *mp_rdb_cell;
|
||||
bool m_with_properties;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
scan_layer (rdb::Category *cat, const db::RecursiveShapeIterator &iter, bool flat)
|
||||
scan_layer (rdb::Category *cat, const db::RecursiveShapeIterator &iter, bool flat, bool with_properties)
|
||||
{
|
||||
if (! iter.top_cell () || ! iter.layout ()) {
|
||||
return;
|
||||
}
|
||||
|
||||
db::CplxTrans trans (iter.layout ()->dbu ());
|
||||
scan_layer (cat, 0, trans, iter, flat);
|
||||
scan_layer (cat, 0, trans, iter, flat, with_properties);
|
||||
}
|
||||
|
||||
void
|
||||
scan_layer (rdb::Category *cat, rdb::Cell *cell, const db::CplxTrans &trans, const db::RecursiveShapeIterator &iter, bool flat)
|
||||
scan_layer (rdb::Category *cat, rdb::Cell *cell, const db::CplxTrans &trans, const db::RecursiveShapeIterator &iter, bool flat, bool with_properties)
|
||||
{
|
||||
if (! cat->database ()) {
|
||||
return;
|
||||
|
|
@ -243,9 +245,9 @@ scan_layer (rdb::Category *cat, rdb::Cell *cell, const db::CplxTrans &trans, con
|
|||
|
||||
std::unique_ptr<db::RecursiveShapeReceiver> rec;
|
||||
if (flat) {
|
||||
rec.reset (new CreateItemsFlatReceiver (cat, trans, cell));
|
||||
rec.reset (new CreateItemsFlatReceiver (cat, trans, cell, with_properties));
|
||||
} else {
|
||||
rec.reset (new CreateItemsRecursiveReceiver (cat, trans, cell));
|
||||
rec.reset (new CreateItemsRecursiveReceiver (cat, trans, cell, with_properties));
|
||||
}
|
||||
|
||||
db::RecursiveShapeIterator (iter).push (rec.get ());
|
||||
|
|
@ -253,37 +255,47 @@ scan_layer (rdb::Category *cat, rdb::Cell *cell, const db::CplxTrans &trans, con
|
|||
|
||||
// ------------------------------------------------------------------------------------------------------------
|
||||
|
||||
void create_items_from_iterator (rdb::Database *db, rdb::id_type cell_id, rdb::id_type cat_id, const db::RecursiveShapeIterator &iter)
|
||||
void create_items_from_iterator (rdb::Database *db, rdb::id_type cell_id, rdb::id_type cat_id, const db::RecursiveShapeIterator &iter, bool with_properties)
|
||||
{
|
||||
tl_assert (iter.layout ());
|
||||
double dbu = iter.layout ()->dbu ();
|
||||
|
||||
for (db::RecursiveShapeIterator i = iter; !i.at_end (); ++i) {
|
||||
std::unique_ptr<rdb::ValueBase> value (rdb::ValueBase::create_from_shape (*i, db::CplxTrans (dbu) * i.trans ()));
|
||||
if (value.get ()) {
|
||||
rdb::Item *item = db->create_item (cell_id, cat_id);
|
||||
item->values ().add (value.release ());
|
||||
}
|
||||
create_item_from_shape (db, cell_id, cat_id, db::CplxTrans (dbu) * i.trans (), *i, with_properties);
|
||||
}
|
||||
}
|
||||
|
||||
void create_items_from_shapes (rdb::Database *db, rdb::id_type cell_id, rdb::id_type cat_id, const db::CplxTrans &trans, const db::Shapes &shapes)
|
||||
void create_items_from_shapes (rdb::Database *db, rdb::id_type cell_id, rdb::id_type cat_id, const db::CplxTrans &trans, const db::Shapes &shapes, bool with_properties)
|
||||
{
|
||||
for (db::Shapes::shape_iterator s = shapes.begin (db::ShapeIterator::All); !s.at_end (); ++s) {
|
||||
std::unique_ptr<rdb::ValueBase> value (rdb::ValueBase::create_from_shape (*s, trans));
|
||||
if (value.get ()) {
|
||||
rdb::Item *item = db->create_item (cell_id, cat_id);
|
||||
item->values ().add (value.release ());
|
||||
}
|
||||
create_item_from_shape (db, cell_id, cat_id, trans, *s, with_properties);
|
||||
}
|
||||
}
|
||||
|
||||
void create_item_from_shape (rdb::Database *db, rdb::id_type cell_id, rdb::id_type cat_id, const db::CplxTrans &trans, const db::Shape &shape)
|
||||
void create_item_from_shape (rdb::Database *db, rdb::id_type cell_id, rdb::id_type cat_id, const db::CplxTrans &trans, const db::Shape &shape, bool with_properties)
|
||||
{
|
||||
std::unique_ptr<rdb::ValueBase> value (rdb::ValueBase::create_from_shape (shape, trans));
|
||||
if (value.get ()) {
|
||||
rdb::Item *item = db->create_item (cell_id, cat_id);
|
||||
item->values ().add (value.release ());
|
||||
if (! value.get ()) {
|
||||
return;
|
||||
}
|
||||
|
||||
rdb::Item *item = db->create_item (cell_id, cat_id);
|
||||
item->values ().add (value.release ());
|
||||
|
||||
// translate properties
|
||||
if (with_properties && shape.has_prop_id () && shape.shapes () && shape.shapes ()->cell ()) {
|
||||
|
||||
const db::Layout *layout = shape.shapes ()->cell ()->layout ();
|
||||
if (layout) {
|
||||
|
||||
auto ps = layout->properties_repository ().properties (shape.prop_id ());
|
||||
for (auto i = ps.begin (); i != ps.end (); ++i) {
|
||||
id_type tag_id = db->tags ().tag (layout->properties_repository ().prop_name (i->first).to_string (), true /*user tag*/).id ();
|
||||
add_item_value (item, i->second, trans, tag_id);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -317,50 +329,101 @@ void create_items_from_edge_pairs (rdb::Database *db, rdb::id_type cell_id, rdb:
|
|||
}
|
||||
}
|
||||
|
||||
void add_item_value (rdb::Item *item, const tl::Variant &v, double dbu)
|
||||
ValueBase *add_item_value (rdb::Item *item, const tl::Variant &v, const db::CplxTrans &trans, rdb::id_type tag_id)
|
||||
{
|
||||
if (dbu > 0 && v.is_user<db::Box> ()) {
|
||||
item->add_value (db::CplxTrans (dbu) * v.to_user<db::Box> ());
|
||||
} else if (dbu > 0 && v.is_user<db::Point> ()) {
|
||||
db::DPoint p = db::CplxTrans (dbu) * v.to_user<db::Point> ();
|
||||
item->add_value (db::DEdge (p, p));
|
||||
} else if (dbu > 0 && v.is_user<db::Polygon> ()) {
|
||||
item->add_value (db::CplxTrans (dbu) * v.to_user<db::Polygon> ());
|
||||
} else if (dbu > 0 && v.is_user<db::SimplePolygon> ()) {
|
||||
if (v.is_user<db::Box> ()) {
|
||||
return item->add_value (trans * v.to_user<db::Box> (), tag_id);
|
||||
} else if (v.is_user<db::Point> ()) {
|
||||
db::DPoint p = trans * v.to_user<db::Point> ();
|
||||
return item->add_value (db::DEdge (p, p), tag_id);
|
||||
} else if (v.is_user<db::Polygon> ()) {
|
||||
return item->add_value (trans * v.to_user<db::Polygon> (), tag_id);
|
||||
} else if (v.is_user<db::SimplePolygon> ()) {
|
||||
db::DPolygon p;
|
||||
db::DSimplePolygon sp = db::CplxTrans (dbu) * v.to_user<db::SimplePolygon> ();
|
||||
db::DSimplePolygon sp = trans * v.to_user<db::SimplePolygon> ();
|
||||
p.assign_hull (sp.begin_hull (), sp.end_hull ());
|
||||
item->add_value (p);
|
||||
} else if (dbu > 0 && v.is_user<db::Edge> ()) {
|
||||
item->add_value (db::CplxTrans (dbu) * v.to_user<db::Edge> ());
|
||||
} else if (dbu > 0 && v.is_user<db::EdgePair> ()) {
|
||||
item->add_value (db::CplxTrans (dbu) * v.to_user<db::EdgePair> ());
|
||||
} else if (dbu > 0 && v.is_user<db::Path> ()) {
|
||||
item->add_value (db::CplxTrans (dbu) * v.to_user<db::Path> ());
|
||||
} else if (dbu > 0 && v.is_user<db::Text> ()) {
|
||||
item->add_value (db::CplxTrans (dbu) * v.to_user<db::Text> ());
|
||||
return item->add_value (p, tag_id);
|
||||
} else if (v.is_user<db::Edge> ()) {
|
||||
return item->add_value (trans * v.to_user<db::Edge> (), tag_id);
|
||||
} else if (v.is_user<db::EdgePair> ()) {
|
||||
return item->add_value (trans * v.to_user<db::EdgePair> (), tag_id);
|
||||
} else if (v.is_user<db::Path> ()) {
|
||||
return item->add_value (trans * v.to_user<db::Path> (), tag_id);
|
||||
} else if (v.is_user<db::Text> ()) {
|
||||
return item->add_value (trans * v.to_user<db::Text> (), tag_id);
|
||||
} else if (v.is_user<db::DBox> ()) {
|
||||
item->add_value (v.to_user<db::DBox> ());
|
||||
return item->add_value (v.to_user<db::DBox> (), tag_id);
|
||||
} else if (v.is_user<db::DPoint> ()) {
|
||||
db::DPoint p = v.to_user<db::DPoint> ();
|
||||
item->add_value (db::DEdge (p, p));
|
||||
return item->add_value (db::DEdge (p, p), tag_id);
|
||||
} else if (v.is_user<db::DPolygon> ()) {
|
||||
item->add_value (v.to_user<db::DPolygon> ());
|
||||
return item->add_value (v.to_user<db::DPolygon> (), tag_id);
|
||||
} else if (v.is_user<db::DSimplePolygon> ()) {
|
||||
db::DPolygon p;
|
||||
db::DSimplePolygon sp = v.to_user<db::DSimplePolygon> ();
|
||||
p.assign_hull (sp.begin_hull (), sp.end_hull ());
|
||||
item->add_value (p);
|
||||
return item->add_value (p, tag_id);
|
||||
} else if (v.is_user<db::DEdge> ()) {
|
||||
item->add_value (v.to_user<db::DEdge> ());
|
||||
return item->add_value (v.to_user<db::DEdge> (), tag_id);
|
||||
} else if (v.is_user<db::DEdgePair> ()) {
|
||||
item->add_value (v.to_user<db::DEdgePair> ());
|
||||
return item->add_value (v.to_user<db::DEdgePair> (), tag_id);
|
||||
} else if (v.is_user<db::DPath> ()) {
|
||||
item->add_value (v.to_user<db::DPath> ());
|
||||
return item->add_value (v.to_user<db::DPath> (), tag_id);
|
||||
} else if (v.is_user<db::DText> ()) {
|
||||
item->add_value (v.to_user<db::DText> ());
|
||||
return item->add_value (v.to_user<db::DText> (), tag_id);
|
||||
} else if (v.is_double () || v.is_long () || v.is_ulong () || v.is_longlong () || v.is_ulonglong ()) {
|
||||
return item->add_value (v.to_double (), tag_id);
|
||||
} else {
|
||||
item->add_value (std::string (v.to_string ()));
|
||||
return item->add_value (std::string (v.to_string ()), tag_id);
|
||||
}
|
||||
}
|
||||
|
||||
ValueBase *add_item_value(rdb::Item *item, const tl::Variant &v, double dbu, rdb::id_type tag_id)
|
||||
{
|
||||
if (dbu > 0 && v.is_user<db::Box> ()) {
|
||||
return item->add_value (db::CplxTrans (dbu) * v.to_user<db::Box> (), tag_id);
|
||||
} else if (dbu > 0 && v.is_user<db::Point> ()) {
|
||||
db::DPoint p = db::CplxTrans (dbu) * v.to_user<db::Point> ();
|
||||
return item->add_value (db::DEdge (p, p), tag_id);
|
||||
} else if (dbu > 0 && v.is_user<db::Polygon> ()) {
|
||||
return item->add_value (db::CplxTrans (dbu) * v.to_user<db::Polygon> (), tag_id);
|
||||
} else if (dbu > 0 && v.is_user<db::SimplePolygon> ()) {
|
||||
db::DPolygon p;
|
||||
db::DSimplePolygon sp = db::CplxTrans (dbu) * v.to_user<db::SimplePolygon> ();
|
||||
p.assign_hull (sp.begin_hull (), sp.end_hull ());
|
||||
return item->add_value (p, tag_id);
|
||||
} else if (dbu > 0 && v.is_user<db::Edge> ()) {
|
||||
return item->add_value (db::CplxTrans (dbu) * v.to_user<db::Edge> (), tag_id);
|
||||
} else if (dbu > 0 && v.is_user<db::EdgePair> ()) {
|
||||
return item->add_value (db::CplxTrans (dbu) * v.to_user<db::EdgePair> (), tag_id);
|
||||
} else if (dbu > 0 && v.is_user<db::Path> ()) {
|
||||
return item->add_value (db::CplxTrans (dbu) * v.to_user<db::Path> (), tag_id);
|
||||
} else if (dbu > 0 && v.is_user<db::Text> ()) {
|
||||
return item->add_value (db::CplxTrans (dbu) * v.to_user<db::Text> (), tag_id);
|
||||
} else if (v.is_user<db::DBox> ()) {
|
||||
return item->add_value (v.to_user<db::DBox> (), tag_id);
|
||||
} else if (v.is_user<db::DPoint> ()) {
|
||||
db::DPoint p = v.to_user<db::DPoint> ();
|
||||
return item->add_value (db::DEdge (p, p), tag_id);
|
||||
} else if (v.is_user<db::DPolygon> ()) {
|
||||
return item->add_value (v.to_user<db::DPolygon> (), tag_id);
|
||||
} else if (v.is_user<db::DSimplePolygon> ()) {
|
||||
db::DPolygon p;
|
||||
db::DSimplePolygon sp = v.to_user<db::DSimplePolygon> ();
|
||||
p.assign_hull (sp.begin_hull (), sp.end_hull ());
|
||||
return item->add_value (p, tag_id);
|
||||
} else if (v.is_user<db::DEdge> ()) {
|
||||
return item->add_value (v.to_user<db::DEdge> (), tag_id);
|
||||
} else if (v.is_user<db::DEdgePair> ()) {
|
||||
return item->add_value (v.to_user<db::DEdgePair> (), tag_id);
|
||||
} else if (v.is_user<db::DPath> ()) {
|
||||
return item->add_value (v.to_user<db::DPath> (), tag_id);
|
||||
} else if (v.is_user<db::DText> ()) {
|
||||
return item->add_value (v.to_user<db::DText> (), tag_id);
|
||||
} else if (v.is_double () || v.is_long () || v.is_ulong () || v.is_longlong () || v.is_ulonglong ()) {
|
||||
return item->add_value (v.to_double (), tag_id);
|
||||
} else {
|
||||
return item->add_value (std::string (v.to_string ()), tag_id);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -51,45 +51,63 @@ namespace rdb
|
|||
*
|
||||
* If "from" is 0, all cells will be scanned. Levels are the number of hierarchy levels scanned if
|
||||
* "from" is given. -1 means "all levels".
|
||||
*
|
||||
* If "with_properties" is true, user properties are translated into values with tags corresponding
|
||||
* to the property names.
|
||||
*/
|
||||
RDB_PUBLIC void scan_layer (rdb::Category *cat, const db::Layout &layout, unsigned int layer, const db::Cell *from_cell = 0, int levels = -1);
|
||||
RDB_PUBLIC void scan_layer (rdb::Category *cat, const db::Layout &layout, unsigned int layer, const db::Cell *from_cell = 0, int levels = -1, bool with_properties = true);
|
||||
|
||||
/**
|
||||
* @brief Scans a recursive shape iterator into a RDB category
|
||||
*
|
||||
* If "with_properties" is true, user properties are translated into values with tags corresponding
|
||||
* to the property names.
|
||||
*/
|
||||
RDB_PUBLIC void scan_layer (rdb::Category *cat, const db::RecursiveShapeIterator &iter, bool flat = false);
|
||||
RDB_PUBLIC void scan_layer (rdb::Category *cat, const db::RecursiveShapeIterator &iter, bool flat = false, bool with_properties = true);
|
||||
|
||||
/**
|
||||
* @brief Scans a recursive shape iterator into a RDB category
|
||||
*
|
||||
* This version allows supplying a cell and a transformation. With this information, the function can also handle
|
||||
* pseudo-iterators which don't deliver the information from a layout from from a plain shape collection.
|
||||
*
|
||||
* If "with_properties" is true, user properties are translated into values with tags corresponding
|
||||
* to the property names.
|
||||
*/
|
||||
RDB_PUBLIC void scan_layer (rdb::Category *cat, rdb::Cell *cell, const db::CplxTrans &trans, const db::RecursiveShapeIterator &iter, bool flat = false);
|
||||
RDB_PUBLIC void scan_layer (rdb::Category *cat, rdb::Cell *cell, const db::CplxTrans &trans, const db::RecursiveShapeIterator &iter, bool flat = false, bool with_properties = true);
|
||||
|
||||
/**
|
||||
* @brief Creates RDB items from a recursive shape iterator
|
||||
*
|
||||
* This function will produce items from the flattened shape iterator. The items will be stored under
|
||||
* the given cell.
|
||||
*
|
||||
* If "with_properties" is true, user properties are translated into values with tags corresponding
|
||||
* to the property names.
|
||||
*/
|
||||
RDB_PUBLIC void create_items_from_iterator (rdb::Database *db, rdb::id_type cell_id, rdb::id_type cat_id, const db::RecursiveShapeIterator &iter);
|
||||
RDB_PUBLIC void create_items_from_iterator (rdb::Database *db, rdb::id_type cell_id, rdb::id_type cat_id, const db::RecursiveShapeIterator &iter, bool with_properties = true);
|
||||
|
||||
/**
|
||||
* @brief Creates RDB items from a shape collection
|
||||
*
|
||||
* An arbitrary transformation can be applied to translate the shapes before turning them to items.
|
||||
* This transformation is useful for providing the DBU-to-micron conversion.
|
||||
*
|
||||
* If "with_properties" is true, user properties are translated into values with tags corresponding
|
||||
* to the property names.
|
||||
*/
|
||||
RDB_PUBLIC void create_items_from_shapes (rdb::Database *db, rdb::id_type cell_id, rdb::id_type cat_id, const db::CplxTrans &trans, const db::Shapes &shapes);
|
||||
RDB_PUBLIC void create_items_from_shapes (rdb::Database *db, rdb::id_type cell_id, rdb::id_type cat_id, const db::CplxTrans &trans, const db::Shapes &shapes, bool with_properties = true);
|
||||
|
||||
/**
|
||||
* @brief Creates RDB items from a single shape
|
||||
*
|
||||
* An arbitrary transformation can be applied to translate the shapes before turning them to items.
|
||||
* This transformation is useful for providing the DBU-to-micron conversion.
|
||||
*
|
||||
* If "with_properties" is true, user properties are translated into values with tags corresponding
|
||||
* to the property names.
|
||||
*/
|
||||
RDB_PUBLIC void create_item_from_shape (rdb::Database *db, rdb::id_type cell_id, rdb::id_type cat_id, const db::CplxTrans &trans, const db::Shape &shape);
|
||||
RDB_PUBLIC void create_item_from_shape (rdb::Database *db, rdb::id_type cell_id, rdb::id_type cat_id, const db::CplxTrans &trans, const db::Shape &shape, bool with_properties = true);
|
||||
|
||||
/**
|
||||
* @brief Creates RDB items from a region
|
||||
|
|
@ -146,7 +164,14 @@ RDB_PUBLIC_TEMPLATE void create_items_from_sequence (rdb::Database *db, rdb::id_
|
|||
*
|
||||
* Unknown types are converted to strings.
|
||||
*/
|
||||
RDB_PUBLIC void add_item_value (rdb::Item *item, const tl::Variant &v, double dbu = 0.0);
|
||||
RDB_PUBLIC ValueBase *add_item_value (rdb::Item *item, const tl::Variant &v, double dbu = 0.0, rdb::id_type tag_id = 0);
|
||||
|
||||
/**
|
||||
* @brief Creates a value from a tl::Variant
|
||||
*
|
||||
* This version takes a db::CplxTrans for converting integer-unit geometry objects to micron-unit ones.
|
||||
*/
|
||||
RDB_PUBLIC ValueBase *add_item_value(rdb::Item *item, const tl::Variant &v, const db::CplxTrans &trans, rdb::id_type tag_id = 0);
|
||||
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@
|
|||
#endif
|
||||
|
||||
#include <memory>
|
||||
#include <cmath>
|
||||
|
||||
namespace tl
|
||||
{
|
||||
|
|
@ -358,6 +359,141 @@ PixelBuffer::diff (const PixelBuffer &other) const
|
|||
return res;
|
||||
}
|
||||
|
||||
void
|
||||
PixelBuffer::blowup (tl::PixelBuffer &dest, unsigned int os)
|
||||
{
|
||||
tl_assert (dest.width () == width () * os);
|
||||
tl_assert (dest.height () == height () * os);
|
||||
|
||||
unsigned int ymax = height ();
|
||||
unsigned int xmax = width ();
|
||||
|
||||
for (unsigned int y = 0; y < ymax; ++y) {
|
||||
for (unsigned int i = 0; i < os; ++i) {
|
||||
const uint32_t *psrc = (const uint32_t *) scan_line (y);
|
||||
uint32_t *pdest = (uint32_t *) dest.scan_line (y * os + i);
|
||||
for (unsigned int x = 0; x < xmax; ++x) {
|
||||
for (unsigned int j = 0; j < os; ++j) {
|
||||
*pdest++ = *psrc;
|
||||
}
|
||||
++psrc;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
PixelBuffer::subsample (tl::PixelBuffer &dest, unsigned int os, double g)
|
||||
{
|
||||
// TODO: this is probably not compatible with the endianess of SPARC ..
|
||||
|
||||
// LUT's for combining the RGB channels
|
||||
|
||||
// forward transformation table
|
||||
unsigned short lut1[256];
|
||||
for (unsigned int i = 0; i < 256; ++i) {
|
||||
double f = (65536 / (os * os)) - 1;
|
||||
lut1[i] = (unsigned short)std::min (f, std::max (0.0, floor (0.5 + pow (i / 255.0, g) * f)));
|
||||
}
|
||||
|
||||
// backward transformation table
|
||||
unsigned char lut2[65536];
|
||||
for (unsigned int i = 0; i < 65536; ++i) {
|
||||
double f = os * os * ((65536 / (os * os)) - 1);
|
||||
lut2[i] = (unsigned char)std::min (255.0, std::max (0.0, floor (0.5 + pow (i / f, 1.0 / g) * 255.0)));
|
||||
}
|
||||
|
||||
// LUT's for alpha channel
|
||||
|
||||
// forward transformation table
|
||||
unsigned short luta1[256];
|
||||
for (unsigned int i = 0; i < 256; ++i) {
|
||||
double f = (65536 / (os * os)) - 1;
|
||||
luta1[i] = (unsigned short)std::min (f, std::max (0.0, floor (0.5 + (i / 255.0) * f)));
|
||||
}
|
||||
|
||||
// backward transformation table
|
||||
unsigned char luta2[65536];
|
||||
for (unsigned int i = 0; i < 65536; ++i) {
|
||||
double f = os * os * ((65536 / (os * os)) - 1);
|
||||
luta2[i] = (unsigned char)std::min (255.0, std::max (0.0, floor (0.5 + (i / f) * 255.0)));
|
||||
}
|
||||
|
||||
unsigned int ymax = dest.height ();
|
||||
unsigned int xmax = dest.width ();
|
||||
|
||||
unsigned short *buffer = new unsigned short[xmax * 4];
|
||||
|
||||
for (unsigned int y = 0; y < ymax; ++y) {
|
||||
|
||||
{
|
||||
|
||||
const unsigned char *psrc = (const unsigned char *) scan_line (y * os);
|
||||
unsigned short *pdest = buffer;
|
||||
|
||||
for (unsigned int x = 0; x < xmax; ++x) {
|
||||
|
||||
pdest[0] = lut1[psrc[0]];
|
||||
pdest[1] = lut1[psrc[1]];
|
||||
pdest[2] = lut1[psrc[2]];
|
||||
pdest[3] = luta1[psrc[3]];
|
||||
psrc += 4;
|
||||
|
||||
for (unsigned int j = os; j > 1; j--) {
|
||||
pdest[0] += lut1[psrc[0]];
|
||||
pdest[1] += lut1[psrc[1]];
|
||||
pdest[2] += lut1[psrc[2]];
|
||||
pdest[3] += luta1[psrc[3]];
|
||||
psrc += 4;
|
||||
}
|
||||
|
||||
pdest += 4;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
for (unsigned int i = 1; i < os; ++i) {
|
||||
|
||||
const unsigned char *psrc = (const unsigned char *) scan_line (y * os + i);
|
||||
unsigned short *pdest = buffer;
|
||||
|
||||
for (unsigned int x = 0; x < xmax; ++x) {
|
||||
|
||||
for (unsigned int j = os; j > 0; j--) {
|
||||
pdest[0] += lut1[psrc[0]];
|
||||
pdest[1] += lut1[psrc[1]];
|
||||
pdest[2] += lut1[psrc[2]];
|
||||
pdest[3] += luta1[psrc[3]];
|
||||
psrc += 4;
|
||||
}
|
||||
|
||||
pdest += 4;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
{
|
||||
|
||||
unsigned char *pdest = (unsigned char *) dest.scan_line (y);
|
||||
const unsigned short *psrc = buffer;
|
||||
|
||||
for (unsigned int x = 0; x < xmax; ++x) {
|
||||
*pdest++ = lut2[*psrc++];
|
||||
*pdest++ = lut2[*psrc++];
|
||||
*pdest++ = lut2[*psrc++];
|
||||
*pdest++ = luta2[*psrc++];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
delete[] buffer;
|
||||
}
|
||||
|
||||
|
||||
#if defined(HAVE_PNG)
|
||||
|
||||
PixelBuffer
|
||||
|
|
|
|||
|
|
@ -257,6 +257,28 @@ public:
|
|||
*/
|
||||
PixelBuffer diff (const PixelBuffer &other) const;
|
||||
|
||||
/**
|
||||
* @brief Subsamples the image and puts the subsampled image into the destination image
|
||||
*
|
||||
* @param dest Where the subsampled image goes to
|
||||
* @param os The subsampling factor
|
||||
* @param g The gamma value for color interpolation
|
||||
*
|
||||
* The dimension of the destination image must be set to the corresponding fraction of
|
||||
* self's dimension.
|
||||
*/
|
||||
void subsample (tl::PixelBuffer &dest, unsigned int os, double g);
|
||||
|
||||
/**
|
||||
* @brief Scales the image into the given destination image
|
||||
*
|
||||
* @param dest Where the scaled image goes to
|
||||
* @param os The scaling factor
|
||||
*
|
||||
* The destination images dimension must have been set of self's dimension times os.
|
||||
*/
|
||||
void blowup (tl::PixelBuffer &dest, unsigned int os);
|
||||
|
||||
/**
|
||||
* @brief Gets the texts
|
||||
*
|
||||
|
|
|
|||
|
|
@ -256,7 +256,7 @@ std::string to_lower_case (const std::string &s)
|
|||
|
||||
std::string to_local (const std::string &s)
|
||||
{
|
||||
std::unique_ptr<char> buffer (new char [MB_CUR_MAX]); // MB_CUR_MAX isn't a constant
|
||||
std::unique_ptr<char []> buffer (new char [MB_CUR_MAX]); // MB_CUR_MAX isn't a constant
|
||||
std::string ls;
|
||||
|
||||
std::wstring ws = to_wstring (s);
|
||||
|
|
|
|||
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue