Skip to content

Conversation

@marc-romu
Copy link
Member

@marc-romu marc-romu commented Aug 23, 2025

Description

Adds visual badges to SmartHopper components to surface AI model status at-a-glance and improves inline UI overlays.

  • Model badges: Floating badges above components for model status:
    • Verified (green check)
    • Deprecated (orange warning)
  • Provider strip: Shows inline label on hover.
  • Model resolution: Uses last-used model from metrics when available; otherwise uses configured/default model.
  • Centralized capabilities: Queries ModelManager for Verified and Deprecated flags.
  • Hover labels: Tooltip-like inline labels on hover for badges and provider icon, auto-hide after 5s.
  • Performance: Badge flags cached per component to avoid recomputation during panning/render.

Implementation details

  • src/SmartHopper.Core/ComponentBase/ComponentBadgesAttributes.cs
    • Renders floating badges above the component.
    • Expands Bounds upward so hover events hit the floating area in Layout().
    • Draws inline labels via InlineLabelRenderer.DrawInlineLabel(...).
    • 5s auto-hide timer for badge labels; repaints via OnDisplayExpired(false).
  • src/SmartHopper.Core/ComponentBase/AIProviderComponentAttributes.cs
    • Renders provider icon in bottom strip.
    • Hover label “Using provider”; 5s auto-hide; repaints via OnDisplayExpired(false).
  • src/SmartHopper.Core/ComponentBase/InlineLabelRenderer.cs
    • Centralized helper to draw compact inline tooltip-like labels.
  • src/SmartHopper.Core/ComponentBase/AIStatefulAsyncComponentBase.cs
    • CreateAttributes() now uses ComponentBadgesAttributes.
    • Badge cache: UpdateBadgeCache(), TryGetCachedBadgeFlags(out bool verified, out bool deprecated).
    • Resolves model for badges via GetLastMetricsModel() or GetModelToDisplay().
    • Calls UpdateBadgeCache() before and after SolveInstance to reflect latest metrics.
  • src/SmartHopper.Core/ComponentBase/SelectingComponentBase.cs
    • Selection highlight (dashed rectangles) uses 5s auto-hide; repaints via OnDisplayExpired(false).

UI/UX

  • Zoom threshold ≥ 0.5 to render provider and badges.
  • Badges centered above the component; provider icon centered in bottom strip.
  • Labels auto-hide after 5s to avoid sticky overlays.

Breaking Changes

  • None. Additive UI-only feature.

Testing Done

  • Manual
    • Place an AI component; ensure provider is set.
    • Zoom ≥ 0.5. Hover provider icon: inline label shows and auto-hides after 5s.
    • Hover badges above the component: label shows and auto-hides after 5s.
    • Run a tool to produce metrics; verify badges reflect last-used model; if none, fallback to configured/default.
  • Behavioral validation
    • Smooth panning/zooming due to cached flags.
    • Auto-hidden state prevents re-show until hover state changes.

Risks and mitigations

  • Render performance: mitigated via cached badge flags and zoom gating.

Future work

  • Additional badge types (e.g., automatic model replacement).
  • Expand capability-driven badges as ModelManager metadata evolves.

Checklist

  • This PR is focused on a single feature or bug fix
  • Version in Solution.props was updated, if necessary, and follows semantic versioning
  • CHANGELOG.md has been updated
  • PR title follows Conventional Commits format
  • PR description follows Pull Request Description Template

Copilot AI review requested due to automatic review settings August 23, 2025 16:23
@github-actions
Copy link
Contributor

🏷️ This PR has been automatically assigned to milestone 0.6.0-alpha based on the version in Solution.props.

@github-actions github-actions bot added this to the 0.6.0-alpha milestone Aug 23, 2025
@marc-romu marc-romu changed the title feat(components/ui): add model badges (Verified/Deprecated) with hover labels and provider strip feat(components/ui): add model badges with hover labels and provider strip Aug 23, 2025
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull Request Overview

This PR adds visual badges and hover labels to SmartHopper components to surface AI model status (Verified/Deprecated) and provider information directly in the UI. The implementation includes floating badges above components that appear at zoom ≥ 0.5, provider icon strips at the bottom of components, and tooltip-like labels that auto-hide after 5 seconds.

  • Model badges showing verified (green check) and deprecated (orange warning) status
  • Provider strip with hover labels showing "Using [provider] provider"
  • Auto-hiding tooltip system with 5-second timers to prevent sticky overlays

Reviewed Changes

Copilot reviewed 15 out of 15 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
ComponentBadgesAttributes.cs New custom attributes class for rendering floating model status badges with hover support
InlineLabelRenderer.cs New utility class for drawing consistent tooltip-like labels
AIProviderComponentAttributes.cs Enhanced to add hover labels for provider icons with auto-hide functionality
AIStatefulAsyncComponentBase.cs Added badge caching and model resolution for UI display
SelectingComponentBase.cs Updated selection highlight to use auto-hide timer system
Test components Three new test components for validating badge rendering with 1, 2, and 3 badges

Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.

Comment on lines +50 to +53
// Timer-based auto-hide for inline badge labels (disappears after 5s even if still hovered)
// Purpose: avoid sticky labels when the cursor remains stationary over a badge.
private Timer? badgeLabelTimer;
private bool badgeLabelAutoHidden = false;
Copy link

Copilot AI Aug 23, 2025

Choose a reason for hiding this comment

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

Timer instances should be properly disposed to prevent memory leaks. Consider implementing IDisposable on this class or ensure timer cleanup in all code paths, as the current implementation only disposes timers in specific scenarios.

Copilot uses AI. Check for mistakes.
Comment on lines +72 to +75
// Ensure the attribute bounds include the floating badges region above the component
// so that Grasshopper dispatches mouse events when hovering the badges.
var bounds = this.Bounds;
float extendTop = FLOAT_OFFSET + BADGE_SIZE;
Copy link

Copilot AI Aug 23, 2025

Choose a reason for hiding this comment

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

The bounds manipulation uses magic numbers and assumes FLOAT_OFFSET is negative. Consider adding validation that FLOAT_OFFSET is negative, or use Math.Abs() to make the intent clearer and prevent layout issues if the constant changes.

Suggested change
// Ensure the attribute bounds include the floating badges region above the component
// so that Grasshopper dispatches mouse events when hovering the badges.
var bounds = this.Bounds;
float extendTop = FLOAT_OFFSET + BADGE_SIZE;
float extendTop = Math.Abs(FLOAT_OFFSET) + BADGE_SIZE;

Copilot uses AI. Check for mistakes.
Comment on lines +37 to +40
// Timer-based auto-hide for inline label (disappears after 5s even if still hovered)
// Purpose: avoid sticky labels when the cursor remains stationary.
private Timer? providerLabelTimer;
private bool providerLabelAutoHidden = false;
Copy link

Copilot AI Aug 23, 2025

Choose a reason for hiding this comment

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

Similar to ComponentBadgesAttributes, this class uses Timer instances that should be properly disposed. Consider implementing IDisposable or ensuring timer cleanup in all scenarios to prevent memory leaks.

Copilot uses AI. Check for mistakes.
Comment on lines +113 to +115
// Timer-based auto-hide of the visual highlight for selected objects.
// Purpose: ensure the dashed highlight disappears after 5s even if the cursor stays hovered.
private Timer? selectDisplayTimer;
Copy link

Copilot AI Aug 23, 2025

Choose a reason for hiding this comment

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

This class also uses Timer instances without implementing IDisposable. The timer disposal pattern is repeated across multiple classes - consider creating a shared auto-hide timer utility class to centralize this functionality and ensure proper resource management.

Suggested change
// Timer-based auto-hide of the visual highlight for selected objects.
// Purpose: ensure the dashed highlight disappears after 5s even if the cursor stays hovered.
private Timer? selectDisplayTimer;
private AutoHideTimer? selectDisplayTimer;

Copilot uses AI. Check for mistakes.
@marc-romu marc-romu changed the title feat(components/ui): add model badges with hover labels and provider strip feat(components): add model badges with hover labels and provider strip Aug 23, 2025
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.

@marc-romu marc-romu merged commit cf8ea62 into dev Aug 23, 2025
9 of 10 checks passed
@github-actions github-actions bot deleted the feat/0.6.0-component-badges branch August 23, 2025 17:33
@marc-romu marc-romu modified the milestones: 0.6.0-alpha, 1.0.0-alpha Oct 11, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants