📄 splittedpanel.java
字号:
/*
* Copyright 2006-2007 Queplix Corp.
*
* Licensed under the Queplix Public License, Version 1.1.1 (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.queplix.com/solutions/commercial-open-source/queplix-public-license/
*
* 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.queplix.core.client.common.ui;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.ui.AbsolutePanel;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.MouseListenerAdapter;
import com.google.gwt.user.client.ui.Widget;
import com.queplix.core.client.app.Application;
import com.queplix.core.client.common.StringUtil;
import com.queplix.core.client.common.ui.resizable.Resizable;
import com.queplix.core.client.common.ui.resizable.ResizableEnforcer;
/**
* Splitted panel.
* @author Sultan Tezadov
* @since 21 Oct 2006
*/
public class SplittedPanel extends Composite implements Resizable {
public static final int HORIZONTAL = 0;
public static final int VERTICAL = 1;
private static final String CSS_CLASS = "Splitter_handle_";
private AbsolutePanel panel;
private Label handle;
private float firstSizeFactor;
private int panelOrientation;
ResizableEnforcer firstWidget;
ResizableEnforcer secondWidget;
private boolean splitterHasBeenDragged;
private boolean splitterCollapsed;
private static final int MIN_VERTICAL_OFFSET =
Application.isInternetExplorer() ? 2 : 0; // in IE need to limit by at least 2 pixels
// otherwise there is a visual bug
public SplittedPanel(Resizable firstWidget,
Resizable secondWidget,
int splitterOffsetPercent,
int panelOrientation) {
if (! (firstWidget instanceof Widget)) {
throw new IllegalArgumentException(
"Illegal argument: firstWidget. Must be instance of Widget or a subclass of Widget.");
}
if (! (secondWidget instanceof Widget)) {
throw new IllegalArgumentException(
"Illegal argument: secondWidget. Must be instance of Widget or a subclass of Widget.");
}
if ((splitterOffsetPercent < 1) || (splitterOffsetPercent > 99)) {
throw new IllegalArgumentException(
"Illegal argument: splitterOffsetPercent. Must be percent value in the range 1..99.");
}
if ((panelOrientation != HORIZONTAL) && (panelOrientation != VERTICAL)) {
throw new IllegalArgumentException(
"Illegal argument: panelOrientation. Valid values: SplittedPanel.HORIZONTAL, SplittedPanel.VERTICAL.");
}
this.firstSizeFactor = splitterOffsetPercent / 100.0f;
this.panel = new AbsolutePanel();
this.panelOrientation = panelOrientation;
this.firstWidget = new ResizableEnforcer(firstWidget);
this.secondWidget = new ResizableEnforcer(secondWidget);
this.splitterHasBeenDragged = false;
initHandle(panelOrientation);
panel.add(this.firstWidget);
panel.add(handle);
panel.add(this.secondWidget);
initWidget(panel);
}
// =================== Resizable implementation ================
private int offsetHeight;
private int offsetWidth;
public int getOffsetWidth() {
return (offsetWidth > 0) ? offsetWidth : super.getOffsetWidth();
}
public int getOffsetHeight() {
return (offsetHeight > 0) ? offsetHeight : super.getOffsetHeight();
}
public void setOffsetHeight(int height) {
if (height < 0) return; // invalid argument
if (panelOrientation == HORIZONTAL) {
String heightSize = StringUtil.pixelToSize(height);
handle.setHeight(heightSize);
firstWidget.setOffsetHeight(height);
secondWidget.setOffsetHeight(height);
panel.setHeight(heightSize);
} else if (panelOrientation == VERTICAL) {
offsetHeight = height;
if (isAttached()) {
layoutChildren();
}
}
}
// public int getOffsetHeight(); -- already implemented in Widget
public void setOffsetWidth(int width) {
if (width < 0) return; // invalid argument
if (panelOrientation == HORIZONTAL) {
offsetWidth = width;
if (isAttached()) {
layoutChildren();
}
} else if (panelOrientation == VERTICAL) {
String widthSize = StringUtil.pixelToSize(width);
handle.setWidth(widthSize);
firstWidget.setOffsetWidth(width);
secondWidget.setOffsetWidth(width);
panel.setWidth(widthSize);
}
}
// public int getOffsetWidth(); -- already implemented in Widget
protected void onAttach() {
super.onAttach();
layoutChildren();
}
public void setHeight(String height) {
offsetHeight = -1; // unset offsetHeight
super.setHeight(height);
}
public void setWidth(String width) {
offsetWidth = -1; // unset offsetWidth
super.setWidth(width);
}
public void setSize(String width, String height) {
offsetHeight = -1; // unset offsetHeight
offsetWidth = -1; // unset offsetWidth
super.setSize(width, height);
}
public void setPixelSize(int width, int height) {
offsetHeight = -1; // unset offsetHeight
offsetWidth = -1; // unset offsetWidth
super.setPixelSize(width, height);
}
// =================== End of Resizable implementation ==================
// =================== Splitter handle implementation ===================
private boolean isMouseDown = false;
private int beginX = 0;
private int beginY = 0;
private void initHandle(int panelOrientation) {
handle = new Label(" ");
switch (panelOrientation) {
case HORIZONTAL:
handle.setStyleName(CSS_CLASS + "h");
break;
case VERTICAL:
handle.setStyleName(CSS_CLASS + "v");
break;
default:
throw new IllegalArgumentException(
"Illegal argument: panelOrientation. Valid values: SplittedPanel.HORIZONTAL, SplittedPanel.VERTICAL.");
}
handle.addMouseListener(new MouseListenerAdapter(){
public void onMouseDown(Widget sender, int x, int y){
isMouseDown = true;
DOM.setCapture(sender.getElement());
beginX = x;
beginY = y;
}
public void onMouseMove(Widget sender, int x, int y){
if(isMouseDown){
int offsetX = x - beginX;
int offsetY = y - beginY;
moveSplitter(offsetX, offsetY);
}
}
public void onMouseUp(Widget sender, int x, int y){
splitterHasBeenDragged = true;
DOM.releaseCapture(sender.getElement());
isMouseDown = false;
layoutChildren();
}
});
}
private void moveSplitter(int offsetX, int offsetY) {
int splitterOffset = 0;
if (panelOrientation == HORIZONTAL) {
splitterOffset = panel.getWidgetLeft(handle) + offsetX;
} else if (panelOrientation == VERTICAL) {
splitterOffset = panel.getWidgetTop(handle) + offsetY;
}
setSplitterOffset(splitterOffset);
}
private void layoutChildren() {
layoutChildren(getSplitterOffset());
}
private void layoutChildren(int splitterOffset) {
int offsetHeight = getOffsetHeight();
int offsetWidth = getOffsetWidth();
if ((offsetHeight > 0) && (offsetWidth > 0)) { // both are set
if (panelOrientation == HORIZONTAL) {
layoutChildrenHorizontal(splitterOffset);
} else if (panelOrientation == VERTICAL) {
layoutChildrenVertical(splitterOffset);
}
super.setPixelSize(offsetWidth, offsetHeight);
}
}
private void setSplitterOffset(int splitterOffset) {
int newX = (panelOrientation == HORIZONTAL) ? splitterOffset : 0;
int newY = (panelOrientation == VERTICAL) ? splitterOffset : 0;
panel.setWidgetPosition(handle, newX, newY);
}
private int getSplitterOffset() {
int splitterOffset;
if (splitterCollapsed) {
splitterOffset = 0;
} else if (splitterHasBeenDragged) {
splitterOffset = getActualSplitterOffset();
} else {
splitterOffset = getDefaultSplitterOffset();
}
return splitterOffset;
}
private int getDefaultSplitterOffset() {
int offset = (panelOrientation == HORIZONTAL) ?
getOffsetWidth() :
getOffsetHeight();
int defaultOffset = (int) (offset * firstSizeFactor);
return defaultOffset;
}
private int getActualSplitterOffset() {
int offset = (panelOrientation == HORIZONTAL) ?
panel.getWidgetLeft(handle) :
panel.getWidgetTop(handle);
return offset;
}
private void layoutChildrenHorizontal(int splitterOffset) {
int offsetHeight = getOffsetHeight();
int offsetWidth = getOffsetWidth();
splitterOffset = (splitterOffset > 0) ? splitterOffset : 0;
int offsetLimit = offsetWidth - handle.getOffsetWidth();
splitterOffset = (splitterOffset < offsetLimit) ? splitterOffset : offsetLimit;
panel.setWidgetPosition(firstWidget, 0, 0);
firstWidget.setOffsetHeight(offsetHeight);
firstWidget.setOffsetWidth(splitterOffset - 1);
panel.setWidgetPosition(handle, splitterOffset, 0);
int secondLeft = splitterOffset + handle.getOffsetWidth();
panel.setWidgetPosition(secondWidget, secondLeft, 0);
secondWidget.setOffsetHeight(offsetHeight);
secondWidget.setOffsetWidth(offsetWidth - secondLeft);
}
private void layoutChildrenVertical(int splitterOffset) {
int offsetHeight = getOffsetHeight();
int offsetWidth = getOffsetWidth();
splitterOffset = (splitterOffset > MIN_VERTICAL_OFFSET) ? splitterOffset : MIN_VERTICAL_OFFSET;
int offsetLimit = offsetHeight - handle.getOffsetHeight();
splitterOffset = (splitterOffset < offsetLimit) ? splitterOffset : offsetLimit;
panel.setWidgetPosition(firstWidget, 0, 0);
firstWidget.setOffsetHeight(splitterOffset - 1);
firstWidget.setOffsetWidth(offsetWidth);
panel.setWidgetPosition(handle, 0, splitterOffset);
int secondTop = splitterOffset + handle.getOffsetHeight();
panel.setWidgetPosition(secondWidget, 0, secondTop);
secondWidget.setOffsetHeight(offsetHeight - secondTop);
secondWidget.setOffsetWidth(offsetWidth);
}
// =================== End of Splitter handle implementation ============
private void setSplitterPosition(int position) {
setSplitterOffset(position);
layoutChildren(position);
}
public boolean isSplitterCollapsed() {
return splitterCollapsed;
}
public void setSplitterCollapsed(boolean splitterCollapsed) {
this.splitterCollapsed = splitterCollapsed;
int offset = splitterCollapsed ? 0 : getDefaultSplitterOffset();
setSplitterPosition(offset);
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -