diff --git a/src/laybasic/laybasic/images/icon_net_16.png b/src/laybasic/laybasic/images/icon_net_16.png
index 0c395df79..48e83bfc5 100644
Binary files a/src/laybasic/laybasic/images/icon_net_16.png and b/src/laybasic/laybasic/images/icon_net_16.png differ
diff --git a/src/laybasic/laybasic/images/icon_net_24.png b/src/laybasic/laybasic/images/icon_net_24.png
index 18347cfde..74661b308 100644
Binary files a/src/laybasic/laybasic/images/icon_net_24.png and b/src/laybasic/laybasic/images/icon_net_24.png differ
diff --git a/src/laybasic/laybasic/images/icon_net_32.png b/src/laybasic/laybasic/images/icon_net_32.png
index a89683443..2cc7aae6d 100644
Binary files a/src/laybasic/laybasic/images/icon_net_32.png and b/src/laybasic/laybasic/images/icon_net_32.png differ
diff --git a/src/laybasic/laybasic/images/icon_net_48.png b/src/laybasic/laybasic/images/icon_net_48.png
index c8ead4e43..dd4598762 100644
Binary files a/src/laybasic/laybasic/images/icon_net_48.png and b/src/laybasic/laybasic/images/icon_net_48.png differ
diff --git a/src/laybasic/laybasic/images/icon_net_light_16.png b/src/laybasic/laybasic/images/icon_net_light_16.png
new file mode 100644
index 000000000..dc10ef9ce
Binary files /dev/null and b/src/laybasic/laybasic/images/icon_net_light_16.png differ
diff --git a/src/laybasic/laybasic/images/icon_net_light_24.png b/src/laybasic/laybasic/images/icon_net_light_24.png
new file mode 100644
index 000000000..95d79a4b3
Binary files /dev/null and b/src/laybasic/laybasic/images/icon_net_light_24.png differ
diff --git a/src/laybasic/laybasic/images/icon_net_light_32.png b/src/laybasic/laybasic/images/icon_net_light_32.png
new file mode 100644
index 000000000..658926a4c
Binary files /dev/null and b/src/laybasic/laybasic/images/icon_net_light_32.png differ
diff --git a/src/laybasic/laybasic/images/icon_net_light_48.png b/src/laybasic/laybasic/images/icon_net_light_48.png
new file mode 100644
index 000000000..10b1e1acc
Binary files /dev/null and b/src/laybasic/laybasic/images/icon_net_light_48.png differ
diff --git a/src/laybasic/laybasic/images/icon_pin_16.png b/src/laybasic/laybasic/images/icon_pin_16.png
index dc886e61d..c8c47d587 100644
Binary files a/src/laybasic/laybasic/images/icon_pin_16.png and b/src/laybasic/laybasic/images/icon_pin_16.png differ
diff --git a/src/laybasic/laybasic/images/icon_pin_24.png b/src/laybasic/laybasic/images/icon_pin_24.png
index 3a92bd666..b0dc43766 100644
Binary files a/src/laybasic/laybasic/images/icon_pin_24.png and b/src/laybasic/laybasic/images/icon_pin_24.png differ
diff --git a/src/laybasic/laybasic/images/icon_pin_32.png b/src/laybasic/laybasic/images/icon_pin_32.png
index 82e305b38..519b11776 100644
Binary files a/src/laybasic/laybasic/images/icon_pin_32.png and b/src/laybasic/laybasic/images/icon_pin_32.png differ
diff --git a/src/laybasic/laybasic/images/icon_pin_48.png b/src/laybasic/laybasic/images/icon_pin_48.png
index 35aca773a..d137d4668 100644
Binary files a/src/laybasic/laybasic/images/icon_pin_48.png and b/src/laybasic/laybasic/images/icon_pin_48.png differ
diff --git a/src/laybasic/laybasic/images/icons.svg b/src/laybasic/laybasic/images/icons.svg
index 3f255edc9..04a3e84ad 100644
--- a/src/laybasic/laybasic/images/icons.svg
+++ b/src/laybasic/laybasic/images/icons.svg
@@ -26,8 +26,8 @@
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="2.8"
- inkscape:cx="396.23267"
- inkscape:cy="867.9533"
+ inkscape:cx="560.64642"
+ inkscape:cy="920.20375"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="true"
@@ -53,7 +53,7 @@
image/svg+xml
-
+
@@ -1031,18 +1031,18 @@
inkscape:export-ydpi="90"
inkscape:export-xdpi="90"
y="79.362206"
- x="356"
+ x="357"
height="0.99999923"
- width="29"
+ width="27"
id="rect5577"
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#5a5a5a;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:4;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" />
@@ -1050,9 +1050,9 @@
inkscape:export-ydpi="90"
inkscape:export-xdpi="90"
y="72.362206"
- x="446"
+ x="447"
height="0.99999923"
- width="13"
+ width="12"
id="rect5589"
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#5a5a5a;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:4;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" />
@@ -1114,7 +1114,7 @@
inkscape:export-xdpi="90"
y="80.362206"
x="370"
- height="17.999992"
+ height="17"
width="1"
id="rect5621"
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#5a5a5a;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:4;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" />
@@ -1122,8 +1122,8 @@
inkscape:export-ydpi="90"
inkscape:export-xdpi="90"
y="76.362206"
- x="416"
- height="14"
+ x="413"
+ height="12.999999"
width="1"
id="rect5627"
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#5a5a5a;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:4;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
@@ -1132,8 +1132,8 @@
inkscape:export-ydpi="90"
inkscape:export-xdpi="90"
y="73.362206"
- x="452"
- height="8.9999933"
+ x="451"
+ height="7.999999"
width="1"
id="rect5633"
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#5a5a5a;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:4;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" />
@@ -1169,14 +1169,14 @@
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#5a5a5a;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:4;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
id="path5635-8-1"
sodipodi:type="arc"
- sodipodi:cx="416.5"
+ sodipodi:cx="413.5"
sodipodi:cy="75.862206"
sodipodi:rx="3.5"
sodipodi:ry="3.4999998"
sodipodi:start="0"
sodipodi:end="6.256953"
sodipodi:open="true"
- d="m 420,75.862206 a 3.5,3.4999998 0 0 1 -3.47705,3.499924 3.5,3.4999998 0 0 1 -3.52265,-3.454019 3.5,3.4999998 0 0 1 3.43084,-3.545228 3.5,3.4999998 0 0 1 3.56766,3.40752"
+ d="m 417,75.862206 a 3.5,3.4999998 0 0 1 -3.47705,3.499924 3.5,3.4999998 0 0 1 -3.52265,-3.454019 3.5,3.4999998 0 0 1 3.43084,-3.545228 3.5,3.4999998 0 0 1 3.56766,3.40752"
inkscape:export-filename="icon_device_net_24.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90" />
@@ -1184,14 +1184,14 @@
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#5a5a5a;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:4;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
id="path5635-8-1-3"
sodipodi:type="arc"
- sodipodi:cx="452.5"
+ sodipodi:cx="451.5"
sodipodi:cy="72.862206"
sodipodi:rx="2.5"
sodipodi:ry="2.5"
sodipodi:start="0"
sodipodi:end="6.256953"
sodipodi:open="true"
- d="m 455,72.862206 a 2.5,2.5 0 0 1 -2.4836,2.499946 2.5,2.5 0 0 1 -2.51618,-2.467157 2.5,2.5 0 0 1 2.4506,-2.532306 2.5,2.5 0 0 1 2.54832,2.433943"
+ d="m 454,72.862206 a 2.5,2.5 0 0 1 -2.4836,2.499946 2.5,2.5 0 0 1 -2.51618,-2.467157 2.5,2.5 0 0 1 2.4506,-2.532306 2.5,2.5 0 0 1 2.54832,2.433943"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90" />
+
+ icon_net_light_48.png
+
+
+
+
+
+
+ icon_net_light_32.png
+ icon_net_light_24.png
+ icon_net_light_16.png
+
+
+
+
+
+
+
+
+
diff --git a/src/laybasic/laybasic/layItemDelegates.h b/src/laybasic/laybasic/layItemDelegates.h
index d64363c6f..de214e18a 100644
--- a/src/laybasic/laybasic/layItemDelegates.h
+++ b/src/laybasic/laybasic/layItemDelegates.h
@@ -23,6 +23,8 @@
#ifndef HDR_layItemDelegates
#define HDR_layItemDelegates
+#include "laybasicCommon.h"
+
#include
namespace lay
@@ -33,7 +35,7 @@ namespace lay
/**
* @brief A delegate displaying the display text as HTML formatted text
*/
-class HTMLItemDelegate
+class LAYBASIC_PUBLIC HTMLItemDelegate
: public QStyledItemDelegate
{
Q_OBJECT
diff --git a/src/laybasic/laybasic/layMarker.cc b/src/laybasic/laybasic/layMarker.cc
index 6a3e5a9a8..dff8c12c0 100644
--- a/src/laybasic/laybasic/layMarker.cc
+++ b/src/laybasic/laybasic/layMarker.cc
@@ -713,7 +713,29 @@ Marker::set (const db::Polygon &poly, const db::ICplxTrans &t1, const std::vecto
GenericMarkerBase::set (t1, trans);
}
-void
+void
+Marker::set (const db::PolygonRef &poly, const db::ICplxTrans &trans)
+{
+ remove_object ();
+
+ m_type = PolygonRef;
+ m_object.polygon_ref = new db::PolygonRef (poly);
+
+ GenericMarkerBase::set (trans);
+}
+
+void
+Marker::set (const db::PolygonRef &poly, const db::ICplxTrans &t1, const std::vector &trans)
+{
+ remove_object ();
+
+ m_type = PolygonRef;
+ m_object.polygon_ref = new db::PolygonRef (poly);
+
+ GenericMarkerBase::set (t1, trans);
+}
+
+void
Marker::set (const db::DPolygon &poly, const db::DCplxTrans &trans)
{
remove_object ();
@@ -960,6 +982,8 @@ Marker::item_bbox () const
return *m_object.dbox;
} else if (m_type == Polygon) {
return db::DBox (m_object.polygon->box ());
+ } else if (m_type == PolygonRef) {
+ return db::DBox (m_object.polygon_ref->box ());
} else if (m_type == DPolygon) {
return m_object.dpolygon->box ();
} else if (m_type == EdgePair) {
@@ -996,6 +1020,8 @@ Marker::remove_object ()
delete m_object.dbox;
} else if (m_type == Polygon) {
delete m_object.polygon;
+ } else if (m_type == PolygonRef) {
+ delete m_object.polygon_ref;
} else if (m_type == DPolygon) {
delete m_object.dpolygon;
} else if (m_type == EdgePair) {
@@ -1031,6 +1057,8 @@ Marker::draw (lay::Renderer &r, const db::CplxTrans &t, lay::CanvasPlane *fill,
r.draw (*m_object.dbox, db::DCplxTrans (t), fill, contour, vertex, text);
} else if (m_type == Polygon) {
r.draw (*m_object.polygon, t, fill, contour, vertex, text);
+ } else if (m_type == PolygonRef) {
+ r.draw (m_object.polygon_ref->obj (), t * db::ICplxTrans (m_object.polygon_ref->trans ()), fill, contour, vertex, text);
} else if (m_type == DPolygon) {
r.draw (*m_object.dpolygon, db::DCplxTrans (t), fill, contour, vertex, text);
} else if (m_type == Path) {
diff --git a/src/laybasic/laybasic/layMarker.h b/src/laybasic/laybasic/layMarker.h
index f9e4f4bf7..fbed1e3ae 100644
--- a/src/laybasic/laybasic/layMarker.h
+++ b/src/laybasic/laybasic/layMarker.h
@@ -562,6 +562,16 @@ public:
*/
void set (const db::DPolygon &poly, const db::DCplxTrans &t1, const std::vector &trans);
+ /**
+ * @brief Set the polygon reference the marker is to display
+ */
+ void set (const db::PolygonRef &poly_ref, const db::ICplxTrans &t1);
+
+ /**
+ * @brief Set the polygon reference the marker is to display
+ */
+ void set (const db::PolygonRef &poly_ref, const db::ICplxTrans &t1, const std::vector &trans);
+
/**
* @brief Set the edge pair the marker is to display
*/
@@ -697,7 +707,7 @@ private:
size_t m_max_shapes;
enum {
- None, Box, DBox, Polygon, DPolygon, EdgePair, DEdgePair, Edge, DEdge, Path, DPath, Text, DText, Instance
+ None, Box, DBox, Polygon, PolygonRef, DPolygon, EdgePair, DEdgePair, Edge, DEdge, Path, DPath, Text, DText, Instance
} m_type;
union {
@@ -705,6 +715,7 @@ private:
db::DBox *dbox;
db::Polygon *polygon;
db::DPolygon *dpolygon;
+ db::PolygonRef *polygon_ref;
db::EdgePair *edge_pair;
db::DEdgePair *dedge_pair;
db::Edge *edge;
diff --git a/src/laybasic/laybasic/layNetlistBrowserDialog.cc b/src/laybasic/laybasic/layNetlistBrowserDialog.cc
index 4fe2de9e5..7d0c21c15 100644
--- a/src/laybasic/laybasic/layNetlistBrowserDialog.cc
+++ b/src/laybasic/laybasic/layNetlistBrowserDialog.cc
@@ -332,7 +332,7 @@ NetlistBrowserDialog::configure (const std::string &name, const std::string &val
need_update = lay::test_and_set (m_auto_colors, colors);
- } else if (name == cfg_l2ndb_marker_cycle_colors) {
+ } else if (name == cfg_l2ndb_marker_cycle_colors_enabled) {
bool f = false;
tl::from_string (value, f);
diff --git a/src/laybasic/laybasic/layNetlistBrowserPage.cc b/src/laybasic/laybasic/layNetlistBrowserPage.cc
index 31138ec8a..ba3284341 100644
--- a/src/laybasic/laybasic/layNetlistBrowserPage.cc
+++ b/src/laybasic/laybasic/layNetlistBrowserPage.cc
@@ -23,16 +23,127 @@
#include "layNetlistBrowserPage.h"
#include "layItemDelegates.h"
+#include "layCellView.h"
+#include "layLayoutView.h"
+#include "layMarker.h"
#include "dbLayoutToNetlist.h"
#include "dbNetlistDeviceClasses.h"
#include
+#include
namespace lay
{
extern std::string cfg_l2ndb_show_all;
+// ----------------------------------------------------------------------------------
+// Utilities
+
+template
+static const Attr *attr_by_object_and_index (const Obj *obj, size_t index, const Iter &begin, const Iter &end, std::map > &cache)
+{
+ typename std::map >::iterator cc = cache.find (obj);
+ if (cc == cache.end ()) {
+ cc = cache.insert (std::make_pair (obj, std::map ())).first;
+ }
+
+ typename std::map::iterator c = cc->second.find (index);
+ if (c == cc->second.end ()) {
+
+ c = cc->second.insert (std::make_pair (index, (const Attr *) 0)).first;
+ for (Iter i = begin; i != end; ++i) {
+ if (index-- == 0) {
+ c->second = i.operator-> ();
+ break;
+ }
+ }
+
+ }
+
+ return c->second;
+}
+
+template
+static size_t index_from_attr (const Attr *attr, const Iter &begin, const Iter &end, std::map &cache)
+{
+ typename std::map::iterator cc = cache.find (attr);
+ if (cc != cache.end ()) {
+ return cc->second;
+ }
+
+ size_t index = 0;
+ for (Iter i = begin; i != end; ++i, ++index) {
+ if (i.operator-> () == attr) {
+ cache.insert (std::make_pair (i.operator-> (), index));
+ return index;
+ }
+ }
+
+ tl_assert (false);
+}
+
+// ----------------------------------------------------------------------------------
+// NetColorizer implementation
+
+NetColorizer::NetColorizer ()
+{
+ m_auto_colors_enabled = false;
+}
+
+void
+NetColorizer::configure (const QColor &marker_color, const lay::ColorPalette *auto_colors)
+{
+ m_marker_color = marker_color;
+ if (auto_colors) {
+ m_auto_colors = *auto_colors;
+ m_auto_colors_enabled = true;
+ } else {
+ m_auto_colors_enabled = false;
+ }
+
+ emit colors_changed ();
+}
+
+void
+NetColorizer::set_color_of_net (const db::Net *net, const QColor &color)
+{
+ m_custom_color[net] = color;
+ emit colors_changed ();
+}
+
+void
+NetColorizer::reset_color_of_net (const db::Net *net)
+{
+ m_custom_color.erase (net);
+ emit colors_changed ();
+}
+
+void
+NetColorizer::clear ()
+{
+ m_net_index_by_object.clear ();
+ m_custom_color.clear ();
+ emit colors_changed ();
+}
+
+QColor
+NetColorizer::color_of_net (const db::Net *net) const
+{
+ std::map::const_iterator c = m_custom_color.find (net);
+ if (c != m_custom_color.end ()) {
+ return c->second;
+ }
+
+ if (m_auto_colors_enabled) {
+ const db::Circuit *circuit = net->circuit ();
+ size_t index = index_from_attr (net, circuit->begin_nets (), circuit->end_nets (), m_net_index_by_object);
+ return m_auto_colors.color_by_index ((unsigned int) index);
+ } else {
+ return m_marker_color;
+ }
+}
+
// ----------------------------------------------------------------------------------
// NetlistBrowserModel implementation
@@ -80,10 +191,10 @@ static inline bool always (bool)
return true;
}
-NetlistBrowserModel::NetlistBrowserModel (QWidget *parent, db::LayoutToNetlist *l2ndb)
- : QAbstractItemModel (parent), mp_l2ndb (l2ndb)
+NetlistBrowserModel::NetlistBrowserModel (QWidget *parent, db::LayoutToNetlist *l2ndb, NetColorizer *colorizer)
+ : QAbstractItemModel (parent), mp_l2ndb (l2ndb), mp_colorizer (colorizer)
{
- // .. nothing yet ..
+ connect (mp_colorizer, SIGNAL (colors_changed ()), this, SLOT (colors_changed ()));
}
NetlistBrowserModel::~NetlistBrowserModel ()
@@ -658,7 +769,7 @@ NetlistBrowserModel::text (const QModelIndex &index) const
if (circuit && circuit->pin_by_id (other_index)) {
const db::Pin *pin = circuit->pin_by_id (other_index);
if (index.column () == 0) {
- return tl::to_qstring (pin->expanded_name ());
+ return make_link_to (pin, circuit);
} else {
return make_link_to (ref->subcircuit ()->net_for_pin (pin->id ()));
}
@@ -707,6 +818,16 @@ static QIcon icon_for_net ()
return icon;
}
+static QIcon light_icon_for_net ()
+{
+ QIcon icon;
+ icon.addPixmap (QPixmap (QString::fromUtf8 (":/images/icon_net_light_48.png")));
+ icon.addPixmap (QPixmap (QString::fromUtf8 (":/images/icon_net_light_32.png")));
+ icon.addPixmap (QPixmap (QString::fromUtf8 (":/images/icon_net_light_24.png")));
+ icon.addPixmap (QPixmap (QString::fromUtf8 (":/images/icon_net_light_16.png")));
+ return icon;
+}
+
static QIcon icon_for_pin ()
{
QIcon icon;
@@ -750,17 +871,73 @@ static QIcon icon_for_circuit ()
return icon;
}
+static QIcon net_icon_with_color (const QColor &color)
+{
+ if (! color.isValid ()) {
+ return icon_for_net ();
+ }
+
+ QIcon colored_icon;
+ QIcon original_icon = light_icon_for_net ();
+
+ QList sizes = original_icon.availableSizes ();
+ for (QList::const_iterator i = sizes.begin (); i != sizes.end (); ++i) {
+
+ QImage image (*i, QImage::Format_ARGB32);
+ image.fill (Qt::transparent);
+ QPainter painter (&image);
+ original_icon.paint (&painter, 0, 0, i->width (), i->height ());
+
+ for (int x = 0; x < i->width (); ++x) {
+ for (int y = 0; y < i->height (); ++y) {
+ QRgb pixel = image.pixel (x, y);
+ pixel = (pixel & ~RGB_MASK) | (color.rgb () & RGB_MASK);
+ image.setPixel (x, y, pixel);
+ }
+
+ }
+
+ colored_icon.addPixmap (QPixmap::fromImage (image));
+
+ }
+
+ return colored_icon;
+}
+
+QIcon
+NetlistBrowserModel::icon_for_net (const db::Net *net) const
+{
+ if (mp_colorizer) {
+
+ QColor color = mp_colorizer->color_of_net (net);
+
+ lay::color_t rgb = lay::color_t (color.rgb ());
+ std::map::const_iterator c = m_net_icon_per_color.find (rgb);
+ if (c == m_net_icon_per_color.end ()) {
+ c = m_net_icon_per_color.insert (std::make_pair (rgb, net_icon_with_color (color))).first;
+ }
+
+ return c->second;
+
+ } else {
+ return lay::icon_for_net ();
+ }
+}
+
QIcon
NetlistBrowserModel::icon (const QModelIndex &index) const
{
void *id = index.internalPointer ();
+ const db::Net *net = net_from_index (index);
+ if (net) {
+ return icon_for_net (net);
+ }
+
if (is_id_circuit (id)) {
return icon_for_circuit ();
- } else if (is_id_circuit_pin (id) || is_id_circuit_subcircuit_pin (id)) {
+ } else if (is_id_circuit_pin (id)) {
return icon_for_pin ();
- } else if (is_id_circuit_pin_net (id)) {
- return icon_for_net ();
} else if (is_id_circuit_device (id)) {
const db::Device *device = device_from_id (id);
@@ -768,12 +945,8 @@ NetlistBrowserModel::icon (const QModelIndex &index) const
return icon_for_device (device->device_class ());
}
- } else if (is_id_circuit_device_terminal (id)) {
- return icon_for_net ();
} else if (is_id_circuit_subcircuit (id)) {
return icon_for_circuit ();
- } else if (is_id_circuit_net (id)) {
- return icon_for_net ();
} else if (is_id_circuit_net_pin (id) || is_id_circuit_net_subcircuit_pin_others (id)) {
return icon_for_pin ();
} else if (is_id_circuit_net_subcircuit_pin (id)) {
@@ -785,8 +958,6 @@ NetlistBrowserModel::icon (const QModelIndex &index) const
return icon_for_device (ref->device ()->device_class ());
}
- } else if (is_id_circuit_net_device_terminal_others (id)) {
- return icon_for_net ();
}
return QIcon ();
@@ -923,6 +1094,76 @@ NetlistBrowserModel::index (int row, int column, const QModelIndex &parent) cons
return createIndex (row, column, new_id);
}
+void
+NetlistBrowserModel::colors_changed ()
+{
+ // @@@ TODO: refresh colors of nets
+}
+
+const db::Net *
+NetlistBrowserModel::net_from_index (const QModelIndex &index) const
+{
+ void *id = index.internalPointer ();
+ if (is_id_circuit_net (id)) {
+
+ return net_from_id (id);
+
+ } else if (is_id_circuit_device_terminal (id)) {
+
+ const db::Device *device = device_from_id (id);
+ if (device && device->device_class ()) {
+ size_t terminal = circuit_device_terminal_index_from_id (id);
+ if (device->device_class ()->terminal_definitions ().size () > terminal) {
+ return device->net_for_terminal (device->device_class ()->terminal_definitions () [terminal].id ());
+ }
+ }
+
+ } else if (is_id_circuit_pin_net (id)) {
+
+ const db::Circuit *circuit = circuit_from_id (id);
+ const db::Pin *pin = pin_from_id (id);
+ if (pin) {
+ return circuit->net_for_pin (pin->id ());
+ }
+
+ } else if (is_id_circuit_subcircuit_pin (id)) {
+
+ const db::SubCircuit *subcircuit = subcircuit_from_id (id);
+ if (subcircuit && subcircuit->circuit () && subcircuit->circuit_ref ()) {
+ const db::Pin *pin = pin_from_id (id);
+ if (pin) {
+ return subcircuit->net_for_pin (pin->id ());
+ }
+ }
+
+ } else if (is_id_circuit_net_subcircuit_pin_others (id)) {
+
+ const db::NetSubcircuitPinRef *ref = net_subcircuit_pinref_from_id (id);
+ size_t other_index = circuit_net_subcircuit_pin_other_index_from_id (id);
+
+ if (ref && ref->pin () && ref->subcircuit ()) {
+ const db::Circuit *circuit = ref->subcircuit ()->circuit_ref ();
+ if (circuit && circuit->pin_by_id (other_index)) {
+ const db::Pin *pin = circuit->pin_by_id (other_index);
+ return ref->subcircuit ()->net_for_pin (pin->id ());
+ }
+ }
+
+ } else if (is_id_circuit_net_device_terminal_others (id)) {
+
+ const db::NetTerminalRef *ref = net_terminalref_from_id (id);
+ size_t other_index = circuit_net_device_terminal_other_index_from_id (id);
+
+ if (ref && ref->device_class () && ref->device_class ()->terminal_definitions ().size () > other_index) {
+ const db::DeviceTerminalDefinition &def = ref->device_class ()->terminal_definitions ()[other_index];
+ return ref->device ()->net_for_terminal (def.id ());
+ }
+
+ }
+
+ return 0;
+}
+
QModelIndex
NetlistBrowserModel::index_from_id (void *id, int column) const
{
@@ -1107,30 +1348,6 @@ NetlistBrowserModel::circuit_from_id (void *id) const
return c->second;
}
-template
-static const Attr *attr_by_object_and_index (const Obj *obj, size_t index, const Iter &begin, const Iter &end, std::map > &cache)
-{
- typename std::map >::iterator cc = cache.find (obj);
- if (cc == cache.end ()) {
- cc = cache.insert (std::make_pair (obj, std::map ())).first;
- }
-
- typename std::map::iterator c = cc->second.find (index);
- if (c == cc->second.end ()) {
-
- c = cc->second.insert (std::make_pair (index, (const Attr *) 0)).first;
- for (Iter i = begin; i != end; ++i) {
- if (index-- == 0) {
- c->second = i.operator-> ();
- break;
- }
- }
-
- }
-
- return c->second;
-}
-
const db::Net *
NetlistBrowserModel::net_from_id (void *id) const
{
@@ -1215,25 +1432,6 @@ NetlistBrowserModel::subcircuit_from_id (void *id) const
}
}
-template
-static size_t index_from_attr (const Attr *attr, const Iter &begin, const Iter &end, std::map &cache)
-{
- typename std::map::iterator cc = cache.find (attr);
- if (cc != cache.end ()) {
- return cc->second;
- }
-
- size_t index = 0;
- for (Iter i = begin; i != end; ++i, ++index) {
- if (i.operator-> () == attr) {
- cache.insert (std::make_pair (i.operator-> (), index));
- return index;
- }
- }
-
- tl_assert (false);
-}
-
size_t
NetlistBrowserModel::circuit_index (const db::Circuit *circuit) const
{
@@ -1273,12 +1471,13 @@ NetlistBrowserPage::NetlistBrowserPage (QWidget * /*parent*/)
m_marker_halo (-1),
m_marker_dither_pattern (-1),
m_marker_intensity (0),
- m_auto_colors_enabled (false),
mp_view (0),
m_cv_index (0),
mp_plugin_root (0),
m_history_ptr (0),
- m_signals_enabled (true)
+ m_signals_enabled (true),
+ m_enable_updates (true),
+ m_update_needed (true)
{
Ui::NetlistBrowserPage::setupUi (this);
@@ -1314,7 +1513,7 @@ NetlistBrowserPage::NetlistBrowserPage (QWidget * /*parent*/)
NetlistBrowserPage::~NetlistBrowserPage ()
{
- // .. nothing yet ..
+ clear_markers ();
}
void
@@ -1326,16 +1525,12 @@ NetlistBrowserPage::set_plugin_root (lay::PluginRoot *pr)
void
NetlistBrowserPage::set_highlight_style (QColor color, int line_width, int vertex_size, int halo, int dither_pattern, int marker_intensity, const lay::ColorPalette *auto_colors)
{
- m_marker_color = color;
+ m_colorizer.configure (color, auto_colors);
m_marker_line_width = line_width;
m_marker_vertex_size = vertex_size;
m_marker_halo = halo;
m_marker_dither_pattern = dither_pattern;
m_marker_intensity = marker_intensity;
- m_auto_colors_enabled = (auto_colors != 0);
- if (auto_colors) {
- m_auto_colors = *auto_colors;
- }
update_highlights ();
}
@@ -1361,9 +1556,7 @@ NetlistBrowserPage::set_max_shape_count (size_t max_shape_count)
{
if (m_max_shape_count != max_shape_count) {
m_max_shape_count = max_shape_count;
-#if 0 // @@@
- update_marker_list (1 /*select first*/);
-#endif
+ update_highlights ();
}
}
@@ -1380,6 +1573,21 @@ NetlistBrowserPage::anchor_clicked (const QString &a)
navigate_to (id, true);
}
+void
+NetlistBrowserPage::current_index_changed (const QModelIndex &index)
+{
+ if (index.isValid () && m_signals_enabled) {
+
+ void *id = index.internalPointer ();
+ add_to_history (id, true);
+
+ NetlistBrowserModel *model = dynamic_cast (directory_tree->model ());
+ tl_assert (model != 0);
+ show_net (model->net_from_index (index));
+
+ }
+}
+
void
NetlistBrowserPage::navigate_to (void *id, bool fwd)
{
@@ -1401,14 +1609,8 @@ NetlistBrowserPage::navigate_to (void *id, bool fwd)
m_signals_enabled = true;
add_to_history (id, fwd);
-}
-void
-NetlistBrowserPage::current_index_changed (const QModelIndex &index)
-{
- if (index.isValid () && m_signals_enabled) {
- add_to_history (index.internalPointer (), true);
- }
+ show_net (model->net_from_index (index));
}
void
@@ -1488,50 +1690,25 @@ NetlistBrowserPage::show_all (bool f)
}
}
-void
-NetlistBrowserPage::update_highlights ()
-{
-#if 0
- if (! m_enable_updates) {
- m_update_needed = true;
- return;
- }
-
- if (m_recursion_sentinel) {
- return;
- }
-
- m_recursion_sentinel = true;
- try {
- do_update_markers ();
- } catch (...) {
- m_recursion_sentinel = false;
- throw;
- }
- m_recursion_sentinel = false;
-#endif
-}
-
void
NetlistBrowserPage::set_l2ndb (db::LayoutToNetlist *database)
{
if (database != mp_database.get ()) {
mp_database.reset (database);
+ clear_markers ();
+ show_net (0);
if (! database) {
directory_tree->setModel (0);
return;
}
- // @@@ release_markers ();
-
// NOTE: with the tree as the parent, the tree will take over ownership of the model
- NetlistBrowserModel *new_model = new NetlistBrowserModel (directory_tree, database);
+ NetlistBrowserModel *new_model = new NetlistBrowserModel (directory_tree, database, &m_colorizer);
directory_tree->setModel (new_model);
connect (directory_tree->selectionModel (), SIGNAL (currentChanged (const QModelIndex &, const QModelIndex &)), this, SLOT (current_index_changed (const QModelIndex &)));
- // @@@ connect (directory_tree->selectionModel (), SIGNAL (selectionChanged (const QItemSelection &, const QItemSelection &)), this, SLOT (directory_selection_changed (const QItemSelection &, const QItemSelection &)));
directory_tree->header ()->setSortIndicatorShown (true);
@@ -1540,23 +1717,200 @@ NetlistBrowserPage::set_l2ndb (db::LayoutToNetlist *database)
}
}
+void
+NetlistBrowserPage::show_net (const db::Net *net)
+{
+ if (net != mp_current_net) {
+
+ mp_current_net = net;
+ clear_markers ();
+
+ if (net) {
+ adjust_view ();
+ update_highlights ();
+ }
+
+ }
+}
+
void
NetlistBrowserPage::enable_updates (bool f)
{
-#if 0 // @@@
if (f != m_enable_updates) {
m_enable_updates = f;
if (f && m_update_needed) {
- update_markers ();
- update_info_text ();
+ update_highlights ();
+ // @@@ update_info_text ();
}
m_update_needed = false;
}
+}
+
+void
+NetlistBrowserPage::adjust_view ()
+{
+ if (! mp_database.get () || ! mp_view || ! mp_current_net || ! mp_current_net->circuit ()) {
+ return;
+ }
+
+ const lay::CellView &cv = mp_view->cellview (m_cv_index);
+ if (! cv.is_valid ()) {
+ return;
+ }
+
+ if (m_window != lay::NetlistBrowserConfig::FitNet && m_window != lay::NetlistBrowserConfig::Center && m_window != lay::NetlistBrowserConfig::CenterSize) {
+ return;
+ }
+
+ const db::Layout *layout = mp_database->internal_layout ();
+ if (! layout) {
+ return;
+ }
+
+ db::cell_index_type cell_index = mp_current_net->circuit ()->cell_index ();
+ size_t cluster_id = mp_current_net->cluster_id ();
+
+ db::DBox bbox;
+
+ // @@@std::map > tv_by_layer = mp_view->cv_transform_variants_by_layer (m_cv_index);
+ std::vector tv = mp_view->cv_transform_variants (m_cv_index);
+
+ const db::Connectivity &conn = mp_database->connectivity ();
+ for (db::Connectivity::layer_iterator layer = conn.begin_layers (); layer != conn.end_layers (); ++layer) {
+
+ // @@@ TODO: how to get the original layer?
+
+ db::Box layer_bbox;
+ db::recursive_cluster_shape_iterator shapes (mp_database->net_clusters (), *layer, cell_index, cluster_id);
+ while (! shapes.at_end ()) {
+ layer_bbox += shapes.trans () * shapes->box ();
+ ++shapes;
+ }
+
+ for (std::vector::const_iterator t = tv.begin (); t != tv.end (); ++t) {
+ bbox += *t * db::CplxTrans (layout->dbu ()) * layer_bbox;
+ }
+
+ }
+
+ if (! bbox.empty ()) {
+
+ if (m_window == lay::NetlistBrowserConfig::FitNet) {
+
+ mp_view->zoom_box (bbox.enlarged (db::DVector (m_window_dim, m_window_dim)));
+
+ } else if (m_window == lay::NetlistBrowserConfig::Center) {
+
+ mp_view->pan_center (bbox.p1 () + (bbox.p2 () - bbox.p1 ()) * 0.5);
+
+ } else if (m_window == lay::NetlistBrowserConfig::CenterSize) {
+
+ double w = std::max (bbox.width (), m_window_dim);
+ double h = std::max (bbox.height (), m_window_dim);
+ db::DPoint center (bbox.p1() + (bbox.p2 () - bbox.p1 ()) * 0.5);
+ db::DVector d (w * 0.5, h * 0.5);
+ mp_view->zoom_box (db::DBox (center - d, center + d));
+
+ }
+
+ }
+}
+
+void
+NetlistBrowserPage::update_highlights ()
+{
+ if (! m_enable_updates) {
+ m_update_needed = true;
+ return;
+ }
+
+ clear_markers ();
+
+ if (! mp_database.get () || ! mp_view || ! mp_current_net || ! mp_current_net->circuit ()) {
+ return;
+ }
+
+ const db::Layout *layout = mp_database->internal_layout ();
+ if (! layout) {
+ return;
+ }
+
+ db::cell_index_type cell_index = mp_current_net->circuit ()->cell_index ();
+ size_t cluster_id = mp_current_net->cluster_id ();
+
+ // @@@std::map > tv_by_layer = mp_view->cv_transform_variants_by_layer (m_cv_index);
+ std::vector tv = mp_view->cv_transform_variants (m_cv_index);
+
+ size_t n_markers = 0;
+ QColor net_color = m_colorizer.color_of_net (mp_current_net);
+
+ const db::Connectivity &conn = mp_database->connectivity ();
+ for (db::Connectivity::layer_iterator layer = conn.begin_layers (); layer != conn.end_layers (); ++layer) {
+
+ // @@@ TODO: how to get the original layer?
+
+ db::recursive_cluster_shape_iterator shapes (mp_database->net_clusters (), *layer, cell_index, cluster_id);
+ while (! shapes.at_end () && n_markers < m_max_shape_count) {
+
+ mp_markers.push_back (new lay::Marker (mp_view, m_cv_index));
+ mp_markers.back ()->set (*shapes, shapes.trans (), tv);
+
+#if 0
+// @@@
+ if (! original.at_end ()) {
+ mp_markers.back ()->set_line_width (original->width (true));
+ mp_markers.back ()->set_vertex_size (1);
+ mp_markers.back ()->set_dither_pattern (original->dither_pattern (true));
+ if (view ()->background_color ().green () < 128) {
+ mp_markers.back ()->set_color (original->eff_fill_color_brighter (true, (m_marker_intensity * 255) / 100));
+ mp_markers.back ()->set_frame_color (original->eff_frame_color_brighter (true, (m_marker_intensity * 255) / 100));
+ } else {
+ mp_markers.back ()->set_color (original->eff_fill_color_brighter (true, (-m_marker_intensity * 255) / 100));
+ mp_markers.back ()->set_frame_color (original->eff_frame_color_brighter (true, (-m_marker_intensity * 255) / 100));
+ }
+ }
#endif
+ // @@@
+ mp_markers.back ()->set_color (net_color);
+ mp_markers.back ()->set_frame_color (net_color);
+ // @@@
+
+ if (m_marker_line_width >= 0) {
+ mp_markers.back ()->set_line_width (m_marker_line_width);
+ }
+
+ if (m_marker_vertex_size >= 0) {
+ mp_markers.back ()->set_vertex_size (m_marker_vertex_size);
+ }
+
+ if (m_marker_halo >= 0) {
+ mp_markers.back ()->set_halo (m_marker_halo);
+ }
+
+ if (m_marker_dither_pattern >= 0) {
+ mp_markers.back ()->set_dither_pattern (m_marker_dither_pattern);
+ }
+
+ ++shapes;
+ ++n_markers;
+
+ }
+
+ }
+}
+
+void
+NetlistBrowserPage::clear_markers ()
+{
+ for (std::vector ::iterator m = mp_markers.begin (); m != mp_markers.end (); ++m) {
+ delete *m;
+ }
+
+ mp_markers.clear ();
}
}
diff --git a/src/laybasic/laybasic/layNetlistBrowserPage.h b/src/laybasic/laybasic/layNetlistBrowserPage.h
index 8a81cbeae..b5d5c1e9b 100644
--- a/src/laybasic/laybasic/layNetlistBrowserPage.h
+++ b/src/laybasic/laybasic/layNetlistBrowserPage.h
@@ -41,6 +41,36 @@ namespace lay
class LayoutView;
class PluginRoot;
+class Marker;
+
+// ----------------------------------------------------------------------------------
+// NetColorizer definition
+
+class LAYBASIC_PUBLIC NetColorizer
+ : public QObject
+{
+Q_OBJECT
+
+public:
+ NetColorizer ();
+
+ void configure (const QColor &marker_color, const lay::ColorPalette *auto_colors);
+ void set_color_of_net (const db::Net *net, const QColor &color);
+ void reset_color_of_net (const db::Net *net);
+ void clear ();
+
+ QColor color_of_net (const db::Net *net) const;
+
+signals:
+ void colors_changed ();
+
+private:
+ QColor m_marker_color;
+ lay::ColorPalette m_auto_colors;
+ bool m_auto_colors_enabled;
+ std::map m_custom_color;
+ mutable std::map m_net_index_by_object;
+};
// ----------------------------------------------------------------------------------
// NetlistBrowserModel definition
@@ -66,8 +96,10 @@ class PluginRoot;
class LAYBASIC_PUBLIC NetlistBrowserModel
: public QAbstractItemModel
{
+Q_OBJECT
+
public:
- NetlistBrowserModel (QWidget *parent, db::LayoutToNetlist *l2ndb);
+ NetlistBrowserModel (QWidget *parent, db::LayoutToNetlist *l2ndb, NetColorizer *colorizer);
~NetlistBrowserModel ();
virtual int columnCount (const QModelIndex &parent) const;
@@ -81,6 +113,11 @@ public:
QModelIndex index_from_id (void *id, int column) const;
+ const db::Net *net_from_index (const QModelIndex &index) const;
+
+private slots:
+ void colors_changed ();
+
private:
void *make_id_circuit (size_t circuit_index) const;
void *make_id_circuit_pin (size_t circuit_index, size_t pin_index) const;
@@ -144,7 +181,10 @@ private:
return const_cast (mp_l2ndb->netlist ());
}
+ QIcon icon_for_net (const db::Net *net) const;
+
db::LayoutToNetlist *mp_l2ndb;
+ NetColorizer *mp_colorizer;
mutable std::map m_circuit_by_index;
mutable std::map > m_net_by_circuit_and_index;
mutable std::map > m_subcircuit_pinref_by_net_and_index;
@@ -157,6 +197,7 @@ private:
mutable std::map m_net_index_by_object;
mutable std::map m_pin_index_by_object;
mutable std::map m_subcircuit_index_by_object;
+ mutable std::map m_net_icon_per_color;
};
/**
@@ -206,14 +247,6 @@ public:
*/
void set_window (lay::NetlistBrowserConfig::net_window_type window_type, double window_dim);
- /**
- * @brief Update the net highlights
- *
- * This method should be called if the cellview has changed so the highlights can
- * be recomputed and shown in the new cell context.
- */
- void update_highlights ();
-
/**
* @brief Set the maximum number of shapes highlighted for a net
*/
@@ -250,6 +283,11 @@ public:
*/
void enable_updates (bool f);
+ /**
+ * @brief Updates net highlights
+ */
+ void update_highlights ();
+
private slots:
void show_all_clicked ();
void filter_changed ();
@@ -261,17 +299,15 @@ private slots:
private:
bool m_show_all;
QAction *m_show_all_action;
+ NetColorizer m_colorizer;
NetlistBrowserConfig::net_window_type m_window;
double m_window_dim;
size_t m_max_shape_count;
- QColor m_marker_color;
int m_marker_line_width;
int m_marker_vertex_size;
int m_marker_halo;
int m_marker_dither_pattern;
int m_marker_intensity;
- lay::ColorPalette m_auto_colors;
- bool m_auto_colors_enabled;
lay::LayoutView *mp_view;
unsigned int m_cv_index;
lay::PluginRoot *mp_plugin_root;
@@ -279,9 +315,16 @@ private:
std::vector m_history;
size_t m_history_ptr;
bool m_signals_enabled;
+ std::vector mp_markers;
+ bool m_enable_updates;
+ bool m_update_needed;
+ const db::Net *mp_current_net;
void add_to_history (void *id, bool fwd);
void navigate_to (void *id, bool forward = true);
+ void adjust_view ();
+ void clear_markers ();
+ void show_net (const db::Net *net);
};
} // namespace lay
diff --git a/src/laybasic/laybasic/laybasicResources.qrc b/src/laybasic/laybasic/laybasicResources.qrc
index 23dfc02e8..c9869e87c 100644
--- a/src/laybasic/laybasic/laybasicResources.qrc
+++ b/src/laybasic/laybasic/laybasicResources.qrc
@@ -24,5 +24,9 @@
images/icon_circuit_24.png
images/icon_circuit_32.png
images/icon_circuit_48.png
+ images/icon_net_light_16.png
+ images/icon_net_light_24.png
+ images/icon_net_light_32.png
+ images/icon_net_light_48.png
diff --git a/src/laybasic/unit_tests/layNetlistBrowserModelTests.cc b/src/laybasic/unit_tests/layNetlistBrowserModelTests.cc
index 59ab5cf22..e168b9eec 100644
--- a/src/laybasic/unit_tests/layNetlistBrowserModelTests.cc
+++ b/src/laybasic/unit_tests/layNetlistBrowserModelTests.cc
@@ -28,7 +28,8 @@ TEST (1)
db::LayoutToNetlist l2n;
l2n.load (tl::testsrc () + "/testdata/lay/l2n_browser.l2n");
- std::auto_ptr model (new lay::NetlistBrowserModel (0, &l2n));
+ lay::NetColorizer colorizer;
+ std::auto_ptr model (new lay::NetlistBrowserModel (0, &l2n, &colorizer));
EXPECT_EQ (model->hasChildren (QModelIndex ()), true);
// two circuits