Skip to content

Commit

Permalink
feat: Promote save settings when updating LSP settings (eclipse-lsp4j…
Browse files Browse the repository at this point in the history
…#209)

feat: Promote save settings when updating LSP settings

Fixes eclipse-lsp4j#206

Co-authored-by: Mitja Leino <[email protected]>
  • Loading branch information
MituuZ and Mitja Leino authored Apr 16, 2024
1 parent ade26c1 commit 4829a15
Show file tree
Hide file tree
Showing 4 changed files with 117 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -332,6 +332,7 @@ private static void configureDetailToolbar(LanguageServerView languageServerView
ActionToolbar tb = ActionManager.getInstance().createActionToolbar("LSP Detail", myToolbarActions, false);
tb.setTargetComponent(detailComponent);
tb.getComponent().setBorder(JBUI.Borders.merge(tb.getComponent().getBorder(), JBUI.Borders.customLine(OnePixelDivider.BACKGROUND, 0, 0, 0, 1), true));
tb.getComponent().setName(ApplyLanguageServerSettingsAction.ACTION_TOOLBAR_COMPONENT_NAME);
detailComponent.add(tb.getComponent(), BorderLayout.WEST);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,17 +14,40 @@
import com.intellij.openapi.actionSystem.ActionUpdateThread;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.impl.ActionToolbarImpl;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.MessageType;
import com.intellij.openapi.ui.popup.Balloon;
import com.intellij.openapi.ui.popup.BalloonBuilder;
import com.intellij.openapi.ui.popup.JBPopupFactory;
import com.intellij.openapi.wm.ToolWindowManager;
import com.intellij.ui.HyperlinkLabel;
import com.intellij.ui.awt.RelativePoint;
import com.intellij.ui.components.JBLabel;
import com.intellij.ui.components.JBPanel;
import com.intellij.util.ui.JBUI;
import com.intellij.util.ui.UIUtil;
import com.redhat.devtools.lsp4ij.LanguageServerBundle;
import com.redhat.devtools.lsp4ij.settings.LanguageServerView;
import com.redhat.devtools.lsp4ij.settings.UserDefinedLanguageServerSettings;
import org.jetbrains.annotations.NotNull;

import javax.swing.*;
import java.awt.*;
import java.util.Arrays;
import java.util.Optional;

/**
* Action to update the proper language server settings and language server definition
* from the UI language server view fields.
*/
public class ApplyLanguageServerSettingsAction extends AnAction {

public static final String ACTION_TOOLBAR_COMPONENT_NAME = "ActionToolbarComponent";
private final LanguageServerView languageServerView;
private Balloon saveTipBalloon;
private boolean hasSaveTipBalloonShown = false;

public ApplyLanguageServerSettingsAction(LanguageServerView languageServerView) {
this.languageServerView = languageServerView;
final String message = LanguageServerBundle.message("action.lsp.detail.apply.text");
Expand All @@ -41,11 +64,82 @@ public void actionPerformed(@NotNull AnActionEvent e) {

@Override
public void update(@NotNull AnActionEvent e) {
e.getPresentation().setEnabled(languageServerView.isModified());
boolean modified = languageServerView.isModified();
var project = e.getProject();

if (project != null) {
boolean showSaveTipOnConfigurationChange = com.redhat.devtools.lsp4ij.settings.UserDefinedLanguageServerSettings.getInstance(project).showSaveTipOnConfigurationChange();
// Only show the tooltip once per configuration change
if (modified && !hasSaveTipBalloonShown && showSaveTipOnConfigurationChange) {
hasSaveTipBalloonShown = true;
showBalloon(project);
}
// If configuration is returned to match the unmodified state, reset the tooltip to be shown again
if (!modified) {
hasSaveTipBalloonShown = false;
}
}

e.getPresentation().setEnabled(modified);
}

@Override
public @NotNull ActionUpdateThread getActionUpdateThread() {
return ActionUpdateThread.BGT;
}

/**
* Create and show a balloon to draw attention to the save button when modifying
* configurations in the LSP console
* @param project passed on to the panel creation to create the button's action listener
*/
private void showBalloon(@NotNull Project project) {
var jbPanel = createBalloonPanel(project);

BalloonBuilder builder = JBPopupFactory.getInstance()
.createBalloonBuilder(jbPanel)
.setFadeoutTime(10000) // How many ms the balloon is shown for
.setHideOnAction(false);

// Have an instance reference to hide the balloon with the button
this.saveTipBalloon = builder.createBalloon();

var components = languageServerView.getComponent().getComponents();
Optional<Component> actionToolbarComponent = Arrays.stream(components)
.filter(c -> ACTION_TOOLBAR_COMPONENT_NAME.equals(c.getName()))
.findFirst();

if (actionToolbarComponent.isEmpty()) {
return;
}
Component applyComponent = ((ActionToolbarImpl) actionToolbarComponent.get()).getComponent(0);

// Move the position by 1/2 of the component width, because the icon is not centered
Point point = new Point(applyComponent.getWidth()/2 ,0);
RelativePoint displayPoint = new RelativePoint(applyComponent, point);

// Use invokeLater to prevent the balloon from resizing when it is shown
ApplicationManager.getApplication().invokeLater(() -> this.saveTipBalloon.show(displayPoint, Balloon.Position.above));
}

/**
* Create the balloon panel that contains the save tip and disable button stacked on top of each other
* @param project necessary for updating the settings
* @return the created JBPanel
*/
private @NotNull JBPanel<JBPanel> createBalloonPanel(Project project) {
var jbPanel = new JBPanel<>();
jbPanel.setLayout(new BoxLayout(jbPanel, BoxLayout.Y_AXIS));
// For some reason the HyperlinkLabel is indented by a single space
JBLabel jbLabel = new JBLabel(" " + LanguageServerBundle.message("action.lsp.detail.apply.balloon"));
HyperlinkLabel hyperlinkLabel = new HyperlinkLabel(LanguageServerBundle.message("action.lsp.detail.apply.balloon.disable"));
hyperlinkLabel.addHyperlinkListener(e -> {
UserDefinedLanguageServerSettings.getInstance(project).showSaveTipOnConfigurationChange(false);
this.saveTipBalloon.hide();
});

jbPanel.add(jbLabel);
jbPanel.add(hyperlinkLabel);
return jbPanel;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,23 @@ public void handleChanged(UserDefinedLanguageServerSettingsListener.LanguageServ
}
}

/**
* Tells whether the save tip balloon is shown when changing language server configuration
* @return true if the balloon should be shown, false otherwise
*/
public boolean showSaveTipOnConfigurationChange() {
return this.myState.showSaveTipOnConfigurationChange;
}

/**
* Sets the value if the save tip balloon should be shown on language server configuration change
* There is no way to set this value to true at the moment, it can only be disabled
* @param value true if the balloon should be shown, false otherwise
*/
public void showSaveTipOnConfigurationChange(boolean value) {
this.myState.showSaveTipOnConfigurationChange = value;
}

public static class LanguageServerDefinitionSettings {

private String debugPort;
Expand Down Expand Up @@ -227,6 +244,7 @@ public static class MyState {
MyState() {
}

private boolean showSaveTipOnConfigurationChange = true;
}

/**
Expand Down
2 changes: 2 additions & 0 deletions src/main/resources/messages/LanguageServerBundle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,8 @@ action.lsp.console.new.language.server.text=New language server
action.lsp.console.new.language.server.description=Open dialog to create a new language server
action.lsp.detail.apply.text=Apply
action.lsp.detail.apply.description=Apply changes for this language server settings
action.lsp.detail.apply.balloon=Press here to save the settings
action.lsp.detail.apply.balloon.disable=Got it
action.lsp.detail.reset.text=Reset
action.lsp.detail.reset.description=Rollback changes for this language server settings
## Dialog
Expand Down

0 comments on commit 4829a15

Please sign in to comment.