* @author Vladimir Kondratyev
*/
public class ThreeComponentsSplitter extends JPanel implements Disposable {
+ public static final int MIN_SIZE = 48;
+
private int myDividerWidth;
/**
* /------/
else {
firstCompontSize = getFirstSize();
lastComponentSize = getLastSize();
- int sizeLack = firstCompontSize + lastComponentSize - (componentSize - dividersCount * dividerWidth);
+ int sizeLack = firstCompontSize + lastComponentSize - (componentSize - dividersCount * dividerWidth - MIN_SIZE);
if (sizeLack > 0) {
- // Lacking size. Reduce first component's size, inner -> empty
- firstCompontSize -= sizeLack;
- innerComponentSize = 0;
+ // Lacking size. Reduce first & last component's size, inner -> MIN_SIZE
+ double firstSizeRatio = (double)firstCompontSize / (firstCompontSize + lastComponentSize);
+ if (firstCompontSize > 0) {
+ firstCompontSize -= sizeLack * firstSizeRatio;
+ firstCompontSize = Math.max(MIN_SIZE, firstCompontSize);
+ }
+ if (lastComponentSize > 0) {
+ lastComponentSize -= sizeLack * (1 - firstSizeRatio);
+ lastComponentSize = Math.max(MIN_SIZE, lastComponentSize);
+ }
+ innerComponentSize = MIN_SIZE;
}
else {
- innerComponentSize = componentSize - dividersCount * dividerWidth - getFirstSize() - getLastSize();
+ innerComponentSize = Math.max(MIN_SIZE, componentSize - dividersCount * dividerWidth - getFirstSize() - getLastSize());
}
if (!innerVisible()) {
return lastVisible() ? myLastSize : 0;
}
+ public int getMinSize(boolean first) {
+ return getMinSize(first? myFirstComponent : myLastComponent);
+ }
+
+ public int getMaxSize(boolean first) {
+ final int size = getOrientation() ? this.getHeight() : this.getWidth();
+ return size - (first? myLastSize: myFirstSize) - MIN_SIZE;
+ }
+
+ private int getMinSize(JComponent component) {
+ if (isHonorMinimumSize()) {
+ if (component != null && myFirstComponent != null && myFirstComponent.isVisible() && myLastComponent != null && myLastComponent.isVisible()) {
+ if (getOrientation()) {
+ return component.getMinimumSize().height;
+ }
+ else {
+ return component.getMinimumSize().width;
+ }
+ }
+ }
+ return MIN_SIZE;
+ }
+
@Override
public void dispose() {
myLastComponent = null;
myGlassPane.setCursor(getResizeCursor(), myListener);
myPoint = SwingUtilities.convertPoint(this, e.getPoint(), ThreeComponentsSplitter.this);
+ final int size = getOrientation() ? ThreeComponentsSplitter.this.getHeight() : ThreeComponentsSplitter.this.getWidth();
if (getOrientation()) {
- if (getHeight() > 0 || myDividerZone > 0) {
+ if (size > 0 || myDividerZone > 0) {
if (myIsFirst) {
- setFirstSize(Math.max(getMinSize(myFirstComponent), myPoint.y));
+ setFirstSize(Math.min(size - myLastSize - MIN_SIZE, Math.max(getMinSize(myFirstComponent), myPoint.y)));
}
else {
- setLastSize(Math.max(getMinSize(myLastComponent), ThreeComponentsSplitter.this.getHeight() - myPoint.y - getDividerWidth()));
+ setLastSize(Math.min(size - myFirstSize - MIN_SIZE, Math.max(getMinSize(myLastComponent), size - myPoint.y - getDividerWidth())));
}
}
}
else {
- if (getWidth() > 0 || myDividerZone > 0) {
+ if (size > 0 || myDividerZone > 0) {
if (myIsFirst) {
- setFirstSize(Math.max(getMinSize(myFirstComponent), myPoint.x));
+ setFirstSize(Math.min(size - myLastSize - MIN_SIZE, Math.max(getMinSize(myFirstComponent), myPoint.x)));
}
else {
- setLastSize(Math.max(getMinSize(myLastComponent), ThreeComponentsSplitter.this.getWidth() - myPoint.x - getDividerWidth()));
+ setLastSize(Math.min(size - myFirstSize - MIN_SIZE, Math.max(getMinSize(myLastComponent), size - myPoint.x - getDividerWidth())));
}
}
}
}
}
- private int getMinSize(JComponent component) {
- if (isHonorMinimumSize()) {
- if (component != null && myFirstComponent != null && myFirstComponent.isVisible() && myLastComponent != null && myLastComponent.isVisible()) {
- if (getOrientation()) {
- return component.getMinimumSize().height;
- }
- else {
- return component.getMinimumSize().width;
- }
- }
- }
- return 0;
- }
-
protected void processMouseEvent(MouseEvent e) {
super.processMouseEvent(e);
if (!isShowing()) {
@Nullable
public abstract Balloon getToolWindowBalloon(String id);
+
+ public abstract boolean isMaximized(@NotNull ToolWindow wnd);
+
+ public abstract void setMaximized(@NotNull ToolWindow wnd, boolean maximized);
}
resize.add(new ResizeToolWindowAction.Right(myToolWindow, this));
resize.add(new ResizeToolWindowAction.Up(myToolWindow, this));
resize.add(new ResizeToolWindowAction.Down(myToolWindow, this));
+ resize.add(ActionManager.getInstance().getAction("MaximizeToolWindow"));
group.add(resize);
--- /dev/null
+/*
+ * Copyright 2000-2014 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.openapi.wm.impl;
+
+import com.intellij.idea.ActionsBundle;
+import com.intellij.openapi.actionSystem.AnAction;
+import com.intellij.openapi.actionSystem.AnActionEvent;
+import com.intellij.openapi.actionSystem.PlatformDataKeys;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.wm.ToolWindow;
+import com.intellij.openapi.wm.ToolWindowManager;
+import org.jetbrains.annotations.NotNull;
+
+public class MaximizeToolWindowAction extends AnAction {
+ public MaximizeToolWindowAction() {
+ super();
+ }
+
+ @Override
+ public void actionPerformed(@NotNull AnActionEvent e) {
+ Project project = e.getProject();
+ if (project == null || project.isDisposed()) return;
+ ToolWindow toolWindow = e.getData(PlatformDataKeys.TOOL_WINDOW);
+ if (toolWindow == null) return;
+ ToolWindowManager manager = ToolWindowManager.getInstance(project);
+ manager.setMaximized(toolWindow, !manager.isMaximized(toolWindow));
+ }
+
+ @Override
+ public void update(@NotNull AnActionEvent e) {
+ e.getPresentation().setEnabled(true);
+ Project project = e.getProject();
+ if (project == null || project.isDisposed()) {
+ e.getPresentation().setEnabled(false);
+ return;
+ }
+ ToolWindow toolWindow = e.getData(PlatformDataKeys.TOOL_WINDOW);
+ if (toolWindow == null) {
+ e.getPresentation().setEnabled(false);
+ return;
+ }
+ ToolWindowManager manager = ToolWindowManager.getInstance(project);
+ e.getPresentation().setText(manager.isMaximized(toolWindow) ?
+ ActionsBundle.message("action.ResizeToolWindowMaximize.text.alternative") :
+ ActionsBundle.message("action.ResizeToolWindowMaximize.text"));
+ }
+}
import com.intellij.openapi.actionSystem.impl.*;
import com.intellij.openapi.keymap.KeymapUtil;
import com.intellij.openapi.project.DumbAware;
+import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.SystemInfo;
import com.intellij.openapi.wm.ToolWindow;
import com.intellij.openapi.wm.ToolWindowAnchor;
+import com.intellij.openapi.wm.ToolWindowManager;
import com.intellij.openapi.wm.ToolWindowType;
import com.intellij.openapi.wm.impl.content.ToolWindowContentUi;
import com.intellij.ui.InplaceButton;
};
}
+ void switchMaximizedState(Project project) {
+ if (project == null || project.isDisposed()) return;
+ ToolWindowManager mgr = ToolWindowManager.getInstance(project);
+ mgr.setMaximized(myToolWindow, !mgr.isMaximized(myToolWindow));
+ }
+
@Override
public void uiSettingsChanged(UISettings source) {
clearCaches();
return null;
}
+ @Override
+ public boolean isMaximized(@NotNull ToolWindow wnd) {
+ return false;
+ }
+
+ @Override
+ public void setMaximized(@NotNull ToolWindow wnd, boolean maximized) {
+ }
+
@Override
public void initToolWindow(@NotNull ToolWindowEP bean) {
private final FileEditorManager myFileEditorManager;
private final LafManager myLafManager;
private final Map<String, Balloon> myWindow2Balloon = new HashMap<String, Balloon>();
+ private Pair<String, Integer> myMaximizedToolwindowSize = null;
private KeyState myCurrentState = KeyState.waiting;
private final Alarm myWaiterForSecondPress = new Alarm();
myToolWindowsPane.stretchWidth(toolWindow, value);
}
+ @Override
+ public boolean isMaximized(@NotNull ToolWindow wnd) {
+ return myToolWindowsPane.isMaximized(wnd);
+ }
+
+ @Override
+ public void setMaximized(@NotNull ToolWindow wnd, boolean maximized) {
+ myToolWindowsPane.setMaximized(wnd, maximized);
+ }
+
public void stretchHeight(ToolWindowImpl toolWindow, int value) {
myToolWindowsPane.stretchHeight(toolWindow, value);
}
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.Splitter;
import com.intellij.openapi.ui.ThreeComponentsSplitter;
+import com.intellij.openapi.util.Condition;
import com.intellij.openapi.util.Disposer;
+import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.registry.Registry;
+import com.intellij.openapi.wm.IdeGlassPaneUtil;
import com.intellij.openapi.wm.ToolWindow;
import com.intellij.openapi.wm.ToolWindowAnchor;
import com.intellij.openapi.wm.ToolWindowType;
-import com.intellij.openapi.wm.ex.ToolWindowEx;
import com.intellij.openapi.wm.impl.commands.FinalizableCommand;
import com.intellij.ui.ScreenUtil;
import com.intellij.ui.components.JBLayeredPane;
import com.intellij.util.containers.HashMap;
import com.intellij.util.ui.FadeInFadeOut;
+import com.intellij.util.ui.UIUtil;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.awt.*;
+import java.awt.event.MouseAdapter;
+import java.awt.event.MouseEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.ArrayList;
private final HashMap<StripeButton, WindowInfoImpl> myButton2Info;
private final HashMap<InternalDecorator, WindowInfoImpl> myDecorator2Info;
private final HashMap<String, Float> myId2SplitProportion;
+ private Pair<ToolWindow, Integer> myMaximizedProportion = null;
/**
* This panel is the layered pane where all sliding tool windows are located. The DEFAULT
* layer contains splitters. The PALETTE layer contains all sliding tool windows.
super.addNotify();
if (ScreenUtil.isStandardAddRemoveNotify(this)) {
UISettings.getInstance().addUISettingsListener(myUISettingsListener, myDisposable);
+ IdeGlassPaneUtil.find(this).addMousePreprocessor(new MouseAdapter() {
+ @Override
+ public void mouseClicked(MouseEvent e) {
+ if (SwingUtilities.isLeftMouseButton(e) && e.getClickCount() == 2 && e.getModifiersEx() == 0) {
+ e = SwingUtilities.convertMouseEvent(e.getComponent(), e, ToolWindowsPane.this);
+ Component component = SwingUtilities.getDeepestComponentAt(ToolWindowsPane.this, e.getX(), e.getY());
+ Component header = component == null ? null : UIUtil.findParentByCondition((JComponent)component, new Condition<Component>() {
+ @Override
+ public boolean value(Component component) {
+ return component instanceof ToolWindowHeader;
+ }
+ });
+ if (header instanceof ToolWindowHeader) {
+ ((ToolWindowHeader)header).switchMaximizedState(myFrame.getProject());
+ }
+ }
+ }
+ }, this);
}
}
}
private void stretch(ToolWindow wnd, int value) {
- if (!wnd.isVisible()) return;
+ Pair<Resizer, Component> pair = findResizerAndComponent(wnd);
+ if (pair == null) return;
+
+ boolean vertical = wnd.getAnchor() == ToolWindowAnchor.TOP || wnd.getAnchor() == ToolWindowAnchor.BOTTOM;
+ int actualSize = (vertical ? pair.second.getHeight() : pair.second.getWidth()) + value;
+ boolean first = wnd.getAnchor() == ToolWindowAnchor.LEFT || wnd.getAnchor() == ToolWindowAnchor.TOP;
+ int maxValue = vertical ? myVerticalSplitter.getMaxSize(first) : myHorizontalSplitter.getMaxSize(first);
+ int minValue = vertical ? myVerticalSplitter.getMinSize(first) : myHorizontalSplitter.getMinSize(first);;
+
+ pair.first.setSize(Math.max(minValue, Math.min(maxValue, actualSize)));
+ }
+
+ @Nullable
+ private Pair<Resizer, Component> findResizerAndComponent(ToolWindow wnd) {
+ if (!wnd.isVisible()) return null;
Resizer resizer = null;
Component cmp = null;
}
}
- if (resizer == null) return;
-
- int currentValue = wnd.getAnchor().isHorizontal() ? cmp.getHeight() : cmp.getWidth();
-
- int actualSize = currentValue + value;
-
- int minValue =
- wnd.getAnchor().isHorizontal() ? ((ToolWindowEx)wnd).getDecorator().getHeaderHeight() : 16 + myHorizontalSplitter.getDividerWidth();
- int maxValue = wnd.getAnchor().isHorizontal() ? myLayeredPane.getHeight() : myLayeredPane.getWidth();
-
-
- if (actualSize < minValue) {
- actualSize = minValue;
- }
-
- if (actualSize > maxValue) {
- actualSize = maxValue;
- }
-
- resizer.setSize(actualSize);
+ return resizer != null ? Pair.create(resizer, cmp) : null;
}
private void updateLayout() {
}
}
+ public boolean isMaximized(@NotNull ToolWindow wnd) {
+ return myMaximizedProportion != null && myMaximizedProportion.first == wnd;
+ }
+
+ public void setMaximized(@NotNull ToolWindow wnd, boolean maximized) {
+ Pair<Resizer, Component> resizerAndComponent = findResizerAndComponent(wnd);
+ if (resizerAndComponent == null) return;
+
+ if (!maximized) {
+ ToolWindow maximizedWindow = myMaximizedProportion.first;
+ assert maximizedWindow == wnd;
+ resizerAndComponent.first.setSize(myMaximizedProportion.second);
+ myMaximizedProportion = null;
+ } else {
+ int size = wnd.getAnchor().isHorizontal() ? resizerAndComponent.second.getHeight() : resizerAndComponent.second.getWidth();
+ stretch(wnd, Short.MAX_VALUE);
+ myMaximizedProportion = Pair.create(wnd, size);
+ }
+ doLayout();
+ }
+
interface Resizer {
void setSize(int size);
action.ResizeToolWindowUp.description=Resize active tool window to the top
action.ResizeToolWindowDown.text=Stretch to Bottom
action.ResizeToolWindowDown.description=Resize active tool window to the bottom
+action.ResizeToolWindowMaximize.text=Maximize tool window
+action.ResizeToolWindowMaximize.text.alternative=Restore tool window size
+action.ResizeToolWindowMaximize.description=Maximize tool widow
action.IncrementWindowWidth.text=Increment Width
action.DecrementWindowWidth.text=Decrement Width
action.IncrementWindowHeight.text=Increment Height
<action id="ResizeToolWindowDown">
<keyboard-shortcut first-keystroke="control shift DOWN"/>
</action>
+ <action id="MaximizeToolWindow">
+ <keyboard-shortcut first-keystroke="control shift QUOTE"/>
+ </action>
<action id="HideSideWindows"/>
<action id="ShowPopupMenu">
<keyboard-shortcut first-keystroke="CONTEXT_MENU"/>
<action id="HideAllWindows" class="com.intellij.ide.actions.HideAllToolWindowsAction"/>
<action id="CloseActiveTab" class="com.intellij.ide.actions.CloseActiveTabAction"/>
<action id="JumpToLastWindow" class="com.intellij.ide.actions.JumpToLastWindowAction"/>
+ <action id="MaximizeToolWindow" class="com.intellij.openapi.wm.impl.MaximizeToolWindowAction"/>
<separator/>
<action id="TogglePinnedMode" class="com.intellij.ide.actions.TogglePinnedModeAction"/>
<action id="ToggleDockMode" class="com.intellij.ide.actions.ToggleDockModeAction"/>
return null;
}
+ @Override
+ public boolean isMaximized(@NotNull ToolWindow wnd) {
+ return false;
+ }
+
+ @Override
+ public void setMaximized(@NotNull ToolWindow wnd, boolean maximized) {
+ }
+
@Override
public void notifyByBalloon(@NotNull final String toolWindowId, @NotNull final MessageType type, @NotNull final String htmlBody) {
}