Skip to content
Open
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
2 changes: 1 addition & 1 deletion bundles/org.eclipse.search/META-INF/MANIFEST.MF
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: %pluginName
Bundle-SymbolicName: org.eclipse.search; singleton:=true
Bundle-Version: 3.19.0.qualifier
Bundle-Version: 3.19.100.qualifier
Bundle-Activator: org.eclipse.search.internal.ui.SearchPlugin
Bundle-ActivationPolicy: lazy
Bundle-Vendor: %providerName
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,14 +26,24 @@
import org.osgi.framework.FrameworkUtil;

import org.eclipse.swt.SWT;
import org.eclipse.swt.events.MouseTrackAdapter;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableItem;
import org.eclipse.swt.widgets.ToolBar;
import org.eclipse.swt.widgets.ToolItem;
import org.eclipse.swt.widgets.Tree;
import org.eclipse.swt.widgets.TreeItem;

import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.IProgressMonitor;
Expand All @@ -54,6 +64,7 @@
import org.eclipse.jface.dialogs.ErrorDialog;
import org.eclipse.jface.dialogs.IDialogSettings;
import org.eclipse.jface.util.OpenStrategy;
import org.eclipse.jface.viewers.AbstractTreeViewer;
import org.eclipse.jface.viewers.DecoratingLabelProvider;
import org.eclipse.jface.viewers.IBaseLabelProvider;
import org.eclipse.jface.viewers.IOpenListener;
Expand Down Expand Up @@ -279,6 +290,8 @@ public void selectionChanged(SelectionChangedEvent event) {
public static final int FLAG_LAYOUT_TREE = 2;
private OpenAndLinkWithEditorHelper openAndLinkWithEditorHelper;

private Shell fHoverShell;
private TreeItem fHoveredItem;

/**
* This constructor must be passed a combination of layout flags combined
Expand Down Expand Up @@ -709,6 +722,8 @@ public void setLayout(int layout) {
}

private void disposeViewer() {
disposeHoverShell();
fHoveredItem = null;
fViewer.removeSelectionChangedListener(fViewerAdapter);
fViewer.getControl().dispose();
fViewer = null;
Expand Down Expand Up @@ -746,6 +761,7 @@ private void createViewer(Composite parent, int layout) {
configureTreeViewer(viewer);
fCollapseAllAction.setViewer(viewer);
fExpandAllAction.setViewer(viewer);
installHoverExpandSupport(viewer);
}

fCopyToClipboardAction.setViewer(fViewer);
Expand Down Expand Up @@ -1559,5 +1575,141 @@ public Integer getElementLimit() {
return fElementLimit;
}

private void installHoverExpandSupport(TreeViewer viewer) {
Tree tree = viewer.getTree();

tree.addMouseMoveListener(e -> {
TreeItem item = tree.getItem(new Point(e.x, e.y));

boolean overShell = fHoverShell != null && !fHoverShell.isDisposed()
&& fHoverShell.getBounds().contains(tree.toDisplay(e.x, e.y));
if (item == null || item.getParentItem() != null) {
if (!overShell) {
disposeHoverShell();
fHoveredItem = null;
}
return;
}
Rectangle rowBounds = item.getBounds();
Rectangle extRowBounds = new Rectangle(rowBounds.x, rowBounds.y,
rowBounds.width + 20, rowBounds.height);
boolean overRow = extRowBounds.contains(e.x, e.y);
if (!overRow) {
if (!overShell) {
disposeHoverShell();
fHoveredItem = null;
}
return;
}
if (item == fHoveredItem) {
return;
}
disposeHoverShell();
fHoveredItem = item;

Object element = item.getData();
if (element == null) {
return;
}
boolean expanded = viewer.getExpandedState(element);
showHoverShell(tree, item, element, viewer, expanded);
});

tree.addMouseTrackListener(new MouseTrackAdapter() {
@Override
public void mouseExit(org.eclipse.swt.events.MouseEvent e) {
if (fHoverShell == null || fHoverShell.isDisposed()) {
fHoveredItem = null;
}
}
});
}

/**
* Creates and displays an option to expand or collapse any single item
*
* @param expanded
* whether the parent is currently expanded
*/
private void showHoverShell(Tree tree, TreeItem item, Object element, TreeViewer viewer, boolean expanded) {
org.eclipse.jface.resource.ImageDescriptor desc = expanded
? fCollapseAllAction.getImageDescriptor()
: fExpandAllAction.getImageDescriptor();
if (desc == null) {
return;
}
Image actionImage = desc.createImage(false);
if (actionImage == null) {
return;
}

Shell shell = new Shell(tree.getShell(), SWT.TOOL | SWT.ON_TOP | SWT.NO_FOCUS | SWT.NO_TRIM);
shell.setBackground(tree.getDisplay().getSystemColor(SWT.COLOR_INFO_BACKGROUND));
ToolBar tb = new ToolBar(shell, SWT.FLAT);
ToolItem ti = new ToolItem(tb, SWT.PUSH);
ti.setImage(actionImage);
ti.setToolTipText(expanded ? SearchMessages.CollapseItemAction_tooltip : SearchMessages.ExpandItemAction_tooltip);

shell.addListener(SWT.Dispose, e -> actionImage.dispose());
shell.addMouseTrackListener(new MouseTrackAdapter() {
@Override
public void mouseExit(org.eclipse.swt.events.MouseEvent e) {
disposeHoverShell();
fHoveredItem = null;
}
});

ti.addSelectionListener(new org.eclipse.swt.events.SelectionAdapter() {
@Override
public void widgetSelected(org.eclipse.swt.events.SelectionEvent e) {
if (!viewer.getControl().isDisposed()) {
viewer.getControl().setRedraw(false);
try {
if (expanded) {
viewer.collapseToLevel(element, AbstractTreeViewer.ALL_LEVELS);
} else {
viewer.expandToLevel(element, AbstractTreeViewer.ALL_LEVELS);
}
} finally {
viewer.getControl().setRedraw(true);
}
}
shell.dispose();
fHoverShell = null;
fHoveredItem = null;
}
});

tb.pack();
shell.pack();

Rectangle textBounds = item.getTextBounds(0);
int shellHeight = shell.getSize().y;
int shellWidth = shell.getSize().x;
int centredY = textBounds.y + (textBounds.height - shellHeight) / 2;
GC gc = new GC(tree);
int textWidth;
try {
textWidth = gc.textExtent(item.getText()).x;
} finally {
gc.dispose();
}
int desiredX = textBounds.x + textWidth + 2;
Rectangle treeDisplayBounds = tree.getDisplay().map(tree, null, tree.getClientArea());
int maxX = treeDisplayBounds.x + treeDisplayBounds.width - shellWidth - 2;
Point desiredDisplay = tree.toDisplay(desiredX, centredY);
int finalX = Math.min(desiredDisplay.x, maxX);
shell.setLocation(finalX, desiredDisplay.y);
shell.setVisible(true);

fHoverShell = shell;
}

private void disposeHoverShell() {
if (fHoverShell != null && !fHoverShell.isDisposed()) {
fHoverShell.dispose();
}
fHoverShell = null;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,8 @@ private SearchMessages() {
public static String CollapseAllAction_1;
public static String ExpandAllAction_label;
public static String ExpandAllAction_tooltip;
public static String ExpandItemAction_tooltip;
public static String CollapseItemAction_tooltip;
public static String SearchView_error_noResultPage;
public static String InternalSearchUI_error_unexpected;
public static String NewSearchUI_error_title;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,8 @@ CollapseAllAction_0=Collapse All
CollapseAllAction_1=Collapse All
ExpandAllAction_label=Expand All
ExpandAllAction_tooltip=Expand All
ExpandItemAction_tooltip=Expand item
CollapseItemAction_tooltip=Collapse item
SearchView_error_noResultPage=No search result page found for search result class {0}
SearchView_empty_search_label=No search results available. Start a search from the <a>search dialog</a>...
InternalSearchUI_error_unexpected=An unexpected exception occurred during search
Expand Down
Loading