Initial implementation 'Goto Symbols' View
This commit is contained in:
@@ -19,7 +19,8 @@ Require-Bundle: org.eclipse.ui,
|
||||
org.eclipse.core.runtime;bundle-version="3.13.0",
|
||||
org.springsource.ide.eclipse.commons.core;bundle-version="3.9.2",
|
||||
io.projectreactor.reactor-core;bundle-version="3.0.7",
|
||||
org.reactivestreams.reactive-streams;bundle-version="1.0.0"
|
||||
org.reactivestreams.reactive-streams;bundle-version="1.0.0",
|
||||
org.springframework.ide.eclipse.boot.dash
|
||||
Bundle-RequiredExecutionEnvironment: JavaSE-1.8
|
||||
Bundle-Activator: org.springframework.tooling.ls.eclipse.gotosymbol.GotoSymbolPlugin
|
||||
Bundle-ActivationPolicy: lazy
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 617 B |
Binary file not shown.
|
After Width: | Height: | Size: 1.5 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 332 B |
Binary file not shown.
|
Before Width: | Height: | Size: 526 B |
@@ -1,6 +1,18 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<?eclipse version="3.4"?>
|
||||
<plugin>
|
||||
|
||||
<extension
|
||||
point="org.eclipse.ui.views">
|
||||
<view
|
||||
name="Spring Symbols"
|
||||
icon="$nl$/icons/boot-icon.png"
|
||||
category="org.springframework.ide.eclipse.ui.views"
|
||||
class="org.springframework.tooling.ls.eclipse.gotosymbol.view.SpringSymbolsView"
|
||||
id="org.springframework.ide.eclipse.boot.dash.views.BootDashView">
|
||||
</view>
|
||||
</extension>
|
||||
|
||||
<extension
|
||||
point="org.eclipse.ui.commands">
|
||||
<category
|
||||
|
||||
@@ -11,196 +11,27 @@
|
||||
*******************************************************************************/
|
||||
package org.springframework.tooling.ls.eclipse.gotosymbol.dialogs;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.eclipse.core.resources.IMarker;
|
||||
import org.eclipse.core.resources.IResource;
|
||||
import org.eclipse.core.runtime.CoreException;
|
||||
import org.eclipse.jface.dialogs.IDialogSettings;
|
||||
import org.eclipse.jface.dialogs.PopupDialog;
|
||||
import org.eclipse.jface.layout.GridDataFactory;
|
||||
import org.eclipse.jface.resource.JFaceColors;
|
||||
import org.eclipse.jface.text.BadLocationException;
|
||||
import org.eclipse.jface.text.IDocument;
|
||||
import org.eclipse.jface.text.IRegion;
|
||||
import org.eclipse.jface.viewers.ColumnViewerToolTipSupport;
|
||||
import org.eclipse.jface.viewers.ISelection;
|
||||
import org.eclipse.jface.viewers.IStructuredSelection;
|
||||
import org.eclipse.jface.viewers.ITreeContentProvider;
|
||||
import org.eclipse.jface.viewers.StructuredSelection;
|
||||
import org.eclipse.jface.viewers.StyledCellLabelProvider;
|
||||
import org.eclipse.jface.viewers.StyledString;
|
||||
import org.eclipse.jface.viewers.TreeViewer;
|
||||
import org.eclipse.jface.viewers.ViewerCell;
|
||||
import org.eclipse.lsp4e.LSPEclipseUtils;
|
||||
import org.eclipse.lsp4e.outline.SymbolsLabelProvider;
|
||||
import org.eclipse.lsp4j.Location;
|
||||
import org.eclipse.lsp4j.Range;
|
||||
import org.eclipse.lsp4j.SymbolInformation;
|
||||
import org.eclipse.lsp4j.jsonrpc.messages.Either;
|
||||
import org.eclipse.jface.operation.IRunnableContext;
|
||||
import org.eclipse.swt.SWT;
|
||||
import org.eclipse.swt.custom.StyledText;
|
||||
import org.eclipse.swt.events.KeyAdapter;
|
||||
import org.eclipse.swt.events.KeyEvent;
|
||||
import org.eclipse.swt.graphics.Color;
|
||||
import org.eclipse.swt.graphics.Font;
|
||||
import org.eclipse.swt.graphics.Point;
|
||||
import org.eclipse.swt.layout.GridData;
|
||||
import org.eclipse.swt.layout.GridLayout;
|
||||
import org.eclipse.swt.widgets.Composite;
|
||||
import org.eclipse.swt.widgets.Control;
|
||||
import org.eclipse.swt.widgets.Display;
|
||||
import org.eclipse.swt.widgets.Event;
|
||||
import org.eclipse.swt.widgets.Shell;
|
||||
import org.eclipse.swt.widgets.Text;
|
||||
import org.eclipse.swt.widgets.TreeItem;
|
||||
import org.eclipse.ui.PlatformUI;
|
||||
import org.eclipse.ui.texteditor.ITextEditor;
|
||||
import org.springframework.tooling.ls.eclipse.gotosymbol.GotoSymbolPlugin;
|
||||
import org.springframework.tooling.ls.eclipse.gotosymbol.dialogs.GotoSymbolDialogModel.Match;
|
||||
import org.springsource.ide.eclipse.commons.core.util.FuzzyMatcher;
|
||||
import org.springsource.ide.eclipse.commons.livexp.core.UIValueListener;
|
||||
import org.springsource.ide.eclipse.commons.livexp.ui.Disposable;
|
||||
import org.springsource.ide.eclipse.commons.livexp.ui.Stylers;
|
||||
import org.springsource.ide.eclipse.commons.livexp.ui.util.SwtConnect;
|
||||
import org.springsource.ide.eclipse.commons.livexp.ui.IPageWithSections;
|
||||
|
||||
@SuppressWarnings("restriction")
|
||||
public class GotoSymbolDialog extends PopupDialog {
|
||||
public class GotoSymbolDialog extends PopupDialog implements IPageWithSections {
|
||||
|
||||
private static class SymbolsContentProvider implements ITreeContentProvider {
|
||||
|
||||
@Override
|
||||
public Object[] getChildren(Object parentElement) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getParent(Object element) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasChildren(Object element) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object[] getElements(Object inputElement) {
|
||||
if (inputElement instanceof GotoSymbolDialogModel) {
|
||||
GotoSymbolDialogModel model = (GotoSymbolDialogModel) inputElement;
|
||||
return model.getSymbols().getValue().toArray();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private class GotoSymbolsLabelProvider extends StyledCellLabelProvider {
|
||||
|
||||
private Stylers stylers;
|
||||
private SymbolsLabelProvider symbolsLabelProvider;
|
||||
|
||||
public GotoSymbolsLabelProvider(Font base) {
|
||||
stylers = new Stylers(base);
|
||||
boolean showSymbolsLabelProviderLocation = false; /* dont show full location. we show relative location in our own implementation below */
|
||||
boolean showKindInformation = false;
|
||||
symbolsLabelProvider = new SymbolsLabelProvider(showSymbolsLabelProviderLocation , showKindInformation) {
|
||||
@Override
|
||||
protected int getMaxSeverity(IResource resource, IDocument doc, Range range)
|
||||
throws CoreException, BadLocationException {
|
||||
int maxSeverity = -1;
|
||||
for (IMarker marker : resource.findMarkers(IMarker.PROBLEM, true, IResource.DEPTH_ZERO)) {
|
||||
int offset = marker.getAttribute(IMarker.CHAR_START, -1);
|
||||
if (offset != -1) {
|
||||
maxSeverity = Math.max(maxSeverity, marker.getAttribute(IMarker.SEVERITY, -1));
|
||||
}
|
||||
}
|
||||
return maxSeverity;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public Color getToolTipBackgroundColor(Object object) {
|
||||
return JFaceColors.getInformationViewerBackgroundColor(Display.getDefault());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Color getToolTipForegroundColor(Object object) {
|
||||
return JFaceColors.getInformationViewerForegroundColor(Display.getDefault());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getToolTipText(Object element) {
|
||||
if (element instanceof Match) {
|
||||
SymbolInformation si = getSymbolInformation((Match<?>)element);
|
||||
if (si!=null) {
|
||||
return si.getName();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(ViewerCell cell) {
|
||||
super.update(cell);
|
||||
Object obj = cell.getElement();
|
||||
if (obj instanceof Match) {
|
||||
Match<?> match = (Match<?>) obj;
|
||||
cell.setImage(symbolsLabelProvider.getImage(match.value));
|
||||
StyledString styledString = getStyledText(match);
|
||||
cell.setText(styledString.getString());
|
||||
cell.setStyleRanges(styledString.getStyleRanges());
|
||||
cell.getControl().redraw();
|
||||
//^^^ Sigh... Yes, this is needed. It seems SWT/Jface isn't smart enough to itself figure out that if
|
||||
//the styleranges change a redraw is needed to make the change visible.
|
||||
} else {
|
||||
super.update(cell);
|
||||
}
|
||||
}
|
||||
|
||||
private StyledString getStyledText(Match<?> element) {
|
||||
SymbolInformation symbolInformation = getSymbolInformation(element);
|
||||
if (symbolInformation != null) {
|
||||
String name = symbolInformation.getName();
|
||||
StyledString s = new StyledString(name);
|
||||
Collection<IRegion> highlights = FuzzyMatcher.highlights(element.query, name.toLowerCase());
|
||||
for (IRegion hl : highlights) {
|
||||
s.setStyle(hl.getOffset(), hl.getLength(), stylers.bold());
|
||||
}
|
||||
String locationText = getSymbolLocationText(symbolInformation);
|
||||
if (locationText != null) {
|
||||
s = s.append(locationText, stylers.italicColoured(SWT.COLOR_DARK_GRAY));
|
||||
}
|
||||
return s;
|
||||
} else {
|
||||
return symbolsLabelProvider.getStyledText(element.value);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
stylers.dispose();
|
||||
symbolsLabelProvider.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
protected String getSymbolLocationText(SymbolInformation symbol) {
|
||||
Optional<String> location = GotoSymbolDialog.this
|
||||
.getSymbolLocation(symbol);
|
||||
if (location.isPresent()) {
|
||||
return " -- [" + location.get() + "]";
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private static final Point DEFAULT_SIZE = new Point(280, 300);
|
||||
|
||||
private GotoSymbolDialogModel model;
|
||||
private List<Disposable> disposables = new ArrayList<>();
|
||||
private final GotoSymbolSection content;
|
||||
private ITextEditor fTextEditor;
|
||||
|
||||
/**
|
||||
@@ -219,26 +50,11 @@ public class GotoSymbolDialog extends PopupDialog {
|
||||
//For the time being I've simply disabled the menu that makes it appear like this should work.
|
||||
this.fTextEditor = textEditor;
|
||||
this.model = model;
|
||||
this.content = new GotoSymbolSection(this, model);
|
||||
this.alignRight = alignRight;
|
||||
create();
|
||||
}
|
||||
|
||||
private SymbolInformation getSymbolInformation(Match<?> element) {
|
||||
if (element.value instanceof SymbolInformation) {
|
||||
return (SymbolInformation) element.value;
|
||||
}
|
||||
if (element.value instanceof Either) {
|
||||
Either<?,?> either = (Either<?, ?>)element.value;
|
||||
if (either.isLeft()) {
|
||||
Object left = either.getLeft();
|
||||
if (left instanceof SymbolInformation) {
|
||||
return (SymbolInformation) left;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected IDialogSettings getDialogSettings() {
|
||||
if (dlgSettings==null) {
|
||||
@@ -247,125 +63,9 @@ public class GotoSymbolDialog extends PopupDialog {
|
||||
return dlgSettings;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine the 'target' for the dialog's action.
|
||||
*/
|
||||
private SymbolInformation getTarget(TreeViewer list) {
|
||||
ISelection sel = list.getSelection();
|
||||
if (sel instanceof IStructuredSelection) {
|
||||
IStructuredSelection ss = (IStructuredSelection) sel;
|
||||
Object selected = ss.getFirstElement();
|
||||
if (selected instanceof Match) {
|
||||
SymbolInformation si = getSymbolInformation((Match<?>) selected);
|
||||
if (si!=null) {
|
||||
return si;
|
||||
}
|
||||
}
|
||||
}
|
||||
//No element selected, target the first element in the list instead.
|
||||
//This allows user to execute the action without explicitly selecting an element.
|
||||
return getFirstElement(list);
|
||||
}
|
||||
|
||||
private void installWidgetListeners(Text pattern, TreeViewer list) {
|
||||
pattern.addKeyListener(new KeyAdapter() {
|
||||
public void keyPressed(KeyEvent e) {
|
||||
if (e.keyCode == SWT.ARROW_DOWN) {
|
||||
if (list.getTree().getItemCount() > 0) {
|
||||
list.getTree().setFocus();
|
||||
TreeItem[] items = list.getTree().getItems();
|
||||
if (items!=null && items.length>0) {
|
||||
list.getTree().setSelection(items[0]);
|
||||
//programatic selection may not fire selection events so...
|
||||
list.getTree().notifyListeners(SWT.Selection,
|
||||
new Event());
|
||||
}
|
||||
}
|
||||
} else if (e.character == '\r') {
|
||||
performOk(list);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
list.getTree().addKeyListener(new KeyAdapter() {
|
||||
public void keyPressed(KeyEvent e) {
|
||||
|
||||
if (e.keyCode == SWT.ARROW_UP && (e.stateMask & SWT.SHIFT) == 0
|
||||
&& (e.stateMask & SWT.CTRL) == 0) {
|
||||
StructuredSelection selection = (StructuredSelection) list
|
||||
.getSelection();
|
||||
|
||||
if (selection.size() == 1) {
|
||||
Object element = selection.getFirstElement();
|
||||
if (element.equals(getFirstElement(list))) {
|
||||
pattern.setFocus();
|
||||
list.setSelection(new StructuredSelection());
|
||||
list.getTree().notifyListeners(SWT.Selection,
|
||||
new Event());
|
||||
}
|
||||
|
||||
}
|
||||
} else if (e.character == '\r') {
|
||||
performOk(list);
|
||||
}
|
||||
|
||||
// if (e.keyCode == SWT.ARROW_DOWN
|
||||
// && (e.stateMask & SWT.SHIFT) != 0
|
||||
// && (e.stateMask & SWT.CTRL) != 0) {
|
||||
//
|
||||
// list.getTree().notifyListeners(SWT.Selection, new Event());
|
||||
// }
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
list.addDoubleClickListener(e -> performOk(list));
|
||||
}
|
||||
|
||||
private Optional<String> getSymbolLocation(SymbolInformation symbolInformation) {
|
||||
String val = null;
|
||||
|
||||
if (!model.fromFileProvider(symbolInformation)) {
|
||||
Location location = symbolInformation.getLocation();
|
||||
|
||||
IResource targetResource = LSPEclipseUtils.findResourceFor(location.getUri());
|
||||
if (targetResource != null && targetResource.getFullPath() != null) {
|
||||
val = targetResource.getFullPath().toString();
|
||||
}
|
||||
}
|
||||
|
||||
return val != null ? Optional.of(val) : Optional.empty();
|
||||
}
|
||||
|
||||
private void performOk(TreeViewer list) {
|
||||
if (model.performOk(getTarget(list))) {
|
||||
close();
|
||||
}
|
||||
}
|
||||
|
||||
private SymbolInformation getFirstElement(TreeViewer list) {
|
||||
TreeItem[] items = list.getTree().getItems();
|
||||
if (items!=null && items.length>0) {
|
||||
TreeItem item = items[0];
|
||||
Object data = item.getData();
|
||||
if (data instanceof Match) {
|
||||
SymbolInformation si = getSymbolInformation((Match<?>) data);
|
||||
if (si!=null) {
|
||||
return si;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Control createDialogArea(Composite parent) {
|
||||
Composite dialogArea = new Composite(parent, SWT.NONE);
|
||||
dialogArea.addDisposeListener(de -> {
|
||||
for (Disposable d : disposables) {
|
||||
d.dispose();
|
||||
}
|
||||
});
|
||||
if (parent.getLayout() instanceof GridLayout) {
|
||||
dialogArea.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
|
||||
}
|
||||
@@ -375,66 +75,7 @@ public class GotoSymbolDialog extends PopupDialog {
|
||||
layout.marginWidth = 0;
|
||||
dialogArea.setLayout(layout);
|
||||
|
||||
Text pattern = new Text(dialogArea, SWT.SINGLE | SWT.BORDER | SWT.SEARCH | SWT.ICON_CANCEL);
|
||||
// pattern.getAccessible().addAccessibleListener(new AccessibleAdapter() {
|
||||
// public void getName(AccessibleEvent e) {
|
||||
// e.result = LegacyActionTools.removeMnemonics(headerLabel)
|
||||
// .getText());
|
||||
// }
|
||||
// });
|
||||
pattern.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
|
||||
pattern.setMessage(model.getSearchBoxHintMessage());
|
||||
|
||||
SwtConnect.connect(pattern, model.getSearchBox());
|
||||
|
||||
TreeViewer viewer = new TreeViewer(dialogArea, SWT.SINGLE);
|
||||
ColumnViewerToolTipSupport.enableFor(viewer);
|
||||
GridDataFactory.fillDefaults().grab(true, true).applyTo(viewer.getControl());
|
||||
viewer.setContentProvider(new SymbolsContentProvider());
|
||||
viewer.setLabelProvider(new GotoSymbolsLabelProvider(viewer.getTree().getFont()));
|
||||
viewer.setUseHashlookup(true);
|
||||
disposables.add(model.getSymbols().onChange(UIValueListener.from((e, v) -> {
|
||||
if (!viewer.getControl().isDisposed()) viewer.refresh();
|
||||
})));
|
||||
//TODO: somehow show selection in local file, (but not in other file ?)
|
||||
// viewer.addSelectionChangedListener(event -> {
|
||||
// IStructuredSelection selection = (IStructuredSelection) event.getSelection();
|
||||
// if (selection.isEmpty()) {
|
||||
// return;
|
||||
// }
|
||||
// SymbolInformation symbolInformation = (SymbolInformation) selection.getFirstElement();
|
||||
// Location location = symbolInformation.getLocation();
|
||||
//
|
||||
// IResource targetResource = LSPEclipseUtils.findResourceFor(location.getUri());
|
||||
// if (targetResource == null) {
|
||||
// return;
|
||||
// }
|
||||
// IDocument targetDocument = FileBuffers.getTextFileBufferManager()
|
||||
// .getTextFileBuffer(targetResource.getFullPath(), LocationKind.IFILE).getDocument();
|
||||
// if (targetDocument != null) {
|
||||
// try {
|
||||
// int offset = LSPEclipseUtils.toOffset(location.getRange().getStart(), targetDocument);
|
||||
// int endOffset = LSPEclipseUtils.toOffset(location.getRange().getEnd(), targetDocument);
|
||||
// fTextEditor.selectAndReveal(offset, endOffset - offset);
|
||||
// } catch (BadLocationException e) {
|
||||
// LanguageServerPlugin.logError(e);
|
||||
// }
|
||||
// }
|
||||
// });
|
||||
installWidgetListeners(pattern, viewer);
|
||||
|
||||
StyledText statusLabel = new StyledText(dialogArea, SWT.NONE);
|
||||
// Allow for some extra space for highlight fonts
|
||||
statusLabel.setLeftMargin(3);
|
||||
statusLabel.setBottomMargin(2);
|
||||
statusLabel.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
|
||||
|
||||
Stylers stylers = new Stylers(dialogArea.getFont());
|
||||
disposables.add(stylers);
|
||||
|
||||
SwtConnect.connectHighlighted(stylers.bold(), statusLabel, model.getStatus(), Duration.ofMillis(500));
|
||||
|
||||
viewer.setInput(model);
|
||||
content.createContents(dialogArea);
|
||||
return dialogArea;
|
||||
}
|
||||
|
||||
@@ -461,6 +102,11 @@ public class GotoSymbolDialog extends PopupDialog {
|
||||
return new Point(control.getBounds().width, control.getBounds().height/2);
|
||||
}
|
||||
|
||||
@Override
|
||||
public IRunnableContext getRunnableContext() {
|
||||
return PlatformUI.getWorkbench().getProgressService();
|
||||
}
|
||||
|
||||
// /**
|
||||
// * Determines the graphical area covered by the given text region.
|
||||
// *
|
||||
|
||||
@@ -0,0 +1,401 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2016, 2019, 2020 Rogue Wave Software Inc. and others.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* https://www.eclipse.org/legal/epl-v10.html
|
||||
*
|
||||
* Contributors:
|
||||
* Michał Niewrzał (Rogue Wave Software Inc.) - initial implementation
|
||||
* Kris De Volder (Pivotal Inc) - Copied and adapted
|
||||
*******************************************************************************/
|
||||
package org.springframework.tooling.ls.eclipse.gotosymbol.dialogs;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.eclipse.core.resources.IMarker;
|
||||
import org.eclipse.core.resources.IResource;
|
||||
import org.eclipse.core.runtime.CoreException;
|
||||
import org.eclipse.jface.layout.GridDataFactory;
|
||||
import org.eclipse.jface.resource.JFaceColors;
|
||||
import org.eclipse.jface.text.BadLocationException;
|
||||
import org.eclipse.jface.text.IDocument;
|
||||
import org.eclipse.jface.text.IRegion;
|
||||
import org.eclipse.jface.viewers.ColumnViewerToolTipSupport;
|
||||
import org.eclipse.jface.viewers.ISelection;
|
||||
import org.eclipse.jface.viewers.IStructuredSelection;
|
||||
import org.eclipse.jface.viewers.ITreeContentProvider;
|
||||
import org.eclipse.jface.viewers.StructuredSelection;
|
||||
import org.eclipse.jface.viewers.StyledCellLabelProvider;
|
||||
import org.eclipse.jface.viewers.StyledString;
|
||||
import org.eclipse.jface.viewers.TreeViewer;
|
||||
import org.eclipse.jface.viewers.ViewerCell;
|
||||
import org.eclipse.lsp4e.LSPEclipseUtils;
|
||||
import org.eclipse.lsp4e.outline.SymbolsLabelProvider;
|
||||
import org.eclipse.lsp4j.Location;
|
||||
import org.eclipse.lsp4j.Range;
|
||||
import org.eclipse.lsp4j.SymbolInformation;
|
||||
import org.eclipse.lsp4j.jsonrpc.messages.Either;
|
||||
import org.eclipse.swt.SWT;
|
||||
import org.eclipse.swt.custom.StyledText;
|
||||
import org.eclipse.swt.events.KeyAdapter;
|
||||
import org.eclipse.swt.events.KeyEvent;
|
||||
import org.eclipse.swt.graphics.Color;
|
||||
import org.eclipse.swt.graphics.Font;
|
||||
import org.eclipse.swt.layout.GridData;
|
||||
import org.eclipse.swt.widgets.Composite;
|
||||
import org.eclipse.swt.widgets.Display;
|
||||
import org.eclipse.swt.widgets.Event;
|
||||
import org.eclipse.swt.widgets.Text;
|
||||
import org.eclipse.swt.widgets.TreeItem;
|
||||
import org.springframework.tooling.ls.eclipse.gotosymbol.dialogs.GotoSymbolDialogModel.Match;
|
||||
import org.springsource.ide.eclipse.commons.core.util.FuzzyMatcher;
|
||||
import org.springsource.ide.eclipse.commons.livexp.core.UIValueListener;
|
||||
import org.springsource.ide.eclipse.commons.livexp.ui.Disposable;
|
||||
import org.springsource.ide.eclipse.commons.livexp.ui.IPageWithSections;
|
||||
import org.springsource.ide.eclipse.commons.livexp.ui.Stylers;
|
||||
import org.springsource.ide.eclipse.commons.livexp.ui.WizardPageSection;
|
||||
import org.springsource.ide.eclipse.commons.livexp.ui.util.SwtConnect;
|
||||
|
||||
@SuppressWarnings("restriction")
|
||||
public class GotoSymbolSection extends WizardPageSection {
|
||||
|
||||
private static class SymbolsContentProvider implements ITreeContentProvider {
|
||||
|
||||
@Override
|
||||
public Object[] getChildren(Object parentElement) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getParent(Object element) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasChildren(Object element) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object[] getElements(Object inputElement) {
|
||||
if (inputElement instanceof GotoSymbolDialogModel) {
|
||||
GotoSymbolDialogModel model = (GotoSymbolDialogModel) inputElement;
|
||||
return model.getSymbols().getValue().toArray();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private class GotoSymbolsLabelProvider extends StyledCellLabelProvider {
|
||||
|
||||
private Stylers stylers;
|
||||
private SymbolsLabelProvider symbolsLabelProvider;
|
||||
|
||||
public GotoSymbolsLabelProvider(Font base) {
|
||||
stylers = new Stylers(base);
|
||||
boolean showSymbolsLabelProviderLocation = false; /* dont show full location. we show relative location in our own implementation below */
|
||||
boolean showKindInformation = false;
|
||||
symbolsLabelProvider = new SymbolsLabelProvider(showSymbolsLabelProviderLocation , showKindInformation) {
|
||||
@Override
|
||||
protected int getMaxSeverity(IResource resource, IDocument doc, Range range)
|
||||
throws CoreException, BadLocationException {
|
||||
int maxSeverity = -1;
|
||||
for (IMarker marker : resource.findMarkers(IMarker.PROBLEM, true, IResource.DEPTH_ZERO)) {
|
||||
int offset = marker.getAttribute(IMarker.CHAR_START, -1);
|
||||
if (offset != -1) {
|
||||
maxSeverity = Math.max(maxSeverity, marker.getAttribute(IMarker.SEVERITY, -1));
|
||||
}
|
||||
}
|
||||
return maxSeverity;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public Color getToolTipBackgroundColor(Object object) {
|
||||
return JFaceColors.getInformationViewerBackgroundColor(Display.getDefault());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Color getToolTipForegroundColor(Object object) {
|
||||
return JFaceColors.getInformationViewerForegroundColor(Display.getDefault());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getToolTipText(Object element) {
|
||||
if (element instanceof Match) {
|
||||
SymbolInformation si = getSymbolInformation((Match<?>)element);
|
||||
if (si!=null) {
|
||||
return si.getName();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(ViewerCell cell) {
|
||||
super.update(cell);
|
||||
Object obj = cell.getElement();
|
||||
if (obj instanceof Match) {
|
||||
Match<?> match = (Match<?>) obj;
|
||||
cell.setImage(symbolsLabelProvider.getImage(match.value));
|
||||
StyledString styledString = getStyledText(match);
|
||||
cell.setText(styledString.getString());
|
||||
cell.setStyleRanges(styledString.getStyleRanges());
|
||||
cell.getControl().redraw();
|
||||
//^^^ Sigh... Yes, this is needed. It seems SWT/Jface isn't smart enough to itself figure out that if
|
||||
//the styleranges change a redraw is needed to make the change visible.
|
||||
} else {
|
||||
super.update(cell);
|
||||
}
|
||||
}
|
||||
|
||||
private StyledString getStyledText(Match<?> element) {
|
||||
SymbolInformation symbolInformation = getSymbolInformation(element);
|
||||
if (symbolInformation != null) {
|
||||
String name = symbolInformation.getName();
|
||||
StyledString s = new StyledString(name);
|
||||
Collection<IRegion> highlights = FuzzyMatcher.highlights(element.query, name.toLowerCase());
|
||||
for (IRegion hl : highlights) {
|
||||
s.setStyle(hl.getOffset(), hl.getLength(), stylers.bold());
|
||||
}
|
||||
String locationText = getSymbolLocationText(symbolInformation);
|
||||
if (locationText != null) {
|
||||
s = s.append(locationText, stylers.italicColoured(SWT.COLOR_DARK_GRAY));
|
||||
}
|
||||
return s;
|
||||
} else {
|
||||
return symbolsLabelProvider.getStyledText(element.value);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
stylers.dispose();
|
||||
symbolsLabelProvider.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
protected String getSymbolLocationText(SymbolInformation symbol) {
|
||||
Optional<String> location = GotoSymbolSection.this
|
||||
.getSymbolLocation(symbol);
|
||||
if (location.isPresent()) {
|
||||
return " -- [" + location.get() + "]";
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private final GotoSymbolDialogModel model;
|
||||
|
||||
|
||||
public GotoSymbolSection(IPageWithSections owner, GotoSymbolDialogModel model) {
|
||||
super(owner);
|
||||
this.model = model;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void createContents(Composite dialogArea) {
|
||||
List<Disposable> disposables = new ArrayList<>();
|
||||
dialogArea.addDisposeListener(de -> {
|
||||
for (Disposable d : disposables) {
|
||||
d.dispose();
|
||||
}
|
||||
});
|
||||
|
||||
//Search box:
|
||||
Text pattern = new Text(dialogArea, SWT.SINGLE | SWT.BORDER | SWT.SEARCH | SWT.ICON_CANCEL);
|
||||
// pattern.getAccessible().addAccessibleListener(new AccessibleAdapter() {
|
||||
// public void getName(AccessibleEvent e) {
|
||||
// e.result = LegacyActionTools.removeMnemonics(headerLabel)
|
||||
// .getText());
|
||||
// }
|
||||
// });
|
||||
pattern.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
|
||||
pattern.setMessage(model.getSearchBoxHintMessage());
|
||||
SwtConnect.connect(pattern, model.getSearchBox());
|
||||
|
||||
//Tree viewer with results
|
||||
TreeViewer viewer = new TreeViewer(dialogArea, SWT.SINGLE);
|
||||
ColumnViewerToolTipSupport.enableFor(viewer);
|
||||
GridDataFactory.fillDefaults().grab(true, true).applyTo(viewer.getControl());
|
||||
viewer.setContentProvider(new SymbolsContentProvider());
|
||||
viewer.setLabelProvider(new GotoSymbolsLabelProvider(viewer.getTree().getFont()));
|
||||
viewer.setUseHashlookup(true);
|
||||
disposables.add(model.getSymbols().onChange(UIValueListener.from((e, v) -> {
|
||||
if (!viewer.getControl().isDisposed()) viewer.refresh();
|
||||
})));
|
||||
//TODO: somehow show selection in local file, (but not in other file ?)
|
||||
// viewer.addSelectionChangedListener(event -> {
|
||||
// IStructuredSelection selection = (IStructuredSelection) event.getSelection();
|
||||
// if (selection.isEmpty()) {
|
||||
// return;
|
||||
// }
|
||||
// SymbolInformation symbolInformation = (SymbolInformation) selection.getFirstElement();
|
||||
// Location location = symbolInformation.getLocation();
|
||||
//
|
||||
// IResource targetResource = LSPEclipseUtils.findResourceFor(location.getUri());
|
||||
// if (targetResource == null) {
|
||||
// return;
|
||||
// }
|
||||
// IDocument targetDocument = FileBuffers.getTextFileBufferManager()
|
||||
// .getTextFileBuffer(targetResource.getFullPath(), LocationKind.IFILE).getDocument();
|
||||
// if (targetDocument != null) {
|
||||
// try {
|
||||
// int offset = LSPEclipseUtils.toOffset(location.getRange().getStart(), targetDocument);
|
||||
// int endOffset = LSPEclipseUtils.toOffset(location.getRange().getEnd(), targetDocument);
|
||||
// fTextEditor.selectAndReveal(offset, endOffset - offset);
|
||||
// } catch (BadLocationException e) {
|
||||
// LanguageServerPlugin.logError(e);
|
||||
// }
|
||||
// }
|
||||
// });
|
||||
installWidgetListeners(pattern, viewer);
|
||||
|
||||
//Status label
|
||||
StyledText statusLabel = new StyledText(dialogArea, SWT.NONE);
|
||||
// Allow for some extra space for highlight fonts
|
||||
statusLabel.setLeftMargin(3);
|
||||
statusLabel.setBottomMargin(2);
|
||||
statusLabel.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
|
||||
|
||||
Stylers stylers = new Stylers(dialogArea.getFont());
|
||||
disposables.add(stylers);
|
||||
|
||||
SwtConnect.connectHighlighted(stylers.bold(), statusLabel, model.getStatus(), Duration.ofMillis(500));
|
||||
viewer.setInput(model);
|
||||
}
|
||||
|
||||
private void installWidgetListeners(Text pattern, TreeViewer list) {
|
||||
pattern.addKeyListener(new KeyAdapter() {
|
||||
public void keyPressed(KeyEvent e) {
|
||||
if (e.keyCode == SWT.ARROW_DOWN) {
|
||||
if (list.getTree().getItemCount() > 0) {
|
||||
list.getTree().setFocus();
|
||||
TreeItem[] items = list.getTree().getItems();
|
||||
if (items!=null && items.length>0) {
|
||||
list.getTree().setSelection(items[0]);
|
||||
//programatic selection may not fire selection events so...
|
||||
list.getTree().notifyListeners(SWT.Selection,
|
||||
new Event());
|
||||
}
|
||||
}
|
||||
} else if (e.character == '\r') {
|
||||
performOk(list);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
list.getTree().addKeyListener(new KeyAdapter() {
|
||||
public void keyPressed(KeyEvent e) {
|
||||
|
||||
if (e.keyCode == SWT.ARROW_UP && (e.stateMask & SWT.SHIFT) == 0
|
||||
&& (e.stateMask & SWT.CTRL) == 0) {
|
||||
StructuredSelection selection = (StructuredSelection) list
|
||||
.getSelection();
|
||||
|
||||
if (selection.size() == 1) {
|
||||
Object element = selection.getFirstElement();
|
||||
if (element.equals(getFirstElement(list))) {
|
||||
pattern.setFocus();
|
||||
list.setSelection(new StructuredSelection());
|
||||
list.getTree().notifyListeners(SWT.Selection,
|
||||
new Event());
|
||||
}
|
||||
|
||||
}
|
||||
} else if (e.character == '\r') {
|
||||
performOk(list);
|
||||
}
|
||||
|
||||
// if (e.keyCode == SWT.ARROW_DOWN
|
||||
// && (e.stateMask & SWT.SHIFT) != 0
|
||||
// && (e.stateMask & SWT.CTRL) != 0) {
|
||||
//
|
||||
// list.getTree().notifyListeners(SWT.Selection, new Event());
|
||||
// }
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
list.addDoubleClickListener(e -> performOk(list));
|
||||
}
|
||||
|
||||
private void performOk(TreeViewer list) {
|
||||
if (model.performOk(getTarget(list))) {
|
||||
close();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine the 'target' for the dialog's action.
|
||||
*/
|
||||
private SymbolInformation getTarget(TreeViewer list) {
|
||||
ISelection sel = list.getSelection();
|
||||
if (sel instanceof IStructuredSelection) {
|
||||
IStructuredSelection ss = (IStructuredSelection) sel;
|
||||
Object selected = ss.getFirstElement();
|
||||
if (selected instanceof Match) {
|
||||
SymbolInformation si = getSymbolInformation((Match<?>) selected);
|
||||
if (si!=null) {
|
||||
return si;
|
||||
}
|
||||
}
|
||||
}
|
||||
//No element selected, target the first element in the list instead.
|
||||
//This allows user to execute the action without explicitly selecting an element.
|
||||
return getFirstElement(list);
|
||||
}
|
||||
|
||||
private SymbolInformation getFirstElement(TreeViewer list) {
|
||||
TreeItem[] items = list.getTree().getItems();
|
||||
if (items!=null && items.length>0) {
|
||||
TreeItem item = items[0];
|
||||
Object data = item.getData();
|
||||
if (data instanceof Match) {
|
||||
SymbolInformation si = getSymbolInformation((Match<?>) data);
|
||||
if (si!=null) {
|
||||
return si;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private SymbolInformation getSymbolInformation(Match<?> element) {
|
||||
if (element.value instanceof SymbolInformation) {
|
||||
return (SymbolInformation) element.value;
|
||||
}
|
||||
if (element.value instanceof Either) {
|
||||
Either<?,?> either = (Either<?, ?>)element.value;
|
||||
if (either.isLeft()) {
|
||||
Object left = either.getLeft();
|
||||
if (left instanceof SymbolInformation) {
|
||||
return (SymbolInformation) left;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private Optional<String> getSymbolLocation(SymbolInformation symbolInformation) {
|
||||
String val = null;
|
||||
|
||||
if (!model.fromFileProvider(symbolInformation)) {
|
||||
Location location = symbolInformation.getLocation();
|
||||
|
||||
IResource targetResource = LSPEclipseUtils.findResourceFor(location.getUri());
|
||||
if (targetResource != null && targetResource.getFullPath() != null) {
|
||||
val = targetResource.getFullPath().toString();
|
||||
}
|
||||
}
|
||||
|
||||
return val != null ? Optional.of(val) : Optional.empty();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2017, 2019 Pivotal, Inc.
|
||||
* Copyright (c) 2017, 2019, 2020 Pivotal, Inc.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
@@ -12,6 +12,7 @@ package org.springframework.tooling.ls.eclipse.gotosymbol.dialogs;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.util.List;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.eclipse.core.commands.ExecutionEvent;
|
||||
@@ -38,11 +39,22 @@ import reactor.core.publisher.Mono;
|
||||
@SuppressWarnings("restriction")
|
||||
public class InWorkspaceSymbolsProvider implements SymbolsProvider {
|
||||
|
||||
public static InWorkspaceSymbolsProvider createFor(Supplier<IProject> _project) {
|
||||
return new InWorkspaceSymbolsProvider(() -> {
|
||||
IProject project = _project.get();
|
||||
if (project!=null) {
|
||||
return LanguageServiceAccessor.getLanguageServers(project,
|
||||
capabilities -> Boolean.TRUE.equals(capabilities.getWorkspaceSymbolProvider()), true);
|
||||
}
|
||||
return ImmutableList.of();
|
||||
});
|
||||
}
|
||||
|
||||
public static InWorkspaceSymbolsProvider createFor(IProject project) {
|
||||
List<LanguageServer> languageServers = LanguageServiceAccessor.getLanguageServers(project,
|
||||
capabilities -> Boolean.TRUE.equals(capabilities.getWorkspaceSymbolProvider()), true);
|
||||
if (!languageServers.isEmpty()) {
|
||||
return new InWorkspaceSymbolsProvider(languageServers);
|
||||
return new InWorkspaceSymbolsProvider(() -> languageServers);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
@@ -50,10 +62,9 @@ public class InWorkspaceSymbolsProvider implements SymbolsProvider {
|
||||
|
||||
private static final Duration TIMEOUT = Duration.ofSeconds(2);
|
||||
private static final int MAX_RESULTS = 200;
|
||||
private Supplier<List<LanguageServer>> languageServers;
|
||||
|
||||
private List<LanguageServer> languageServers;
|
||||
|
||||
public InWorkspaceSymbolsProvider(List<LanguageServer> languageServers) {
|
||||
public InWorkspaceSymbolsProvider(Supplier<List<LanguageServer>> languageServers) {
|
||||
this.languageServers = languageServers;
|
||||
}
|
||||
|
||||
@@ -75,7 +86,7 @@ public class InWorkspaceSymbolsProvider implements SymbolsProvider {
|
||||
// really use this with a single language server anyways.
|
||||
WorkspaceSymbolParams params = new WorkspaceSymbolParams(query);
|
||||
|
||||
Flux<Either<SymbolInformation, DocumentSymbol>> symbols = Flux.fromIterable(this.languageServers)
|
||||
Flux<Either<SymbolInformation, DocumentSymbol>> symbols = Flux.fromIterable(this.languageServers.get())
|
||||
.flatMap(server -> Mono.fromFuture(server.getWorkspaceService().symbol(params))
|
||||
.timeout(TIMEOUT)
|
||||
.doOnError(e -> log(e))
|
||||
|
||||
@@ -0,0 +1,129 @@
|
||||
package org.springframework.tooling.ls.eclipse.gotosymbol.view;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.eclipse.core.resources.IProject;
|
||||
import org.eclipse.core.resources.IResource;
|
||||
import org.eclipse.core.runtime.CoreException;
|
||||
import org.eclipse.core.runtime.IAdaptable;
|
||||
import org.eclipse.jface.action.IMenuManager;
|
||||
import org.eclipse.jface.action.IToolBarManager;
|
||||
import org.eclipse.jface.text.ITextSelection;
|
||||
import org.eclipse.jface.viewers.ISelection;
|
||||
import org.eclipse.jface.viewers.IStructuredSelection;
|
||||
import org.eclipse.swt.widgets.Composite;
|
||||
import org.eclipse.ui.IActionBars;
|
||||
import org.eclipse.ui.IEditorInput;
|
||||
import org.eclipse.ui.IEditorPart;
|
||||
import org.eclipse.ui.ISelectionListener;
|
||||
import org.eclipse.ui.ISelectionService;
|
||||
import org.eclipse.ui.IWorkbenchPart;
|
||||
import org.springframework.ide.eclipse.boot.dash.views.sections.ViewPartWithSections;
|
||||
import org.springframework.tooling.ls.eclipse.gotosymbol.dialogs.GotoSymbolSection;
|
||||
import org.springsource.ide.eclipse.commons.livexp.core.LiveExpression;
|
||||
import org.springsource.ide.eclipse.commons.livexp.core.LiveVariable;
|
||||
import org.springsource.ide.eclipse.commons.livexp.ui.DescriptionSection;
|
||||
import org.springsource.ide.eclipse.commons.livexp.ui.IPageSection;
|
||||
import org.springsource.ide.eclipse.commons.livexp.ui.InfoFieldSection;
|
||||
import org.springsource.ide.eclipse.commons.livexp.ui.StringFieldSection;
|
||||
import org.springsource.ide.eclipse.commons.livexp.util.Log;
|
||||
|
||||
public class SpringSymbolsView extends ViewPartWithSections {
|
||||
|
||||
/**
|
||||
* Adds scroll support to the whole view. You probably want to disable this
|
||||
* if view is broken into pieces that have their own scrollbars
|
||||
*/
|
||||
private static final boolean ENABLE_SCROLLING = false;
|
||||
|
||||
private final SpringSymbolsViewModel model = new SpringSymbolsViewModel();
|
||||
|
||||
private final LiveExpression<String> projectAsString = model.currentProject.apply(p -> {
|
||||
System.out.println("project = "+p);
|
||||
return p==null ? "null" : p.getName();
|
||||
});
|
||||
|
||||
private ISelectionListener selectionListener = new ISelectionListener() {
|
||||
|
||||
@Override
|
||||
public void selectionChanged(IWorkbenchPart arg0, ISelection selection) {
|
||||
if (selection instanceof IStructuredSelection) {
|
||||
IStructuredSelection ss = (IStructuredSelection) selection;
|
||||
Object element = ss.getFirstElement();
|
||||
IProject project = getProject(element);
|
||||
if (project!=null) {
|
||||
model.currentProject.setValue(project);
|
||||
}
|
||||
} else if (selection instanceof ITextSelection) {
|
||||
//Let's assume the selection is in the active editor
|
||||
try {
|
||||
IEditorPart editor = getSite().getWorkbenchWindow().getActivePage().getActiveEditor();
|
||||
if (editor!=null) {
|
||||
IEditorInput input = editor.getEditorInput();
|
||||
IResource resource = input.getAdapter(IResource.class);
|
||||
if (resource != null) {
|
||||
IProject project = resource.getProject();
|
||||
if (project!=null) {
|
||||
model.currentProject.setValue(project);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
Log.log(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private IProject getProject(Object element) {
|
||||
if (element instanceof IResource) {
|
||||
return ((IResource) element).getProject();
|
||||
} else if (element instanceof IAdaptable) {
|
||||
IResource resource = ((IAdaptable) element).getAdapter(IResource.class);
|
||||
if (resource!=null) {
|
||||
return resource.getProject();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
public SpringSymbolsView() {
|
||||
super(ENABLE_SCROLLING);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<IPageSection> createSections() throws CoreException {
|
||||
List<IPageSection> sections = new ArrayList<>();
|
||||
sections.add(new InfoFieldSection(this, "Project", projectAsString));
|
||||
sections.add(new GotoSymbolSection(this, model.gotoSymbols));
|
||||
ISelectionService selectitonService = getSite().getWorkbenchWindow().getSelectionService();
|
||||
selectitonService.addSelectionListener(selectionListener);
|
||||
return sections;
|
||||
}
|
||||
|
||||
/**
|
||||
* This is a callback that will allow us to create the viewer and initialize
|
||||
* it.
|
||||
*/
|
||||
public void createPartControl(Composite parent) {
|
||||
super.createPartControl(parent);
|
||||
contributeToActionBars();
|
||||
}
|
||||
|
||||
private void contributeToActionBars() {
|
||||
IActionBars bars = getViewSite().getActionBars();
|
||||
fillLocalPullDown(bars.getMenuManager());
|
||||
fillLocalToolBar(bars.getToolBarManager());
|
||||
}
|
||||
|
||||
/**
|
||||
* Fills the pull-down menu for this view (accessible from the toolbar)
|
||||
*/
|
||||
private void fillLocalPullDown(IMenuManager manager) {
|
||||
}
|
||||
|
||||
private void fillLocalToolBar(IToolBarManager manager) {
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package org.springframework.tooling.ls.eclipse.gotosymbol.view;
|
||||
|
||||
import org.eclipse.core.resources.IProject;
|
||||
import org.springframework.tooling.ls.eclipse.gotosymbol.dialogs.GotoSymbolDialogModel;
|
||||
import org.springframework.tooling.ls.eclipse.gotosymbol.dialogs.InWorkspaceSymbolsProvider;
|
||||
import org.springsource.ide.eclipse.commons.livexp.core.LiveVariable;
|
||||
|
||||
public class SpringSymbolsViewModel {
|
||||
|
||||
public final LiveVariable<IProject> currentProject = new LiveVariable<>();
|
||||
public final GotoSymbolDialogModel gotoSymbols = new GotoSymbolDialogModel(null, InWorkspaceSymbolsProvider.createFor(currentProject::getValue));
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user