diff --git a/flutter-idea/src/io/flutter/FlutterInitializer.java b/flutter-idea/src/io/flutter/FlutterInitializer.java index 3a5c9cdea..73c609bb8 100644 --- a/flutter-idea/src/io/flutter/FlutterInitializer.java +++ b/flutter-idea/src/io/flutter/FlutterInitializer.java @@ -38,7 +38,6 @@ import io.flutter.editor.FlutterSaveActionsManager; import io.flutter.logging.FlutterConsoleLogManager; import io.flutter.module.FlutterModuleBuilder; -import io.flutter.preview.PreviewViewFactory; import io.flutter.pub.PubRoot; import io.flutter.pub.PubRoots; import io.flutter.run.FlutterReloadManager; @@ -320,7 +319,6 @@ public void actionPerformed(@NotNull AnActionEvent event) { private void initializeToolWindows(@NotNull Project project) { // Start watching for Flutter debug active events. FlutterViewFactory.init(project); - PreviewViewFactory.init(project); RemainingDevToolsViewFactory.init(project); DevToolsExtensionsViewFactory.init(project); toolWindowsInitialized = true; diff --git a/flutter-idea/src/io/flutter/preview/DartElementPresentationUtil.java b/flutter-idea/src/io/flutter/preview/DartElementPresentationUtil.java deleted file mode 100644 index f07ebc73b..000000000 --- a/flutter-idea/src/io/flutter/preview/DartElementPresentationUtil.java +++ /dev/null @@ -1,118 +0,0 @@ -/* - * Copyright 2018 The Chromium Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ -package io.flutter.preview; - -import com.intellij.openapi.util.text.StringUtil; -import com.intellij.ui.LayeredIcon; -import com.intellij.ui.SimpleTextAttributes; -import com.jetbrains.lang.dart.DartComponentType; -import com.jetbrains.lang.dart.util.DartPresentableUtil; -import org.dartlang.analysis.server.protocol.Element; -import org.dartlang.analysis.server.protocol.ElementKind; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import javax.swing.*; - -import static com.intellij.icons.AllIcons.Nodes.Class; -import static com.intellij.icons.AllIcons.Nodes.Enum; -import static com.intellij.icons.AllIcons.Nodes.*; -import static com.intellij.icons.AllIcons.RunConfigurations.Junit; - -/** - * Most of the class is copied from Dart Plugin. - * https://github.com/JetBrains/intellij-plugins/blob/master/Dart/src/com/jetbrains/lang/dart/ide/structure/DartStructureViewElement.java - */ -public class DartElementPresentationUtil { - private static final LayeredIcon STATIC_FINAL_FIELD_ICON = new LayeredIcon(Field, StaticMark, FinalMark); - private static final LayeredIcon FINAL_FIELD_ICON = new LayeredIcon(Field, FinalMark); - private static final LayeredIcon STATIC_FIELD_ICON = new LayeredIcon(Field, StaticMark); - private static final LayeredIcon STATIC_METHOD_ICON = new LayeredIcon(Method, StaticMark); - private static final LayeredIcon TOP_LEVEL_FUNCTION_ICON = new LayeredIcon(Function, StaticMark); - private static final LayeredIcon TOP_LEVEL_VAR_ICON = new LayeredIcon(Variable, StaticMark); - private static final LayeredIcon CONSTRUCTOR_INVOCATION_ICON = new LayeredIcon(Class, TabPin); - private static final LayeredIcon FUNCTION_INVOCATION_ICON = new LayeredIcon(Method, TabPin); - private static final LayeredIcon TOP_LEVEL_CONST_ICON = new LayeredIcon(Variable, StaticMark, FinalMark); - - @Nullable - public static Icon getIcon(@NotNull Element element) { - final boolean finalOrConst = element.isConst() || element.isFinal(); - - switch (element.getKind()) { - case ElementKind.CLASS: - return element.isAbstract() ? AbstractClass : Class; - case ElementKind.EXTENSION: - return Include; - case ElementKind.MIXIN: - return AbstractClass; - case ElementKind.CONSTRUCTOR: - return Method; - case ElementKind.CONSTRUCTOR_INVOCATION: - return CONSTRUCTOR_INVOCATION_ICON; - case ElementKind.ENUM: - return Enum; - case ElementKind.ENUM_CONSTANT: - return STATIC_FINAL_FIELD_ICON; - case ElementKind.FIELD: - if (finalOrConst && element.isTopLevelOrStatic()) return STATIC_FINAL_FIELD_ICON; - if (finalOrConst) return FINAL_FIELD_ICON; - if (element.isTopLevelOrStatic()) return STATIC_FIELD_ICON; - return Field; - case ElementKind.FUNCTION: - return element.isTopLevelOrStatic() ? TOP_LEVEL_FUNCTION_ICON : Lambda; - case ElementKind.FUNCTION_INVOCATION: - return FUNCTION_INVOCATION_ICON; - case ElementKind.FUNCTION_TYPE_ALIAS: - return DartComponentType.TYPEDEF.getIcon(); - case ElementKind.GETTER: - return element.isTopLevelOrStatic() ? PropertyReadStatic : PropertyRead; - case ElementKind.METHOD: - if (element.isAbstract()) return AbstractMethod; - return element.isTopLevelOrStatic() ? STATIC_METHOD_ICON : Method; - case ElementKind.SETTER: - return element.isTopLevelOrStatic() ? PropertyWriteStatic : PropertyWrite; - case ElementKind.TOP_LEVEL_VARIABLE: - return finalOrConst ? TOP_LEVEL_CONST_ICON : TOP_LEVEL_VAR_ICON; - case ElementKind.UNIT_TEST_GROUP: - return TestSourceFolder; - case ElementKind.UNIT_TEST_TEST: - return Junit; - - case ElementKind.CLASS_TYPE_ALIAS: - case ElementKind.COMPILATION_UNIT: - case ElementKind.FILE: - case ElementKind.LABEL: - case ElementKind.LIBRARY: - case ElementKind.LOCAL_VARIABLE: - case ElementKind.PARAMETER: - case ElementKind.PREFIX: - case ElementKind.TYPE_PARAMETER: - case ElementKind.UNKNOWN: - default: - return null; // unexpected - } - } - - public static void renderElement(@NotNull Element element, @NotNull OutlineTreeCellRenderer renderer, boolean nameInBold) { - final SimpleTextAttributes attributes = - nameInBold ? SimpleTextAttributes.REGULAR_BOLD_ATTRIBUTES : SimpleTextAttributes.REGULAR_ATTRIBUTES; - - renderer.appendSearch(element.getName(), attributes); - - if (!StringUtil.isEmpty(element.getTypeParameters())) { - renderer.appendSearch(element.getTypeParameters(), attributes); - } - if (!StringUtil.isEmpty(element.getParameters())) { - renderer.appendSearch(element.getParameters(), attributes); - } - if (!StringUtil.isEmpty(element.getReturnType())) { - renderer.append(" "); - renderer.append(DartPresentableUtil.RIGHT_ARROW); - renderer.append(" "); - renderer.appendSearch(element.getReturnType(), SimpleTextAttributes.REGULAR_ATTRIBUTES); - } - } -} diff --git a/flutter-idea/src/io/flutter/preview/ModelUtils.java b/flutter-idea/src/io/flutter/preview/ModelUtils.java deleted file mode 100644 index 8694ebb28..000000000 --- a/flutter-idea/src/io/flutter/preview/ModelUtils.java +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright 2018 The Chromium Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ -package io.flutter.preview; - -import com.intellij.openapi.util.text.StringUtil; -import org.dartlang.analysis.server.protocol.Element; -import org.jetbrains.annotations.NotNull; - -public class ModelUtils { - private ModelUtils() { - } - - public static boolean isBuildMethod(@NotNull Element element) { - if (element.getName() == null || element.getParameters() == null) { - return false; - } - return StringUtil.equals("build", element.getName()) && - StringUtil.startsWith(element.getParameters(), "(BuildContext "); - } -} diff --git a/flutter-idea/src/io/flutter/preview/PreviewView.java b/flutter-idea/src/io/flutter/preview/PreviewView.java deleted file mode 100644 index ec992807a..000000000 --- a/flutter-idea/src/io/flutter/preview/PreviewView.java +++ /dev/null @@ -1,887 +0,0 @@ -/* - * Copyright 2018 The Chromium Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ -package io.flutter.preview; - -import com.google.common.collect.ImmutableList; -import com.google.common.collect.Maps; -import com.google.common.collect.Sets; -import com.intellij.icons.AllIcons; -import com.intellij.openapi.actionSystem.*; -import com.intellij.openapi.application.ApplicationManager; -import com.intellij.openapi.components.PersistentStateComponent; -import com.intellij.openapi.components.Storage; -import com.intellij.openapi.editor.Caret; -import com.intellij.openapi.editor.Editor; -import com.intellij.openapi.fileEditor.*; -import com.intellij.openapi.project.Project; -import com.intellij.openapi.ui.SimpleToolWindowPanel; -import com.intellij.openapi.ui.Splitter; -import com.intellij.openapi.util.io.FileUtil; -import com.intellij.openapi.util.text.StringUtil; -import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.openapi.wm.ToolWindow; -import com.intellij.ui.*; -import com.intellij.ui.content.ContentFactory; -import com.intellij.ui.content.ContentManager; -import com.intellij.ui.speedSearch.SpeedSearchUtil; -import com.intellij.ui.treeStructure.Tree; -import com.intellij.util.messages.MessageBusConnection; -import io.flutter.FlutterUtils; -import io.flutter.dart.FlutterDartAnalysisServer; -import io.flutter.editor.PropertyEditorPanel; -import io.flutter.inspector.InspectorGroupManagerService; -import io.flutter.settings.FlutterSettings; -import io.flutter.utils.CustomIconMaker; -import io.flutter.utils.EventStream; -import org.dartlang.analysis.server.protocol.Element; -import org.dartlang.analysis.server.protocol.FlutterOutline; -import org.dartlang.analysis.server.protocol.FlutterOutlineAttribute; -import org.dartlang.analysis.server.protocol.FlutterOutlineKind; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import javax.swing.*; -import javax.swing.event.TreeSelectionEvent; -import javax.swing.event.TreeSelectionListener; -import javax.swing.text.SimpleAttributeSet; -import javax.swing.text.StyleConstants; -import javax.swing.text.StyleContext; -import javax.swing.tree.DefaultMutableTreeNode; -import javax.swing.tree.DefaultTreeModel; -import javax.swing.tree.TreeNode; -import javax.swing.tree.TreePath; -import java.awt.*; -import java.util.List; -import java.util.*; - -@com.intellij.openapi.components.State( - name = "FlutterPreviewView", - storages = {@Storage("$WORKSPACE_FILE$")} -) -public class PreviewView implements PersistentStateComponent { - public static final String TOOL_WINDOW_ID = "Flutter Outline"; - - @NotNull - private final PreviewViewState state = new PreviewViewState(); - - @NotNull - private final Project project; - - @NotNull - private final FlutterDartAnalysisServer flutterAnalysisServer; - - private final InspectorGroupManagerService inspectorGroupManagerService; - - private SimpleToolWindowPanel windowPanel; - - private boolean isSettingSplitterProportion = false; - private Splitter splitter; - private Splitter propertyEditSplitter; - private JScrollPane scrollPane; - private OutlineTree tree; - - private final Set outlinesWithWidgets = Sets.newHashSet(); - private final Map outlineToNodeMap = Maps.newHashMap(); - - private final EventStream currentFile; - private String currentFilePath; - FileEditor currentFileEditor; - private Editor currentEditor; - private FlutterOutline currentOutline; - private final EventStream> activeOutlines; - - private final WidgetEditToolbar widgetEditToolbar; - //private final FlutterOutlineListener outlineListener = new FlutterOutlineListener() { - // @Override - // public void outlineUpdated(@NotNull String filePath, @NotNull FlutterOutline outline, @Nullable String instrumentedCode) { - // - // final String filePathOrUri = flutterAnalysisServer.getAnalysisService().getLocalFileUri(currentFilePath); - // if (Objects.equals(filePathOrUri, filePath)) { - // ApplicationManager.getApplication().invokeLater(() -> updateOutline(outline)); - // } - // } - //}; - - //private final CaretListener caretListener = new CaretListener() { - // @Override - // public void caretPositionChanged(CaretEvent e) { - // final Caret caret = e.getCaret(); - // if (caret != null) { - // ApplicationManager.getApplication().invokeLater(() -> applyEditorSelectionToTree(caret)); - // } - // } - // - // @Override - // public void caretAdded(@NotNull CaretEvent e) { - // } - // - // @Override - // public void caretRemoved(@NotNull CaretEvent e) { - // } - //}; - - private final TreeSelectionListener treeSelectionListener = this::handleTreeSelectionEvent; - private PropertyEditorPanel propertyEditPanel; - private DefaultActionGroup propertyEditToolbarGroup; - - public PreviewView(@NotNull Project project) { - this.project = project; - currentFile = new EventStream<>(); - activeOutlines = new EventStream<>(ImmutableList.of()); - flutterAnalysisServer = FlutterDartAnalysisServer.getInstance(project); - - inspectorGroupManagerService = InspectorGroupManagerService.getInstance(project); - - // Show preview for the file selected when the view is being opened. - final FileEditorManager fileEditorManager = FileEditorManager.getInstance(project); - if(fileEditorManager != null) { - final VirtualFile[] selectedFiles = fileEditorManager.getSelectedFiles(); - if (selectedFiles.length != 0) { - setSelectedFile(selectedFiles[0]); - } - - final FileEditor[] selectedEditors = fileEditorManager.getSelectedEditors(); - if (selectedEditors.length != 0) { - setSelectedEditor(selectedEditors[0]); - } - } - // Listen for selecting files. - final MessageBusConnection bus = project.getMessageBus().connect(project); - bus.subscribe(FileEditorManagerListener.FILE_EDITOR_MANAGER, new FileEditorManagerListener() { - @Override - public void selectionChanged(@NotNull FileEditorManagerEvent event) { - setSelectedFile(event.getNewFile()); - setSelectedEditor(event.getNewEditor()); - } - }); - - widgetEditToolbar = new WidgetEditToolbar( - FlutterSettings.getInstance().isEnableHotUi(), - activeOutlines, - currentFile, - project, - flutterAnalysisServer - ); - } - - @NotNull - @Override - public PreviewViewState getState() { - return this.state; - } - - @Override - public void loadState(@NotNull PreviewViewState state) { - this.state.copyFrom(state); - } - - public void initToolWindow(@NotNull ToolWindow toolWindow) { - final ContentFactory contentFactory = ContentFactory.getInstance(); - final ContentManager contentManager = toolWindow.getContentManager(); - - final JPanel warning = new JPanel(new BorderLayout(50, 50)); - JTextPane text = new JTextPane(); - text.setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20)); - text.setCharacterAttributes( - StyleContext.getDefaultStyleContext().addAttribute(SimpleAttributeSet.EMPTY, StyleConstants.Foreground, new Color(234, 57, 35)), false); - text.setText(""" - The Flutter Outline window is being removed soon. Use the Structure view instead: View -> Tool Windows -> Structure\ - - - The refactorings in the Outline view can be found in the editor as Context Actions ⌥⏎ (macOS) / Alt+Enter (Windows/Linux)\s"""); - text.setFont(UIManager.getFont("Label.font").deriveFont(Font.BOLD)); - warning.add(text); - contentManager.getComponent().add(warning); - - //final Content content = contentFactory.createContent(null, null, false); - //content.setCloseable(false); - // - //windowPanel = new OutlineComponent(this); - //content.setComponent(windowPanel); - // - //windowPanel.setToolbar(widgetEditToolbar.getToolbar().getComponent()); - // - final DefaultMutableTreeNode rootNode = new DefaultMutableTreeNode(); - - tree = new OutlineTree(rootNode); - //tree.setCellRenderer(new OutlineTreeCellRenderer()); - //tree.expandAll(); - // - //initTreePopup(); - // - //// Add collapse all, expand all, and show only widgets buttons. - //if (toolWindow instanceof ToolWindowEx toolWindowEx) { - // - // final CommonActionsManager actions = CommonActionsManager.getInstance(); - // final TreeExpander expander = new DefaultTreeExpander(tree); - // - // final AnAction expandAllAction = actions.createExpandAllAction(expander, tree); - // expandAllAction.getTemplatePresentation().setIcon(AllIcons.Actions.Expandall); - // - // final AnAction collapseAllAction = actions.createCollapseAllAction(expander, tree); - // collapseAllAction.getTemplatePresentation().setIcon(AllIcons.Actions.Collapseall); - // - // final ShowOnlyWidgetsAction showOnlyWidgetsAction = new ShowOnlyWidgetsAction(); - // - // toolWindowEx.setTitleActions(Arrays.asList(expandAllAction, collapseAllAction, showOnlyWidgetsAction)); - //} - // - //new TreeSpeedSearch(tree) { - // @Override - // protected String getElementText(Object element) { - // final TreePath path = (TreePath)element; - // final DefaultMutableTreeNode node = (DefaultMutableTreeNode)path.getLastPathComponent(); - // final Object object = node.getUserObject(); - // if (object instanceof OutlineObject) { - // return ((OutlineObject)object).getSpeedSearchString(); - // } - // return null; - // } - //}; - // - //tree.addMouseListener(new MouseAdapter() { - // @Override - // public void mouseClicked(MouseEvent e) { - // if (e.getClickCount() > 1) { - // final TreePath selectionPath = tree.getSelectionPath(); - // if (selectionPath != null) { - // selectPath(selectionPath, true); - // } - // } - // } - //}); - // - //tree.addTreeSelectionListener(treeSelectionListener); - // - //scrollPane = ScrollPaneFactory.createScrollPane(tree); - //content.setPreferredFocusableComponent(tree); - // - //contentManager.addContent(content); - //contentManager.setSelectedContent(content); - // - //splitter = new Splitter(true); - //setSplitterProportion(getState().getSplitterProportion()); - //getState().addListener(e -> { - // final float newProportion = getState().getSplitterProportion(); - // if (splitter.getProportion() != newProportion) { - // setSplitterProportion(newProportion); - // } - //}); - ////noinspection Convert2Lambda - //splitter.addPropertyChangeListener("proportion", new PropertyChangeListener() { - // @Override - // public void propertyChange(PropertyChangeEvent evt) { - // if (!isSettingSplitterProportion) { - // getState().setSplitterProportion(splitter.getProportion()); - // } - // } - //}); - //scrollPane.setMinimumSize(new Dimension(1, 1)); - //splitter.setFirstComponent(scrollPane); - //windowPanel.setContent(splitter); - } - - private void initTreePopup() { - tree.addMouseListener(new PopupHandler() { - public void invokePopup(Component comp, int x, int y) { - // Ensure that at least one Widget item is selected. - final List selectedOutlines = getOutlinesSelectedInTree(); - if (selectedOutlines.isEmpty()) { - return; - } - for (FlutterOutline outline : selectedOutlines) { - if (outline.getDartElement() != null) { - return; - } - } - - widgetEditToolbar.createPopupMenu(comp, x, y); - } - }); - } - - private OutlineOffsetConverter getOutlineOffsetConverter() { - return new OutlineOffsetConverter(project, currentFile.getValue()); - } - - private void handleTreeSelectionEvent(TreeSelectionEvent e) { - final TreePath selectionPath = e.getNewLeadSelectionPath(); - if (selectionPath != null) { - ApplicationManager.getApplication().invokeLater(() -> selectPath(selectionPath, false)); - } - - activeOutlines.setValue(getOutlinesSelectedInTree()); - } - - private void selectPath(TreePath selectionPath, boolean focusEditor) { - final FlutterOutline outline = getOutlineOfPath(selectionPath); - jumpToOutlineInEditor(outline, focusEditor); - } - - private void jumpToOutlineInEditor(FlutterOutline outline, boolean focusEditor) { - if (outline == null) { - return; - } - final int offset = outline.getDartElement() != null ? outline.getDartElement().getLocation().getOffset() : outline.getOffset(); - final int editorOffset = getOutlineOffsetConverter().getConvertedFileOffset(offset); - - //if (currentFile != null) { - // currentEditor.getCaretModel().removeCaretListener(caretListener); - // try { - // new OpenFileDescriptor(project, currentFile.getValue(), editorOffset).navigate(focusEditor); - // } - // finally { - // currentEditor.getCaretModel().addCaretListener(caretListener); - // } - //} - } - - // TODO: Add parent relationship info to FlutterOutline instead of this O(n^2) traversal. - private Element getElementParentFor(@Nullable Element element) { - if (element == null) { - return null; - } - - for (FlutterOutline outline : outlineToNodeMap.keySet()) { - final List children = outline.getChildren(); - if (children != null) { - for (FlutterOutline child : children) { - if (child.getDartElement() == element) { - return outline.getDartElement(); - } - } - } - } - - return null; - } - - private DefaultTreeModel getTreeModel() { - return (DefaultTreeModel)tree.getModel(); - } - - private DefaultMutableTreeNode getRootNode() { - return (DefaultMutableTreeNode)getTreeModel().getRoot(); - } - - private void updateOutline(@NotNull FlutterOutline outline) { - currentOutline = outline; - - final DefaultMutableTreeNode rootNode = getRootNode(); - rootNode.removeAllChildren(); - - outlinesWithWidgets.clear(); - outlineToNodeMap.clear(); - if (outline.getChildren() != null) { - computeOutlinesWithWidgets(outline); - updateOutlineImpl(rootNode, outline.getChildren()); - } - - getTreeModel().reload(rootNode); - tree.expandAll(); - - if (currentEditor != null) { - final Caret caret = currentEditor.getCaretModel().getPrimaryCaret(); - applyEditorSelectionToTree(caret); - } - - if (FlutterSettings.getInstance().isEnableHotUi() && propertyEditPanel == null) { - propertyEditSplitter = new Splitter(false, 0.75f); - propertyEditPanel = new PropertyEditorPanel(inspectorGroupManagerService, project, flutterAnalysisServer, false, false, project); - propertyEditPanel.initalize(null, activeOutlines, currentFile); - propertyEditToolbarGroup = new DefaultActionGroup(); - final ActionToolbar windowToolbar = ActionManager.getInstance().createActionToolbar("PropertyArea", propertyEditToolbarGroup, true); - - final SimpleToolWindowPanel window = new SimpleToolWindowPanel(true, true); - window.setToolbar(windowToolbar.getComponent()); - final JScrollPane propertyScrollPane = ScrollPaneFactory.createScrollPane(propertyEditPanel); - window.setContent(propertyScrollPane); - propertyEditSplitter.setFirstComponent(window.getComponent()); - final InspectorGroupManagerService.Client inspectorStateServiceClient = new InspectorGroupManagerService.Client(project) { - @Override - public void onInspectorAvailabilityChanged() { - super.onInspectorAvailabilityChanged(); - propertyEditSplitter.setSecondComponent(null); - } - }; - inspectorGroupManagerService.addListener(inspectorStateServiceClient, project); - - splitter.setSecondComponent(propertyEditSplitter); - } - } - - private boolean computeOutlinesWithWidgets(FlutterOutline outline) { - boolean hasWidget = false; - if (outline.getDartElement() == null) { - outlinesWithWidgets.add(outline); - hasWidget = true; - } - - final List children = outline.getChildren(); - if (children != null) { - for (final FlutterOutline child : children) { - if (computeOutlinesWithWidgets(child)) { - outlinesWithWidgets.add(outline); - hasWidget = true; - } - } - } - return hasWidget; - } - - private void updateOutlineImpl(@NotNull DefaultMutableTreeNode parent, @NotNull List outlines) { - int index = 0; - for (final FlutterOutline outline : outlines) { - if (FlutterSettings.getInstance().isShowOnlyWidgets() && !outlinesWithWidgets.contains(outline)) { - continue; - } - - final OutlineObject object = new OutlineObject(outline); - final DefaultMutableTreeNode node = new DefaultMutableTreeNode(object); - outlineToNodeMap.put(outline, node); - - getTreeModel().insertNodeInto(node, parent, index++); - - if (outline.getChildren() != null) { - updateOutlineImpl(node, outline.getChildren()); - } - } - } - - @NotNull - private List getOutlinesSelectedInTree() { - final List selectedOutlines = new ArrayList<>(); - final DefaultMutableTreeNode[] selectedNodes = tree.getSelectedNodes(DefaultMutableTreeNode.class, null); - for (DefaultMutableTreeNode selectedNode : selectedNodes) { - final FlutterOutline outline = getOutlineOfNode(selectedNode); - selectedOutlines.add(outline); - } - return selectedOutlines; - } - - static private FlutterOutline getOutlineOfNode(DefaultMutableTreeNode node) { - final OutlineObject object = (OutlineObject)node.getUserObject(); - return object.outline; - } - - @Nullable - private FlutterOutline getOutlineOfPath(@Nullable TreePath path) { - if (path == null) { - return null; - } - - final DefaultMutableTreeNode node = (DefaultMutableTreeNode)path.getLastPathComponent(); - return getOutlineOfNode(node); - } - - private void addOutlinesCoveredByRange(List covered, int start, int end, @Nullable FlutterOutline outline) { - if (outline == null) { - return; - } - final OutlineOffsetConverter converter = getOutlineOffsetConverter(); - final int outlineStart = converter.getConvertedOutlineOffset(outline); - final int outlineEnd = converter.getConvertedOutlineEnd(outline); - // The outline ends before, or starts after the selection. - if (outlineEnd < start || outlineStart > end) { - return; - } - // The outline is covered by the selection. - if (outlineStart >= start && outlineEnd <= end) { - covered.add(outline); - return; - } - // The outline covers the selection. - if (outlineStart <= start && end <= outlineEnd) { - if (outline.getChildren() != null) { - for (FlutterOutline child : outline.getChildren()) { - addOutlinesCoveredByRange(covered, start, end, child); - } - } - } - } - - private void setSelectedFile(VirtualFile newFile) { - if (currentFile.getValue() != null) { - //flutterAnalysisServer.removeOutlineListener(currentFilePath, outlineListener); - currentFile.setValue(null); - currentFilePath = null; - } - - // If not a Dart file, ignore it. - if (newFile != null && !FlutterUtils.isDartFile(newFile)) { - newFile = null; - } - - // Show the toolbar if the new file is a Dart file, or hide otherwise. - if (windowPanel != null) { - if (newFile != null) { - windowPanel.setToolbar(widgetEditToolbar.getToolbar().getComponent()); - } - else if (windowPanel.isToolbarVisible()) { - windowPanel.setToolbar(null); - } - } - - // If the tree is already created, clear it now, until the outline for the new file is received. - if (tree != null) { - final DefaultMutableTreeNode rootNode = getRootNode(); - rootNode.removeAllChildren(); - getTreeModel().reload(rootNode); - } - - // Subscribe for the outline for the new file. - if (newFile != null) { - currentFile.setValue(newFile); - currentFilePath = FileUtil.toSystemDependentName(newFile.getPath()); - //flutterAnalysisServer.addOutlineListener(currentFilePath, outlineListener); - } - } - - private void setSelectedEditor(FileEditor newEditor) { - //if (currentEditor != null) { - // currentEditor.getCaretModel().removeCaretListener(caretListener); - //} - //if (newEditor instanceof TextEditor) { - // currentFileEditor = newEditor; - // currentEditor = ((TextEditor)newEditor).getEditor(); - // currentEditor.getCaretModel().addCaretListener(caretListener); - //} - } - - private void applyEditorSelectionToTree(Caret caret) { - final List selectedOutlines = new ArrayList<>(); - - // Try to find outlines covered by the selection. - addOutlinesCoveredByRange(selectedOutlines, caret.getSelectionStart(), caret.getSelectionEnd(), currentOutline); - - // If no covered outlines, try to find the outline under the caret. - if (selectedOutlines.isEmpty()) { - final FlutterOutline outline = getOutlineOffsetConverter().findOutlineAtOffset(currentOutline, caret.getOffset()); - if (outline != null) { - selectedOutlines.add(outline); - } - } - - activeOutlines.setValue(selectedOutlines); - - applyOutlinesSelectionToTree(selectedOutlines); - } - - private void applyOutlinesSelectionToTree(List outlines) { - final List selectedPaths = new ArrayList<>(); - TreeNode[] lastNodePath = null; - TreePath lastTreePath = null; - for (FlutterOutline outline : outlines) { - final DefaultMutableTreeNode selectedNode = outlineToNodeMap.get(outline); - if (selectedNode != null) { - lastNodePath = selectedNode.getPath(); - lastTreePath = new TreePath(lastNodePath); - selectedPaths.add(lastTreePath); - } - } - - if (lastNodePath != null) { - // Ensure that all parent nodes are expected. - tree.scrollPathToVisible(lastTreePath); - - // Ensure that the top-level declaration (class) is on the top of the tree. - if (lastNodePath.length >= 2) { - scrollTreeToNodeOnTop(lastNodePath[1]); - } - - // Ensure that the selected node is still visible, even if the top-level declaration is long. - tree.scrollPathToVisible(lastTreePath); - } - - // Now actually select the node. - tree.removeTreeSelectionListener(treeSelectionListener); - tree.setSelectionPaths(selectedPaths.toArray(new TreePath[0])); - tree.addTreeSelectionListener(treeSelectionListener); - - // JTree attempts to show as much of the node as possible, so scrolls horizontally. - // But we actually need to see the whole hierarchy, so we scroll back to zero. - scrollPane.getHorizontalScrollBar().setValue(0); - } - - private void scrollTreeToNodeOnTop(TreeNode node) { - if (node instanceof DefaultMutableTreeNode defaultNode) { - final Rectangle bounds = tree.getPathBounds(new TreePath(defaultNode.getPath())); - // Set the height to the visible tree height to force the node to top. - if (bounds != null) { - bounds.height = tree.getVisibleRect().height; - tree.scrollRectToVisible(bounds); - } - } - } - - private void setSplitterProportion(float value) { - isSettingSplitterProportion = true; - try { - splitter.setProportion(value); - } - finally { - isSettingSplitterProportion = false; - } - doLayoutRecursively(splitter); - } - - // TODO(jacobr): is this method really useful? This is from re-applying the - // PreviewArea but it doesn't really seem that useful. - private static void doLayoutRecursively(Component component) { - if (component != null) { - component.doLayout(); - if (component instanceof Container container) { - for (Component child : container.getComponents()) { - doLayoutRecursively(child); - } - } - } - } - - private class ShowOnlyWidgetsAction extends AnAction implements Toggleable, RightAlignedToolbarAction { - ShowOnlyWidgetsAction() { - super("Show Only Widgets", "Show only widgets", AllIcons.General.Filter); - } - - @Override - public void actionPerformed(@NotNull AnActionEvent e) { - final FlutterSettings flutterSettings = FlutterSettings.getInstance(); - flutterSettings.setShowOnlyWidgets(!flutterSettings.isShowOnlyWidgets()); - if (currentOutline != null) { - updateOutline(currentOutline); - } - } - - @Override - public void update(AnActionEvent e) { - final Presentation presentation = e.getPresentation(); - presentation.putClientProperty(SELECTED_PROPERTY, FlutterSettings.getInstance().isShowOnlyWidgets()); - presentation.setEnabled(currentOutline != null); - } - - @Override - public @NotNull ActionUpdateThread getActionUpdateThread() { - return ActionUpdateThread.BGT; - } - } -} - -/** - * We subclass {@link SimpleToolWindowPanel} to implement "getData" and return {@link PlatformDataKeys#FILE_EDITOR}, - * so that Undo/Redo actions work. - */ -class OutlineComponent extends SimpleToolWindowPanel { - private final PreviewView myView; - - OutlineComponent(PreviewView view) { - super(true, true); - myView = view; - } - - @Override - public Object getData(@NotNull String dataId) { - if (PlatformDataKeys.FILE_EDITOR.is(dataId)) { - return myView.currentFileEditor; - } - return super.getData(dataId); - } -} - -class OutlineTree extends Tree { - OutlineTree(DefaultMutableTreeNode model) { - super(model); - - setRootVisible(false); - setToggleClickCount(0); - } - - void expandAll() { - for (int row = 0; row < getRowCount(); row++) { - expandRow(row); - } - } -} - -class OutlineObject { - private static final CustomIconMaker iconMaker = new CustomIconMaker(); - private static final Map flutterDecoratedIcons = new HashMap<>(); - - final FlutterOutline outline; - private Icon icon; - - OutlineObject(FlutterOutline outline) { - this.outline = outline; - } - - Icon getIcon() { - if (outline.getKind().equals(FlutterOutlineKind.DART_ELEMENT)) { - return null; - } - - if (icon == null) { - final String className = outline.getClassName(); - if (icon == null) { - icon = iconMaker.fromWidgetName(className); - } - } - - return icon; - } - - /** - * Return the string that is suitable for speed search. It has every name part separated so that we search only inside individual name - * parts, but not in their accidential concatenation. - */ - @NotNull - String getSpeedSearchString() { - final StringBuilder builder = new StringBuilder(); - final Element dartElement = outline.getDartElement(); - if (dartElement != null) { - builder.append(dartElement.getName()); - } - else { - builder.append(outline.getClassName()); - } - if (outline.getVariableName() != null) { - builder.append('|'); - builder.append(outline.getVariableName()); - } - - final List attributes = outline.getAttributes(); - if (attributes != null) { - for (FlutterOutlineAttribute attribute : attributes) { - builder.append(attribute.getName()); - builder.append(':'); - builder.append(attribute.getLabel()); - } - } - - return builder.toString(); - } -} - -class OutlineTreeCellRenderer extends ColoredTreeCellRenderer { - private JTree tree; - private boolean selected; - - public void customizeCellRenderer( - @NotNull final JTree tree, - final Object value, - final boolean selected, - final boolean expanded, - final boolean leaf, - final int row, - final boolean hasFocus - ) { - final Object userObject = ((DefaultMutableTreeNode)value).getUserObject(); - if (!(userObject instanceof OutlineObject node)) { - return; - } - final FlutterOutline outline = node.outline; - - this.tree = tree; - this.selected = selected; - - // Render a Dart element. - final Element dartElement = outline.getDartElement(); - if (dartElement != null) { - final Icon icon = DartElementPresentationUtil.getIcon(dartElement); - setIcon(icon); - - final boolean renderInBold = hasWidgetChild(outline) && ModelUtils.isBuildMethod(dartElement); - DartElementPresentationUtil.renderElement(dartElement, this, renderInBold); - return; - } - - final Icon icon = node.getIcon(); - if (icon != null) { - setIcon(icon); - } - - // Render the widget class. - appendSearch(outline.getClassName(), SimpleTextAttributes.REGULAR_ATTRIBUTES); - - // Render the variable. - if (outline.getVariableName() != null) { - append(" "); - appendSearch(outline.getVariableName(), SimpleTextAttributes.GRAYED_ATTRIBUTES); - } - - // Render a generic label. - if (outline.getKind().equals(FlutterOutlineKind.GENERIC) && outline.getLabel() != null) { - append(" "); - final String label = outline.getLabel(); - appendSearch(label, SimpleTextAttributes.GRAYED_ATTRIBUTES); - } - - // Append all attributes. - final List attributes = outline.getAttributes(); - if (attributes != null) { - if (attributes.size() == 1 && isAttributeElidable(attributes.get(0).getName())) { - final FlutterOutlineAttribute attribute = attributes.get(0); - append(" "); - appendSearch(attribute.getLabel(), SimpleTextAttributes.GRAYED_ATTRIBUTES); - } - else { - for (int i = 0; i < attributes.size(); i++) { - final FlutterOutlineAttribute attribute = attributes.get(i); - - if (i > 0) { - append(","); - } - append(" "); - - if (!StringUtil.equals("data", attribute.getName())) { - appendSearch(attribute.getName(), SimpleTextAttributes.GRAYED_ATTRIBUTES); - append(": ", SimpleTextAttributes.GRAYED_ATTRIBUTES); - } - - appendSearch(attribute.getLabel(), SimpleTextAttributes.GRAYED_ATTRIBUTES); - } - } - } - } - - private boolean hasWidgetChild(FlutterOutline outline) { - if (outline.getChildren() == null) { - return false; - } - - for (FlutterOutline child : outline.getChildren()) { - if (child.getDartElement() == null) { - return true; - } - } - - return false; - } - - void appendSearch(@NotNull String text, @NotNull SimpleTextAttributes attributes) { - SpeedSearchUtil.appendFragmentsForSpeedSearch(tree, text, attributes, selected, this); - } - - private static boolean isAttributeElidable(String name) { - return StringUtil.equals("text", name) || StringUtil.equals("icon", name); - } -} - -/** - * Delegate to the given action, but do not render the action's icon. - */ -class TextOnlyActionWrapper extends AnAction { - private final AnAction action; - - public TextOnlyActionWrapper(AnAction action) { - super(action.getTemplatePresentation().getText()); - - this.action = action; - } - - @Override - public void actionPerformed(@NotNull AnActionEvent event) { - action.actionPerformed(event); - } -} diff --git a/flutter-idea/src/io/flutter/preview/PreviewViewFactory.java b/flutter-idea/src/io/flutter/preview/PreviewViewFactory.java deleted file mode 100644 index 5e13ac5ad..000000000 --- a/flutter-idea/src/io/flutter/preview/PreviewViewFactory.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright 2018 The Chromium Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ -package io.flutter.preview; - -import com.intellij.ide.util.PropertiesComponent; -import com.intellij.openapi.project.DumbAware; -import com.intellij.openapi.project.DumbService; -import com.intellij.openapi.project.Project; -import com.intellij.openapi.wm.ToolWindow; -import com.intellij.openapi.wm.ToolWindowFactory; -import com.intellij.openapi.wm.ToolWindowManager; -import io.flutter.utils.ViewListener; -import org.jetbrains.annotations.NotNull; - -public class PreviewViewFactory implements ToolWindowFactory, DumbAware { - private static final String TOOL_WINDOW_VISIBLE_PROPERTY = "flutter.preview.tool.window.visible"; - - public static void init(@NotNull Project project) { - final ToolWindow window = ToolWindowManager.getInstance(project).getToolWindow(PreviewView.TOOL_WINDOW_ID); - if (window != null) { - window.setAvailable(true); - - if (PropertiesComponent.getInstance(project).getBoolean(TOOL_WINDOW_VISIBLE_PROPERTY, false)) { - window.activate(null, false); - } - } - } - - @Override - public void createToolWindowContent(@NotNull Project project, @NotNull ToolWindow toolWindow) { - //noinspection CodeBlock2Expr - DumbService.getInstance(project).runWhenSmart(() -> { - (project.getService(PreviewView.class)).initToolWindow(toolWindow); - }); - } - - @Override - public boolean shouldBeAvailable(@NotNull Project project) { - return false; - } - - public static class PreviewViewListener extends ViewListener { - public PreviewViewListener(@NotNull Project project) { - super(project, PreviewView.TOOL_WINDOW_ID, TOOL_WINDOW_VISIBLE_PROPERTY); - } - } -} diff --git a/flutter-idea/src/io/flutter/preview/PreviewViewState.java b/flutter-idea/src/io/flutter/preview/PreviewViewState.java deleted file mode 100644 index 7e1c3a297..000000000 --- a/flutter-idea/src/io/flutter/preview/PreviewViewState.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright 2018 The Chromium Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ -package io.flutter.preview; - -import com.intellij.util.EventDispatcher; -import com.intellij.util.xmlb.annotations.Attribute; - -import javax.swing.event.ChangeEvent; -import javax.swing.event.ChangeListener; - -/** - * State for the Preview view. - */ -public class PreviewViewState { - private final EventDispatcher dispatcher = EventDispatcher.create(ChangeListener.class); - - @Attribute(value = "splitter-proportion") - public float splitterProportion; - - public PreviewViewState() { - } - - public float getSplitterProportion() { - return splitterProportion <= 0.0f ? 0.7f : splitterProportion; - } - - public void setSplitterProportion(float value) { - splitterProportion = value; - dispatcher.getMulticaster().stateChanged(new ChangeEvent(this)); - } - - public void addListener(ChangeListener listener) { - dispatcher.addListener(listener); - } - - public void removeListener(ChangeListener listener) { - dispatcher.removeListener(listener); - } - - // This attribute exists only to silence the "com.intellij.util.xmlb.Binding - no accessors for class" warning. - @Attribute(value = "placeholder") - public String placeholder; - - void copyFrom(PreviewViewState other) { - this.placeholder = other.placeholder; - splitterProportion = other.splitterProportion; - } -} diff --git a/flutter-idea/src/io/flutter/preview/WidgetEditToolbar.java b/flutter-idea/src/io/flutter/preview/WidgetEditToolbar.java index 4dac30c92..f7472bbdd 100644 --- a/flutter-idea/src/io/flutter/preview/WidgetEditToolbar.java +++ b/flutter-idea/src/io/flutter/preview/WidgetEditToolbar.java @@ -335,69 +335,4 @@ private void applyChangeAndShowException(SourceChange change) { } }); } - - public void createPopupMenu(Component comp, int x, int y) { - // The corresponding tree item may have just been selected. - // Wait short time for receiving assists from the server. - // TODO(jacobr): this hard coded sleep seems like a hack. Figure out a - // more robust way to wait for all assists to be received. - for (int i = 0; i < 20 && actionToChangeMap.isEmpty(); i++) { - Uninterruptibles.sleepUninterruptibly(5, TimeUnit.MILLISECONDS); - } - - final DefaultActionGroup group = new DefaultActionGroup(); - boolean hasAction = false; - if (actionCenter.isEnabled()) { - hasAction = true; - group.add(new TextOnlyActionWrapper(actionCenter)); - } - if (actionPadding.isEnabled()) { - hasAction = true; - group.add(new TextOnlyActionWrapper(actionPadding)); - } - if (actionColumn.isEnabled()) { - hasAction = true; - group.add(new TextOnlyActionWrapper(actionColumn)); - } - if (actionRow.isEnabled()) { - hasAction = true; - group.add(new TextOnlyActionWrapper(actionRow)); - } - if (actionContainer.isEnabled()) { - hasAction = true; - group.add(new TextOnlyActionWrapper(actionContainer)); - } - group.addSeparator(); - if (actionExtractMethod.isEnabled()) { - hasAction = true; - group.add(new TextOnlyActionWrapper(actionExtractMethod)); - } - if (actionExtractWidget.isEnabled()) { - hasAction = true; - group.add(new TextOnlyActionWrapper(actionExtractWidget)); - } - group.addSeparator(); - if (actionMoveUp.isEnabled()) { - hasAction = true; - group.add(new TextOnlyActionWrapper(actionMoveUp)); - } - if (actionMoveDown.isEnabled()) { - hasAction = true; - group.add(new TextOnlyActionWrapper(actionMoveDown)); - } - group.addSeparator(); - if (actionRemove.isEnabled()) { - hasAction = true; - group.add(new TextOnlyActionWrapper(actionRemove)); - } - - // Don't show the empty popup. - if (!hasAction) { - return; - } - - final ActionManager actionManager = ActionManager.getInstance(); - final ActionPopupMenu popupMenu = actionManager.createActionPopupMenu(ActionPlaces.UNKNOWN, group); - popupMenu.getComponent().show(comp, x, y); - } } diff --git a/flutter-idea/src/io/flutter/view/FlutterViewFactory.java b/flutter-idea/src/io/flutter/view/FlutterViewFactory.java index 41a0bf7d7..46aaf3ef4 100644 --- a/flutter-idea/src/io/flutter/view/FlutterViewFactory.java +++ b/flutter-idea/src/io/flutter/view/FlutterViewFactory.java @@ -1,5 +1,5 @@ /* - * Copyright 2017 The Chromium Authors. All rights reserved. + * Copyright 2024 The Chromium Authors. All rights reserved. * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/resources/META-INF/plugin.xml b/resources/META-INF/plugin.xml index 402e555b4..7c097c340 100644 --- a/resources/META-INF/plugin.xml +++ b/resources/META-INF/plugin.xml @@ -306,12 +306,6 @@ topic="com.intellij.openapi.project.ProjectManagerListener"/> - - - - - @@ -379,14 +373,6 @@ - - - - - - diff --git a/resources/META-INF/plugin_template.xml b/resources/META-INF/plugin_template.xml index ff1a4f081..a7e716f79 100644 --- a/resources/META-INF/plugin_template.xml +++ b/resources/META-INF/plugin_template.xml @@ -243,12 +243,6 @@ topic="com.intellij.openapi.project.ProjectManagerListener"/> - - - - - @@ -316,14 +310,6 @@ - - - - - -