Skip to content

Commit

Permalink
Find/Replace overlay: add a search- and replace- history
Browse files Browse the repository at this point in the history
Adds a history feature for the find and replace bar of the overlay.
The history is displayed using a menu filled with entries from the
HistoryStore.

fixes #1907
  • Loading branch information
Maximilian Wittmer authored and Maximilian Wittmer committed Jun 24, 2024
1 parent 54609c8 commit 3b71076
Show file tree
Hide file tree
Showing 8 changed files with 216 additions and 17 deletions.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,8 @@ private FindReplaceMessages() {
public static String FindReplaceOverlay_searchBar_message;
public static String FindReplaceOverlay_replaceBar_message;
public static String FindReplaceOverlay_replaceToggle_toolTip;
public static String FindReplaceOverlay_searchHistory_toolTip;
public static String FindReplaceOverlay_replaceHistory_toolTip;
public static String FindReplaceOverlayFirstTimePopup_FindReplaceOverlayFirstTimePopup_message;
public static String FindReplaceOverlayFirstTimePopup_FindReplaceOverlayFirstTimePopup_title;
}
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ FindReplace_ReplaceAllButton_label=Replace &All
FindReplace_SelectAllButton_label=&Select All
FindReplace_CloseButton_label=Close

# Messages for the "new" Find-Replace-Overlay
# Messages for the Find-Replace-Overlay
FindReplaceOverlay_upSearchButton_toolTip=Search backward (Shift + Enter)
FindReplaceOverlay_downSearchButton_toolTip=Search forward (Enter)
FindReplaceOverlay_searchAllButton_toolTip=Search all (Ctrl + Enter)
Expand All @@ -55,8 +55,10 @@ FindReplaceOverlay_caseSensitiveButton_toolTip=Match case (Ctrl + Shift + C)
FindReplaceOverlay_wholeWordsButton_toolTip=Match whole word (Ctrl + Shift + W)
FindReplaceOverlay_replaceButton_toolTip=Replace (Enter)
FindReplaceOverlay_replaceAllButton_toolTip=Replace all (Ctrl + Enter)
FindReplaceOverlay_searchBar_message=Find
FindReplaceOverlay_replaceBar_message=Replace
FindReplaceOverlay_searchBar_message=Find (\u2195 for history)
FindReplaceOverlay_replaceBar_message=Replace (\u2195 for history)
FindReplaceOverlay_replaceToggle_toolTip=Toggle input for replace (Ctrl + R)
FindReplaceOverlay_searchHistory_toolTip=Show search history
FindReplaceOverlay_replaceHistory_toolTip=Show replace history
FindReplaceOverlayFirstTimePopup_FindReplaceOverlayFirstTimePopup_message=Find and replace can now be done using an overlay embedded inside the editor. If you prefer the dialog, you can disable the overlay in the preferences or <a>disable it now</a>.
FindReplaceOverlayFirstTimePopup_FindReplaceOverlayFirstTimePopup_title=New Find/Replace Overlay
Original file line number Diff line number Diff line change
Expand Up @@ -109,4 +109,8 @@ private void writeHistory() {
settingsManager.put(sectionName, names);
}

public List<String> asList() {
return new ArrayList<>(history);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
package org.eclipse.ui.internal.findandreplace.overlay;

import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.events.ShellAdapter;
import org.eclipse.swt.events.ShellEvent;
import org.eclipse.swt.events.ShellListener;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.swt.widgets.TableItem;

import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.layout.GridDataFactory;

import org.eclipse.ui.internal.findandreplace.HistoryStore;

public class SearchHistoryMenu extends Dialog {
private final SelectionListener selectionListener;
private final HistoryStore history;
private final ShellListener shellFocusListener = new ShellAdapter() {
@Override
public void shellDeactivated(ShellEvent e) {
if (getShell().getParent() != null) {
getShell().getParent().forceFocus();
}
close();
}
};
private Point location;
private int width;

public SearchHistoryMenu(Shell parent, HistoryStore history,
SelectionListener menuItemSelectionListener) {
super(parent);
setShellStyle(SWT.MODELESS);
setBlockOnOpen(false);

this.selectionListener = menuItemSelectionListener;
this.history = history;
}

public void setPosition(int x, int y, int width) {
location = new Point(x, y);
this.width = width;
}

@Override
public Control createContents(Composite parent) {

Table table = new Table(parent, SWT.NONE);
GridDataFactory.fillDefaults().grab(true, true).align(SWT.FILL, SWT.FILL).applyTo(table);
TableColumn column = new TableColumn(table, SWT.NONE);

for (String entry : history.get()) {
TableItem item = new TableItem(table, SWT.NONE);
item.setText(entry);
}

table.addSelectionListener(selectionListener);
table.addSelectionListener(SelectionListener.widgetSelectedAdapter(e -> close()));
getShell().layout();

positionShell(table, column);
return table;
}

private void positionShell(Table table, TableColumn column) {
if (location != null) {
getShell().setBounds(location.x, location.y, width,
Math.min(table.getItemHeight() * 7, table.getItemHeight() * table.getItemCount()));
}
int columnSize = table.getSize().x;
if (table.getVerticalBar() != null) {
columnSize -= table.getVerticalBar().getSize().x;
}
column.setWidth(columnSize);
}

@Override
public int open() {
int code = super.open();

getShell().addShellListener(shellFocusListener);

return code;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Scrollable;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableItem;
import org.eclipse.swt.widgets.Text;
import org.eclipse.swt.widgets.ToolItem;
import org.eclipse.swt.widgets.Widget;
Expand All @@ -59,7 +61,9 @@
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.internal.findandreplace.FindReplaceLogic;
import org.eclipse.ui.internal.findandreplace.FindReplaceMessages;
import org.eclipse.ui.internal.findandreplace.HistoryStore;
import org.eclipse.ui.internal.findandreplace.SearchOptions;
import org.eclipse.ui.internal.findandreplace.overlay.SearchHistoryMenu;
import org.eclipse.ui.internal.findandreplace.status.IFindReplaceStatus;

/**
Expand Down Expand Up @@ -87,25 +91,38 @@ class FindReplaceOverlay extends Dialog {
private Composite searchBarContainer;
private Text searchBar;
private AccessibleToolBar searchTools;

@SuppressWarnings("unused")

Check warning on line 94 in bundles/org.eclipse.ui.workbench.texteditor/src/org/eclipse/ui/texteditor/FindReplaceOverlay.java

View check run for this annotation

Jenkins - Eclipse Platform / Compiler and API Tools

Unnecessary Code

LOW: At least one of the problems in category 'unused' is not analysed due to a compiler option being ignored
private ToolItem searchHistoryButton;
private ToolItem searchInSelectionButton;
private ToolItem wholeWordSearchButton;
private ToolItem caseSensitiveSearchButton;
private ToolItem regexSearchButton;

@SuppressWarnings("unused")
private ToolItem searchUpButton;
private ToolItem searchDownButton;

@SuppressWarnings("unused")
private ToolItem searchAllButton;

private Composite replaceContainer;
private Composite replaceBarContainer;
private Text replaceBar;
private AccessibleToolBar replaceTools;

@SuppressWarnings("unused")

Check warning on line 113 in bundles/org.eclipse.ui.workbench.texteditor/src/org/eclipse/ui/texteditor/FindReplaceOverlay.java

View check run for this annotation

Jenkins - Eclipse Platform / Compiler and API Tools

Unnecessary Code

LOW: At least one of the problems in category 'unused' is not analysed due to a compiler option being ignored
private ToolItem replaceHistoryButton;

@SuppressWarnings("unused")
private ToolItem replaceButton;
private ToolItem replaceAllButton;

Check warning on line 118 in bundles/org.eclipse.ui.workbench.texteditor/src/org/eclipse/ui/texteditor/FindReplaceOverlay.java

View check run for this annotation

Jenkins - Eclipse Platform / Compiler and API Tools

Unnecessary Code

NORMAL: The value of the field FindReplaceOverlay.replaceAllButton is not used

private Color backgroundToUse;
private Color normalTextForegroundColor;
private boolean positionAtTop = true;
private static final int HISTORY_SIZE = 15;
private HistoryStore searchHistory;
private HistoryStore replaceHistory;

public FindReplaceOverlay(Shell parent, IWorkbenchPart part, IFindReplaceTarget target) {
super(parent);
Expand All @@ -114,7 +131,12 @@ public FindReplaceOverlay(Shell parent, IWorkbenchPart part, IFindReplaceTarget
setShellStyle(SWT.MODELESS);
setBlockOnOpen(false);
targetPart = part;
setupHistory();
}

private void setupHistory() {
searchHistory = new HistoryStore(getDialogSettings(), "findhistory", HISTORY_SIZE); //$NON-NLS-1$
replaceHistory = new HistoryStore(getDialogSettings(), "replacehistory", HISTORY_SIZE); //$NON-NLS-1$
}

@Override
Expand All @@ -138,11 +160,14 @@ private void createFindReplaceLogic(IFindReplaceTarget target) {
private void performReplaceAll() {
BusyIndicator.showWhile(getShell() != null ? getShell().getDisplay() : Display.getCurrent(),
() -> findReplaceLogic.performReplaceAll(getFindString(), getReplaceString()));
updateHistory(replaceBar, replaceHistory);
updateHistory(searchBar, searchHistory);
}

private void performSelectAll() {
BusyIndicator.showWhile(getShell() != null ? getShell().getDisplay() : Display.getCurrent(),
() -> findReplaceLogic.performSelectAll(getFindString()));
updateHistory(searchBar, searchHistory);
}

private KeyListener shortcuts = KeyListener.keyPressedAdapter(e -> {
Expand All @@ -165,11 +190,31 @@ private void performSelectAll() {
performEnterAction(e);
} else if (e.keyCode == SWT.ESC) {
close();
} else if (e.keyCode == SWT.ARROW_UP || e.keyCode == SWT.ARROW_DOWN) {
int stepDirection = e.keyCode == SWT.ARROW_UP ? 1 : -1;
if (replaceBar.isFocusControl()) {
navigateInHistory(replaceBar, replaceHistory, stepDirection);
} else {
navigateInHistory(searchBar, searchHistory, stepDirection);
}
} else {
e.doit = true;
}
});

private void navigateInHistory(Text textBar, HistoryStore history, int navigationOffset) {
int offset = history.asList().indexOf(textBar.getText());

offset += navigationOffset;
offset = offset % history.asList().size();

if (offset + navigationOffset < 0) {
offset = history.asList().size() - 1;
}

textBar.setText(history.get(offset));
}

private void performEnterAction(KeyEvent e) {
boolean isShiftPressed = (e.stateMask & SWT.SHIFT) != 0;
boolean isCtrlPressed = (e.stateMask & SWT.CTRL) != 0;
Expand Down Expand Up @@ -338,24 +383,15 @@ private void restoreOverlaySettings() {

private void applyOverlayColors(Color color, boolean tryToColorReplaceBar) {
searchTools.setBackground(color);
searchInSelectionButton.setBackground(color);
wholeWordSearchButton.setBackground(color);
regexSearchButton.setBackground(color);
caseSensitiveSearchButton.setBackground(color);
searchAllButton.setBackground(color);
searchUpButton.setBackground(color);
searchDownButton.setBackground(color);

searchBarContainer.setBackground(color);
searchBar.setBackground(color);
searchContainer.setBackground(color);

if (replaceBarOpen && tryToColorReplaceBar) {
replaceContainer.setBackground(color);
replaceBar.setBackground(color);
replaceBarContainer.setBackground(color);
replaceAllButton.setBackground(color);
replaceButton.setBackground(color);
replaceTools.setBackground(color);
replaceBar.setBackground(color);
}
}

Expand Down Expand Up @@ -425,13 +461,36 @@ private void createSearchTools() {
searchTools = new AccessibleToolBar(searchContainer);
GridDataFactory.fillDefaults().grab(false, true).align(GridData.CENTER, GridData.END).applyTo(searchTools);

searchHistoryButton = new AccessibleToolItemBuilder(searchTools)
.withStyleBits(SWT.PUSH).withToolTipText(FindReplaceMessages.FindReplaceOverlay_searchHistory_toolTip)
.withImage(FindReplaceOverlayImages.get(FindReplaceOverlayImages.KEY_OPEN_HISTORY))
.withSelectionListener(SelectionListener.widgetSelectedAdapter(e -> {
@SuppressWarnings("unused")

Check warning on line 468 in bundles/org.eclipse.ui.workbench.texteditor/src/org/eclipse/ui/texteditor/FindReplaceOverlay.java

View check run for this annotation

Jenkins - Eclipse Platform / Compiler and API Tools

Unnecessary Code

LOW: At least one of the problems in category 'unused' is not analysed due to a compiler option being ignored
SearchHistoryMenu menu = new SearchHistoryMenu(getShell(), searchHistory,
SelectionListener.widgetSelectedAdapter(f -> {
Table table = (Table) f.widget;
TableItem[] selection = table.getSelection();
String text = selection[0].getText();
if (text != null) {
searchBar.setText(text);
}
}));

Point searchBarPosition = searchBar.toDisplay(0, 0);
menu.setPosition(searchBarPosition.x, searchBarPosition.y + searchHistoryButton.getWidth(),
searchBar.getSize().x + searchHistoryButton.getWidth());
menu.open();
})).build();

@SuppressWarnings("unused")
ToolItem separator = searchTools.createToolItem(SWT.SEPARATOR);

createWholeWordsButton();
createCaseSensitiveButton();
createRegexSearchButton();
createAreaSearchButton();

@SuppressWarnings("unused")
ToolItem separator = searchTools.createToolItem(SWT.SEPARATOR);
separator = searchTools.createToolItem(SWT.SEPARATOR);

searchUpButton = new AccessibleToolItemBuilder(searchTools).withStyleBits(SWT.PUSH)
.withImage(FindReplaceOverlayImages.get(FindReplaceOverlayImages.KEY_FIND_PREV))
Expand Down Expand Up @@ -507,6 +566,34 @@ private void createReplaceTools() {
Color warningColor = JFaceColors.getErrorText(getShell().getDisplay());

replaceTools = new AccessibleToolBar(replaceContainer);

replaceHistoryButton = new AccessibleToolItemBuilder(replaceTools)
.withStyleBits(SWT.PUSH)
.withToolTipText(FindReplaceMessages.FindReplaceOverlay_replaceHistory_toolTip)
.withImage(FindReplaceOverlayImages.get(FindReplaceOverlayImages.KEY_OPEN_HISTORY))
.withSelectionListener(SelectionListener.widgetSelectedAdapter(e -> {
@SuppressWarnings("unused")

Check warning on line 575 in bundles/org.eclipse.ui.workbench.texteditor/src/org/eclipse/ui/texteditor/FindReplaceOverlay.java

View check run for this annotation

Jenkins - Eclipse Platform / Compiler and API Tools

Unnecessary Code

LOW: At least one of the problems in category 'unused' is not analysed due to a compiler option being ignored
SearchHistoryMenu menu = new SearchHistoryMenu(getShell(), replaceHistory,
SelectionListener.widgetSelectedAdapter(f -> {
Table table = (Table) f.widget;
TableItem[] selection = table.getSelection();
String text = selection[0].getText();
if (text != null) {
replaceBar.setText(text);
}
}));


Point searchBarPosition = replaceBar.toDisplay(0, 0);
menu.setPosition(searchBarPosition.x,
searchBarPosition.y + replaceHistoryButton.getWidth(),
replaceBar.getSize().x + replaceHistoryButton.getWidth());
menu.open();
})).build();

@SuppressWarnings("unused")
ToolItem separator = replaceTools.createToolItem(SWT.SEPARATOR);

GridDataFactory.fillDefaults().grab(false, true).align(GridData.CENTER, GridData.END).applyTo(replaceTools);
replaceButton = new AccessibleToolItemBuilder(replaceTools).withStyleBits(SWT.PUSH)
.withImage(FindReplaceOverlayImages.get(FindReplaceOverlayImages.KEY_REPLACE))
Expand Down Expand Up @@ -805,6 +892,8 @@ private String getReplaceString() {

private void performSingleReplace() {
findReplaceLogic.performReplaceAndFind(getFindString(), getReplaceString());
updateHistory(replaceBar, replaceHistory);
updateHistory(searchBar, searchHistory);
}

private void performSearch(boolean forward) {
Expand All @@ -814,6 +903,7 @@ private void performSearch(boolean forward) {
findReplaceLogic.performSearch(getFindString());
activateInFindReplacerIf(SearchOptions.FORWARD, oldForwardSearchSetting);
findReplaceLogic.activate(SearchOptions.INCREMENTAL);
updateHistory(searchBar, searchHistory);
}

private void initFindStringFromSelection() {
Expand Down Expand Up @@ -864,4 +954,10 @@ private static boolean okayToUse(Widget widget) {
public void setPositionToTop(boolean shouldPositionOverlayOnTop) {
positionAtTop = shouldPositionOverlayOnTop;
}

private void updateHistory(Text text, HistoryStore history) {
String string = text.getText();
history.remove(string); // ensure findString is now on the newest index of the history
history.add(string);
}
}
Loading

0 comments on commit 3b71076

Please sign in to comment.