From 53bec8a285527decd392e54fe801092612dceadc Mon Sep 17 00:00:00 2001 From: Alexander Lobas Date: Tue, 14 May 2013 11:08:56 +0400 Subject: [PATCH] IDEA-106210 --- .../openapi/wm/impl/InternalDecorator.java | 8 +- .../openapi/wm/impl/ToolWindowHeader.java | 2 +- .../util/src/com/intellij/util/ui/UIUtil.java | 7 +- .../designer/AbstractToolWindowManager.java | 198 ++++++- .../intellij/designer/DesignerToolWindow.java | 166 ++++++ .../designer/DesignerToolWindowManager.java | 161 ++---- .../intellij/designer/LightToolWindow.java | 527 ++++++++++++++++++ .../designer/LightToolWindowContent.java | 23 + .../designSurface/DesignerEditorPanel.java | 102 +++- .../inspection/DesignerHighlightingPass.java | 2 +- .../designer/palette/PalettePanel.java | 8 +- .../palette/PaletteToolWindowManager.java | 43 +- .../propertyTable/PropertyTablePanel.java | 12 +- 13 files changed, 1083 insertions(+), 176 deletions(-) create mode 100644 plugins/ui-designer-core/src/com/intellij/designer/DesignerToolWindow.java create mode 100644 plugins/ui-designer-core/src/com/intellij/designer/LightToolWindow.java create mode 100644 plugins/ui-designer-core/src/com/intellij/designer/LightToolWindowContent.java diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/InternalDecorator.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/InternalDecorator.java index 8bfca62e54ea..d37e976dfc22 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/InternalDecorator.java +++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/InternalDecorator.java @@ -81,10 +81,10 @@ public final class InternalDecorator extends JPanel implements Queryable, TypeSa private final ToolWindowHandler myToolWindowHandler; private final MyKeymapManagerListener myWeakKeymapManagerListener; @NonNls private static final String HIDE_ACTIVE_WINDOW_ACTION_ID = "HideActiveWindow"; - @NonNls private static final String TOGGLE_PINNED_MODE_ACTION_ID = "TogglePinnedMode"; - @NonNls private static final String TOGGLE_DOCK_MODE_ACTION_ID = "ToggleDockMode"; - @NonNls private static final String TOGGLE_FLOATING_MODE_ACTION_ID = "ToggleFloatingMode"; - @NonNls private static final String TOGGLE_SIDE_MODE_ACTION_ID = "ToggleSideMode"; + @NonNls public static final String TOGGLE_PINNED_MODE_ACTION_ID = "TogglePinnedMode"; + @NonNls public static final String TOGGLE_DOCK_MODE_ACTION_ID = "ToggleDockMode"; + @NonNls public static final String TOGGLE_FLOATING_MODE_ACTION_ID = "ToggleFloatingMode"; + @NonNls public static final String TOGGLE_SIDE_MODE_ACTION_ID = "ToggleSideMode"; @NonNls private static final String TOGGLE_CONTENT_UI_TYPE_ACTION_ID = "ToggleContentUiTypeMode"; private ToolWindowHeader myHeader; diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/ToolWindowHeader.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/ToolWindowHeader.java index 0d0e04cbb122..86a848f7619a 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/ToolWindowHeader.java +++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/ToolWindowHeader.java @@ -314,7 +314,7 @@ public abstract class ToolWindowHeader extends JPanel implements Disposable { BufferedImage image = UIUtil.createImage(width, height, BufferedImage.TYPE_INT_ARGB); Graphics2D g = image.createGraphics(); - UIUtil.drawHeader(g, 0, width, height, active, true, !floating); + UIUtil.drawHeader(g, 0, width, height, active, true, !floating, true); g.dispose(); return image; diff --git a/platform/util/src/com/intellij/util/ui/UIUtil.java b/platform/util/src/com/intellij/util/ui/UIUtil.java index 7abc96b7e809..90adc64366f2 100644 --- a/platform/util/src/com/intellij/util/ui/UIUtil.java +++ b/platform/util/src/com/intellij/util/ui/UIUtil.java @@ -1320,7 +1320,7 @@ public class UIUtil { } public static void drawHeader(Graphics g, int x, int width, int height, boolean active, boolean drawTopLine) { - drawHeader(g, x, width, height, active, false, drawTopLine); + drawHeader(g, x, width, height, active, false, drawTopLine, true); } public static void drawHeader(Graphics g, @@ -1329,7 +1329,8 @@ public class UIUtil { int height, boolean active, boolean toolWindow, - boolean drawTopLine) { + boolean drawTopLine, + boolean drawBottomLine) { g.setColor(getPanelBackground()); g.fillRect(x, 0, width, height); @@ -1338,7 +1339,7 @@ public class UIUtil { g.setColor(new Color(0, 0, 0, toolWindow ? 90 : 50)); if (drawTopLine) g.drawLine(x, 0, width, 0); - g.drawLine(x, height - 1, width, height - 1); + if (drawBottomLine) g.drawLine(x, height - 1, width, height - 1); g.setColor(isUnderDarcula() ? Gray._255.withAlpha(30) : new Color(255, 255, 255, 100)); g.drawLine(x, drawTopLine ? 1 : 0, width, drawTopLine ? 1 : 0); diff --git a/plugins/ui-designer-core/src/com/intellij/designer/AbstractToolWindowManager.java b/plugins/ui-designer-core/src/com/intellij/designer/AbstractToolWindowManager.java index 87656783aaff..02a4aaef0c66 100644 --- a/plugins/ui-designer-core/src/com/intellij/designer/AbstractToolWindowManager.java +++ b/plugins/ui-designer-core/src/com/intellij/designer/AbstractToolWindowManager.java @@ -16,6 +16,11 @@ package com.intellij.designer; import com.intellij.designer.designSurface.DesignerEditorPanel; +import com.intellij.ide.util.PropertiesComponent; +import com.intellij.openapi.actionSystem.AnAction; +import com.intellij.openapi.actionSystem.AnActionEvent; +import com.intellij.openapi.actionSystem.DefaultActionGroup; +import com.intellij.openapi.actionSystem.ToggleAction; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.components.ProjectComponent; import com.intellij.openapi.fileEditor.FileEditor; @@ -26,15 +31,21 @@ import com.intellij.openapi.project.Project; import com.intellij.openapi.startup.StartupManager; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.openapi.wm.ToolWindow; +import com.intellij.openapi.wm.ex.ToolWindowEx; +import com.intellij.util.messages.MessageBusConnection; import com.intellij.util.ui.update.MergingUpdateQueue; import com.intellij.util.ui.update.Update; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import javax.swing.*; + /** * @author Alexander Lobas */ public abstract class AbstractToolWindowManager implements ProjectComponent { + public static final String EDITOR_MODE = "UI_DESIGNER_EDITOR_MODE."; + private final MergingUpdateQueue myWindowQueue = new MergingUpdateQueue(getComponentName(), 200, true, null); protected final Project myProject; protected final FileEditorManager myFileEditorManager; @@ -42,18 +53,57 @@ public abstract class AbstractToolWindowManager implements ProjectComponent { private volatile boolean myToolWindowReady; private volatile boolean myToolWindowDisposed; - public AbstractToolWindowManager(Project project, FileEditorManager fileEditorManager) { + protected final PropertiesComponent myPropertiesComponent; + + private MessageBusConnection myConnection; + private final FileEditorManagerListener myListener = new FileEditorManagerListener() { + @Override + public void fileOpened(@NotNull FileEditorManager source, @NotNull VirtualFile file) { + bindToDesigner(getActiveDesigner()); + } + + @Override + public void fileClosed(@NotNull FileEditorManager source, @NotNull VirtualFile file) { + ApplicationManager.getApplication().invokeLater(new Runnable() { + @Override + public void run() { + bindToDesigner(getActiveDesigner()); + } + }); + } + + @Override + public void selectionChanged(@NotNull FileEditorManagerEvent event) { + bindToDesigner(getDesigner(event.getNewEditor())); + } + }; + + private final int myStyle; + + ////////////////////////////////////////////////////////////////////////////////////////// + // + // ToolWindow + // + ////////////////////////////////////////////////////////////////////////////////////////// + + protected AbstractToolWindowManager(Project project, FileEditorManager fileEditorManager, int style) { myProject = project; myFileEditorManager = fileEditorManager; + myPropertiesComponent = PropertiesComponent.getInstance(myProject); + myStyle = style; } @Override public void projectOpened() { + initToolWindow(); + StartupManager.getInstance(myProject).registerPostStartupActivity(new Runnable() { public void run() { myToolWindowReady = true; - initListeners(); - bindToDesigner(getActiveDesigner()); + if (!isEditorMode()) { + initListeners(); + bindToDesigner(getActiveDesigner()); + } } }); } @@ -68,27 +118,13 @@ public abstract class AbstractToolWindowManager implements ProjectComponent { } private void initListeners() { - myProject.getMessageBus().connect(myProject).subscribe(FileEditorManagerListener.FILE_EDITOR_MANAGER, new FileEditorManagerListener() { - @Override - public void fileOpened(@NotNull FileEditorManager source, @NotNull VirtualFile file) { - bindToDesigner(getActiveDesigner()); - } + myConnection = myProject.getMessageBus().connect(myProject); + myConnection.subscribe(FileEditorManagerListener.FILE_EDITOR_MANAGER, myListener); + } - @Override - public void fileClosed(@NotNull FileEditorManager source, @NotNull VirtualFile file) { - ApplicationManager.getApplication().invokeLater(new Runnable() { - @Override - public void run() { - bindToDesigner(getActiveDesigner()); - } - }); - } - - @Override - public void selectionChanged(@NotNull FileEditorManagerEvent event) { - bindToDesigner(getDesigner(event.getNewEditor())); - } - }); + private void removeListeners() { + myConnection.disconnect(); + myConnection = null; } @Nullable @@ -140,6 +176,26 @@ public abstract class AbstractToolWindowManager implements ProjectComponent { protected abstract void updateToolWindow(@Nullable DesignerEditorPanel designer); + protected final void initGearActions() { + if (!ApplicationManager.getApplication().isInternal()) { + return; // XXX: delete after test + } + + DefaultActionGroup group = new DefaultActionGroup(); + group.add(new ToggleAction("In Editor Mode", "Pin/unpin tool window to Designer Editor", null) { + @Override + public boolean isSelected(AnActionEvent e) { + return false; + } + + @Override + public void setSelected(AnActionEvent e, boolean state) { + setEditorMode(true); + } + }); + ((ToolWindowEx)myToolWindow).setAdditionalGearActions(group); + } + @Override public void initComponent() { } @@ -147,4 +203,100 @@ public abstract class AbstractToolWindowManager implements ProjectComponent { @Override public void disposeComponent() { } + + ////////////////////////////////////////////////////////////////////////////////////////// + // + // LightToolWindow + // + ////////////////////////////////////////////////////////////////////////////////////////// + + public final void bind(DesignerEditorPanel designer) { + if (isEditorMode()) { + updateContent(designer, true); + } + } + + public final void dispose(DesignerEditorPanel designer) { + if (isEditorMode()) { + disposeContent(designer); + } + } + + protected final Object getContent(DesignerEditorPanel designer) { + LightToolWindow toolWindow = (LightToolWindow)designer.getClientProperty(getComponentName()); + return toolWindow.getContent(); + } + + protected final void updateContent(DesignerEditorPanel designer, boolean bindToEditor) { + if (bindToEditor) { + designer.putClientProperty(getComponentName(), createContent(designer)); + } + else { + disposeContent(designer); + } + } + + protected abstract LightToolWindow createContent(DesignerEditorPanel designer); + + protected final LightToolWindow createContent(DesignerEditorPanel designer, + LightToolWindowContent content, + String title, + String title2, Icon icon, + JComponent component, + JComponent focusedComponent, + int defaultWidth, + AnAction[] actions) { + return new LightToolWindow(content, + title, + title2, + icon, + component, + focusedComponent, + designer.getContentSplitter(), + myStyle, + this, + myProject, + myPropertiesComponent, + getComponentName(), + defaultWidth, + actions); + } + + protected final void disposeContent(DesignerEditorPanel designer) { + String key = getComponentName(); + LightToolWindow toolWindow = (LightToolWindow)designer.getClientProperty(key); + designer.putClientProperty(key, null); + toolWindow.dispose(); + } + + private void updateContent(boolean bindToEditor) { + for (FileEditor editor : myFileEditorManager.getAllEditors()) { + DesignerEditorPanel designer = getDesigner(editor); + if (designer != null) { + updateContent(designer, bindToEditor); + } + } + } + + public final boolean isEditorMode() { + return myPropertiesComponent.getBoolean(EDITOR_MODE + getComponentName(), false); // XXX: sets true after test + } + + public final void setEditorMode(boolean value) { + if (value) { + removeListeners(); + updateToolWindow(null); + updateContent(true); + } + else { + updateContent(false); + initListeners(); + bindToDesigner(getActiveDesigner()); + } + myPropertiesComponent.setValue(EDITOR_MODE + getComponentName(), Boolean.toString(value)); + } + + final ToolWindow getToolWindow() { + return myToolWindow; + } } \ No newline at end of file diff --git a/plugins/ui-designer-core/src/com/intellij/designer/DesignerToolWindow.java b/plugins/ui-designer-core/src/com/intellij/designer/DesignerToolWindow.java new file mode 100644 index 000000000000..3c8b155b2197 --- /dev/null +++ b/plugins/ui-designer-core/src/com/intellij/designer/DesignerToolWindow.java @@ -0,0 +1,166 @@ +/* + * Copyright 2000-2013 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.designer; + +import com.intellij.designer.componentTree.ComponentTree; +import com.intellij.designer.componentTree.ComponentTreeBuilder; +import com.intellij.designer.designSurface.DesignerEditorPanel; +import com.intellij.designer.propertyTable.PropertyTablePanel; +import com.intellij.designer.propertyTable.RadPropertyTable; +import com.intellij.icons.AllIcons; +import com.intellij.openapi.actionSystem.AnAction; +import com.intellij.openapi.actionSystem.AnActionEvent; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.ui.Splitter; +import com.intellij.openapi.util.Disposer; +import com.intellij.ui.IdeBorderFactory; +import com.intellij.ui.ScrollPaneFactory; +import com.intellij.ui.SideBorder; +import com.intellij.util.ui.tree.TreeUtil; + +import javax.swing.*; +import java.awt.*; +import java.awt.event.ComponentAdapter; +import java.awt.event.ComponentEvent; + +/** + * @author Alexander Lobas + */ +public final class DesignerToolWindow implements LightToolWindowContent { + private final Splitter myToolWindowPanel; + private ComponentTree myComponentTree; + private ComponentTreeBuilder myTreeBuilder; + private PropertyTablePanel myPropertyTablePanel; + + public DesignerToolWindow(Project project, boolean updateOrientation) { + myComponentTree = new ComponentTree(); + JScrollPane treeScrollPane = ScrollPaneFactory.createScrollPane(myComponentTree); + treeScrollPane.setBorder(IdeBorderFactory.createBorder(SideBorder.BOTTOM)); + treeScrollPane.setPreferredSize(new Dimension(250, -1)); + myComponentTree.initQuickFixManager(treeScrollPane.getViewport()); + + myPropertyTablePanel = new PropertyTablePanel(project); + + myToolWindowPanel = new Splitter(true, 0.42f); + myToolWindowPanel.setDividerWidth(3); + myToolWindowPanel.setShowDividerControls(false); + myToolWindowPanel.setShowDividerIcon(false); + myToolWindowPanel.setFirstComponent(treeScrollPane); + myToolWindowPanel.setSecondComponent(myPropertyTablePanel); + + if (updateOrientation) { + myToolWindowPanel.addComponentListener(new ComponentAdapter() { + @Override + public void componentResized(ComponentEvent e) { + Dimension size = myToolWindowPanel.getSize(); + boolean newVertical = size.width < size.height; + if (myToolWindowPanel.getOrientation() != newVertical) { + myToolWindowPanel.setOrientation(newVertical); + } + } + }); + } + } + + void update(DesignerEditorPanel designer) { + clearTreeBuilder(); + myComponentTree.newModel(); + if (designer == null) { + myComponentTree.setDesignerPanel(null); + myPropertyTablePanel.setArea(null, null); + } + else { + myComponentTree.setDesignerPanel(designer); + myTreeBuilder = new ComponentTreeBuilder(myComponentTree, designer); + myPropertyTablePanel.setArea(designer, myTreeBuilder.getTreeArea()); + } + } + + @Override + public void dispose() { + clearTreeBuilder(); + myToolWindowPanel.dispose(); + myComponentTree = null; + myPropertyTablePanel = null; + } + + private void clearTreeBuilder() { + if (myTreeBuilder != null) { + Disposer.dispose(myTreeBuilder); + myTreeBuilder = null; + } + } + + Splitter getToolWindowPanel() { + return myToolWindowPanel; + } + + AnAction[] createActions() { + AnAction expandAll = new AnAction("Expand All", null, AllIcons.Actions.Expandall) { + @Override + public void actionPerformed(AnActionEvent e) { + if (myTreeBuilder != null) { + myTreeBuilder.expandAll(null); + } + } + }; + + AnAction collapseAll = new AnAction("Collapse All", null, AllIcons.Actions.Collapseall) { + @Override + public void actionPerformed(AnActionEvent e) { + if (myTreeBuilder != null) { + TreeUtil.collapseAll(myComponentTree, 1); + } + } + }; + + return new AnAction[]{expandAll, collapseAll}; + } + + public ComponentTree getComponentTree() { + return myComponentTree; + } + + public RadPropertyTable getPropertyTable() { + return myPropertyTablePanel.getPropertyTable(); + } + + public void expandFromState() { + if (myTreeBuilder != null) { + myTreeBuilder.expandFromState(); + } + } + + public void refresh(boolean updateProperties) { + if (myTreeBuilder != null) { + if (updateProperties) { + myTreeBuilder.selectFromSurface(); + } + else { + myTreeBuilder.queueUpdate(); + } + } + } + + public void updateInspections() { + if (myComponentTree != null) { + myComponentTree.updateInspections(); + } + if (myPropertyTablePanel != null) { + myPropertyTablePanel.getPropertyTable().updateInspections(); + } + } +} \ No newline at end of file diff --git a/plugins/ui-designer-core/src/com/intellij/designer/DesignerToolWindowManager.java b/plugins/ui-designer-core/src/com/intellij/designer/DesignerToolWindowManager.java index 10d2aefe92a3..fce18f32d453 100644 --- a/plugins/ui-designer-core/src/com/intellij/designer/DesignerToolWindowManager.java +++ b/plugins/ui-designer-core/src/com/intellij/designer/DesignerToolWindowManager.java @@ -15,117 +15,82 @@ */ package com.intellij.designer; -import com.intellij.designer.componentTree.ComponentTree; -import com.intellij.designer.componentTree.ComponentTreeBuilder; import com.intellij.designer.designSurface.DesignerEditorPanel; -import com.intellij.designer.propertyTable.PropertyTablePanel; -import com.intellij.designer.propertyTable.RadPropertyTable; -import com.intellij.icons.AllIcons; -import com.intellij.openapi.actionSystem.AnAction; -import com.intellij.openapi.actionSystem.AnActionEvent; import com.intellij.openapi.fileEditor.FileEditorManager; import com.intellij.openapi.project.Project; -import com.intellij.openapi.ui.Splitter; -import com.intellij.openapi.util.Disposer; import com.intellij.openapi.wm.ToolWindowAnchor; import com.intellij.openapi.wm.ToolWindowManager; import com.intellij.openapi.wm.ex.ToolWindowEx; import com.intellij.openapi.wm.impl.content.ToolWindowContentUi; -import com.intellij.ui.IdeBorderFactory; -import com.intellij.ui.ScrollPaneFactory; import com.intellij.ui.SideBorder; import com.intellij.ui.content.Content; import com.intellij.ui.content.ContentManager; -import com.intellij.util.ui.tree.TreeUtil; import icons.UIDesignerNewIcons; -import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import javax.swing.*; -import java.awt.*; -import java.awt.event.ComponentAdapter; -import java.awt.event.ComponentEvent; - /** * @author Alexander Lobas */ public final class DesignerToolWindowManager extends AbstractToolWindowManager { - private Splitter myToolWindowPanel; - private ComponentTree myComponentTree; - private ComponentTreeBuilder myTreeBuilder; - private PropertyTablePanel myPropertyTablePanel; + private final DesignerToolWindow myToolWindowContent; + + ////////////////////////////////////////////////////////////////////////////////////////// + // + // Public Access + // + ////////////////////////////////////////////////////////////////////////////////////////// public DesignerToolWindowManager(Project project, FileEditorManager fileEditorManager) { - super(project, fileEditorManager); + super(project, fileEditorManager, SideBorder.LEFT); + myToolWindowContent = new DesignerToolWindow(project, true); } - - @Override - public void disposeComponent() { - clearTreeBuilder(); - myComponentTree = null; - myPropertyTablePanel = null; - } - - private void clearTreeBuilder() { - if (myTreeBuilder != null) { - Disposer.dispose(myTreeBuilder); - myTreeBuilder = null; + public static DesignerToolWindow getInstance(DesignerEditorPanel designer) { + DesignerToolWindowManager manager = getInstance(designer.getProject()); + if (manager.isEditorMode()) { + return (DesignerToolWindow)manager.getContent(designer); } + return manager.myToolWindowContent; } + public static DesignerToolWindowManager getInstance(Project project) { return project.getComponent(DesignerToolWindowManager.class); } - public ComponentTree getComponentTree() { - return myComponentTree; - } + ////////////////////////////////////////////////////////////////////////////////////////// + // + // Impl + // + ////////////////////////////////////////////////////////////////////////////////////////// - public RadPropertyTable getPropertyTable() { - return myPropertyTablePanel.getPropertyTable(); - } + @Override + protected LightToolWindow createContent(DesignerEditorPanel designer) { + DesignerToolWindow toolWindowContent = new DesignerToolWindow(myProject, false); + toolWindowContent.update(designer); - public void expandFromState() { - if (myTreeBuilder != null) { - myTreeBuilder.expandFromState(); - } - } + String title = DesignerBundle.message("designer.toolwindow.title"); - public void refresh(boolean updateProperties) { - if (myTreeBuilder != null) { - if (updateProperties) { - myTreeBuilder.selectFromSurface(); - } - else { - myTreeBuilder.queueUpdate(); - } - } - } - - public void updateInspections() { - if (myComponentTree != null) { - myComponentTree.updateInspections(); - } - if (myPropertyTablePanel != null) { - myPropertyTablePanel.getPropertyTable().updateInspections(); - } + return createContent(designer, + toolWindowContent, + title, + title, + UIDesignerNewIcons.ToolWindow, + toolWindowContent.getToolWindowPanel(), + toolWindowContent.getComponentTree(), + 320, + toolWindowContent.createActions()); } @Override protected void updateToolWindow(@Nullable DesignerEditorPanel designer) { - clearTreeBuilder(); - myComponentTree.newModel(); + myToolWindowContent.update(designer); + if (designer == null) { - myComponentTree.setDesignerPanel(null); - myPropertyTablePanel.setArea(null, null); myToolWindow.setAvailable(false, null); } else { - myComponentTree.setDesignerPanel(designer); - myTreeBuilder = new ComponentTreeBuilder(myComponentTree, designer); - myPropertyTablePanel.setArea(designer, myTreeBuilder.getTreeArea()); myToolWindow.setAvailable(true, null); myToolWindow.show(null); } @@ -133,28 +98,6 @@ public final class DesignerToolWindowManager extends AbstractToolWindowManager { @Override protected void initToolWindow() { - myComponentTree = new ComponentTree(); - JScrollPane treeScrollPane = ScrollPaneFactory.createScrollPane(myComponentTree); - treeScrollPane.setBorder(IdeBorderFactory.createBorder(SideBorder.BOTTOM)); - treeScrollPane.setPreferredSize(new Dimension(250, -1)); - myComponentTree.initQuickFixManager(treeScrollPane.getViewport()); - - myPropertyTablePanel = new PropertyTablePanel(myProject); - - myToolWindowPanel = new Splitter(true, 0.42f); - myToolWindowPanel.setFirstComponent(treeScrollPane); - myToolWindowPanel.setSecondComponent(myPropertyTablePanel); - myToolWindowPanel.addComponentListener(new ComponentAdapter() { - @Override - public void componentResized(ComponentEvent e) { - Dimension size = myToolWindowPanel.getSize(); - boolean newVertical = size.width < size.height; - if (myToolWindowPanel.getOrientation() != newVertical) { - myToolWindowPanel.setOrientation(newVertical); - } - } - }); - DesignerCustomizations customization = getCustomizations(); ToolWindowAnchor anchor = customization != null ? customization.getStructureAnchor() : ToolWindowAnchor.LEFT; @@ -163,42 +106,26 @@ public final class DesignerToolWindowManager extends AbstractToolWindowManager { myToolWindow.setIcon(UIDesignerNewIcons.ToolWindow); myToolWindow.getComponent().putClientProperty(ToolWindowContentUi.HIDE_ID_LABEL, "true"); - ((ToolWindowEx)myToolWindow).setTitleActions(createActions()); + ((ToolWindowEx)myToolWindow).setTitleActions(myToolWindowContent.createActions()); + initGearActions(); ContentManager contentManager = myToolWindow.getContentManager(); Content content = - contentManager.getFactory().createContent(myToolWindowPanel, DesignerBundle.message("designer.toolwindow.title"), false); + contentManager.getFactory() + .createContent(myToolWindowContent.getToolWindowPanel(), DesignerBundle.message("designer.toolwindow.title"), false); content.setCloseable(false); - content.setPreferredFocusableComponent(myComponentTree); + content.setPreferredFocusableComponent(myToolWindowContent.getComponentTree()); contentManager.addContent(content); contentManager.setSelectedContent(content, true); myToolWindow.setAvailable(false, null); } - private AnAction[] createActions() { - AnAction expandAll = new AnAction("Expand All", null, AllIcons.Actions.Expandall) { - @Override - public void actionPerformed(AnActionEvent e) { - if (myTreeBuilder != null) { - myTreeBuilder.expandAll(null); - } - } - }; - - AnAction collapseAll = new AnAction("Collapse All", null, AllIcons.Actions.Collapseall) { - @Override - public void actionPerformed(AnActionEvent e) { - if (myTreeBuilder != null) { - TreeUtil.collapseAll(myComponentTree, 1); - } - } - }; - - return new AnAction[]{expandAll, collapseAll}; + @Override + public void disposeComponent() { + myToolWindowContent.dispose(); } @NotNull - @NonNls @Override public String getComponentName() { return "UIDesignerToolWindowManager2"; diff --git a/plugins/ui-designer-core/src/com/intellij/designer/LightToolWindow.java b/plugins/ui-designer-core/src/com/intellij/designer/LightToolWindow.java new file mode 100644 index 000000000000..9b6269d372e0 --- /dev/null +++ b/plugins/ui-designer-core/src/com/intellij/designer/LightToolWindow.java @@ -0,0 +1,527 @@ +/* + * Copyright 2000-2013 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.designer; + +import com.intellij.icons.AllIcons; +import com.intellij.ide.util.PropertiesComponent; +import com.intellij.openapi.actionSystem.*; +import com.intellij.openapi.actionSystem.impl.ActionManagerImpl; +import com.intellij.openapi.actionSystem.impl.MenuItemPresentationFactory; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.ui.ThreeComponentsSplitter; +import com.intellij.openapi.util.SystemInfo; +import com.intellij.openapi.wm.*; +import com.intellij.openapi.wm.ex.ToolWindowEx; +import com.intellij.openapi.wm.impl.AnchoredButton; +import com.intellij.openapi.wm.impl.InternalDecorator; +import com.intellij.openapi.wm.impl.StripeButtonUI; +import com.intellij.openapi.wm.impl.content.ToolWindowContentUi; +import com.intellij.ui.*; +import com.intellij.ui.components.panels.Wrapper; +import com.intellij.ui.tabs.TabsUtil; +import com.intellij.util.ui.EmptyIcon; +import com.intellij.util.ui.UIUtil; + +import javax.swing.*; +import java.awt.*; +import java.awt.event.*; +import java.awt.image.BufferedImage; + +/** + * @author Alexander Lobas + */ +public class LightToolWindow extends JPanel { + private final LightToolWindowContent myContent; + private final JComponent myFocusedComponent; + private final ThreeComponentsSplitter myContentSplitter; + private final Project myProject; + private final AbstractToolWindowManager myManager; + private final PropertiesComponent myPropertiesComponent; + private final int myStyle; + private boolean myShowContent; + private final String myShowStateKey; + private int myCurrentWidth; + private final String myWidthKey; + private final JPanel myMinimizeComponent; + private final AnchoredButton myMinimizeButton; + + private final ToggleInEditorModeAction myToggleInEditorModeAction = new ToggleInEditorModeAction(); + private final TogglePinnedModeAction myToggleAutoHideModeAction = new TogglePinnedModeAction(); + private final ToggleDockModeAction myToggleDockModeAction = new ToggleDockModeAction(); + private final ToggleFloatingModeAction myToggleFloatingModeAction = new ToggleFloatingModeAction(); + private final ToggleSideModeAction myToggleSideModeAction = new ToggleSideModeAction(); + + private final ComponentListener myWidthListener = new ComponentAdapter() { + @Override + public void componentResized(ComponentEvent e) { + int width = myStyle == SideBorder.LEFT ? myContentSplitter.getFirstSize() : myContentSplitter.getLastSize(); + if (width > 0 && width != myCurrentWidth) { + myPropertiesComponent.setValue(myWidthKey, Integer.toString(width)); + } + } + }; + + public LightToolWindow(LightToolWindowContent content, + String title, + String title2, + Icon icon, + JComponent component, + JComponent focusedComponent, + ThreeComponentsSplitter contentSplitter, + int style, + AbstractToolWindowManager manager, + Project project, + PropertiesComponent propertiesComponent, + String key, + int defaultWidth, + AnAction[] actions) { + super(new BorderLayout()); + myContent = content; + myFocusedComponent = focusedComponent; + myContentSplitter = contentSplitter; + myProject = project; + myManager = manager; + myPropertiesComponent = propertiesComponent; + setBorder(IdeBorderFactory.createBorder((style == SideBorder.LEFT ? SideBorder.RIGHT : SideBorder.LEFT) | SideBorder.BOTTOM)); + + myStyle = style; + myShowStateKey = AbstractToolWindowManager.EDITOR_MODE + key + ".SHOW"; + myWidthKey = AbstractToolWindowManager.EDITOR_MODE + key + ".WIDTH"; + + HeaderPanel header = new HeaderPanel(); + header.setLayout(new BorderLayout()); + add(header, BorderLayout.NORTH); + + JLabel titleLabel = new JLabel(title); + titleLabel.setBorder(IdeBorderFactory.createEmptyBorder(2, 5, 2, 10)); + titleLabel.setFont(UIUtil.getLabelFont(UIUtil.FontSize.SMALL)); + header.add(titleLabel, BorderLayout.CENTER); + + JPanel actionPanel = new JPanel(new FlowLayout(FlowLayout.CENTER, 5, 0)); + actionPanel.setBorder(IdeBorderFactory.createEmptyBorder(2, 0, 2, 0)); + actionPanel.setOpaque(false); + header.add(actionPanel, BorderLayout.EAST); + + if (actions != null) { + for (AnAction action : actions) { + addAction(actionPanel, action); + } + + actionPanel.add(new JLabel(AllIcons.General.Divider)); + } + + addAction(actionPanel, new GearAction()); + addAction(actionPanel, new HideAction()); + + JPanel contentWrapper = new JPanel(new BorderLayout()); + contentWrapper.setBorder(IdeBorderFactory.createBorder(SideBorder.TOP)); + contentWrapper.add(component, BorderLayout.CENTER); + + add(contentWrapper, BorderLayout.CENTER); + + addMouseListener(new MouseAdapter() { + public void mouseReleased(final MouseEvent e) { + IdeFocusManager.getInstance(myProject).requestFocus(myFocusedComponent, true); + } + }); + + addMouseListener(new PopupHandler() { + public void invokePopup(Component component, int x, int y) { + showGearPopup(component, x, y); + } + }); + + myMinimizeButton = new AnchoredButton(title2, icon) { + @Override + public void updateUI() { + setUI(StripeButtonUI.createUI(this)); + setFont(UIUtil.getLabelFont(UIUtil.FontSize.SMALL)); + } + + @Override + public int getMnemonic2() { + return 0; + } + + @Override + public ToolWindowAnchor getAnchor() { + return myStyle == SideBorder.LEFT ? ToolWindowAnchor.LEFT : ToolWindowAnchor.RIGHT; + } + }; + myMinimizeButton.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + myMinimizeButton.setSelected(false); + updateContent(true, true); + } + }); + myMinimizeButton.setBorder(BorderFactory.createEmptyBorder(5, 5, 0, 5)); + myMinimizeButton.setFocusable(false); + + myMinimizeButton.setRolloverEnabled(true); + myMinimizeButton.setOpaque(false); + + myMinimizeComponent = new JPanel() { + @Override + public void doLayout() { + Dimension size = myMinimizeButton.getPreferredSize(); + myMinimizeButton.setBounds(0, 0, getWidth(), size.height); + } + }; + myMinimizeComponent.setBorder(IdeBorderFactory.createBorder(style == SideBorder.LEFT ? SideBorder.RIGHT : SideBorder.LEFT)); + myMinimizeComponent.add(myMinimizeButton); + + configureWidth(defaultWidth); + updateContent(myPropertiesComponent.getBoolean(myShowStateKey, true), false); + } + + private void configureWidth(int defaultWidth) { + myCurrentWidth = myPropertiesComponent.getOrInitInt(myWidthKey, defaultWidth); + + if (myStyle == SideBorder.LEFT) { + myContentSplitter.setFirstSize(myCurrentWidth); + } + else { + myContentSplitter.setLastSize(myCurrentWidth); + } + + myContentSplitter.getInnerComponent().addComponentListener(myWidthListener); + } + + private void updateContent(boolean show, boolean flag) { + myShowContent = show; + + String key = myStyle == SideBorder.LEFT ? "left" : "right"; + + JComponent minimizeParent = myContentSplitter.getInnerComponent(); + + if (show) { + minimizeParent.putClientProperty(key, null); + minimizeParent.remove(myMinimizeComponent); + } + + setContentComponent(show ? this : null); + + if (!show) { + minimizeParent.putClientProperty(key, myMinimizeComponent); + minimizeParent.add(myMinimizeComponent); + } + + minimizeParent.revalidate(); + + if (flag) { + myPropertiesComponent.setValue(myShowStateKey, Boolean.toString(show)); + } + } + + private void setContentComponent(JComponent component) { + if (myStyle == SideBorder.LEFT) { + myContentSplitter.setFirstComponent(component); + } + else { + myContentSplitter.setLastComponent(component); + } + } + + public void dispose() { + JComponent minimizeParent = myContentSplitter.getInnerComponent(); + minimizeParent.removeComponentListener(myWidthListener); + + setContentComponent(null); + myContent.dispose(); + + if (!myShowContent) { + minimizeParent.putClientProperty(myStyle == SideBorder.LEFT ? "left" : "right", null); + minimizeParent.remove(myMinimizeComponent); + minimizeParent.revalidate(); + } + } + + public Object getContent() { + return myContent; + } + + private boolean isActive() { + IdeFocusManager fm = IdeFocusManager.getInstance(myProject); + Component component = fm.getFocusedDescendantFor(this); + if (component != null) { + return true; + } + Component owner = fm.getLastFocusedFor(WindowManager.getInstance().getIdeFrame(myProject)); + return owner != null && SwingUtilities.isDescendingFrom(owner, this); + } + + private void addAction(JPanel actionPanel, AnAction action) { + actionPanel.add(new ActionButton(action)); + } + + private DefaultActionGroup createGearPopupGroup() { + DefaultActionGroup group = new DefaultActionGroup(); + + group.add(myToggleInEditorModeAction); + group.addSeparator(); + + ToolWindowType type = myManager.getToolWindow().getType(); + if (type == ToolWindowType.DOCKED) { + group.add(myToggleAutoHideModeAction); + group.add(myToggleDockModeAction); + group.add(myToggleFloatingModeAction); + group.add(myToggleSideModeAction); + } + else if (type == ToolWindowType.FLOATING) { + group.add(myToggleAutoHideModeAction); + group.add(myToggleFloatingModeAction); + } + else if (type == ToolWindowType.SLIDING) { + group.add(myToggleDockModeAction); + group.add(myToggleFloatingModeAction); + } + + return group; + } + + private void showGearPopup(Component component, int x, int y) { + ActionPopupMenu popupMenu = + ((ActionManagerImpl)ActionManager.getInstance()) + .createActionPopupMenu(ToolWindowContentUi.POPUP_PLACE, createGearPopupGroup(), new MenuItemPresentationFactory(true)); + popupMenu.getComponent().show(component, x, y); + } + + private class GearAction extends AnAction { + public GearAction() { + Presentation presentation = getTemplatePresentation(); + presentation.setIcon(AllIcons.General.Gear); + presentation.setHoveredIcon(AllIcons.General.GearHover); + } + + @Override + public void actionPerformed(AnActionEvent e) { + int x = 0; + int y = 0; + InputEvent inputEvent = e.getInputEvent(); + if (inputEvent instanceof MouseEvent) { + x = ((MouseEvent)inputEvent).getX(); + y = ((MouseEvent)inputEvent).getY(); + } + + showGearPopup(inputEvent.getComponent(), x, y); + } + } + + private class HideAction extends AnAction { + public HideAction() { + Presentation presentation = getTemplatePresentation(); + presentation.setText(UIBundle.message("tool.window.hide.action.name")); + if (myStyle == SideBorder.LEFT) { + presentation.setIcon(AllIcons.General.HideLeftPart); + presentation.setHoveredIcon(AllIcons.General.HideLeftHover); + } + else { + presentation.setIcon(AllIcons.General.HideRightPart); + presentation.setHoveredIcon(AllIcons.General.HideRightHover); + } + } + + @Override + public void actionPerformed(AnActionEvent e) { + updateContent(false, true); + } + } + + private class ToggleInEditorModeAction extends ToggleAction { + public ToggleInEditorModeAction() { + super("In Editor Mode", "Pin/unpin tool window to Designer Editor", null); + } + + @Override + public boolean isSelected(AnActionEvent e) { + return true; + } + + @Override + public void setSelected(AnActionEvent e, boolean state) { + myManager.setEditorMode(false); + } + } + + private class TogglePinnedModeAction extends ToggleAction { + public TogglePinnedModeAction() { + copyFrom(ActionManager.getInstance().getAction(InternalDecorator.TOGGLE_PINNED_MODE_ACTION_ID)); + } + + @Override + public boolean isSelected(AnActionEvent e) { + return !myManager.getToolWindow().isAutoHide(); + } + + @Override + public void setSelected(AnActionEvent e, boolean state) { + ToolWindow window = myManager.getToolWindow(); + window.setAutoHide(!window.isAutoHide()); + myManager.setEditorMode(false); + } + } + + private class ToggleDockModeAction extends ToggleAction { + public ToggleDockModeAction() { + copyFrom(ActionManager.getInstance().getAction(InternalDecorator.TOGGLE_DOCK_MODE_ACTION_ID)); + } + + @Override + public boolean isSelected(AnActionEvent e) { + return myManager.getToolWindow().getType() == ToolWindowType.DOCKED; + } + + @Override + public void setSelected(AnActionEvent e, boolean state) { + ToolWindow window = myManager.getToolWindow(); + ToolWindowType type = window.getType(); + if (type == ToolWindowType.DOCKED) { + window.setType(ToolWindowType.SLIDING, null); + } + else if (type == ToolWindowType.SLIDING) { + window.setType(ToolWindowType.DOCKED, null); + } + myManager.setEditorMode(false); + } + } + + private class ToggleFloatingModeAction extends ToggleAction { + public ToggleFloatingModeAction() { + copyFrom(ActionManager.getInstance().getAction(InternalDecorator.TOGGLE_FLOATING_MODE_ACTION_ID)); + } + + @Override + public boolean isSelected(AnActionEvent e) { + return myManager.getToolWindow().getType() == ToolWindowType.FLOATING; + } + + @Override + public void setSelected(AnActionEvent e, boolean state) { + ToolWindow window = myManager.getToolWindow(); + ToolWindowType type = window.getType(); + if (type == ToolWindowType.FLOATING) { + window.setType(((ToolWindowEx)window).getInternalType(), null); + } + else { + window.setType(ToolWindowType.FLOATING, null); + } + myManager.setEditorMode(false); + } + } + + private class ToggleSideModeAction extends ToggleAction { + public ToggleSideModeAction() { + copyFrom(ActionManager.getInstance().getAction(InternalDecorator.TOGGLE_SIDE_MODE_ACTION_ID)); + } + + @Override + public boolean isSelected(AnActionEvent e) { + return myManager.getToolWindow().isSplitMode(); + } + + @Override + public void setSelected(AnActionEvent e, boolean state) { + myManager.getToolWindow().setSplitMode(state, null); + myManager.setEditorMode(false); + } + } + + private class ActionButton extends Wrapper implements ActionListener { + private final AnAction myAction; + + public ActionButton(AnAction action) { + myAction = action; + + Presentation presentation = action.getTemplatePresentation(); + InplaceButton button = new InplaceButton(AnAction.createTooltipText(presentation.getText(), action), EmptyIcon.ICON_16, this) { + @Override + public boolean isActive() { + return LightToolWindow.this.isActive(); + } + }; + button.setHoveringEnabled(!SystemInfo.isMac); + setContent(button); + + Icon icon = presentation.getIcon(); + Icon hoveredIcon = presentation.getHoveredIcon(); + button.setIcons(icon, icon, hoveredIcon == null ? icon : hoveredIcon); + } + + @Override + public void actionPerformed(ActionEvent e) { + InputEvent inputEvent = e.getSource() instanceof InputEvent ? (InputEvent)e.getSource() : null; + myAction.actionPerformed(AnActionEvent.createFromInputEvent(myAction, inputEvent, ActionPlaces.UNKNOWN)); + } + } + + private class HeaderPanel extends JPanel { + private BufferedImage myActiveImage; + private BufferedImage myImage; + + @Override + public Dimension getPreferredSize() { + Dimension size = super.getPreferredSize(); + return new Dimension(size.width, TabsUtil.getTabsHeight()); + } + + @Override + public Dimension getMinimumSize() { + Dimension size = super.getMinimumSize(); + return new Dimension(size.width, TabsUtil.getTabsHeight()); + } + + @Override + protected void paintComponent(Graphics g) { + Rectangle r = getBounds(); + + Image image; + if (isActive()) { + if (myActiveImage == null || myActiveImage.getHeight() != r.height) { + myActiveImage = drawToBuffer(true, r.height); + } + image = myActiveImage; + } + else { + if (myImage == null || myImage.getHeight() != r.height) { + myImage = drawToBuffer(false, r.height); + } + image = myImage; + } + + Graphics2D g2d = (Graphics2D)g; + Rectangle clipBounds = g2d.getClip().getBounds(); + for (int x = clipBounds.x; x < clipBounds.x + clipBounds.width; x += 150) { + g2d.drawImage(image, x, 0, null); + } + } + + protected boolean isActive() { + return LightToolWindow.this.isActive(); + } + } + + private static BufferedImage drawToBuffer(boolean active, int height) { + final int width = 150; + + BufferedImage image = UIUtil.createImage(width, height, BufferedImage.TYPE_INT_ARGB); + Graphics2D g = image.createGraphics(); + UIUtil.drawHeader(g, 0, width, height, active, true, false, false); + g.dispose(); + + return image; + } +} \ No newline at end of file diff --git a/plugins/ui-designer-core/src/com/intellij/designer/LightToolWindowContent.java b/plugins/ui-designer-core/src/com/intellij/designer/LightToolWindowContent.java new file mode 100644 index 000000000000..c3e00f7236f5 --- /dev/null +++ b/plugins/ui-designer-core/src/com/intellij/designer/LightToolWindowContent.java @@ -0,0 +1,23 @@ +/* + * Copyright 2000-2013 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.designer; + +/** + * @author Alexander Lobas + */ +public interface LightToolWindowContent { + void dispose(); +} \ No newline at end of file diff --git a/plugins/ui-designer-core/src/com/intellij/designer/designSurface/DesignerEditorPanel.java b/plugins/ui-designer-core/src/com/intellij/designer/designSurface/DesignerEditorPanel.java index 96411c342b2d..2a6298654002 100644 --- a/plugins/ui-designer-core/src/com/intellij/designer/designSurface/DesignerEditorPanel.java +++ b/plugins/ui-designer-core/src/com/intellij/designer/designSurface/DesignerEditorPanel.java @@ -15,10 +15,7 @@ */ package com.intellij.designer.designSurface; -import com.intellij.designer.DesignerEditor; -import com.intellij.designer.DesignerEditorState; -import com.intellij.designer.DesignerToolWindowManager; -import com.intellij.designer.ModuleProvider; +import com.intellij.designer.*; import com.intellij.designer.actions.AbstractComboBoxAction; import com.intellij.designer.actions.DesignerActionPanel; import com.intellij.designer.componentTree.TreeComponentDecorator; @@ -42,9 +39,11 @@ import com.intellij.openapi.module.ModuleUtilCore; import com.intellij.openapi.progress.ProgressIndicator; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.Messages; +import com.intellij.openapi.ui.ThreeComponentsSplitter; import com.intellij.openapi.ui.VerticalFlowLayout; import com.intellij.openapi.util.Disposer; import com.intellij.openapi.util.Pair; +import com.intellij.openapi.util.registry.Registry; import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.ui.HyperlinkLabel; @@ -97,6 +96,7 @@ public abstract class DesignerEditorPanel extends JPanel implements DataProvider protected final VirtualFile myFile; private final CardLayout myLayout = new CardLayout(); + private final ThreeComponentsSplitter myContentSplitter = new ThreeComponentsSplitter(); private final JPanel myPanel = new JPanel(myLayout); private JPanel myDesignerCard; @@ -144,15 +144,36 @@ public abstract class DesignerEditorPanel extends JPanel implements DataProvider myModule = module; myFile = file; - setLayout(new FillLayout()); - createDesignerCard(); - createErrorCard(); - createProgressPanel(); + initUI(); myToolProvider.loadDefaultTool(); } + private void initUI() { + setLayout(new BorderLayout()); + + myContentSplitter.setDividerWidth(0); + myContentSplitter.setDividerMouseZoneSize(Registry.intValue("ide.splitter.mouseZone")); + add(myContentSplitter, BorderLayout.CENTER); + + createDesignerCard(); + createErrorCard(); + createProgressPanel(); + + UIUtil.invokeLaterIfNeeded(new Runnable() { + @Override + public void run() { + DesignerEditorPanel designer = DesignerEditorPanel.this; + DesignerToolWindowManager.getInstance(myProject).bind(designer); + PaletteToolWindowManager.getInstance(myProject).bind(designer); + } + }); + } + private void createDesignerCard() { + JPanel panel = new JPanel(new FillLayout()); + myContentSplitter.setInnerComponent(panel); + myLayeredPane = new MyLayeredPane(); mySurfaceArea = createEditableArea(); @@ -206,8 +227,8 @@ public abstract class DesignerEditorPanel extends JPanel implements DataProvider myActionPanel = createActionPanel(); myWarnAction = new FixableMessageAction(); - add(myActionPanel.getToolbarComponent()); - add(myPanel); + panel.add(myActionPanel.getToolbarComponent()); + panel.add(myPanel); myDesignerCard = content; myPanel.add(myDesignerCard, DESIGNER_CARD); @@ -220,6 +241,10 @@ public abstract class DesignerEditorPanel extends JPanel implements DataProvider }); } + public final ThreeComponentsSplitter getContentSplitter() { + return myContentSplitter; + } + protected EditableArea createEditableArea() { return new DesignerEditableArea(); } @@ -351,7 +376,7 @@ public abstract class DesignerEditorPanel extends JPanel implements DataProvider myErrorPanel.revalidate(); myLayout.show(myPanel, ERROR_CARD); - DesignerToolWindowManager.getInstance(getProject()).refresh(true); + DesignerToolWindowManager.getInstance(this).refresh(true); repaint(); } @@ -575,7 +600,7 @@ public abstract class DesignerEditorPanel extends JPanel implements DataProvider } protected void restoreState() { - DesignerToolWindowManager toolManager = DesignerToolWindowManager.getInstance(getProject()); + DesignerToolWindow toolManager = DesignerToolWindowManager.getInstance(this); if (myExpandedState != null) { List expanded = new ArrayList(); @@ -705,6 +730,9 @@ public abstract class DesignerEditorPanel extends JPanel implements DataProvider public void dispose() { Disposer.dispose(myProgressIcon); + DesignerToolWindowManager.getInstance(myProject).dispose(this); + PaletteToolWindowManager.getInstance(myProject).dispose(this); + Disposer.dispose(myContentSplitter); } @Nullable @@ -780,6 +808,8 @@ public abstract class DesignerEditorPanel extends JPanel implements DataProvider // ////////////////////////////////////////////////////////////////////////////////////////// + private static final int MINIMIZE_WIDTH = 25; + private static final class FillLayout implements LayoutManager2 { @Override public void addLayoutComponent(Component comp, Object constraints) { @@ -817,7 +847,15 @@ public abstract class DesignerEditorPanel extends JPanel implements DataProvider Component toolbar = parent.getComponent(0); Dimension toolbarSize = toolbar.isVisible() ? toolbar.getPreferredSize() : new Dimension(); Dimension contentSize = parent.getComponent(1).getPreferredSize(); - return new Dimension(Math.max(toolbarSize.width, contentSize.width), toolbarSize.height + contentSize.height); + int extraWidth = 0; + JComponent jParent = (JComponent)parent; + if (jParent.getClientProperty("left") != null) { + extraWidth += MINIMIZE_WIDTH; + } + if (jParent.getClientProperty("right") != null) { + extraWidth += MINIMIZE_WIDTH; + } + return new Dimension(Math.max(toolbarSize.width, contentSize.width + extraWidth), toolbarSize.height + contentSize.height); } @Override @@ -825,17 +863,45 @@ public abstract class DesignerEditorPanel extends JPanel implements DataProvider Component toolbar = parent.getComponent(0); Dimension toolbarSize = toolbar.isVisible() ? toolbar.getMinimumSize() : new Dimension(); Dimension contentSize = parent.getComponent(1).getMinimumSize(); - return new Dimension(Math.max(toolbarSize.width, contentSize.width), toolbarSize.height + contentSize.height); + int extraWidth = 0; + JComponent jParent = (JComponent)parent; + if (jParent.getClientProperty("left") != null) { + extraWidth += MINIMIZE_WIDTH; + } + if (jParent.getClientProperty("right") != null) { + extraWidth += MINIMIZE_WIDTH; + } + return new Dimension(Math.max(toolbarSize.width, contentSize.width + extraWidth), toolbarSize.height + contentSize.height); } @Override public void layoutContainer(Container parent) { - int width = parent.getWidth(); + int leftWidth = 0; + int rightWidth = 0; + JComponent jParent = (JComponent)parent; + JComponent left = (JComponent)jParent.getClientProperty("left"); + if (left != null) { + leftWidth = MINIMIZE_WIDTH; + } + JComponent right = (JComponent)jParent.getClientProperty("right"); + if (right != null) { + rightWidth = MINIMIZE_WIDTH; + } + int extraWidth = leftWidth + rightWidth; + + int width = parent.getWidth() - extraWidth; int height = parent.getHeight(); Component toolbar = parent.getComponent(0); Dimension toolbarSize = toolbar.isVisible() ? toolbar.getPreferredSize() : new Dimension(); - toolbar.setBounds(0, 0, width, toolbarSize.height); - parent.getComponent(1).setBounds(0, toolbarSize.height, width, height - toolbarSize.height); + toolbar.setBounds(leftWidth, 0, width, toolbarSize.height); + parent.getComponent(1).setBounds(leftWidth, toolbarSize.height, width, height - toolbarSize.height); + + if (left != null) { + left.setBounds(0, 0, leftWidth, height); + } + if (right != null) { + right.setBounds(width + leftWidth, 0, rightWidth, height); + } } } @@ -943,7 +1009,7 @@ public abstract class DesignerEditorPanel extends JPanel implements DataProvider @Override public void setActiveTool(InputTool tool) { if (getActiveTool() instanceof CreationTool && !(tool instanceof CreationTool)) { - PaletteToolWindowManager.getInstance(getProject()).clearActiveItem(); + PaletteToolWindowManager.getInstance(DesignerEditorPanel.this).clearActiveItem(); } if (!(tool instanceof SelectionTool)) { hideInspections(); diff --git a/plugins/ui-designer-core/src/com/intellij/designer/inspection/DesignerHighlightingPass.java b/plugins/ui-designer-core/src/com/intellij/designer/inspection/DesignerHighlightingPass.java index 20ef0504d9e8..fc3fe23b02a4 100644 --- a/plugins/ui-designer-core/src/com/intellij/designer/inspection/DesignerHighlightingPass.java +++ b/plugins/ui-designer-core/src/com/intellij/designer/inspection/DesignerHighlightingPass.java @@ -38,7 +38,7 @@ public final class DesignerHighlightingPass implements HighlightingPass { @Override public void applyInformationToEditor() { - DesignerToolWindowManager.getInstance(myDesigner.getProject()).updateInspections(); + DesignerToolWindowManager.getInstance(myDesigner).updateInspections(); myDesigner.updateInspections(); } } \ No newline at end of file diff --git a/plugins/ui-designer-core/src/com/intellij/designer/palette/PalettePanel.java b/plugins/ui-designer-core/src/com/intellij/designer/palette/PalettePanel.java index a7d2621fa9b8..67bfd77753a0 100644 --- a/plugins/ui-designer-core/src/com/intellij/designer/palette/PalettePanel.java +++ b/plugins/ui-designer-core/src/com/intellij/designer/palette/PalettePanel.java @@ -15,6 +15,7 @@ */ package com.intellij.designer.palette; +import com.intellij.designer.LightToolWindowContent; import com.intellij.designer.designSurface.DesignerEditorPanel; import com.intellij.openapi.actionSystem.*; import com.intellij.openapi.application.ApplicationManager; @@ -41,7 +42,7 @@ import java.util.List; /** * @author Alexander Lobas */ -public class PalettePanel extends JPanel implements DataProvider { +public class PalettePanel extends JPanel implements DataProvider, LightToolWindowContent { private final JPanel myPaletteContainer = new PaletteContainer(); private List myGroupComponents = Collections.emptyList(); private List myItemsComponents = Collections.emptyList(); @@ -95,6 +96,7 @@ public class PalettePanel extends JPanel implements DataProvider { } } + @Override public void dispose() { if (!ApplicationManager.getApplication().isHeadlessEnvironment()) { DragSource.getDefaultDragSource().removeDragSourceListener(myDragSourceListener); @@ -123,6 +125,10 @@ public class PalettePanel extends JPanel implements DataProvider { } } + public void refresh() { + repaint(); + } + public boolean isEmpty() { return myGroups.isEmpty(); } diff --git a/plugins/ui-designer-core/src/com/intellij/designer/palette/PaletteToolWindowManager.java b/plugins/ui-designer-core/src/com/intellij/designer/palette/PaletteToolWindowManager.java index a10ea8c3f048..4568e0c0b645 100644 --- a/plugins/ui-designer-core/src/com/intellij/designer/palette/PaletteToolWindowManager.java +++ b/plugins/ui-designer-core/src/com/intellij/designer/palette/PaletteToolWindowManager.java @@ -17,12 +17,14 @@ package com.intellij.designer.palette; import com.intellij.designer.AbstractToolWindowManager; import com.intellij.designer.DesignerCustomizations; +import com.intellij.designer.LightToolWindow; import com.intellij.designer.designSurface.DesignerEditorPanel; import com.intellij.icons.AllIcons; import com.intellij.openapi.fileEditor.FileEditorManager; import com.intellij.openapi.project.Project; import com.intellij.openapi.wm.ToolWindowAnchor; import com.intellij.openapi.wm.ToolWindowManager; +import com.intellij.ui.SideBorder; import com.intellij.ui.content.Content; import com.intellij.ui.content.ContentManager; import org.jetbrains.annotations.NotNull; @@ -34,20 +36,48 @@ import org.jetbrains.annotations.Nullable; public class PaletteToolWindowManager extends AbstractToolWindowManager { private final PalettePanel myToolWindowPanel = new PalettePanel(); + ////////////////////////////////////////////////////////////////////////////////////////// + // + // Public Access + // + ////////////////////////////////////////////////////////////////////////////////////////// + public PaletteToolWindowManager(Project project, FileEditorManager fileEditorManager) { - super(project, fileEditorManager); + super(project, fileEditorManager, SideBorder.RIGHT); + } + + public static PalettePanel getInstance(DesignerEditorPanel designer) { + PaletteToolWindowManager manager = getInstance(designer.getProject()); + if (manager.isEditorMode()) { + return (PalettePanel)manager.getContent(designer); + } + return manager.myToolWindowPanel; } public static PaletteToolWindowManager getInstance(Project project) { return project.getComponent(PaletteToolWindowManager.class); } - public void clearActiveItem() { - myToolWindowPanel.clearActiveItem(); - } + ////////////////////////////////////////////////////////////////////////////////////////// + // + // Impl + // + ////////////////////////////////////////////////////////////////////////////////////////// - public void refresh() { - myToolWindowPanel.repaint(); + @Override + protected LightToolWindow createContent(DesignerEditorPanel designer) { + PalettePanel palettePanel = new PalettePanel(); + palettePanel.loadPalette(designer); + + return createContent(designer, + palettePanel, + "Palette", + "Palette ", + AllIcons.Toolwindows.ToolWindowPalette, + palettePanel, + palettePanel, + 180, + null); } @Override @@ -57,6 +87,7 @@ public class PaletteToolWindowManager extends AbstractToolWindowManager { myToolWindow = ToolWindowManager.getInstance(myProject).registerToolWindow("Palette\t", false, anchor, myProject, true); myToolWindow.setIcon(AllIcons.Toolwindows.ToolWindowPalette); + initGearActions(); ContentManager contentManager = myToolWindow.getContentManager(); Content content = contentManager.getFactory().createContent(myToolWindowPanel, null, false); diff --git a/plugins/ui-designer-core/src/com/intellij/designer/propertyTable/PropertyTablePanel.java b/plugins/ui-designer-core/src/com/intellij/designer/propertyTable/PropertyTablePanel.java index 182fbaf6c7da..44da0e05937a 100644 --- a/plugins/ui-designer-core/src/com/intellij/designer/propertyTable/PropertyTablePanel.java +++ b/plugins/ui-designer-core/src/com/intellij/designer/propertyTable/PropertyTablePanel.java @@ -23,6 +23,7 @@ import com.intellij.openapi.actionSystem.*; import com.intellij.openapi.actionSystem.impl.ActionButton; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Comparing; +import com.intellij.openapi.wm.IdeFocusManager; import com.intellij.ui.IdeBorderFactory; import com.intellij.ui.PopupHandler; import com.intellij.ui.ScrollPaneFactory; @@ -36,6 +37,8 @@ import javax.swing.*; import javax.swing.event.ListSelectionEvent; import javax.swing.event.ListSelectionListener; import java.awt.*; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; /** * @author Alexander Lobas @@ -53,11 +56,10 @@ public final class PropertyTablePanel extends JPanel implements ListSelectionLis private TablePanelActionPolicy myActionPolicy; private final JLabel myTitleLabel; - public PropertyTablePanel(Project project) { + public PropertyTablePanel(final Project project) { myPropertyTable = new RadPropertyTable(project); setLayout(new GridBagLayout()); - setBorder(IdeBorderFactory.createBorder(SideBorder.TOP)); int gridX = 0; @@ -119,6 +121,12 @@ public final class PropertyTablePanel extends JPanel implements ListSelectionLis new Insets(0, 0, 0, 0), 0, 0)); myPropertyTable.setPropertyTablePanel(this); + + addMouseListener(new MouseAdapter() { + public void mouseReleased(final MouseEvent e) { + IdeFocusManager.getInstance(project).requestFocus(myPropertyTable, true); + } + }); } public void setArea(@Nullable DesignerEditorPanel designer, @Nullable EditableArea area) {