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 91838651169f..e93491f3e24b 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 @@ -7,17 +7,18 @@ import com.intellij.openapi.actionSystem.AnAction; import com.intellij.openapi.actionSystem.DataProvider; import com.intellij.openapi.actionSystem.PlatformDataKeys; import com.intellij.openapi.keymap.KeymapUtil; +import com.intellij.openapi.project.DumbService; import com.intellij.openapi.ui.Queryable; import com.intellij.openapi.ui.Splitter; import com.intellij.openapi.util.Disposer; import com.intellij.openapi.util.SystemInfo; import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.wm.*; -import com.intellij.openapi.wm.impl.content.ToolWindowContentUi; import com.intellij.ui.ComponentWithMnemonics; import com.intellij.ui.Gray; import com.intellij.ui.JBColor; import com.intellij.ui.content.Content; +import com.intellij.ui.content.ContentManager; import com.intellij.ui.paint.LinePainter2D; import com.intellij.util.ui.JBUI; import org.jetbrains.annotations.NonNls; @@ -40,43 +41,30 @@ import java.util.Map; */ public final class InternalDecorator extends JPanel implements Queryable, DataProvider, ComponentWithMnemonics { private final ToolWindowImpl toolWindow; - private final JPanel myDivider; - private IdeGlassPane myGlassPane; - - private Disposable myDisposable; - private final MouseAdapter myListener = new MyMouseListener(); - private boolean myDragging; + private final MyDivider myDivider; /** * Catches all event from tool window and modifies decorator's appearance. */ static final String HIDE_ACTIVE_WINDOW_ACTION_ID = "HideActiveWindow"; - // see ToolWindowViewModeAction and ToolWindowMoveAction + //See ToolWindowViewModeAction and ToolWindowMoveAction public static final String TOGGLE_DOCK_MODE_ACTION_ID = "ToggleDockMode"; public static final String TOGGLE_FLOATING_MODE_ACTION_ID = "ToggleFloatingMode"; public static final String TOGGLE_SIDE_MODE_ACTION_ID = "ToggleSideMode"; private final ToolWindowHeader header; - InternalDecorator(@NotNull ToolWindowImpl toolWindow, @NotNull ToolWindowContentUi contentUi) { + InternalDecorator(@NotNull ToolWindowImpl toolWindow) { super(new BorderLayout()); this.toolWindow = toolWindow; - myDivider = new JPanel() { - @NotNull - @Override - public Cursor getCursor() { - WindowInfo info = InternalDecorator.this.toolWindow.getWindowInfo(); - boolean isVerticalCursor = info.getType() == ToolWindowType.DOCKED ? info.getAnchor().isSplitVertically() : info.getAnchor().isHorizontal(); - return isVerticalCursor ? Cursor.getPredefinedCursor(Cursor.S_RESIZE_CURSOR) : Cursor.getPredefinedCursor(Cursor.E_RESIZE_CURSOR); - } - }; + myDivider = new MyDivider(); setFocusable(false); setFocusTraversalPolicy(new LayoutFocusTraversalPolicy()); - header = new ToolWindowHeader(toolWindow, contentUi, () -> toolWindow.createPopupGroup(true)) { + header = new ToolWindowHeader(toolWindow, () -> toolWindow.createPopupGroup(true)) { @Override protected boolean isActive() { return toolWindow.isActive(); @@ -95,8 +83,6 @@ public final class InternalDecorator extends JPanel implements Queryable, DataPr if (SystemInfo.isMac) { setBackground(new JBColor(Gray._200, Gray._90)); } - - setBorder(new InnerPanelBorder(toolWindow)); } @Override @@ -104,21 +90,37 @@ public final class InternalDecorator extends JPanel implements Queryable, DataPr return toolWindow.getId(); } + public boolean isFocused(@NotNull JFrame frame) { + IdeFocusManager focusManager = toolWindow.getToolWindowManager().getFocusManager(); + JComponent toolWindowComponent = toolWindow.getComponentIfInitialized(); + if (toolWindowComponent == null) { + return false; + } + + Component component = focusManager.getFocusedDescendantFor(toolWindowComponent); + if (component != null) { + return true; + } + + Component owner = focusManager.getLastFocusedFor(frame); + return owner != null && SwingUtilities.isDescendingFrom(owner, toolWindowComponent); + } + void applyWindowInfo(@NotNull WindowInfo info) { // Anchor ToolWindowAnchor anchor = info.getAnchor(); if (info.isSliding()) { myDivider.invalidate(); - if (anchor == ToolWindowAnchor.TOP) { + if (ToolWindowAnchor.TOP == anchor) { add(myDivider, BorderLayout.SOUTH); } - else if (anchor == ToolWindowAnchor.LEFT) { + else if (ToolWindowAnchor.LEFT == anchor) { add(myDivider, BorderLayout.EAST); } - else if (anchor == ToolWindowAnchor.BOTTOM) { + else if (ToolWindowAnchor.BOTTOM == anchor) { add(myDivider, BorderLayout.NORTH); } - else if (anchor == ToolWindowAnchor.RIGHT) { + else if (ToolWindowAnchor.RIGHT == anchor) { add(myDivider, BorderLayout.WEST); } myDivider.setPreferredSize(new Dimension(0, 0)); @@ -128,6 +130,9 @@ public final class InternalDecorator extends JPanel implements Queryable, DataPr remove(myDivider); } + validate(); + repaint(); + // push "apply" request forward if (info.isFloating()) { FloatingDecorator floatingDecorator = (FloatingDecorator)SwingUtilities.getAncestorOfClass(FloatingDecorator.class, this); @@ -135,6 +140,9 @@ public final class InternalDecorator extends JPanel implements Queryable, DataPr floatingDecorator.apply(info); } } + + toolWindow.getContentUI().setType(info.getContentUiType()); + setBorder(new InnerPanelBorder(toolWindow, info)); } @Nullable @@ -146,6 +154,14 @@ public final class InternalDecorator extends JPanel implements Queryable, DataPr return null; } + void addContentComponent(boolean dumbAware, @NotNull ContentManager contentManager) { + JComponent toolWindowComponent = contentManager.getComponent(); + if (!dumbAware) { + toolWindowComponent = DumbService.getInstance(toolWindow.getToolWindowManager().getProject()).wrapGently(toolWindowComponent, toolWindow.getDisposable()); + } + add(toolWindowComponent, BorderLayout.CENTER); + } + @Override protected boolean processKeyBinding(KeyStroke ks, KeyEvent e, int condition, boolean pressed) { if (condition == WHEN_ANCESTOR_OF_FOCUSED_COMPONENT && pressed) { @@ -169,13 +185,16 @@ public final class InternalDecorator extends JPanel implements Queryable, DataPr private static final class InnerPanelBorder implements Border { @NotNull private final ToolWindowImpl window; + @NotNull + private final WindowInfo windowInfo; - private InnerPanelBorder(@NotNull ToolWindowImpl window) { + private InnerPanelBorder(@NotNull ToolWindowImpl window, @NotNull WindowInfo windowInfo) { this.window = window; + this.windowInfo = windowInfo; } @Override - public void paintBorder(@NotNull Component c, @NotNull Graphics g, int x, int y, int width, int height) { + public void paintBorder(final Component c, final Graphics g, final int x, final int y, final int width, final int height) { g.setColor(JBColor.border()); doPaintBorder(c, g, x, y, width, height); } @@ -208,7 +227,6 @@ public final class InternalDecorator extends JPanel implements Queryable, DataPr @Override public Insets getBorderInsets(@NotNull Component c) { ToolWindowManagerImpl toolWindowManager = window.getToolWindowManager(); - WindowInfo windowInfo = window.getWindowInfo(); if (toolWindowManager.getProject().isDisposed() || !toolWindowManager.isToolWindowRegistered(window.getId()) || windowInfo.getType() == ToolWindowType.FLOATING || windowInfo.getType() == ToolWindowType.WINDOWED) { return JBUI.emptyInsets(); @@ -262,91 +280,103 @@ public final class InternalDecorator extends JPanel implements Queryable, DataPr header.setVisible(value); } - @Override - public void addNotify() { - super.addNotify(); + private final class MyDivider extends JPanel { + private boolean myDragging; + private Disposable myDisposable; + private IdeGlassPane myGlassPane; - myGlassPane = IdeGlassPaneUtil.find(this); - myDisposable = Disposer.newDisposable(); - myGlassPane.addMouseMotionPreprocessor(myListener, myDisposable); - myGlassPane.addMousePreprocessor(myListener, myDisposable); - } + private final MouseAdapter myListener = new MyMouseAdapter(); - @Override - public void removeNotify() { - super.removeNotify(); - - Disposable disposable = myDisposable; - if (disposable != null && !Disposer.isDisposed(myDisposable)) { - myDisposable = null; - Disposer.dispose(disposable); + @Override + public void addNotify() { + super.addNotify(); + myGlassPane = IdeGlassPaneUtil.find(this); + myDisposable = Disposer.newDisposable(); + myGlassPane.addMouseMotionPreprocessor(myListener, myDisposable); + myGlassPane.addMousePreprocessor(myListener, myDisposable); } - } - private final class MyMouseListener extends MouseAdapter { - private boolean isInDragZone(MouseEvent e) { - Point p = SwingUtilities.convertMouseEvent(e.getComponent(), e, myDivider).getPoint(); + @Override + public void removeNotify() { + super.removeNotify(); + if (myDisposable != null && !Disposer.isDisposed(myDisposable)) { + Disposer.dispose(myDisposable); + } + } + + boolean isInDragZone(MouseEvent e) { + Point p = SwingUtilities.convertMouseEvent(e.getComponent(), e, this).getPoint(); return Math.abs(toolWindow.getWindowInfo().getAnchor().isHorizontal() ? p.y : p.x) < 6; } - private void updateCursor(MouseEvent e) { - if (isInDragZone(e)) { - myGlassPane.setCursor(myDivider.getCursor(), myDivider); + private final class MyMouseAdapter extends MouseAdapter { + private void updateCursor(MouseEvent e) { + if (isInDragZone(e)) { + myGlassPane.setCursor(MyDivider.this.getCursor(), MyDivider.this); + e.consume(); + } + } + + @Override + public void mousePressed(MouseEvent e) { + myDragging = isInDragZone(e); + updateCursor(e); + } + + @Override + public void mouseClicked(MouseEvent e) { + updateCursor(e); + } + + @Override + public void mouseReleased(MouseEvent e) { + updateCursor(e); + myDragging = false; + } + + @Override + public void mouseMoved(MouseEvent e) { + updateCursor(e); + } + + @Override + public void mouseDragged(MouseEvent e) { + if (!myDragging) { + return; + } + + MouseEvent event = SwingUtilities.convertMouseEvent(e.getComponent(), e, MyDivider.this); + final ToolWindowAnchor anchor = toolWindow.getAnchor(); + final Point point = event.getPoint(); + final Container windowPane = InternalDecorator.this.getParent(); + Point lastPoint = SwingUtilities.convertPoint(MyDivider.this, point, windowPane); + lastPoint.x = Math.min(Math.max(lastPoint.x, 0), windowPane.getWidth()); + lastPoint.y = Math.min(Math.max(lastPoint.y, 0), windowPane.getHeight()); + + final Rectangle bounds = InternalDecorator.this.getBounds(); + if (anchor == ToolWindowAnchor.TOP) { + InternalDecorator.this.setBounds(0, 0, bounds.width, lastPoint.y); + } + else if (anchor == ToolWindowAnchor.LEFT) { + InternalDecorator.this.setBounds(0, 0, lastPoint.x, bounds.height); + } + else if (anchor == ToolWindowAnchor.BOTTOM) { + InternalDecorator.this.setBounds(0, lastPoint.y, bounds.width, windowPane.getHeight() - lastPoint.y); + } + else if (anchor == ToolWindowAnchor.RIGHT) { + InternalDecorator.this.setBounds(lastPoint.x, 0, windowPane.getWidth() - lastPoint.x, bounds.height); + } + InternalDecorator.this.validate(); e.consume(); } } + @NotNull @Override - public void mousePressed(MouseEvent e) { - myDragging = isInDragZone(e); - updateCursor(e); - } - - @Override - public void mouseClicked(MouseEvent e) { - updateCursor(e); - } - - @Override - public void mouseReleased(MouseEvent e) { - updateCursor(e); - myDragging = false; - } - - @Override - public void mouseMoved(MouseEvent e) { - updateCursor(e); - } - - @Override - public void mouseDragged(MouseEvent e) { - if (!myDragging) { - return; - } - - MouseEvent event = SwingUtilities.convertMouseEvent(e.getComponent(), e, myDivider); - final ToolWindowAnchor anchor = toolWindow.getAnchor(); - final Point point = event.getPoint(); - final Container windowPane = InternalDecorator.this.getParent(); - Point lastPoint = SwingUtilities.convertPoint(myDivider, point, windowPane); - lastPoint.x = Math.min(Math.max(lastPoint.x, 0), windowPane.getWidth()); - lastPoint.y = Math.min(Math.max(lastPoint.y, 0), windowPane.getHeight()); - - final Rectangle bounds = InternalDecorator.this.getBounds(); - if (anchor == ToolWindowAnchor.TOP) { - InternalDecorator.this.setBounds(0, 0, bounds.width, lastPoint.y); - } - else if (anchor == ToolWindowAnchor.LEFT) { - InternalDecorator.this.setBounds(0, 0, lastPoint.x, bounds.height); - } - else if (anchor == ToolWindowAnchor.BOTTOM) { - InternalDecorator.this.setBounds(0, lastPoint.y, bounds.width, windowPane.getHeight() - lastPoint.y); - } - else if (anchor == ToolWindowAnchor.RIGHT) { - InternalDecorator.this.setBounds(lastPoint.x, 0, windowPane.getWidth() - lastPoint.x, bounds.height); - } - InternalDecorator.this.validate(); - e.consume(); + public Cursor getCursor() { + WindowInfo info = toolWindow.getWindowInfo(); + boolean isVerticalCursor = info.getType() == ToolWindowType.DOCKED ? info.getAnchor().isSplitVertically() : info.getAnchor().isHorizontal(); + return isVerticalCursor ? Cursor.getPredefinedCursor(Cursor.S_RESIZE_CURSOR) : Cursor.getPredefinedCursor(Cursor.E_RESIZE_CURSOR); } } @@ -354,7 +384,7 @@ public final class InternalDecorator extends JPanel implements Queryable, DataPr public void putInfo(@NotNull Map info) { info.put("toolWindowTitle", toolWindow.getTitle()); - Content selection = toolWindow.getContentManager().getSelectedContent(); + final Content selection = toolWindow.getContentManager().getSelectedContent(); if (selection != null) { info.put("toolWindowTab", selection.getTabName()); }