thin tool window splitters

This commit is contained in:
Kirill Kalishev
2010-06-28 15:49:50 +04:00
parent 26e4a6cfa4
commit 4eeeedb6b5
7 changed files with 219 additions and 60 deletions
@@ -15,14 +15,20 @@
*/
package com.intellij.openapi.ui;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.IconLoader;
import com.intellij.openapi.wm.IdeGlassPane;
import com.intellij.openapi.wm.IdeGlassPaneUtil;
import com.intellij.ui.UIBundle;
import com.intellij.util.ui.update.LazyUiDisposable;
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.awt.event.*;
/**
* @author Vladimir Kondratyev
@@ -58,6 +64,7 @@ public class ThreeComponentsSplitter extends JPanel {
private int myLastSize = 10;
private boolean myShowDividerControls;
private int myDividerZone;
/**
@@ -85,6 +92,10 @@ public class ThreeComponentsSplitter extends JPanel {
setOrientation(myVerticalSplit);
}
public void setDividerMouseZoneSize(int size) {
myDividerZone = size;
}
public boolean isHonorMinimumSize() {
return myHonorMinimumSize;
}
@@ -262,7 +273,7 @@ public class ThreeComponentsSplitter extends JPanel {
}
public void setDividerWidth(int width) {
if (width <= 0) {
if (width < 0) {
throw new IllegalArgumentException("Wrong divider width: " + width);
}
if (myDividerWidth != width) {
@@ -382,17 +393,79 @@ public class ThreeComponentsSplitter extends JPanel {
return lastVisible() ? myLastSize : 0;
}
protected class Divider extends JPanel {
protected class Divider extends JPanel implements Disposable {
protected boolean myDragging;
protected Point myPoint;
private final boolean myIsFirst;
private MouseAdapter myListener = new MouseAdapter() {
@Override
public void mousePressed(MouseEvent e) {
MouseEvent event = SwingUtilities.convertMouseEvent(e.getComponent(), e, Divider.this);
processMouseEvent(event);
if (event.isConsumed()) {
e.consume();
}
}
@Override
public void mouseReleased(MouseEvent e) {
MouseEvent event = SwingUtilities.convertMouseEvent(e.getComponent(), e, Divider.this);
processMouseEvent(event);
if (event.isConsumed()) {
e.consume();
}
}
@Override
public void mouseDragged(MouseEvent e) {
MouseEvent event = SwingUtilities.convertMouseEvent(e.getComponent(), e, Divider.this);
processMouseMotionEvent(event);
if (event.isConsumed()) {
e.consume();
}
}
};
private boolean myWasPressedOnMe;
public Divider(boolean isFirst) {
super(new GridBagLayout());
setFocusable(false);
enableEvents(MouseEvent.MOUSE_EVENT_MASK | MouseEvent.MOUSE_MOTION_EVENT_MASK);
myIsFirst = isFirst;
setOrientation(myVerticalSplit);
new LazyUiDisposable<Divider>(null, this, this) {
@Override
protected void initialize(@NotNull Disposable parent, @NotNull Divider child, @Nullable Project project) {
init();
}
};
}
private boolean isInside(Point p) {
if (myVerticalSplit) {
if (getHeight() > 0) {
return p.y >= 0 && p.y < getHeight();
} else {
return p.y >= -myDividerZone / 2 && p.y < myDividerZone / 2;
}
} else {
if (getWidth() > 0) {
return p.x >= 0 && p.x < getWidth();
} else {
return p.x >= -myDividerZone / 2 && p.x < myDividerZone / 2;
}
}
}
private void init() {
IdeGlassPane gp = IdeGlassPaneUtil.find(this);
gp.addMouseMotionPreprocessor(myListener, this);
gp.addMousePreprocessor(myListener, this);
}
public void dispose() {
}
private void setOrientation(boolean isVerticalSplit) {
@@ -485,13 +558,13 @@ public class ThreeComponentsSplitter extends JPanel {
protected void processMouseMotionEvent(MouseEvent e) {
super.processMouseMotionEvent(e);
if (MouseEvent.MOUSE_DRAGGED == e.getID()) {
if (MouseEvent.MOUSE_DRAGGED == e.getID() && myWasPressedOnMe) {
myDragging = true;
setCursor(getOrientation() ? Cursor.getPredefinedCursor(Cursor.S_RESIZE_CURSOR) : Cursor.getPredefinedCursor(Cursor.E_RESIZE_CURSOR));
myPoint = SwingUtilities.convertPoint(this, e.getPoint(), ThreeComponentsSplitter.this);
float proportion;
if (getOrientation()) {
if (getHeight() > 0) {
if (getHeight() > 0 || myDividerZone > 0) {
if (myIsFirst) {
setFirstSize(Math.max(getMinSize(myFirstComponent), myPoint.y));
}
@@ -501,7 +574,7 @@ public class ThreeComponentsSplitter extends JPanel {
}
}
else {
if (getWidth() > 0) {
if (getWidth() > 0 || myDividerZone > 0) {
if (myIsFirst) {
setFirstSize(Math.max(getMinSize(myFirstComponent), myPoint.x));
}
@@ -512,6 +585,10 @@ public class ThreeComponentsSplitter extends JPanel {
}
ThreeComponentsSplitter.this.doLayout();
}
if (myWasPressedOnMe) {
e.consume();
}
}
private int getMinSize(JComponent component) {
@@ -545,11 +622,21 @@ public class ThreeComponentsSplitter extends JPanel {
}
case MouseEvent.MOUSE_PRESSED:
{
setCursor(getOrientation() ? Cursor.getPredefinedCursor(9) : Cursor.getPredefinedCursor(11));
if (isInside(e.getPoint())) {
myWasPressedOnMe = true;
setCursor(getOrientation() ? Cursor.getPredefinedCursor(9) : Cursor.getPredefinedCursor(11));
e.consume();
} else {
myWasPressedOnMe = false;
}
break;
}
case MouseEvent.MOUSE_RELEASED:
{
if (myWasPressedOnMe) {
e.consume();
}
myWasPressedOnMe = false;
myDragging = false;
myPoint = null;
break;
@@ -16,7 +16,9 @@
package com.intellij.util.ui.update;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.actionSystem.DataContext;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.AsyncResult;
import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.actionSystem.PlatformDataKeys;
import com.intellij.openapi.actionSystem.DataKey;
@@ -58,10 +60,18 @@ public abstract class LazyUiDisposable<T extends Disposable> implements Activata
if (myWasEverShown) return;
try {
final Disposable parent = findParentDisposable();
initialize(parent, myChild, findProject());
Disposer.register(parent, myChild);
} finally {
findParentDisposable().doWhenDone(new AsyncResult.Handler<Disposable>() {
public void run(Disposable parent) {
Project project = null;
if (ApplicationManager.getApplication() != null) {
project = PlatformDataKeys.PROJECT.getData(DataManager.getInstance().getDataContext());
}
initialize(parent, myChild, project);
Disposer.register(parent, myChild);
}
});
}
finally {
myWasEverShown = true;
}
}
@@ -72,26 +82,32 @@ public abstract class LazyUiDisposable<T extends Disposable> implements Activata
protected abstract void initialize(@NotNull Disposable parent, @NotNull T child, @Nullable Project project);
@NotNull
private Disposable findParentDisposable() {
final Disposable parent = findObject(myParent, PlatformDataKeys.UI_DISPOSABLE);
return parent != null ? parent : Disposer.get("ui");
private AsyncResult<Disposable> findParentDisposable() {
return findDisposable(myParent, PlatformDataKeys.UI_DISPOSABLE);
}
@Nullable
private Project findProject() {
return (Project) findObject(myProject, PlatformDataKeys.PROJECT);
}
private Disposable findObject(Disposable defaultValue, DataKey<? extends Disposable> key) {
private static AsyncResult<Disposable> findDisposable(Disposable defaultValue, final DataKey<? extends Disposable> key) {
if (defaultValue == null) {
if (ApplicationManager.getApplication() != null) {
return key.getData(DataManager.getInstance().getDataContext());
} else {
final AsyncResult<Disposable> result = new AsyncResult<Disposable>();
DataManager.getInstance().getDataContextFromFocus().doWhenDone(new AsyncResult.Handler<DataContext>() {
public void run(DataContext context) {
Disposable disposable = key.getData(context);
if (disposable == null) {
disposable = Disposer.get("ui");
}
result.setDone(disposable);
}
});
return result;
}
else {
return null;
}
} else {
return defaultValue;
}
else {
return new AsyncResult.Done<Disposable>(defaultValue);
}
}
@@ -147,6 +147,18 @@ final class EditorTabbedContainer implements Disposable, CloseAction.CloseTarget
UISettings uiSettings = UISettings.getInstance();
List<String> topIds = mgr.getIdsOn(ToolWindowAnchor.TOP);
List<String> bottom = mgr.getIdsOn(ToolWindowAnchor.BOTTOM);
List<String> rightIds = mgr.getIdsOn(ToolWindowAnchor.RIGHT);
List<String> leftIds = mgr.getIdsOn(ToolWindowAnchor.LEFT);
if (!uiSettings.HIDE_TOOL_STRIPES) {
border.top = topIds.size() > 0 ? 1: 0;
border.bottom = bottom.size() > 0 ? 1: 0;
border.left = leftIds.size() > 0 ? 1: 0;
border.right = rightIds.size() > 0 ? 1: 0;
}
for (String each : ids) {
ToolWindow eachWnd = mgr.getToolWindow(each);
if (!eachWnd.isAvailable()) continue;
@@ -160,35 +172,11 @@ final class EditorTabbedContainer implements Disposable, CloseAction.CloseTarget
} else if (eachAnchor == ToolWindowAnchor.LEFT) {
border.left = 1;
} else if (eachAnchor == ToolWindowAnchor.RIGHT) {
border.right = 1;
border.right = 0;
}
}
}
if (!uiSettings.HIDE_TOOL_STRIPES) {
if (mgr.getIdsOn(ToolWindowAnchor.TOP).size() > 0) {
border.top = 1;
}
if (mgr.getIdsOn(ToolWindowAnchor.BOTTOM).size() > 0) {
border.bottom = 1;
}
if (mgr.getIdsOn(ToolWindowAnchor.LEFT).size() > 0) {
border.left = 1;
}
if (mgr.getIdsOn(ToolWindowAnchor.RIGHT).size() > 0) {
border.right = 1;
}
if (!uiSettings.SHOW_STATUS_BAR && !uiSettings.HIDE_TOOL_STRIPES) {
border.bottom = 1;
}
}
myTabs.getComponent().setBorder(new EmptyBorder(1, 0, 0, 0));
myTabs.getPresentation().setPaintBorder(border.top, border.left, border.right, border.bottom).setTabSidePaintBorder(5);
}
@@ -46,12 +46,14 @@ import org.jetbrains.annotations.NonNls;
import javax.swing.*;
import javax.swing.border.Border;
import javax.swing.border.EmptyBorder;
import javax.swing.event.EventListenerList;
import java.awt.*;
import java.awt.event.*;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.Map;
import java.util.*;
import java.util.List;
/**
* @author Eugene Belyaev
@@ -429,6 +431,7 @@ public final class InternalDecorator extends JPanel implements Queryable, TypeSa
contentPane.add(inner, BorderLayout.CENTER);
add(contentPane, BorderLayout.CENTER);
setBorder(new EmptyBorder(0, 0, 0, 0));
// Add listeners
registerKeyboardAction(new ActionListener() {
@@ -448,21 +451,83 @@ public final class InternalDecorator extends JPanel implements Queryable, TypeSa
public void paintBorder(final Component c, final Graphics g, final int x, final int y, final int width, final int height) {
g.setColor(UIUtil.getBorderInactiveColor());
UIUtil.drawLine(g, x, y, x, y + height - 2);
UIUtil.drawLine(g, x + width - 1, y, x + width - 1, y + height - 2);
if (hasBottomLine()) {
UIUtil.drawLine(g, x + 1, y + height - 1, x + width - 2, y + height - 1);
Insets insets = getBorderInsets(c);
if (insets.left > 0) {
UIUtil.drawLine(g, x, y, x, y + height - 2);
}
if (insets.right > 0) {
UIUtil.drawLine(g, x + width - 1, y, x + width - 1, y + height - 2);
}
if (insets.bottom > 0) {
UIUtil.drawLine(g, x + 1, y + height - 1, x + width - 2, y + height - 1);
}
}
private boolean hasBottomLine() {
return (myWindow.getAnchor() == ToolWindowAnchor.BOTTOM || myWindow.getAnchor() == ToolWindowAnchor.LEFT || myWindow.getAnchor() == ToolWindowAnchor.RIGHT)
&& !UISettings.getInstance().HIDE_TOOL_STRIPES && UISettings.getInstance().SHOW_STATUS_BAR;
&& !UISettings.getInstance().HIDE_TOOL_STRIPES && UISettings.getInstance().SHOW_STATUS_BAR || (myWindow.getAnchor() == ToolWindowAnchor.TOP);
}
public Insets getBorderInsets(final Component c) {
return new Insets(0, 1, hasBottomLine() ? 1 : 0, 1);
UISettings settings = UISettings.getInstance();
ToolWindowManagerImpl mgr = ((ToolWindowImpl)myWindow).getToolWindowManager();
List<String> topIds = mgr.getIdsOn(ToolWindowAnchor.TOP);
boolean topButtons = !settings.HIDE_TOOL_STRIPES && topIds.size() > 0;
boolean windowAtTop = hasDockedVisible(mgr, topIds);
List<String> bottomIds = mgr.getIdsOn(ToolWindowAnchor.BOTTOM);
boolean bottomButtons = !settings.HIDE_TOOL_STRIPES && bottomIds.size() > 0;
boolean windowAtBottom = hasDockedVisible(mgr, bottomIds);
List<String> leftIds = mgr.getIdsOn(ToolWindowAnchor.LEFT);
boolean leftButtons = !settings.HIDE_TOOL_STRIPES && leftIds.size() > 0;
boolean windowAtLeft = hasDockedVisible(mgr, leftIds);
List<String> rightIds = mgr.getIdsOn(ToolWindowAnchor.RIGHT);
boolean rightBottoms = !settings.HIDE_TOOL_STRIPES && rightIds.size() > 0;
boolean windowAtRight = hasDockedVisible(mgr, rightIds);
Insets insets = new Insets(0, 0, 0, 0);
if (myWindow.getAnchor() == ToolWindowAnchor.TOP) {
insets.top = topButtons ? 1 : 0;
insets.left = leftButtons ? 1: 0;
insets.right = rightBottoms ? 1: 0;
insets.bottom = 1;
} else if (myWindow.getAnchor() == ToolWindowAnchor.BOTTOM) {
insets.top = 0;
insets.left = leftButtons ? 1 : 0;
insets.right = rightBottoms ? 1: 0;
insets.bottom = bottomButtons ? 1 : 0;
} else if (myWindow.getAnchor() == ToolWindowAnchor.LEFT) {
insets.top = topButtons && !windowAtTop ? 1 : 0;
insets.left = leftButtons ? 1: 0;
insets.right = 0;
insets.bottom = bottomButtons && !windowAtBottom ? 1 : 0;
} else if (myWindow.getAnchor() == ToolWindowAnchor.RIGHT) {
insets.top = topButtons && !windowAtTop ? 1: 0;
insets.left = 1;
insets.right = rightBottoms ? 1: 0;
insets.bottom = bottomButtons && !windowAtBottom ? 1: 0;
}
return insets;
}
private boolean hasDockedVisible(ToolWindowManager mgr, List<String> ids) {
for (String each : ids) {
ToolWindow eachWnd = mgr.getToolWindow(each);
if (eachWnd.isVisible()) {
if (eachWnd.getType() == ToolWindowType.DOCKED) return true;
}
}
return false;
}
public boolean isBorderOpaque() {
@@ -60,7 +60,7 @@ public final class TitlePanel extends JPanel {
public final static Color ACTIVE_SIDE_BUTTON_BG = new Color(179, 197, 231);
public final static Color INACTIVE_SIDE_BUTTON_BG = new Color(200, 200, 200);
public static final int STRUT = 1;
public static final int STRUT = 0;
TitlePanel() {
super(new BorderLayout());
@@ -92,8 +92,12 @@ final class ToolWindowsPane extends JLayeredPane {
// Splitters
myVerticalSplitter = new ThreeComponentsSplitter(true);
myVerticalSplitter.setDividerWidth(0);
myVerticalSplitter.setDividerMouseZoneSize(5);
myVerticalSplitter.setBackground(Color.gray);
myHorizontalSplitter = new ThreeComponentsSplitter(false);
myHorizontalSplitter.setDividerWidth(0);
myHorizontalSplitter.setDividerMouseZoneSize(5);
myHorizontalSplitter.setBackground(Color.gray);
myVerticalSplitter.setInnerComponent(myHorizontalSplitter);
@@ -75,7 +75,6 @@ public class PositionPanel implements StatusBarWidget, StatusBarWidget.TextPrese
return "#############";
}
@Override
public float getAlignment() {
return JComponent.CENTER_ALIGNMENT;
}
@@ -141,7 +140,7 @@ public class PositionPanel implements StatusBarWidget, StatusBarWidget.TextPrese
public void caretPositionChanged(final CaretEvent e) {
final Editor editor = e.getEditor();
if (FileEditorManager.getInstance(editor.getProject()).getSelectedTextEditor() == e.getEditor()) {
if (editor.getProject() != null && FileEditorManager.getInstance(editor.getProject()).getSelectedTextEditor() == e.getEditor()) {
updatePosition(editor);
}
}