Skip to content

Commit

Permalink
[js] custom floating toolbar for JS, TS and HTML WEB-68037
Browse files Browse the repository at this point in the history
GitOrigin-RevId: c753f085abf154876ec739b1f192fa803590904f
  • Loading branch information
vepanimas authored and intellij-monorepo-bot committed Jan 9, 2025
1 parent 7bafe78 commit cc6bf30
Show file tree
Hide file tree
Showing 7 changed files with 95 additions and 7 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@ public abstract class ActionGroup extends AnAction {
}
};

@ApiStatus.Internal
public static final DataKey<ActionGroup> CONTEXT_ACTION_GROUP_KEY = DataKey.create("context.action.group");

private boolean mySearchable = true;
private Set<AnAction> mySecondaryActions;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,11 @@ public void update(@NotNull AnActionEvent e) {

@Override
public void actionPerformed(@NotNull AnActionEvent e) {
performShowUsagesAction(e);
}

@ApiStatus.Internal
public static void performShowUsagesAction(@NotNull AnActionEvent e) {
Project project = e.getProject();
if (project == null) return;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,18 @@

package com.intellij.refactoring.actions;

import com.intellij.openapi.actionSystem.ActionGroup;
import com.intellij.openapi.actionSystem.ActionPlaces;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.util.text.StringUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

public abstract class ExtractSuperActionBase extends BasePlatformRefactoringAction {

private static final String[] PREFIXES = {"Extract", "Introduce"};

@Override
public boolean isAvailableInEditorOnly() {
return false;
Expand All @@ -34,13 +39,26 @@ public void update(@NotNull AnActionEvent e) {
removeFirstWordInMainMenu(this, e);
}

public static void removeFirstWordInMainMenu(AnAction action, @NotNull AnActionEvent e) {
String place = e.getPlace();
if (place.equals(ActionPlaces.MAIN_MENU) || place.contains(ActionPlaces.EDITOR_FLOATING_TOOLBAR)) {
public static void removeFirstWordInMainMenu(@NotNull AnAction action, @NotNull AnActionEvent e) {
if (e.getPlace().equals(ActionPlaces.MAIN_MENU) || isInToolbarActionGroupWithKnownPrefix(e)) {
String templateText = action.getTemplatePresentation().getText();
if (templateText.startsWith("Extract") || templateText.startsWith("Introduce")) {
if (startsWithKnownPrefix(templateText)) {
e.getPresentation().setText(templateText.substring(templateText.indexOf(' ') + 1));
}
}
}

private static boolean isInToolbarActionGroupWithKnownPrefix(@NotNull AnActionEvent e) {
if (!e.getPlace().contains(ActionPlaces.EDITOR_FLOATING_TOOLBAR) && !e.isFromContextMenu()) return false;
ActionGroup actionGroup = e.getData(ActionGroup.CONTEXT_ACTION_GROUP_KEY);
return actionGroup != null && startsWithKnownPrefix(actionGroup.getTemplatePresentation().getText());
}

private static boolean startsWithKnownPrefix(@Nullable String text) {
if (text == null) return false;
for (String prefix : PREFIXES) {
if (StringUtil.startsWith(text, prefix)) return true;
}
return false;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,16 @@ import com.intellij.openapi.actionSystem.ex.CustomComponentAction
import com.intellij.openapi.actionSystem.impl.ActionButtonWithText
import javax.swing.JComponent

internal class RefactorDropdownActionGroup: DefaultActionGroup(), CustomComponentAction {
internal class RefactorDropdownActionGroup : DefaultActionGroup(), CustomComponentAction {
override fun getActionUpdateThread(): ActionUpdateThread = ActionUpdateThread.BGT

override fun createCustomComponent(presentation: Presentation, place: String): JComponent {
return object: ActionButtonWithText(this, presentation, place, ActionToolbar.DEFAULT_MINIMUM_BUTTON_SIZE) {
return object : ActionButtonWithText(this, presentation, place, ActionToolbar.DEFAULT_MINIMUM_BUTTON_SIZE) {
override fun actionPerformed(event: AnActionEvent) {
showActionGroupPopup(this@RefactorDropdownActionGroup, event)
val newEvent = event.withDataContext(CustomizedDataContext.withSnapshot(event.dataContext) { sink ->
sink[CONTEXT_ACTION_GROUP_KEY] = this@RefactorDropdownActionGroup
})
showActionGroupPopup(this@RefactorDropdownActionGroup, newEvent)
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1035,6 +1035,8 @@ action.EmmetPreview.description=Show preview for emmet abbreviation
action.SurroundWithEmmet.text=Surround with Emmet
action.SurroundWithEmmet.description=Surround selected code with Emmet abbreviation
group.Emmet.text=Emmet
action.SurroundWithTagTemplate.text=Surround with Tag
action.SurroundWithTagTemplate.description=Surround selected code with a tag
group.OpenInBrowserEditorContextBarGroupAction.text=Open In\u2026
group.OpenInBrowserEditorContextBarGroupAction.description=Open In\u2026
action.OpenInBrowser.text=Open in default _browser
Expand Down
2 changes: 2 additions & 0 deletions platform/platform-resources/src/META-INF/XmlActions.xml
Original file line number Diff line number Diff line change
Expand Up @@ -73,5 +73,7 @@
<action id="ToggleMinimap" class="com.intellij.ide.minimap.actions.ToggleMinimapAction"/>
<action id="OpenMinimapSettings" class="com.intellij.ide.minimap.actions.OpenMinimapSettingsAction"/>
<action id="MoveMinimap" class="com.intellij.ide.minimap.actions.MoveMinimapAction"/>

<action id="SurroundWithTagTemplate" class="com.intellij.xml.actions.XmlSurroundWithTagTemplateAction" icon="AllIcons.Nodes.Tag"/>
</actions>
</idea-plugin>
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.xml.actions

import com.intellij.codeInsight.actions.SimpleCodeInsightAction
import com.intellij.codeInsight.template.TemplateActionContext
import com.intellij.codeInsight.template.impl.InvokeTemplateAction
import com.intellij.codeInsight.template.impl.TemplateImpl
import com.intellij.codeInsight.template.impl.TemplateManagerImpl
import com.intellij.codeInsight.template.impl.TemplateSettings
import com.intellij.openapi.actionSystem.*
import com.intellij.openapi.editor.Editor
import com.intellij.openapi.fileEditor.FileDocumentManager
import com.intellij.openapi.project.Project
import com.intellij.psi.PsiFile
import com.intellij.psi.util.PsiUtilBase

class XmlSurroundWithTagTemplateAction : SimpleCodeInsightAction() {

init {
setInjectedContext(true)
}

override fun update(e: AnActionEvent) {
super.update(e)

val project = e.project ?: return
val editor = e.getData(CommonDataKeys.EDITOR) ?: return
val file = PsiUtilBase.getPsiFileInEditor(editor, project) ?: return

if (!e.place.contains(ActionPlaces.EDITOR_FLOATING_TOOLBAR) && !e.isFromContextMenu) {
e.presentation.isEnabledAndVisible = false
return
}
if (!editor.getSelectionModel().hasSelection()) {
e.presentation.isEnabled = false
return
}
e.presentation.isEnabled = createAction(editor, file) != null
}

override fun invoke(project: Project, editor: Editor, file: PsiFile) {
if (!FileDocumentManager.getInstance().requestWriting(editor.document, project)) return
createAction(editor, file)?.perform()
}

private fun createAction(editor: Editor, file: PsiFile): InvokeTemplateAction? {
val templateActionContext = TemplateActionContext.surrounding(file, editor)
val template = createTemplate()?.takeIf { TemplateManagerImpl.isApplicable(it, templateActionContext) } ?: return null
return InvokeTemplateAction(template, editor, file.getProject(), mutableSetOf())
}

private fun createTemplate(): TemplateImpl? {
return TemplateSettings.getInstance().getTemplate("T", "HTML/XML")
}
}

0 comments on commit cc6bf30

Please sign in to comment.