Skip to content

gui: Add context menu to WebGUI#10630

Open
jorge-ferreira-pii wants to merge 1 commit into
The-OpenROAD-Project:masterfrom
The-OpenROAD-Project-staging:feature-context-menu-WebGUI
Open

gui: Add context menu to WebGUI#10630
jorge-ferreira-pii wants to merge 1 commit into
The-OpenROAD-Project:masterfrom
The-OpenROAD-Project-staging:feature-context-menu-WebGUI

Conversation

@jorge-ferreira-pii

@jorge-ferreira-pii jorge-ferreira-pii commented Jun 10, 2026

Copy link
Copy Markdown
Contributor

Addresses a portion of #10619

2.7 Right-click context menu (layout canvas)

Feature GUI Web Status
Select → Connected Insts / Output / Input / All Nets / All buffer trees layoutViewer
Highlight → same + 8-color submenu yes
Save → Visible / Entire layout yes
Clear → Selections/Highlights/Rulers/Labels/Focus/Guides/Tracks/All yes partial (Clear Rulers in Tools)

2.12 Rulers & labels

Feature GUI Web Status
Custom labels / text annotations label.{h,cpp}, add_label

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces a context menu and label management system to the web layout viewer, allowing users to select, highlight, clear, and download layout images. It also adds backend support for processing these context actions and rendering colored polygons. The review identified two issues: an open polygon outline bug in TileGenerator::drawColoredPolygons where the final edge is not drawn, and a signed-to-unsigned conversion bug in toWebHighlightColor that can cause incorrect modulo results when the highlight group index is negative.

Comment thread src/web/src/tile_generator.cpp Outdated
Comment on lines +3641 to +3652
for (int i = 0; i < n - 1; ++i) {
const int px0
= static_cast<int>((points[i].x() - dbu_tile.xMin()) * scale);
const int py0
= 255 - static_cast<int>((points[i].y() - dbu_tile.yMin()) * scale);
const int px1
= static_cast<int>((points[i + 1].x() - dbu_tile.xMin()) * scale);
const int py1
= 255
- static_cast<int>((points[i + 1].y() - dbu_tile.yMin()) * scale);
drawLine(image, px0, py0, px1, py1, border);
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The loop only draws lines between consecutive points up to n - 1, which leaves the polygon outline open because the final edge connecting the last point (points[n-1]) back to the first point (points[0]) is never drawn.

To ensure the polygon outline is fully closed (regardless of whether the input points list is already closed or open), we should iterate up to n and use modulo arithmetic to wrap around to the first point.

    for (int i = 0; i < n; ++i) {
      const auto& p0 = points[i];
      const auto& p1 = points[(i + 1) % n];
      const int px0
          = static_cast<int>((p0.x() - dbu_tile.xMin()) * scale);
      const int py0
          = 255 - static_cast<int>((p0.y() - dbu_tile.yMin()) * scale);
      const int px1
          = static_cast<int>((p1.x() - dbu_tile.xMin()) * scale);
      const int py1
          = 255
            - static_cast<int>((p1.y() - dbu_tile.yMin()) * scale);
      drawLine(image, px0, py0, px1, py1, border);
    }

Comment on lines +832 to +841
Color toWebHighlightColor(const int group)
{
const auto& colors = gui::Painter::kHighlightColors;
const auto& c
= colors[((group % colors.size()) + colors.size()) % colors.size()];
return Color{static_cast<unsigned char>(c.r),
static_cast<unsigned char>(c.g),
static_cast<unsigned char>(c.b),
static_cast<unsigned char>(c.a)};
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

In toWebHighlightColor, colors.size() is of type size_t (unsigned). When performing group % colors.size(), the signed group is implicitly converted to size_t (unsigned). If group is negative, this leads to incorrect modulo results on non-power-of-two sizes, and can also trigger compiler warnings (e.g., -Wsign-conversion).

We should cast colors.size() to int first to ensure signed arithmetic is used, and also add a defensive check to prevent division by zero if colors is empty.

Color toWebHighlightColor(const int group)
{
  const auto& colors = gui::Painter::kHighlightColors;
  const int num_colors = static_cast<int>(colors.size());
  if (num_colors == 0) {
    return Color{0, 0, 0, 255};
  }
  const auto& c
      = colors[((group % num_colors) + num_colors) % num_colors];
  return Color{static_cast<unsigned char>(c.r),
               static_cast<unsigned char>(c.g),
               static_cast<unsigned char>(c.b),
               static_cast<unsigned char>(c.a)};
}

@jorge-ferreira-pii

Copy link
Copy Markdown
Contributor Author

Frontend (UI & Interactions)

context-menu.js, add-label-widget.js, main.js, style.css & CMakeLists.txt: Added a custom right-click context menu to the layout viewer. The menu allows users to add/remove custom text labels, select or highlight connected objects (instances, nets, buffer trees) with specific colors, clear highlights, and download images of the layout. The mouse events were updated to support both the new menu and the existing right-click drag zoom.
Backend (WebSocket & Database)

request_handler.cpp & .h: Added a new WebSocket handler for context_action messages. It implements the logic to traverse the database to find connected nets, instances, and buffer trees, and updates the session state to track these new colored highlights and net flightlines.
Backend (Rendering & HTTP)

tile_generator.cpp/h & web.cpp: Enhanced the tile generator to support drawing colored polygons for highlights. Extracted the PNG generation logic into a new in-memory function (renderImagePng) and created a new HTTP endpoint (/download/image) to serve layout screenshots directly to the user's browser.

@openroad-ci openroad-ci force-pushed the feature-context-menu-WebGUI branch from 90a810e to c52ef75 Compare June 10, 2026 12:34
Signed-off-by: Jorge Ferreira <jorge.ferreira@precisioninno.com>
@openroad-ci openroad-ci force-pushed the feature-context-menu-WebGUI branch from c52ef75 to 019659d Compare June 10, 2026 13:01
@jorge-ferreira-pii jorge-ferreira-pii marked this pull request as ready for review June 10, 2026 13:10
@jorge-ferreira-pii jorge-ferreira-pii requested a review from a team as a code owner June 10, 2026 13:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant