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