Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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
* <em>inactive</em>. 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 -> {
Expand All @@ -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;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand All @@ -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();
}

Expand Down Expand Up @@ -1055,4 +1046,4 @@ private void decorate() {
}
}

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@
class FindReplaceOverlayAction {
private final Runnable operation;

private final List<Runnable> executionListeners = new ArrayList<>();

private final List<KeyStroke> shortcuts = new ArrayList<>();

FindReplaceOverlayAction(Runnable operation) {
Expand All @@ -31,6 +33,7 @@ void addShortcuts(List<KeyStroke> shortcutsToAdd) {

void execute() {
operation.run();
notifyExecutionListeners();
}

List<KeyStroke> getShortcuts() {
Expand All @@ -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();
}
}

}
Original file line number Diff line number Diff line change
@@ -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;
}

}
Loading