blob: 2b0097005dc1decbd1eea7b5f077de5aae08d638 [file] [log] [blame]
/*
* 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.ui;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.util.SystemInfo;
import com.intellij.openapi.util.Weighted;
import com.intellij.openapi.wm.IdeGlassPane;
import com.intellij.openapi.wm.IdeGlassPaneUtil;
import com.intellij.ui.Gray;
import com.intellij.ui.JBColor;
import javax.swing.*;
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
/**
* @author Konstantin Bulenkov
*/
public class OnePixelDivider extends Divider {
private boolean myVertical;
private Splitter mySplitter;
private boolean myResizeEnabled;
private boolean mySwitchOrientationEnabled;
protected Point myPoint;
private IdeGlassPane myGlassPane;
private final MouseAdapter myListener = new MyMouseAdapter();
private Disposable myDisposable;
public OnePixelDivider(boolean vertical, Splitter splitter) {
super(new GridBagLayout());
mySplitter = splitter;
myResizeEnabled = true;
mySwitchOrientationEnabled = false;
setFocusable(false);
enableEvents(AWTEvent.MOUSE_EVENT_MASK | AWTEvent.MOUSE_MOTION_EVENT_MASK);
//setOpaque(false);
setOrientation(vertical);
setBackground(new JBColor(Gray._153.withAlpha(128), Gray._100.withAlpha(128)));
}
@Override
public void addNotify() {
super.addNotify();
init();
}
@Override
public void removeNotify() {
super.removeNotify();
if (myDisposable != null && !Disposer.isDisposed(myDisposable)) {
Disposer.dispose(myDisposable);
}
}
private boolean dragging = false;
private class MyMouseAdapter extends MouseAdapter implements Weighted {
@Override
public void mousePressed(MouseEvent e) {
dragging = isInDragZone(e);
_processMouseEvent(e);
}
boolean isInDragZone(MouseEvent e) {
final MouseEvent event = getTargetEvent(e);
final Point p = event.getPoint();
final int r = Math.abs(isVertical() ? p.y : p.x);
return r < 6;
}
@Override
public void mouseReleased(MouseEvent e) {
_processMouseEvent(e);
dragging = false;
}
@Override
public void mouseMoved(MouseEvent e) {
final OnePixelDivider divider = OnePixelDivider.this;
if (isInDragZone(e)) {
myGlassPane.setCursor(divider.getCursor(), divider);
} else {
myGlassPane.setCursor(null, divider);
}
_processMouseMotionEvent(e);
}
@Override
public void mouseDragged(MouseEvent e) {
_processMouseMotionEvent(e);
}
@Override
public double getWeight() {
return 1;
}
private void _processMouseMotionEvent(MouseEvent e) {
MouseEvent event = getTargetEvent(e);
if (event == null) {
myGlassPane.setCursor(null, myListener);
return;
}
processMouseMotionEvent(event);
if (event.isConsumed()) {
e.consume();
}
}
private void _processMouseEvent(MouseEvent e) {
MouseEvent event = getTargetEvent(e);
if (event == null) {
myGlassPane.setCursor(null, myListener);
return;
}
processMouseEvent(event);
if (event.isConsumed()) {
e.consume();
}
}
}
private MouseEvent getTargetEvent(MouseEvent e) {
return SwingUtilities.convertMouseEvent(e.getComponent(), e, this);
}
private void init() {
myGlassPane = IdeGlassPaneUtil.find(this);
myDisposable = Disposer.newDisposable();
myGlassPane.addMouseMotionPreprocessor(myListener, myDisposable);
myGlassPane.addMousePreprocessor(myListener, myDisposable);
}
public void setOrientation(boolean vertical) {
removeAll();
myVertical = vertical;
final int cursorType = isVertical() ? Cursor.N_RESIZE_CURSOR : Cursor.W_RESIZE_CURSOR;
setCursor(Cursor.getPredefinedCursor(cursorType));
}
@Override
protected void processMouseMotionEvent(MouseEvent e) {
super.processMouseMotionEvent(e);
if (!myResizeEnabled) return;
if (MouseEvent.MOUSE_DRAGGED == e.getID() && dragging) {
myPoint = SwingUtilities.convertPoint(this, e.getPoint(), mySplitter);
float proportion;
final float firstMinProportion = getMinProportion(mySplitter.getFirstComponent());
final float secondMinProportion = getMinProportion(mySplitter.getSecondComponent());
if (isVertical()) {
if (getHeight() > 0) {
proportion = Math.min(1.0f, Math
.max(.0f, Math.min(Math.max(firstMinProportion, (float)myPoint.y / (float)mySplitter.getHeight()), 1 - secondMinProportion)));
mySplitter.setProportion(proportion);
}
}
else {
if (getWidth() > 0) {
proportion = Math.min(1.0f, Math.max(.0f, Math.min(
Math.max(firstMinProportion, (float)myPoint.x / (float)mySplitter.getWidth()), 1 - secondMinProportion)));
mySplitter.setProportion(proportion);
}
}
}
}
private float getMinProportion(JComponent component) {
if (component != null &&
mySplitter.getFirstComponent() != null &&
mySplitter.getFirstComponent().isVisible() &&
mySplitter.getSecondComponent() != null &&
mySplitter.getSecondComponent().isVisible()) {
if (isVertical()) {
return (float)component.getMinimumSize().height / (float)(mySplitter.getHeight() - 1);
} else {
return (float)component.getMinimumSize().width / (float)(mySplitter.getWidth() - 1);
}
}
return 0.0f;
}
@Override
protected void processMouseEvent(MouseEvent e) {
super.processMouseEvent(e);
if (e.getID() == MouseEvent.MOUSE_CLICKED) {
if (mySwitchOrientationEnabled
&& e.getClickCount() == 1
&& SwingUtilities.isLeftMouseButton(e) && (SystemInfo.isMac ? e.isMetaDown() : e.isControlDown())) {
mySplitter.setOrientation(!mySplitter.getOrientation());
}
if (myResizeEnabled && e.getClickCount() == 2) {
mySplitter.setProportion(.5f);
}
}
}
public void setResizeEnabled(boolean resizeEnabled) {
myResizeEnabled = resizeEnabled;
if (!myResizeEnabled) {
setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
}
else {
setCursor(isVertical() ?
Cursor.getPredefinedCursor(Cursor.N_RESIZE_CURSOR) :
Cursor.getPredefinedCursor(Cursor.W_RESIZE_CURSOR));
}
}
public void setSwitchOrientationEnabled(boolean switchOrientationEnabled) {
mySwitchOrientationEnabled = switchOrientationEnabled;
}
public boolean isVertical() {
return myVertical;
}
}