Skip to content

Comments

Custom selection context commands#81

Open
GeKtvi wants to merge 10 commits intoCAD-Booster:developfrom
GeKtvi:contextMenu2
Open

Custom selection context commands#81
GeKtvi wants to merge 10 commits intoCAD-Booster:developfrom
GeKtvi:contextMenu2

Conversation

@GeKtvi
Copy link
Contributor

@GeKtvi GeKtvi commented Feb 2, 2026

SolidDNA changes

Summary

This PR adds a more structured API for SolidDNA context menu popup icons and context menu items (groups/submenus), plus updates the Menus tutorial (Tutorials/05-Menus) with improved examples, icon assets, and documentation.

Key changes

  • Introduced context menu item/icon abstractions (CommandContext* types) and related create-info / created-state types.
  • Made context menu creation more explicit and safer (creation failures throw, cookie is passed explicitly via info objects).
  • Updated CommandManager construction to accept the SolidWorks add-in cookie (new constructor overload) and store it for context-menu registration, the old constructor is marked obsolete. SolidWorks APIs require this cookie for registration but it cannot be read back from the ICommandManager object, so it must be passed in. This avoids relying on global application access for the cookie and makes the lifetime/ownership clearer.
  • Added/updated tutorial assets and examples for:
    • command tab / flyout icons via sprite sheets (Icons/icons{size}.png)
    • context menu icons via per-size icon files (Icons/icon_*{size}.png)
  • Added unit-style tests for context menu items/groups/icons that **.
  • NOTE: Application realted tests are intentionally not added yet because the repo currently has the new IApplication/Application naming/property situation and I don’t want to build changes on top of that until it’s stabilized/renamed.
  • Added documentation/comments explaining why context menu item/icon removal is not implemented.
  • Expanded comments and docs around context menu usage, selection-type filtering, and state checks.

Main types

  • Two-phase model (CreatableCreated):
    • CommandContext* classes are configuration + top-level creation logic (what to create, for which doc types, which selection context, how to build nested paths).
    • CommandContext*Created classes are the registered SolidWorks artifacts (what was actually added to the UI) and own the created-state lifetime/disposal behavior.
  • Immutability boundary:
    • CommandContextItem / CommandContextIcon are intended to be treated as creation-time configuration, after Create(...) they effectively become immutable for a given registration (prevents “create twice / change fields / create again” issues).
  • Creation context is explicit:
    • ICommandContextCreateInfo carries runtime data like the SolidWorks cookie, CommandContextItemCreateInfo additionally carries the current path for nested @ hierarchy.
  • Groups are a composition mechanism:
    • CommandContextGroup is a creatable “container” that creates a CommandContextGroupCreated.
    • CommandContextGroupCreated holds the created children and is responsible for disposing them (and for passing derived create info, like the nested path, down to child items).

Design notes / rationale

  • SRP split (Create vs Created): one type is responsible for creation/transition to a created state, the created type owns lifetime + disposal responsibilities.
  • Creation is a state transition: base Create should only move an object to a “created” state.
  • Prefer IEnumerable<T> for returned collections (details/justification): Iterator pattern approach discussion
  • Command ID immutability: avoid mutating CommandId after creation to prevent inconsistent CommandManager state.

Style / conventions

  • Uses newer C# syntax where applicable (modern collection expressions, etc.). This is intended to match the library direction, if the repo prefers older syntax, I can align it in a follow-up.
  • New/updated code prefers _field naming over legacy mField naming (older classes may still use m).
  • Avoids #region blocks in small classes (keeps files shorter and relies on IDE navigation instead).
SolidWorks API context

Raw SolidWorks API interop

  • Context menu items are registered via ISldWorks.AddMenuPopupItem3 per (DocumentType, SelectionType) combination, using the add-in cookie and SolidDNA callback strings (SolidAddIn.Callback(CallbackId) / SolidAddIn.ItemStateCheck(CallbackId)).
  • Context menu popup icons are registered via IFrame.AddMenuPopupIcon3 (frame obtained from ISldWorks.Frame), also using the add-in cookie plus the same callback/update pattern.

SolidWorks API bugs / limitations

  • Separators via ISldWorks.AddMenuPopupItem3: SolidWorks documentation suggests you can add a separator by appending an at-sign (@) and quoting the popup item name, but this does not work (observed on SW 2022 and 2024). SolidWorks still parses the quoted string and treats the empty part as a submenu name.
  • Popup icon image list behavior: if multiple batch icons are provided, SolidWorks uses the first icon (no index support).
  • Icon state support: for popup icons, only SelectedEnabled, DeselectedEnabled, and Hidden states are supported, disabled states are not supported.

Removal / unregister limitations (Dispose strategy)

  • Removal is not reliably supported (Dispose strategy): SolidWorks does not reliably support removing context entries once registered, so SolidDNA uses a hide-by-state-check approach.
    • This is an internal implementation detail (CommandContext*Created), library users are not expected to manually dispose these.
    • The CommandManager / add-in lifecycle owns disposal (no manual disposal in normal usage): after disposal, state-check keeps returning Hidden to effectively remove the item/icon from the UI.
    • Context registration is runtime-only: if SolidWorks restarts and the add-in does not register items again, no “old” items/icons remain in the UI.
  • Removing context menu items: no reliable API was found to remove items after adding them.
  • Removing context menu popup icons: no reliable API was found to remove icons after adding them.
    • IFrame.RemoveMenuPopupIcon is C++ only.
    • Even if you call it, you cannot safely determine the icon index because other add-ins can add icons too.
  • Add-in unload behavior: when the add-in is unloaded by the user (SolidWorks: Tools → Add-ins → checkbox unchecked), SolidWorks removes the add-in’s registered context menu items/icons from the UI (this happens regardless of the Hidden/Dispose workaround).
  • Add-in reload behavior: when the user loads the add-in again (checkbox checked), SolidWorks runs the add-in connect/startup flow and the items/icons are registered again from scratch and work as usual.

SolidWorks UI/behavior limitations

  • Context menu icon count: SolidWorks does not wrap to a new row, too many icons stretches/breaks usability.
    • Consider adding a static/per-version limit with logging once exceeded (avoid throwing to prevent breaking other add-ins).
    • Observed that visible context item count varies by monitor DPI (some items may move under “more commands”).
  • Separator does not work reliably: the documented pattern (quoted item name ending with @) does not work reliably (observed SW 2022/2024), SolidWorks still parses @ and treats the empty segment as a submenu name.
  • SelectionType quirk (Part FeatureManager): in a Part document, selecting the top “component” entry in FeatureManager appears to be treated by SolidWorks as SelectionType.Component (even though it’s a Part), interesting observation.
  • If a context popup for a selection type isn’t shown, it may not be possible to add a context icon for that selection type.

Out of scope / deferred

  • Documentation for SpecificFeatureSelectionType (and related selection-type details) is intentionally deferred to a follow-up PR.
  • More complex, prebuilt context menu item/icon building blocks (higher-level “ready to use” classes on top of the current CommandContext* primitives) are intentionally deferred to follow-up PRs.
  • If SolidDNA’s SolidWorks application access surface (Application / IApplication) changes during/after merge, this PR may need a small follow-up to align with the updated/official application access approach.

@GeKtvi
Copy link
Contributor Author

GeKtvi commented Feb 2, 2026

Screenshots

Component selection: context menu open + popup icon visible + context menu item + nested group

Component selection - menu + icon + items

Edge selection: context popup visible + icon shown

Edge selection - popup icon

Face selection: context popup visible + icon shown

Face selection - popup icon

Popup icon selected state (if applicable)

Popup icon - selected state

DPI/overflow example: demonstrate “More commands” / DPI variance

DPI/overflow - example 1

DPI/overflow - example 2

FeatureManager component folder selection: multiple popup icons assigned and shown

Feature folder selection - multiple popup icons

@brinkdinges
Copy link
Member

I've been going through this PR for the past two days. The unload/dispose issues worry me, so I'd like to try those for myself. I can hardly believe all those methods do not work. Don't we keep a reference somewhere that needs to be disposed first, before solidworks can remove the menu item? Maybe an event handler? We had something similar with a toolbar, where our reference would keep it from being removed.

I also hope we can simplify this, 15 new classes for two new menu items is too much.

My goal is to include this in SolidDNA 4.1 so I can make more time for this instead of feeling rushed.

@GeKtvi
Copy link
Contributor Author

GeKtvi commented Feb 13, 2026

Don't we keep a reference somewhere that needs to be disposed first, before solidworks can remove the menu item? Maybe an event handler?

That's a good point - I'll recheck it this weekend. But this part of the API doesn't seem to return any objects (except IFrame), so I don't think there's no way to hold a reference anyway.

I also hope we can simplify this, 15 new classes for two new menu items is too much.

I'd recommend not simplifying it, the structure is intended to support future expansion.
If we need to add/remove items during the add-in's lifetime, we could later implement a variation using ObservableCollection, which would work well for document-specific commands - I've used this approach in two places in my own projects.
I can explain further if you're still unsure - feel free to ask in the GitHub UI comments and I'll respond there.

My goal is to include this in SolidDNA 4.1 so I can make more time for this instead of feeling rushed.

No need to rush - I've already added it to my fork branch and am using it in my projects. I just wanted to share it with others.

@GeKtvi
Copy link
Contributor Author

GeKtvi commented Feb 19, 2026

It seems I misunderstood how Icon Button UI placement works. I didn't realize that users can configure specific Popup icons.

It appears that users can actually add new rows. Icons added by the add-in are inserted at the start of the first virtual line positioned right after SW standard commands.

Also, could different Cookie values pased to SW create new rows? If so, then we might be able to use a C++ method to remove icon items from the Popup.

In settings:
image

In usage:
image

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