diff --git a/clients/eclipse/feature/feature.xml b/clients/eclipse/feature/feature.xml index 70ad69781b2d..3657b12090c0 100644 --- a/clients/eclipse/feature/feature.xml +++ b/clients/eclipse/feature/feature.xml @@ -2,7 +2,7 @@ @@ -19,6 +19,6 @@ + version="0.0.1.11"/> diff --git a/clients/eclipse/plugin/META-INF/MANIFEST.MF b/clients/eclipse/plugin/META-INF/MANIFEST.MF index 5825fe077637..e8ec68c66c56 100644 --- a/clients/eclipse/plugin/META-INF/MANIFEST.MF +++ b/clients/eclipse/plugin/META-INF/MANIFEST.MF @@ -2,7 +2,7 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: Tabby Plugin for Eclipse Bundle-SymbolicName: com.tabbyml.tabby4eclipse;singleton:=true -Bundle-Version: 0.0.1.10 +Bundle-Version: 0.0.1.11 Bundle-Activator: com.tabbyml.tabby4eclipse.Activator Bundle-Vendor: com.tabbyml Require-Bundle: org.eclipse.ui, diff --git a/clients/eclipse/plugin/images/check-dark.png b/clients/eclipse/plugin/images/check-dark.png deleted file mode 100644 index e3dfdce7cb6a..000000000000 Binary files a/clients/eclipse/plugin/images/check-dark.png and /dev/null differ diff --git a/clients/eclipse/plugin/images/check-dark@2x.png b/clients/eclipse/plugin/images/check-dark@2x.png deleted file mode 100644 index 9ba3ed1ed0ba..000000000000 Binary files a/clients/eclipse/plugin/images/check-dark@2x.png and /dev/null differ diff --git a/clients/eclipse/plugin/images/check-light.png b/clients/eclipse/plugin/images/check-light.png deleted file mode 100644 index 559d1819d848..000000000000 Binary files a/clients/eclipse/plugin/images/check-light.png and /dev/null differ diff --git a/clients/eclipse/plugin/images/check-light@2x.png b/clients/eclipse/plugin/images/check-light@2x.png deleted file mode 100644 index fb39665815a8..000000000000 Binary files a/clients/eclipse/plugin/images/check-light@2x.png and /dev/null differ diff --git a/clients/eclipse/plugin/images/check_tsk.png b/clients/eclipse/plugin/images/check_tsk.png new file mode 100644 index 000000000000..6d5b4e3c4316 Binary files /dev/null and b/clients/eclipse/plugin/images/check_tsk.png differ diff --git a/clients/eclipse/plugin/images/check_tsk@2x.png b/clients/eclipse/plugin/images/check_tsk@2x.png new file mode 100644 index 000000000000..2f7682f1b773 Binary files /dev/null and b/clients/eclipse/plugin/images/check_tsk@2x.png differ diff --git a/clients/eclipse/plugin/images/hprio_tsk.png b/clients/eclipse/plugin/images/hprio_tsk.png new file mode 100644 index 000000000000..4e2910d5c920 Binary files /dev/null and b/clients/eclipse/plugin/images/hprio_tsk.png differ diff --git a/clients/eclipse/plugin/images/hprio_tsk@2x.png b/clients/eclipse/plugin/images/hprio_tsk@2x.png new file mode 100644 index 000000000000..fafd371e259c Binary files /dev/null and b/clients/eclipse/plugin/images/hprio_tsk@2x.png differ diff --git a/clients/eclipse/plugin/images/progress_task.png b/clients/eclipse/plugin/images/progress_task.png new file mode 100644 index 000000000000..b4f61de8a120 Binary files /dev/null and b/clients/eclipse/plugin/images/progress_task.png differ diff --git a/clients/eclipse/plugin/images/progress_task@2x.png b/clients/eclipse/plugin/images/progress_task@2x.png new file mode 100644 index 000000000000..1c8333bbdb50 Binary files /dev/null and b/clients/eclipse/plugin/images/progress_task@2x.png differ diff --git a/clients/eclipse/plugin/images/warn_tsk.png b/clients/eclipse/plugin/images/warn_tsk.png new file mode 100644 index 000000000000..b900f3b909fc Binary files /dev/null and b/clients/eclipse/plugin/images/warn_tsk.png differ diff --git a/clients/eclipse/plugin/images/warn_tsk@2x.png b/clients/eclipse/plugin/images/warn_tsk@2x.png new file mode 100644 index 000000000000..97339df8e0b8 Binary files /dev/null and b/clients/eclipse/plugin/images/warn_tsk@2x.png differ diff --git a/clients/eclipse/plugin/src/com/tabbyml/tabby4eclipse/Images.java b/clients/eclipse/plugin/src/com/tabbyml/tabby4eclipse/Images.java index fb919ed34b02..4f168ede67f8 100644 --- a/clients/eclipse/plugin/src/com/tabbyml/tabby4eclipse/Images.java +++ b/clients/eclipse/plugin/src/com/tabbyml/tabby4eclipse/Images.java @@ -6,6 +6,7 @@ import org.eclipse.core.runtime.Path; import org.eclipse.core.runtime.Platform; import org.eclipse.jface.resource.ImageDescriptor; +import org.eclipse.jface.resource.ImageRegistry; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.graphics.RGB; import org.eclipse.ui.PlatformUI; @@ -14,22 +15,29 @@ public class Images { private static Bundle bundle = Platform.getBundle(Activator.PLUGIN_ID); private static Logger logger = new Logger("Images"); - + private static boolean isDark = isDarkTheme(); - private static Image iconCheck = null; + private static ImageRegistry icons = Activator.getDefault().getImageRegistry(); + + public static final String ICON_CHECK = "check_tsk.png"; + public static final String ICON_ERROR = "hprio_tsk.png"; + public static final String ICON_WARN = "warn_tsk.png"; + public static final String ICON_LOADING = "progress_task.png"; - public static Image getIconCheck() { - if (iconCheck == null) { - iconCheck = createImage(isDark ? "images/check-dark.png" : "images/check-light.png"); + public static Image getIcon(String filename) { + Image icon = icons.get(filename); + if (icon == null) { + icon = createImageFromFile(filename); + icons.put(filename, icon); } - return iconCheck; + return icon; } private static boolean isDarkTheme() { RGB bgColor = PlatformUI.getWorkbench().getThemeManager().getCurrentTheme().getColorRegistry() .getRGB("org.eclipse.ui.workbench.ACTIVE_TAB_BG_START"); if (bgColor != null) { - boolean isBgDark = (bgColor.red + bgColor.green + bgColor.blue) / 3 < 128; + boolean isBgDark = (bgColor.red + bgColor.green + bgColor.blue) / 3 < 128; logger.info("Detected theme: " + (isBgDark ? "dark" : "light")); return isBgDark; } @@ -37,7 +45,8 @@ private static boolean isDarkTheme() { return false; } - private static Image createImage(String path) { + private static Image createImageFromFile(String filename) { + String path = "images/" + filename; URL url = FileLocator.find(bundle, new Path(path)); ImageDescriptor imageDesc = ImageDescriptor.createFromURL(url); return imageDesc.createImage(); diff --git a/clients/eclipse/plugin/src/com/tabbyml/tabby4eclipse/editor/InlineCompletionService.java b/clients/eclipse/plugin/src/com/tabbyml/tabby4eclipse/editor/InlineCompletionService.java index 9fafa27f79a6..6df323efcdd8 100644 --- a/clients/eclipse/plugin/src/com/tabbyml/tabby4eclipse/editor/InlineCompletionService.java +++ b/clients/eclipse/plugin/src/com/tabbyml/tabby4eclipse/editor/InlineCompletionService.java @@ -33,7 +33,7 @@ import com.tabbyml.tabby4eclipse.lsp.LanguageServerService; import com.tabbyml.tabby4eclipse.lsp.protocol.ILanguageServer; import com.tabbyml.tabby4eclipse.lsp.protocol.InlineCompletionParams; -import com.tabbyml.tabby4eclipse.lsp.protocol.TextDocumentServiceExt; +import com.tabbyml.tabby4eclipse.lsp.protocol.ITextDocumentServiceExt; public class InlineCompletionService { public static InlineCompletionService getInstance() { @@ -114,9 +114,9 @@ public void provideInlineCompletion(ITextEditor textEditor, int offset, int offs } current = null; } - + ITextViewer textViewer = (ITextViewer) textEditor.getAdapter(ITextViewer.class); - + InlineCompletionContext.Request request = new InlineCompletionContext.Request(textEditor, offset); logger.debug("Request request: " + request.offset + "," + offsetInWidget); InlineCompletionParams params = request.toInlineCompletionParams(); @@ -126,7 +126,7 @@ public void provideInlineCompletion(ITextEditor textEditor, int offset, int offs } Function> jobFn = ( server) -> { - TextDocumentServiceExt textDocumentService = ((ILanguageServer) server).getTextDocumentServiceExt(); + ITextDocumentServiceExt textDocumentService = ((ILanguageServer) server).getTextDocumentServiceExt(); return textDocumentService.inlineCompletion(params); }; CompletableFuture job = LanguageServerService @@ -283,7 +283,7 @@ private ITextEditor getActiveEditor() { private boolean isActiveEditor(ITextEditor textEditor) { return textEditor == getActiveEditor(); } - + private class TriggerEvent { private ITextEditor textEditor; private long modificationStamp; @@ -376,7 +376,7 @@ private static int getDocumentOffset(ITextEditor textEditor, DocumentEvent event return event.getOffset() + event.getText().length(); } } - + private static long getDocumentModificationStamp(ITextEditor textEditor) { IDocument document = LSPEclipseUtils.getDocument(textEditor.getEditorInput()); if (document instanceof IDocumentExtension4 documentExt) { diff --git a/clients/eclipse/plugin/src/com/tabbyml/tabby4eclipse/lsp/ConnectionProvider.java b/clients/eclipse/plugin/src/com/tabbyml/tabby4eclipse/lsp/ConnectionProvider.java index 86e23d38e39c..76fffcc83351 100644 --- a/clients/eclipse/plugin/src/com/tabbyml/tabby4eclipse/lsp/ConnectionProvider.java +++ b/clients/eclipse/plugin/src/com/tabbyml/tabby4eclipse/lsp/ConnectionProvider.java @@ -20,6 +20,7 @@ import com.tabbyml.tabby4eclipse.lsp.protocol.ClientCapabilities.TextDocumentClientCapabilities; import com.tabbyml.tabby4eclipse.lsp.protocol.ClientInfo; import com.tabbyml.tabby4eclipse.lsp.protocol.ClientInfo.TabbyPluginInfo; +import com.tabbyml.tabby4eclipse.statusbar.StatusInfoHolder; import com.tabbyml.tabby4eclipse.lsp.protocol.ClientProvidedConfig; import com.tabbyml.tabby4eclipse.lsp.protocol.InitializationOptions; @@ -44,6 +45,7 @@ public ConnectionProvider() { } } if (nodeExecutableFile == null) { + StatusInfoHolder.getInstance().setConnectionFailed(true); logger.error("Cannot find node executable."); return; } @@ -51,6 +53,7 @@ public ConnectionProvider() { Bundle bundle = Platform.getBundle(Activator.PLUGIN_ID); URL agentScriptUrl = FileLocator.find(bundle, new Path("tabby-agent/dist/node/index.js")); if (agentScriptUrl == null) { + StatusInfoHolder.getInstance().setConnectionFailed(true); logger.error("Cannot find tabby-agent script."); return; } @@ -61,6 +64,7 @@ public ConnectionProvider() { logger.info("Will use command " + commands.toString() + " to start Tabby language server."); this.setCommands(commands); } catch (IOException e) { + StatusInfoHolder.getInstance().setConnectionFailed(true); logger.error("Failed to setup command to start Tabby language server.", e); } } @@ -108,6 +112,8 @@ private ClientCapabilities getClientCapabilities() { textDocumentClientCapabilities.setInlineCompletion(true); TabbyClientCapabilities tabbyClientCapabilities = new TabbyClientCapabilities(); + tabbyClientCapabilities.setConfigDidChangeListener(false); + tabbyClientCapabilities.setStatusDidChangeListener(true); ClientCapabilities clientCapabilities = new ClientCapabilities(); clientCapabilities.setTextDocument(textDocumentClientCapabilities); diff --git a/clients/eclipse/plugin/src/com/tabbyml/tabby4eclipse/lsp/LanguageClientImpl.java b/clients/eclipse/plugin/src/com/tabbyml/tabby4eclipse/lsp/LanguageClientImpl.java index c997d4c0eb3c..8fefaf705f2e 100644 --- a/clients/eclipse/plugin/src/com/tabbyml/tabby4eclipse/lsp/LanguageClientImpl.java +++ b/clients/eclipse/plugin/src/com/tabbyml/tabby4eclipse/lsp/LanguageClientImpl.java @@ -1,5 +1,15 @@ package com.tabbyml.tabby4eclipse.lsp; -public class LanguageClientImpl extends org.eclipse.lsp4e.LanguageClientImpl { +import java.util.concurrent.CompletableFuture; + +import org.eclipse.lsp4j.jsonrpc.services.JsonNotification; +import com.tabbyml.tabby4eclipse.lsp.protocol.StatusInfo; +import com.tabbyml.tabby4eclipse.statusbar.StatusInfoHolder; + +public class LanguageClientImpl extends org.eclipse.lsp4e.LanguageClientImpl { + @JsonNotification("tabby/status/didChange") + void statusDidChange(StatusInfo params) { + StatusInfoHolder.getInstance().setStatusInfo(params); + } } diff --git a/clients/eclipse/plugin/src/com/tabbyml/tabby4eclipse/lsp/protocol/ClientCapabilities.java b/clients/eclipse/plugin/src/com/tabbyml/tabby4eclipse/lsp/protocol/ClientCapabilities.java index 2d1213b1b237..8c6563a1dc0d 100644 --- a/clients/eclipse/plugin/src/com/tabbyml/tabby4eclipse/lsp/protocol/ClientCapabilities.java +++ b/clients/eclipse/plugin/src/com/tabbyml/tabby4eclipse/lsp/protocol/ClientCapabilities.java @@ -50,7 +50,8 @@ public void setInlineCompletion(boolean inlineCompletion) { } public static class TabbyClientCapabilities { - private boolean agent; + private boolean configDidChangeListener; + private boolean statusDidChangeListener; private boolean workspaceFileSystem; private boolean dataStore; private boolean languageSupport; @@ -58,7 +59,8 @@ public static class TabbyClientCapabilities { private boolean editorOptions; public TabbyClientCapabilities() { - this.agent = false; + this.configDidChangeListener = false; + this.statusDidChangeListener = false; this.workspaceFileSystem = false; this.dataStore = false; this.languageSupport = false; @@ -66,12 +68,20 @@ public TabbyClientCapabilities() { this.editorOptions = false; } - public boolean getAgent() { - return agent; + public boolean getConfigDidChangeListener() { + return configDidChangeListener; } - public void setAgent(boolean agent) { - this.agent = agent; + public void setConfigDidChangeListener(boolean configDidChangeListener) { + this.configDidChangeListener = configDidChangeListener; + } + + public boolean getStatusDidChangeListener() { + return statusDidChangeListener; + } + + public void setStatusDidChangeListener(boolean statusDidChangeListener) { + this.statusDidChangeListener = statusDidChangeListener; } public boolean getWorkspaceFileSystem() { diff --git a/clients/eclipse/plugin/src/com/tabbyml/tabby4eclipse/lsp/protocol/ILanguageServer.java b/clients/eclipse/plugin/src/com/tabbyml/tabby4eclipse/lsp/protocol/ILanguageServer.java index 7d066b84507c..bf8184c93fe3 100644 --- a/clients/eclipse/plugin/src/com/tabbyml/tabby4eclipse/lsp/protocol/ILanguageServer.java +++ b/clients/eclipse/plugin/src/com/tabbyml/tabby4eclipse/lsp/protocol/ILanguageServer.java @@ -5,5 +5,8 @@ public interface ILanguageServer extends LanguageServer { @JsonDelegate - TextDocumentServiceExt getTextDocumentServiceExt(); + ITextDocumentServiceExt getTextDocumentServiceExt(); + + @JsonDelegate + IStatusService getStatusService(); } diff --git a/clients/eclipse/plugin/src/com/tabbyml/tabby4eclipse/lsp/protocol/IStatusService.java b/clients/eclipse/plugin/src/com/tabbyml/tabby4eclipse/lsp/protocol/IStatusService.java new file mode 100644 index 000000000000..72343619cd62 --- /dev/null +++ b/clients/eclipse/plugin/src/com/tabbyml/tabby4eclipse/lsp/protocol/IStatusService.java @@ -0,0 +1,17 @@ +package com.tabbyml.tabby4eclipse.lsp.protocol; + +import java.util.concurrent.CompletableFuture; +import org.eclipse.lsp4j.jsonrpc.services.JsonRequest; +import org.eclipse.lsp4j.jsonrpc.services.JsonSegment; + +@JsonSegment("tabby") +public interface IStatusService { + @JsonRequest("status") + CompletableFuture getStatus(StatusRequestParams params); + + @JsonRequest("status/showHelpMessage") + CompletableFuture showHelpMessage(Object params); + + @JsonRequest("status/ignoredIssues/edit") + CompletableFuture editIngoredIssues(StatusIgnoredIssuesEditParams params); +} diff --git a/clients/eclipse/plugin/src/com/tabbyml/tabby4eclipse/lsp/protocol/TextDocumentServiceExt.java b/clients/eclipse/plugin/src/com/tabbyml/tabby4eclipse/lsp/protocol/ITextDocumentServiceExt.java similarity index 88% rename from clients/eclipse/plugin/src/com/tabbyml/tabby4eclipse/lsp/protocol/TextDocumentServiceExt.java rename to clients/eclipse/plugin/src/com/tabbyml/tabby4eclipse/lsp/protocol/ITextDocumentServiceExt.java index 12b73c3e69f0..ecd67941fe92 100644 --- a/clients/eclipse/plugin/src/com/tabbyml/tabby4eclipse/lsp/protocol/TextDocumentServiceExt.java +++ b/clients/eclipse/plugin/src/com/tabbyml/tabby4eclipse/lsp/protocol/ITextDocumentServiceExt.java @@ -5,7 +5,7 @@ import org.eclipse.lsp4j.jsonrpc.services.JsonSegment; @JsonSegment("textDocument") -public interface TextDocumentServiceExt { +public interface ITextDocumentServiceExt { @JsonRequest CompletableFuture inlineCompletion(InlineCompletionParams params); } diff --git a/clients/eclipse/plugin/src/com/tabbyml/tabby4eclipse/lsp/protocol/StatusIgnoredIssuesEditParams.java b/clients/eclipse/plugin/src/com/tabbyml/tabby4eclipse/lsp/protocol/StatusIgnoredIssuesEditParams.java new file mode 100644 index 000000000000..53572627b3c3 --- /dev/null +++ b/clients/eclipse/plugin/src/com/tabbyml/tabby4eclipse/lsp/protocol/StatusIgnoredIssuesEditParams.java @@ -0,0 +1,35 @@ +package com.tabbyml.tabby4eclipse.lsp.protocol; + +public class StatusIgnoredIssuesEditParams { + private String operation; + private String[] issues; + + public StatusIgnoredIssuesEditParams() { + } + + public String getOperation() { + return operation; + } + + public void setOperation(String operation) { + this.operation = operation; + } + + public String[] getIssues() { + return issues; + } + + public void setIssues(String[] issues) { + this.issues = issues; + } + + public static class Operation { + public static final String ADD = "add"; + public static final String REMOVE = "remove"; + public static final String REMOVE_ALL = "removeAll"; + } + + public static class StatusIssuesName { + public static final String COMPLETION_RESPONSE_SLOW = "completionResponseSlow"; + } +} diff --git a/clients/eclipse/plugin/src/com/tabbyml/tabby4eclipse/lsp/protocol/StatusInfo.java b/clients/eclipse/plugin/src/com/tabbyml/tabby4eclipse/lsp/protocol/StatusInfo.java new file mode 100644 index 000000000000..0f496c8149a4 --- /dev/null +++ b/clients/eclipse/plugin/src/com/tabbyml/tabby4eclipse/lsp/protocol/StatusInfo.java @@ -0,0 +1,61 @@ +package com.tabbyml.tabby4eclipse.lsp.protocol; + +import java.util.Map; + +import org.eclipse.lsp4j.Command; + +public class StatusInfo { + private String status; + private String tooltip; + private Map serverHealth; + private Command command; + + public StatusInfo() { + this.status = Status.NOT_INITIALIZED; + } + + public String getStatus() { + return status; + } + + public void setStatus(String status) { + this.status = status; + } + + public String getTooltip() { + return tooltip; + } + + public void setTooltip(String tooltip) { + this.tooltip = tooltip; + } + + public Map getServerHealth() { + return serverHealth; + } + + public void setServerHealth(Map serverHealth) { + this.serverHealth = serverHealth; + } + + public Command getCommand() { + return command; + } + + public void setCommand(Command command) { + this.command = command; + } + + public static class Status { + public static final String NOT_INITIALIZED = "notInitialized"; + public static final String FINALIZED = "finalized"; + public static final String CONNECTING = "connecting"; + public static final String UNAUTHORIZED = "unauthorized"; + public static final String DISCONNECTED = "disconnected"; + public static final String READY = "ready"; + public static final String READY_FOR_AUTO_TRIGGER = "readyForAutoTrigger"; + public static final String READY_FOR_MANUAL_TRIGGER = "readyForManualTrigger"; + public static final String FETCHING = "fetching"; + public static final String COMPLETION_RESPONSE_SLOW = "completionResponseSlow"; + } +} diff --git a/clients/eclipse/plugin/src/com/tabbyml/tabby4eclipse/lsp/protocol/StatusRequestParams.java b/clients/eclipse/plugin/src/com/tabbyml/tabby4eclipse/lsp/protocol/StatusRequestParams.java new file mode 100644 index 000000000000..d0f08866f567 --- /dev/null +++ b/clients/eclipse/plugin/src/com/tabbyml/tabby4eclipse/lsp/protocol/StatusRequestParams.java @@ -0,0 +1,16 @@ +package com.tabbyml.tabby4eclipse.lsp.protocol; + +public class StatusRequestParams { + private boolean recheckConnection; + + public StatusRequestParams() { + } + + public boolean getRecheckConnection() { + return recheckConnection; + } + + public void setRecheckConnection(boolean recheckConnection) { + this.recheckConnection = recheckConnection; + } +} diff --git a/clients/eclipse/plugin/src/com/tabbyml/tabby4eclipse/statusbar/StatusInfoHolder.java b/clients/eclipse/plugin/src/com/tabbyml/tabby4eclipse/statusbar/StatusInfoHolder.java new file mode 100644 index 000000000000..3e05961e371c --- /dev/null +++ b/clients/eclipse/plugin/src/com/tabbyml/tabby4eclipse/statusbar/StatusInfoHolder.java @@ -0,0 +1,53 @@ +package com.tabbyml.tabby4eclipse.statusbar; + +import java.util.ArrayList; +import java.util.List; + +import com.tabbyml.tabby4eclipse.lsp.protocol.StatusInfo; + +public class StatusInfoHolder { + public static StatusInfoHolder getInstance() { + return LazyHolder.INSTANCE; + } + + private static class LazyHolder { + private static final StatusInfoHolder INSTANCE = new StatusInfoHolder(); + } + + private boolean isConnectionFailed = false; + private StatusInfo statusInfo = new StatusInfo(); + private List listeners = new ArrayList<>(); + + public boolean isConnectionFailed() { + return isConnectionFailed; + } + + public void setConnectionFailed(boolean isConnectionFailed) { + if (this.isConnectionFailed == isConnectionFailed) { + return; + } + this.isConnectionFailed = isConnectionFailed; + for (StatusDidChangeListener listener : listeners) { + listener.statusDidChange(); + } + } + + public StatusInfo getStatusInfo() { + return statusInfo; + } + + public void setStatusInfo(StatusInfo statusInfo) { + this.statusInfo = statusInfo; + for (StatusDidChangeListener listener : listeners) { + listener.statusDidChange(); + } + } + + public void addStatusDidChangeListener(StatusDidChangeListener listener) { + listeners.add(listener); + } + + public interface StatusDidChangeListener { + void statusDidChange(); + } +} diff --git a/clients/eclipse/plugin/src/com/tabbyml/tabby4eclipse/statusbar/StatusbarContribution.java b/clients/eclipse/plugin/src/com/tabbyml/tabby4eclipse/statusbar/StatusbarContribution.java index f2b20c4f48ca..325398f11f1f 100644 --- a/clients/eclipse/plugin/src/com/tabbyml/tabby4eclipse/statusbar/StatusbarContribution.java +++ b/clients/eclipse/plugin/src/com/tabbyml/tabby4eclipse/statusbar/StatusbarContribution.java @@ -1,36 +1,143 @@ package com.tabbyml.tabby4eclipse.statusbar; -import org.eclipse.swt.graphics.Image; +import org.eclipse.lsp4j.Command; +import org.eclipse.lsp4j.ExecuteCommandParams; +import org.eclipse.swt.custom.CLabel; +import org.eclipse.swt.events.MouseAdapter; +import org.eclipse.swt.events.MouseEvent; +import org.eclipse.swt.events.SelectionAdapter; +import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Menu; import org.eclipse.swt.widgets.MenuItem; -import org.eclipse.swt.custom.CLabel; -import org.eclipse.swt.events.MouseAdapter; -import org.eclipse.swt.events.MouseEvent; -import org.eclipse.ui.ISharedImages; -import org.eclipse.ui.PlatformUI; import org.eclipse.ui.menus.WorkbenchWindowControlContribution; import com.tabbyml.tabby4eclipse.Images; +import com.tabbyml.tabby4eclipse.lsp.LanguageServerService; +import com.tabbyml.tabby4eclipse.lsp.protocol.StatusInfo; public class StatusbarContribution extends WorkbenchWindowControlContribution { - private CLabel label; + private static final String TOOLTIP_INITIALIZATION_FAILED = "Tabby: Initialization Failed"; + + private StatusInfoHolder statusInfoHolder = StatusInfoHolder.getInstance(); @Override protected Control createControl(Composite parent) { - label = new CLabel(parent, 0); + CLabel label = new CLabel(parent, 0); label.setText("Tabby"); - label.setToolTipText("Tabby"); label.addMouseListener(new MouseAdapter() { @Override public void mouseUp(MouseEvent e) { - Menu menu = new Menu(label); - MenuItem item = new MenuItem(menu, 0); - item.setText("Tabby plugin is active."); + Menu menu = createMenu(label); menu.setVisible(true); } }); + + updateLabel(label); + + StatusInfoHolder.getInstance().addStatusDidChangeListener(() -> { + label.getDisplay().asyncExec(() -> { + updateLabel(label); + }); + }); + return label; } + + private void updateLabel(CLabel label) { + if (statusInfoHolder.isConnectionFailed()) { + label.setImage(Images.getIcon(Images.ICON_ERROR)); + label.setToolTipText(TOOLTIP_INITIALIZATION_FAILED); + } + StatusInfo statusInfo = statusInfoHolder.getStatusInfo(); + if (statusInfo.getTooltip() != null) { + label.setToolTipText(statusInfo.getTooltip()); + } else { + label.setToolTipText("Tabby: " + statusInfo.getStatus()); + } + switch (statusInfo.getStatus()) { + case StatusInfo.Status.NOT_INITIALIZED: + label.setImage(Images.getIcon(Images.ICON_LOADING)); + break; + case StatusInfo.Status.CONNECTING: + label.setImage(Images.getIcon(Images.ICON_LOADING)); + break; + case StatusInfo.Status.UNAUTHORIZED: + label.setImage(Images.getIcon(Images.ICON_WARN)); + break; + case StatusInfo.Status.DISCONNECTED: + label.setImage(Images.getIcon(Images.ICON_ERROR)); + break; + case StatusInfo.Status.READY: + label.setImage(Images.getIcon(Images.ICON_CHECK)); + break; + case StatusInfo.Status.FETCHING: + label.setImage(Images.getIcon(Images.ICON_LOADING)); + break; + case StatusInfo.Status.COMPLETION_RESPONSE_SLOW: + label.setImage(Images.getIcon(Images.ICON_WARN)); + break; + default: + break; + } + } + + private Menu createMenu(CLabel label) { + Menu menu = new Menu(label); + MenuItem statusItem = new MenuItem(menu, 0); + + if (statusInfoHolder.isConnectionFailed()) { + statusItem.setImage(Images.getIcon(Images.ICON_ERROR)); + statusItem.setText(TOOLTIP_INITIALIZATION_FAILED); + } + + StatusInfo statusInfo = statusInfoHolder.getStatusInfo(); + if (statusInfo.getTooltip() != null) { + statusItem.setText(statusInfo.getTooltip()); + } else { + statusItem.setText("Tabby: " + statusInfo.getStatus()); + } + Command commmand = statusInfo.getCommand(); + if (commmand != null) { + statusItem.addSelectionListener(new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent e) { + LanguageServerService.getInstance().getServer().execute((server) -> { + ExecuteCommandParams params = new ExecuteCommandParams(); + params.setCommand(commmand.getCommand()); + params.setArguments(commmand.getArguments()); + server.getWorkspaceService().executeCommand(params); + return null; + }); + } + }); + } + switch (statusInfo.getStatus()) { + case StatusInfo.Status.NOT_INITIALIZED: + statusItem.setImage(Images.getIcon(Images.ICON_LOADING)); + break; + case StatusInfo.Status.CONNECTING: + statusItem.setImage(Images.getIcon(Images.ICON_LOADING)); + break; + case StatusInfo.Status.UNAUTHORIZED: + statusItem.setImage(Images.getIcon(Images.ICON_WARN)); + break; + case StatusInfo.Status.DISCONNECTED: + statusItem.setImage(Images.getIcon(Images.ICON_ERROR)); + break; + case StatusInfo.Status.READY: + statusItem.setImage(Images.getIcon(Images.ICON_CHECK)); + break; + case StatusInfo.Status.FETCHING: + statusItem.setImage(Images.getIcon(Images.ICON_LOADING)); + break; + case StatusInfo.Status.COMPLETION_RESPONSE_SLOW: + statusItem.setImage(Images.getIcon(Images.ICON_WARN)); + break; + default: + break; + } + return menu; + } }