Skip to content

Fix #364 - Use image registries#365

Open
travkin79 wants to merge 9 commits into
microsoft:mainfrom
travkin79:fix-use-image-registry
Open

Fix #364 - Use image registries#365
travkin79 wants to merge 9 commits into
microsoft:mainfrom
travkin79:fix-use-image-registry

Conversation

@travkin79

Copy link
Copy Markdown
Contributor

This PR fixes issue #364.

  • Adds CopilotImages, a facade for the ui plug-in's images
  • Adds CopilotJobsImages, a facade for the jobs plug-in's images
  • Adds unit tests to ensure the resources can be loaded
  • Improves plug-in instantiation

travkin79 and others added 6 commits July 22, 2026 11:43
- Add CopilotImages, a facade for the ui plug-in's images
- Add CopilotJobsImages, a facade for the jobs plug-in's images
- Add unit tests to ensure the resources can be loaded
- Improve plug-in instantiation

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
…ft#364)

Use image registries to access static images, no longer dispose them, since the registries handle Image disposals. Keep dynamic image loading and disposal as it was.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
…rosoft#364)

Re-direct calls of PlatformUI.getWorkbench().getSharedImages().getImage(...) to the image registry.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
…#364)

Drop the icon-path/shared-image factory variants of WrappableIconLink in favor of a single create(...) that accepts an already-resolved Image. Callers now pass registry images (CopilotImages.IMG_INFORMATION) or shared workbench images directly, and the widget no longer owns or disposes the icon.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
All icon lookups now go through the image registries (CopilotImages / CopilotJobsImages), so the raw PNG-path helpers are no longer referenced. Drop them from the ui-bundle UiUtils and delete the jobs-bundle UiUtils, whose sole purpose was these two methods.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
…ons (microsoft#364)

Add an Image Registries subsection under Resource Management.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot AI 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.

Pull request overview

This PR addresses issue #364 by centralizing image loading in the ui and ui.jobs bundles via plugin ImageRegistry-backed facades (CopilotImages, CopilotJobsImages), replacing ad-hoc image creation/disposal at call sites and adding tests to catch missing icon resources.

Changes:

  • Introduces CopilotImages (UI) and CopilotJobsImages (Jobs) registries and migrates many call sites to registry/shared-image access.
  • Removes UiUtils.buildImage*FromPngPath(...) usage patterns and associated manual disposal logic across UI widgets/handlers/dialogs.
  • Adds reflection-based unit tests to validate that all IMG_* constants map to real bundle resources; adjusts plugin/test initialization accordingly.

Reviewed changes

Copilot reviewed 64 out of 64 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
com.microsoft.copilot.eclipse.ui/src/com/microsoft/copilot/eclipse/ui/utils/UiUtils.java Removes ad-hoc PNG image helper APIs to push callers toward registries.
com.microsoft.copilot.eclipse.ui/src/com/microsoft/copilot/eclipse/ui/utils/MenuUtils.java Switches quota/blank icon descriptors to CopilotImages keys.
com.microsoft.copilot.eclipse.ui/src/com/microsoft/copilot/eclipse/ui/utils/McpUtils.java Uses shared default MCP icon from CopilotImages.
com.microsoft.copilot.eclipse.ui/src/com/microsoft/copilot/eclipse/ui/swt/SpinnerAnimator.java Uses registry spinner frames instead of per-frame image creation/disposal.
com.microsoft.copilot.eclipse.ui/src/com/microsoft/copilot/eclipse/ui/swt/ModelHoverContentProvider.java Replaces static cached/disposed icons with themed registry images.
com.microsoft.copilot.eclipse.ui/src/com/microsoft/copilot/eclipse/ui/swt/DropdownPopup.java Replaces static cached/disposed icons with themed registry images.
com.microsoft.copilot.eclipse.ui/src/com/microsoft/copilot/eclipse/ui/swt/DropdownButton.java Replaces static cached/disposed arrow icon with themed registry images.
com.microsoft.copilot.eclipse.ui/src/com/microsoft/copilot/eclipse/ui/quickstart/FeaturePage.java Converts quickstart icons to registry-managed images and removes manual disposal.
com.microsoft.copilot.eclipse.ui/src/com/microsoft/copilot/eclipse/ui/preferences/WrappableIconLink.java Changes API to accept Image (non-owned) instead of path/shared-image variants.
com.microsoft.copilot.eclipse.ui/src/com/microsoft/copilot/eclipse/ui/preferences/McpPreferencePage.java Uses CopilotImages for info/red-notice icons and shared images.
com.microsoft.copilot.eclipse.ui/src/com/microsoft/copilot/eclipse/ui/preferences/GlobalAutoApproveSection.java Uses CopilotImages for shared warning icon.
com.microsoft.copilot.eclipse.ui/src/com/microsoft/copilot/eclipse/ui/preferences/CustomModesPreferencePage.java Uses CopilotImages for information icon.
com.microsoft.copilot.eclipse.ui/src/com/microsoft/copilot/eclipse/ui/preferences/ByokPreferencePage.java Uses CopilotImages for keep/delete icons and removes image disposal.
com.microsoft.copilot.eclipse.ui/src/com/microsoft/copilot/eclipse/ui/preferences/AutoApprovePreferencePage.java Uses CopilotImages for shared info icon.
com.microsoft.copilot.eclipse.ui/src/com/microsoft/copilot/eclipse/ui/preferences/AddByokModelDialog.java Uses themed registry eye/eye-closed icons (no manual disposal).
com.microsoft.copilot.eclipse.ui/src/com/microsoft/copilot/eclipse/ui/preferences/AddApiKeyDialog.java Uses themed registry eye/eye-closed icons (no manual disposal).
com.microsoft.copilot.eclipse.ui/src/com/microsoft/copilot/eclipse/ui/nes/RulerColumn.java Uses CopilotImages for gutter-arrow descriptor source.
com.microsoft.copilot.eclipse.ui/src/com/microsoft/copilot/eclipse/ui/nes/ActionMenu.java Uses CopilotImages for menu action icon descriptors.
com.microsoft.copilot.eclipse.ui/src/com/microsoft/copilot/eclipse/ui/handlers/ToolConfigurationContextMenuHandler.java Uses CopilotImages for context menu icon descriptors.
com.microsoft.copilot.eclipse.ui/src/com/microsoft/copilot/eclipse/ui/handlers/ShowStatusBarMenuHandler.java Uses CopilotImages descriptors (including spinner frames) instead of path literals.
com.microsoft.copilot.eclipse.ui/src/com/microsoft/copilot/eclipse/ui/handlers/ShowMenuBarMenuHandler.java Uses CopilotImages icon descriptors instead of path literals.
com.microsoft.copilot.eclipse.ui/src/com/microsoft/copilot/eclipse/ui/handlers/ShowContextMenuHandler.java Uses CopilotImages for context menu icon descriptor.
com.microsoft.copilot.eclipse.ui/src/com/microsoft/copilot/eclipse/ui/dialogs/MissingTerminalDependenciesDialog.java Uses registry Copilot icon (no manual disposal).
com.microsoft.copilot.eclipse.ui/src/com/microsoft/copilot/eclipse/ui/dialogs/mcp/McpServerItem.java Uses themed registry images for MCP meta-row icons (no manual disposal).
com.microsoft.copilot.eclipse.ui/src/com/microsoft/copilot/eclipse/ui/dialogs/mcp/McpServerDetailDialog.java Uses registry/themed images and removes label-level disposal.
com.microsoft.copilot.eclipse.ui/src/com/microsoft/copilot/eclipse/ui/dialogs/mcp/McpRegistryDialog.java Uses registry images for dialog/buttons/banner icons and removes disposal.
com.microsoft.copilot.eclipse.ui/src/com/microsoft/copilot/eclipse/ui/dialogs/mcp/McpApprovalDialog.java Uses registry/shared images for approve/deny icons (no manual disposal).
com.microsoft.copilot.eclipse.ui/src/com/microsoft/copilot/eclipse/ui/dialogs/jobs/BaseCopilotDialog.java Uses registry Copilot icon (no manual disposal).
com.microsoft.copilot.eclipse.ui/src/com/microsoft/copilot/eclipse/ui/CopilotUi.java Initializes image registry via CopilotImages and adjusts plugin singleton lifecycle.
com.microsoft.copilot.eclipse.ui/src/com/microsoft/copilot/eclipse/ui/CopilotImages.java New UI image facade defining keys + registry/shared-image access helpers.
com.microsoft.copilot.eclipse.ui/src/com/microsoft/copilot/eclipse/ui/chat/WorkingSetBar.java Switches arrows/keep/undo/file icons to registry/shared images.
com.microsoft.copilot.eclipse.ui/src/com/microsoft/copilot/eclipse/ui/chat/WarnWidget.java Uses shared warning icon via CopilotImages.
com.microsoft.copilot.eclipse.ui/src/com/microsoft/copilot/eclipse/ui/chat/viewers/NoSubscriptionViewer.java Switches main icon to registry image and removes disposal.
com.microsoft.copilot.eclipse.ui/src/com/microsoft/copilot/eclipse/ui/chat/viewers/LoadingViewer.java Switches main icon to registry image and removes disposal.
com.microsoft.copilot.eclipse.ui/src/com/microsoft/copilot/eclipse/ui/chat/viewers/ChatHistoryViewer.java Switches navigation/edit icons to registry images; shared delete icon via facade.
com.microsoft.copilot.eclipse.ui/src/com/microsoft/copilot/eclipse/ui/chat/viewers/BeforeLoginWelcomeViewer.java Switches welcome/feature icons to registry images and removes disposal.
com.microsoft.copilot.eclipse.ui/src/com/microsoft/copilot/eclipse/ui/chat/viewers/AgentModeViewer.java Switches welcome/tools/attach-context icons to registry images and removes disposal.
com.microsoft.copilot.eclipse.ui/src/com/microsoft/copilot/eclipse/ui/chat/viewers/AfterLoginWelcomeViewer.java Switches welcome/attach-context icons to registry images and removes disposal.
com.microsoft.copilot.eclipse.ui/src/com/microsoft/copilot/eclipse/ui/chat/tools/RunInTerminalToolAdapter.java Uses registry Copilot icon descriptor for terminal integration.
com.microsoft.copilot.eclipse.ui/src/com/microsoft/copilot/eclipse/ui/chat/TodoListBar.java Switches status/arrow/clear icons to registry images and removes disposal code paths.
com.microsoft.copilot.eclipse.ui/src/com/microsoft/copilot/eclipse/ui/chat/ThinkingBlock.java Uses registry cancel/arrow icons and removes disposal helper.
com.microsoft.copilot.eclipse.ui/src/com/microsoft/copilot/eclipse/ui/chat/StaticBanner.java Uses shared severity/close icons via CopilotImages.
com.microsoft.copilot.eclipse.ui/src/com/microsoft/copilot/eclipse/ui/chat/SourceViewerComposite.java Uses shared copy/paste icons via CopilotImages.
com.microsoft.copilot.eclipse.ui/src/com/microsoft/copilot/eclipse/ui/chat/services/AvatarService.java Uses registry default avatars and stops disposing them in service dispose().
com.microsoft.copilot.eclipse.ui/src/com/microsoft/copilot/eclipse/ui/chat/ReferencedFile.java Uses registry close icon and shared warning icon via CopilotImages.
com.microsoft.copilot.eclipse.ui/src/com/microsoft/copilot/eclipse/ui/chat/ModelPickerGroupsBuilder.java Uses themed warning icon via CopilotImages instead of static cache/dispose.
com.microsoft.copilot.eclipse.ui/src/com/microsoft/copilot/eclipse/ui/chat/ErrorWidget.java Uses shared error icon via CopilotImages.
com.microsoft.copilot.eclipse.ui/src/com/microsoft/copilot/eclipse/ui/chat/dialogs/DynamicOauthDialog.java Uses registry Copilot icon and removes manual disposal.
com.microsoft.copilot.eclipse.ui/src/com/microsoft/copilot/eclipse/ui/chat/CurrentReferencedFile.java Replaces static never-disposed eye icons with registry images.
com.microsoft.copilot.eclipse.ui/src/com/microsoft/copilot/eclipse/ui/chat/AgentToolCancelLabel.java Uses registry cancel icon and removes disposal.
com.microsoft.copilot.eclipse.ui/src/com/microsoft/copilot/eclipse/ui/chat/AgentStatusLabel.java Uses registry status icons and shared error icon; removes disposal of registry images.
com.microsoft.copilot.eclipse.ui/src/com/microsoft/copilot/eclipse/ui/chat/AgentMessageWidget.java Uses themed jobs PR icons via CopilotImages (no disposal).
com.microsoft.copilot.eclipse.ui/src/com/microsoft/copilot/eclipse/ui/chat/AddContextButton.java Uses registry attach-context icon and removes disposal.
com.microsoft.copilot.eclipse.ui/src/com/microsoft/copilot/eclipse/ui/chat/ActionBar.java Uses registry/shared images for action bar icons and removes disposal blocks.
com.microsoft.copilot.eclipse.ui.test/src/com/microsoft/copilot/eclipse/ui/jobs/CopilotJobsImagesTest.java New reflection-based test to validate jobs bundle icon resources exist.
com.microsoft.copilot.eclipse.ui.test/src/com/microsoft/copilot/eclipse/ui/CopilotUiTests.java Updates UI plugin test startup approach (needs adjustment per review).
com.microsoft.copilot.eclipse.ui.test/src/com/microsoft/copilot/eclipse/ui/CopilotImagesTest.java New reflection-based test to validate UI bundle icon resources exist.
com.microsoft.copilot.eclipse.ui.test/META-INF/MANIFEST.MF Adds dependency on com.microsoft.copilot.eclipse.ui.jobs for new tests.
com.microsoft.copilot.eclipse.ui.jobs/src/com/microsoft/copilot/eclipse/ui/jobs/views/JobsView.java Migrates jobs view icons to CopilotJobsImages and removes disposal.
com.microsoft.copilot.eclipse.ui.jobs/src/com/microsoft/copilot/eclipse/ui/jobs/utils/UiUtils.java Deletes ad-hoc jobs image helper in favor of registry facade.
com.microsoft.copilot.eclipse.ui.jobs/src/com/microsoft/copilot/eclipse/ui/jobs/CopilotJobsImages.java New jobs image facade defining keys + registry/shared-image access helpers.
com.microsoft.copilot.eclipse.ui.jobs/src/com/microsoft/copilot/eclipse/ui/jobs/CopilotJobs.java Initializes image registry via CopilotJobsImages and adds plugin singleton accessor.
com.microsoft.copilot.eclipse.ui.jobs/META-INF/MANIFEST.MF Exports jobs package (visibility consideration raised in review).
.github/copilot-instructions.md Documents the new “prefer image registries; don’t dispose registry images” guideline.

Comment on lines +151 to +167
private static volatile ImageRegistry imageRegistry;

private CopilotImages() {
// prevent instantiation
}

/**
* Returns the plugin's image registry, initializing it on first access.
* Called by {@link CopilotUi#initializeImageRegistry(ImageRegistry)} to pre-register descriptors.
*/
static ImageRegistry getImageRegistry() {
ImageRegistry registry = imageRegistry;
if (registry == null) {
registry = imageRegistry = CopilotUi.getPlugin().getImageRegistry();
}
return registry;
}

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

fixed

Comment on lines +32 to +48
private static volatile ImageRegistry imageRegistry;

private CopilotJobsImages() {
// prevent instantiation
}

/**
* Returns the plugin's image registry, initializing it on first access.
* Called by {@link CopilotJobs#initializeImageRegistry(ImageRegistry)} to pre-register descriptors.
*/
static ImageRegistry getImageRegistry() {
ImageRegistry registry = imageRegistry;
if (registry == null) {
registry = imageRegistry = CopilotJobs.getPlugin().getImageRegistry();
}
return registry;
}

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

fixed

Comment on lines 22 to 25
BundleContext context = FrameworkUtil.getBundle(CopilotUi.class).getBundleContext();
CopilotUi ui = new CopilotUi();
ui.start(null);
ui.start(context);

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

fixed

Bundle-Localization: plugin
Automatic-Module-Name: com.microsoft.copilot.eclipse.ui.jobs
Bundle-ActivationPolicy: lazy
Export-Package: com.microsoft.copilot.eclipse.ui.jobs

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

fixed

Apply suggested improvement: check plug-in availability, retrieve the plug-in's registry, do no longer cache the registry in a static variable since it is already cached.
Apply suggested improvement: The ui.jobs package is exported only so the test bundle can access CopilotJobsImages. Limit its visibility with x-friends to avoid exposing it as public OSGi API, matching the existing convention used for ui.chat.confirmation.
Apply suggested improvement: Start the UI bundle through the OSGi framework so the framework-owned activator runs as it would at runtime.
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