diff --git a/bundles/org.eclipse.ui.workbench.texteditor/src/org/eclipse/ui/internal/findandreplace/overlay/AccessibleToolItemBuilder.java b/bundles/org.eclipse.ui.workbench.texteditor/src/org/eclipse/ui/internal/findandreplace/overlay/AccessibleToolItemBuilder.java index a7078045fdd..186fe5eb7c0 100644 --- a/bundles/org.eclipse.ui.workbench.texteditor/src/org/eclipse/ui/internal/findandreplace/overlay/AccessibleToolItemBuilder.java +++ b/bundles/org.eclipse.ui.workbench.texteditor/src/org/eclipse/ui/internal/findandreplace/overlay/AccessibleToolItemBuilder.java @@ -30,10 +30,6 @@ class AccessibleToolItemBuilder { private int styleBits = SWT.NONE; private Image image; private String toolTipText; - private FindReplaceOverlayAction action; - private SearchOptions searchOption; - private IFindReplaceLogic findReplaceLogic; - private boolean invertSearchOption; public AccessibleToolItemBuilder(AccessibleToolBar accessibleToolBar) { this.accessibleToolBar = Objects.requireNonNull(accessibleToolBar); @@ -54,51 +50,53 @@ public AccessibleToolItemBuilder withToolTipText(String newToolTipText) { return this; } - public AccessibleToolItemBuilder withAction(FindReplaceOverlayAction newAction) { - this.action = newAction; - return this; + public AccessibleToolItemForActionBuilder withAction(FindReplaceOverlayAction action) { + return new AccessibleToolItemForActionBuilder(this, action); } - /** - * Binds a {@link SearchOptions} value to this item. When built, the item's - * selection state is initialized from the logic's current activation state and - * kept in sync automatically. The item's enabled state is also initialized from - * and kept in sync with the option's availability. - */ - public AccessibleToolItemBuilder withSearchOption(SearchOptions option, IFindReplaceLogic logic) { - this.searchOption = option; - this.findReplaceLogic = logic; - this.invertSearchOption = false; - return this; + public class AccessibleToolItemForActionBuilder { + private final AccessibleToolItemBuilder parentBuilder; + + private final FindReplaceOverlayAction action; + + private AccessibleToolItemForActionBuilder(AccessibleToolItemBuilder parentBuilder, + FindReplaceOverlayAction action) { + this.parentBuilder = parentBuilder; + this.action = action; + } + + public ToolItem build() { + AccessibleToolItem accessibleToolItem = parentBuilder.buildAccessibleToolItem(); + accessibleToolItem.setAction(action); + return accessibleToolItem.getToolItem(); + } } - /** - * Like {@link #withSearchOption(SearchOptions, IFindReplaceLogic)} but inverts - * the selection mapping: the item is selected when the option is - * inactive. Useful for options like {@link SearchOptions#GLOBAL} where - * a "search in selection" button should be selected when searching globally is - * turned off. - */ - public AccessibleToolItemBuilder withInvertedSearchOption(SearchOptions option, IFindReplaceLogic logic) { - this.searchOption = option; - this.findReplaceLogic = logic; - this.invertSearchOption = true; - return this; + public AccessibleToolItemForSearchOptionBuilder withAction(FindReplaceOverlaySearchOptionAction action) { + return new AccessibleToolItemForSearchOptionBuilder(this, action); } - public ToolItem build() { - AccessibleToolItem accessibleToolItem = accessibleToolBar.createToolItem(styleBits); - if (image != null) { - accessibleToolItem.setImage(image); - } - if (toolTipText != null) { - accessibleToolItem.setToolTipText(toolTipText); + public class AccessibleToolItemForSearchOptionBuilder extends AccessibleToolItemForActionBuilder { + private final FindReplaceOverlaySearchOptionAction searchOptionAction; + + private boolean invertSearchOption; + + private AccessibleToolItemForSearchOptionBuilder(AccessibleToolItemBuilder parentBuilder, + FindReplaceOverlaySearchOptionAction searchOptionAction) { + super(parentBuilder, searchOptionAction); + this.searchOptionAction = searchOptionAction; } - if (action != null) { - accessibleToolItem.setAction(action); + + public AccessibleToolItemForSearchOptionBuilder displayInverted() { + this.invertSearchOption = true; + return this; } - ToolItem toolItem = accessibleToolItem.getToolItem(); - if (searchOption != null) { + + @Override + public ToolItem build() { + ToolItem toolItem = super.build(); + IFindReplaceLogic findReplaceLogic = searchOptionAction.getFindReplaceLogic(); + SearchOptions searchOption = searchOptionAction.getSearchOption(); boolean initial = findReplaceLogic.isActive(searchOption); toolItem.setSelection(invertSearchOption ? !initial : initial); findReplaceLogic.addSearchOptionActivationChangedListener(searchOption, state -> { @@ -107,12 +105,28 @@ public ToolItem build() { } }); toolItem.setEnabled(findReplaceLogic.isAvailable(searchOption)); - findReplaceLogic.addSearchOptionAvailabilityChangedListener(searchOption, available -> { + findReplaceLogic.addSearchOptionAvailabilityChangedListener(searchOption, state -> { if (!toolItem.isDisposed()) { - toolItem.setEnabled(available); + toolItem.setEnabled(state); } }); + return toolItem; } - return toolItem; } + + public ToolItem build() { + return buildAccessibleToolItem().getToolItem(); + } + + private AccessibleToolItem buildAccessibleToolItem() { + AccessibleToolItem accessibleToolItem = accessibleToolBar.createToolItem(styleBits); + if (image != null) { + accessibleToolItem.setImage(image); + } + if (toolTipText != null) { + accessibleToolItem.setToolTipText(toolTipText); + } + return accessibleToolItem; + } + } diff --git a/bundles/org.eclipse.ui.workbench.texteditor/src/org/eclipse/ui/internal/findandreplace/overlay/FindReplaceOverlay.java b/bundles/org.eclipse.ui.workbench.texteditor/src/org/eclipse/ui/internal/findandreplace/overlay/FindReplaceOverlay.java index ae88160cc86..efb18ffe6da 100644 --- a/bundles/org.eclipse.ui.workbench.texteditor/src/org/eclipse/ui/internal/findandreplace/overlay/FindReplaceOverlay.java +++ b/bundles/org.eclipse.ui.workbench.texteditor/src/org/eclipse/ui/internal/findandreplace/overlay/FindReplaceOverlay.java @@ -570,30 +570,25 @@ private void createCloseTools() { } private void createAreaSearchButton() { - FindReplaceOverlayAction searchInSelectionAction = new FindReplaceOverlayAction(() -> { - findReplaceLogic.toggle(SearchOptions.GLOBAL); - updateIncrementalSearch(); - }); + FindReplaceOverlaySearchOptionAction searchInSelectionAction = new FindReplaceOverlaySearchOptionAction(SearchOptions.GLOBAL, findReplaceLogic); + searchInSelectionAction.addExecutionListener(this::updateIncrementalSearch); searchInSelectionAction.addShortcuts(KeyboardShortcuts.OPTION_SEARCH_IN_SELECTION); commonActions.add(searchInSelectionAction); searchInSelectionButton = new AccessibleToolItemBuilder(searchTools).withStyleBits(SWT.CHECK) .withImage(FindReplaceOverlayImages.get(FindReplaceOverlayImages.KEY_SEARCH_IN_AREA)) .withToolTipText(FindReplaceMessages.FindReplaceOverlay_searchInSelectionButton_toolTip) - .withInvertedSearchOption(SearchOptions.GLOBAL, findReplaceLogic) - .withAction(searchInSelectionAction).build(); + .withAction(searchInSelectionAction).displayInverted().build(); } private void createRegexSearchButton() { - FindReplaceOverlayAction regexAction = new FindReplaceOverlayAction(() -> { - findReplaceLogic.toggle(SearchOptions.REGEX); - updateIncrementalSearch(); - }); + FindReplaceOverlaySearchOptionAction regexAction = new FindReplaceOverlaySearchOptionAction(SearchOptions.REGEX, + findReplaceLogic); + regexAction.addExecutionListener(this::updateIncrementalSearch); regexAction.addShortcuts(KeyboardShortcuts.OPTION_REGEX); commonActions.add(regexAction); regexSearchButton = new AccessibleToolItemBuilder(searchTools).withStyleBits(SWT.CHECK) .withImage(FindReplaceOverlayImages.get(FindReplaceOverlayImages.KEY_FIND_REGEX)) .withToolTipText(FindReplaceMessages.FindReplaceOverlay_regexSearchButton_toolTip) - .withSearchOption(SearchOptions.REGEX, findReplaceLogic) .withAction(regexAction).build(); findReplaceLogic.addSearchOptionActivationChangedListener(SearchOptions.REGEX, activated -> { updateContentAssistAvailability(); @@ -602,30 +597,26 @@ private void createRegexSearchButton() { } private void createCaseSensitiveButton() { - FindReplaceOverlayAction caseSensitiveAction = new FindReplaceOverlayAction(() -> { - findReplaceLogic.toggle(SearchOptions.CASE_SENSITIVE); - updateIncrementalSearch(); - }); + FindReplaceOverlaySearchOptionAction caseSensitiveAction = new FindReplaceOverlaySearchOptionAction( + SearchOptions.CASE_SENSITIVE, findReplaceLogic); + caseSensitiveAction.addExecutionListener(this::updateIncrementalSearch); caseSensitiveAction.addShortcuts(KeyboardShortcuts.OPTION_CASE_SENSITIVE); commonActions.add(caseSensitiveAction); caseSensitiveSearchButton = new AccessibleToolItemBuilder(searchTools).withStyleBits(SWT.CHECK) .withImage(FindReplaceOverlayImages.get(FindReplaceOverlayImages.KEY_CASE_SENSITIVE)) .withToolTipText(FindReplaceMessages.FindReplaceOverlay_caseSensitiveButton_toolTip) - .withSearchOption(SearchOptions.CASE_SENSITIVE, findReplaceLogic) .withAction(caseSensitiveAction).build(); } private void createWholeWordsButton() { - FindReplaceOverlayAction wholeWordAction = new FindReplaceOverlayAction(() -> { - findReplaceLogic.toggle(SearchOptions.WHOLE_WORD); - updateIncrementalSearch(); - }); + FindReplaceOverlaySearchOptionAction wholeWordAction = new FindReplaceOverlaySearchOptionAction( + SearchOptions.WHOLE_WORD, findReplaceLogic); + wholeWordAction.addExecutionListener(this::updateIncrementalSearch); wholeWordAction.addShortcuts(KeyboardShortcuts.OPTION_WHOLE_WORD); commonActions.add(wholeWordAction); wholeWordSearchButton = new AccessibleToolItemBuilder(searchTools).withStyleBits(SWT.CHECK) .withImage(FindReplaceOverlayImages.get(FindReplaceOverlayImages.KEY_WHOLE_WORD)) .withToolTipText(FindReplaceMessages.FindReplaceOverlay_wholeWordsButton_toolTip) - .withSearchOption(SearchOptions.WHOLE_WORD, findReplaceLogic) .withAction(wholeWordAction).build(); } @@ -1055,4 +1046,4 @@ private void decorate() { } } -} \ No newline at end of file +} diff --git a/bundles/org.eclipse.ui.workbench.texteditor/src/org/eclipse/ui/internal/findandreplace/overlay/FindReplaceOverlayAction.java b/bundles/org.eclipse.ui.workbench.texteditor/src/org/eclipse/ui/internal/findandreplace/overlay/FindReplaceOverlayAction.java index 03e5368e426..28d66801bef 100644 --- a/bundles/org.eclipse.ui.workbench.texteditor/src/org/eclipse/ui/internal/findandreplace/overlay/FindReplaceOverlayAction.java +++ b/bundles/org.eclipse.ui.workbench.texteditor/src/org/eclipse/ui/internal/findandreplace/overlay/FindReplaceOverlayAction.java @@ -19,6 +19,8 @@ class FindReplaceOverlayAction { private final Runnable operation; + private final List executionListeners = new ArrayList<>(); + private final List shortcuts = new ArrayList<>(); FindReplaceOverlayAction(Runnable operation) { @@ -31,6 +33,7 @@ void addShortcuts(List shortcutsToAdd) { void execute() { operation.run(); + notifyExecutionListeners(); } List getShortcuts() { @@ -52,4 +55,14 @@ String addShortcutHintToTooltipText(String originalTooltipText) { return originalTooltipText + " (" + shortcuts.get(0).format() + ")"; //$NON-NLS-1$ //$NON-NLS-2$ } + void addExecutionListener(Runnable listener) { + executionListeners.add(listener); + } + + void notifyExecutionListeners() { + for (Runnable listener : executionListeners) { + listener.run(); + } + } + } diff --git a/bundles/org.eclipse.ui.workbench.texteditor/src/org/eclipse/ui/internal/findandreplace/overlay/FindReplaceOverlaySearchOptionAction.java b/bundles/org.eclipse.ui.workbench.texteditor/src/org/eclipse/ui/internal/findandreplace/overlay/FindReplaceOverlaySearchOptionAction.java new file mode 100644 index 00000000000..87a12266168 --- /dev/null +++ b/bundles/org.eclipse.ui.workbench.texteditor/src/org/eclipse/ui/internal/findandreplace/overlay/FindReplaceOverlaySearchOptionAction.java @@ -0,0 +1,36 @@ +/******************************************************************************* + * Copyright (c) 2026 Vector Informatik GmbH and others. + * + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + *******************************************************************************/ +package org.eclipse.ui.internal.findandreplace.overlay; + +import org.eclipse.ui.internal.findandreplace.IFindReplaceLogic; +import org.eclipse.ui.internal.findandreplace.SearchOptions; + +class FindReplaceOverlaySearchOptionAction extends FindReplaceOverlayAction { + + private final SearchOptions searchOption; + + private final IFindReplaceLogic findReplaceLogic; + + FindReplaceOverlaySearchOptionAction(SearchOptions searchOption, IFindReplaceLogic findReplaceLogic) { + super(() -> findReplaceLogic.toggle(searchOption)); + this.searchOption = searchOption; + this.findReplaceLogic = findReplaceLogic; + } + + SearchOptions getSearchOption() { + return searchOption; + } + + IFindReplaceLogic getFindReplaceLogic() { + return findReplaceLogic; + } + +}