123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584 |
- /*
- @ITMillApache2LicenseForJavaFiles@
- */
-
- package com.vaadin.terminal.gwt.client.ui;
-
- import java.util.Set;
-
- import com.google.gwt.user.client.Command;
- import com.google.gwt.user.client.DOM;
- import com.google.gwt.user.client.DeferredCommand;
- import com.google.gwt.user.client.Element;
- import com.google.gwt.user.client.Event;
- import com.google.gwt.user.client.ui.ComplexPanel;
- import com.google.gwt.user.client.ui.RootPanel;
- import com.google.gwt.user.client.ui.Widget;
- import com.vaadin.terminal.gwt.client.ApplicationConnection;
- import com.vaadin.terminal.gwt.client.BrowserInfo;
- import com.vaadin.terminal.gwt.client.Container;
- import com.vaadin.terminal.gwt.client.ContainerResizedListener;
- import com.vaadin.terminal.gwt.client.Paintable;
- import com.vaadin.terminal.gwt.client.RenderInformation;
- import com.vaadin.terminal.gwt.client.RenderSpace;
- import com.vaadin.terminal.gwt.client.UIDL;
- import com.vaadin.terminal.gwt.client.Util;
-
- public class VSplitPanel extends ComplexPanel implements Container,
- ContainerResizedListener {
- public static final String CLASSNAME = "i-splitpanel";
-
- public static final int ORIENTATION_HORIZONTAL = 0;
-
- public static final int ORIENTATION_VERTICAL = 1;
-
- private static final int MIN_SIZE = 30;
-
- private int orientation = ORIENTATION_HORIZONTAL;
-
- private Widget firstChild;
-
- private Widget secondChild;
-
- private final Element wrapper = DOM.createDiv();
-
- private final Element firstContainer = DOM.createDiv();
-
- private final Element secondContainer = DOM.createDiv();
-
- private final Element splitter = DOM.createDiv();
-
- private boolean resizing;
-
- private int origX;
-
- private int origY;
-
- private int origMouseX;
-
- private int origMouseY;
-
- private boolean locked = false;
-
- private String[] componentStyleNames;
-
- private Element draggingCurtain;
-
- private ApplicationConnection client;
-
- private String width = "";
-
- private String height = "";
-
- private RenderSpace firstRenderSpace = new RenderSpace(0, 0, true);
- private RenderSpace secondRenderSpace = new RenderSpace(0, 0, true);
-
- RenderInformation renderInformation = new RenderInformation();
-
- private String id;
-
- private boolean immediate;
-
- private boolean rendering = false;
-
- public VSplitPanel() {
- this(ORIENTATION_HORIZONTAL);
- }
-
- public VSplitPanel(int orientation) {
- setElement(DOM.createDiv());
- switch (orientation) {
- case ORIENTATION_HORIZONTAL:
- setStyleName(CLASSNAME + "-horizontal");
- break;
- case ORIENTATION_VERTICAL:
- default:
- setStyleName(CLASSNAME + "-vertical");
- break;
- }
- // size below will be overridden in update from uidl, initial size
- // needed to keep IE alive
- setWidth(MIN_SIZE + "px");
- setHeight(MIN_SIZE + "px");
- constructDom();
- setOrientation(orientation);
- DOM.sinkEvents(splitter, (Event.MOUSEEVENTS));
- DOM.sinkEvents(getElement(), (Event.MOUSEEVENTS));
- }
-
- protected void constructDom() {
- DOM.appendChild(splitter, DOM.createDiv()); // for styling
- DOM.appendChild(getElement(), wrapper);
- DOM.setStyleAttribute(wrapper, "position", "relative");
- DOM.setStyleAttribute(wrapper, "width", "100%");
- DOM.setStyleAttribute(wrapper, "height", "100%");
-
- DOM.appendChild(wrapper, secondContainer);
- DOM.appendChild(wrapper, firstContainer);
- DOM.appendChild(wrapper, splitter);
-
- DOM.setStyleAttribute(splitter, "position", "absolute");
- DOM.setStyleAttribute(secondContainer, "position", "absolute");
-
- DOM.setStyleAttribute(firstContainer, "overflow", "auto");
- DOM.setStyleAttribute(secondContainer, "overflow", "auto");
-
- }
-
- private void setOrientation(int orientation) {
- this.orientation = orientation;
- if (orientation == ORIENTATION_HORIZONTAL) {
- DOM.setStyleAttribute(splitter, "height", "100%");
- DOM.setStyleAttribute(splitter, "top", "0");
- DOM.setStyleAttribute(firstContainer, "height", "100%");
- DOM.setStyleAttribute(secondContainer, "height", "100%");
- } else {
- DOM.setStyleAttribute(splitter, "width", "100%");
- DOM.setStyleAttribute(splitter, "left", "0");
- DOM.setStyleAttribute(firstContainer, "width", "100%");
- DOM.setStyleAttribute(secondContainer, "width", "100%");
- }
-
- DOM.setElementProperty(firstContainer, "className", CLASSNAME
- + "-first-container");
- DOM.setElementProperty(secondContainer, "className", CLASSNAME
- + "-second-container");
- }
-
- public void updateFromUIDL(UIDL uidl, ApplicationConnection client) {
- this.client = client;
- id = uidl.getId();
- rendering = true;
-
- immediate = uidl.hasAttribute("immediate");
-
- if (client.updateComponent(this, uidl, true)) {
- rendering = false;
- return;
- }
-
- if (uidl.hasAttribute("style")) {
- componentStyleNames = uidl.getStringAttribute("style").split(" ");
- } else {
- componentStyleNames = new String[0];
- }
-
- setLocked(uidl.getBooleanAttribute("locked"));
-
- setStylenames();
-
- setSplitPosition(uidl.getStringAttribute("position"));
-
- final Paintable newFirstChild = client.getPaintable(uidl
- .getChildUIDL(0));
- final Paintable newSecondChild = client.getPaintable(uidl
- .getChildUIDL(1));
- if (firstChild != newFirstChild) {
- if (firstChild != null) {
- client.unregisterPaintable((Paintable) firstChild);
- }
- setFirstWidget((Widget) newFirstChild);
- }
- if (secondChild != newSecondChild) {
- if (secondChild != null) {
- client.unregisterPaintable((Paintable) secondChild);
- }
- setSecondWidget((Widget) newSecondChild);
- }
- newFirstChild.updateFromUIDL(uidl.getChildUIDL(0), client);
- newSecondChild.updateFromUIDL(uidl.getChildUIDL(1), client);
-
- renderInformation.updateSize(getElement());
-
- if (BrowserInfo.get().isIE7()) {
- // Part III of IE7 hack
- DeferredCommand.addCommand(new Command() {
- public void execute() {
- iLayout();
- }
- });
- }
- rendering = false;
-
- }
-
- private void setLocked(boolean newValue) {
- if (locked != newValue) {
- locked = newValue;
- splitterSize = -1;
- setStylenames();
- }
- }
-
- private void setSplitPosition(String pos) {
- if (orientation == ORIENTATION_HORIZONTAL) {
- DOM.setStyleAttribute(splitter, "left", pos);
- } else {
- DOM.setStyleAttribute(splitter, "top", pos);
- }
- iLayout();
- client.runDescendentsLayout(this);
-
- }
-
- /*
- * Calculates absolutely positioned container places/sizes (non-Javadoc)
- *
- * @see com.vaadin.terminal.gwt.client.NeedsLayout#layout()
- */
- public void iLayout() {
- if (!isAttached()) {
- return;
- }
-
- renderInformation.updateSize(getElement());
-
- int wholeSize;
- int pixelPosition;
-
- switch (orientation) {
- case ORIENTATION_HORIZONTAL:
- wholeSize = DOM.getElementPropertyInt(wrapper, "clientWidth");
- pixelPosition = DOM.getElementPropertyInt(splitter, "offsetLeft");
-
- // reposition splitter in case it is out of box
- if (pixelPosition > 0
- && pixelPosition + getSplitterSize() > wholeSize) {
- pixelPosition = wholeSize - getSplitterSize();
- if (pixelPosition < 0) {
- pixelPosition = 0;
- }
- setSplitPosition(pixelPosition + "px");
- return;
- }
-
- DOM
- .setStyleAttribute(firstContainer, "width", pixelPosition
- + "px");
- int secondContainerWidth = (wholeSize - pixelPosition - getSplitterSize());
- if (secondContainerWidth < 0) {
- secondContainerWidth = 0;
- }
- DOM.setStyleAttribute(secondContainer, "width",
- secondContainerWidth + "px");
- DOM.setStyleAttribute(secondContainer, "left",
- (pixelPosition + getSplitterSize()) + "px");
-
- int contentHeight = renderInformation.getRenderedSize().getHeight();
- firstRenderSpace.setHeight(contentHeight);
- firstRenderSpace.setWidth(pixelPosition);
- secondRenderSpace.setHeight(contentHeight);
- secondRenderSpace.setWidth(secondContainerWidth);
-
- break;
- case ORIENTATION_VERTICAL:
- wholeSize = DOM.getElementPropertyInt(wrapper, "clientHeight");
- pixelPosition = DOM.getElementPropertyInt(splitter, "offsetTop");
-
- // reposition splitter in case it is out of box
- if (pixelPosition > 0
- && pixelPosition + getSplitterSize() > wholeSize) {
- pixelPosition = wholeSize - getSplitterSize();
- if (pixelPosition < 0) {
- pixelPosition = 0;
- }
- setSplitPosition(pixelPosition + "px");
- return;
- }
-
- DOM.setStyleAttribute(firstContainer, "height", pixelPosition
- + "px");
- int secondContainerHeight = (wholeSize - pixelPosition - getSplitterSize());
- if (secondContainerHeight < 0) {
- secondContainerHeight = 0;
- }
- DOM.setStyleAttribute(secondContainer, "height",
- secondContainerHeight + "px");
- DOM.setStyleAttribute(secondContainer, "top",
- (pixelPosition + getSplitterSize()) + "px");
-
- int contentWidth = renderInformation.getRenderedSize().getWidth();
- firstRenderSpace.setHeight(pixelPosition);
- firstRenderSpace.setWidth(contentWidth);
- secondRenderSpace.setHeight(secondContainerHeight);
- secondRenderSpace.setWidth(contentWidth);
-
- break;
- }
-
- // fixes scrollbars issues on webkit based browsers
- Util.runWebkitOverflowAutoFix(secondContainer);
- Util.runWebkitOverflowAutoFix(firstContainer);
-
- }
-
- private void setFirstWidget(Widget w) {
- if (firstChild != null) {
- firstChild.removeFromParent();
- }
- super.add(w, firstContainer);
- firstChild = w;
- }
-
- private void setSecondWidget(Widget w) {
- if (secondChild != null) {
- secondChild.removeFromParent();
- }
- super.add(w, secondContainer);
- secondChild = w;
- }
-
- @Override
- public void onBrowserEvent(Event event) {
- switch (DOM.eventGetType(event)) {
- case Event.ONMOUSEMOVE:
- if (resizing) {
- onMouseMove(event);
- }
- break;
- case Event.ONMOUSEDOWN:
- onMouseDown(event);
- break;
- case Event.ONMOUSEUP:
- if (resizing) {
- onMouseUp(event);
- }
- break;
- case Event.ONCLICK:
- resizing = false;
- break;
- }
- }
-
- public void onMouseDown(Event event) {
- if (locked) {
- return;
- }
- final Element trg = DOM.eventGetTarget(event);
- if (trg == splitter || trg == DOM.getChild(splitter, 0)) {
- resizing = true;
- if (BrowserInfo.get().isGecko()) {
- showDraggingCurtain();
- }
- DOM.setCapture(getElement());
- origX = DOM.getElementPropertyInt(splitter, "offsetLeft");
- origY = DOM.getElementPropertyInt(splitter, "offsetTop");
- origMouseX = DOM.eventGetClientX(event);
- origMouseY = DOM.eventGetClientY(event);
- DOM.eventCancelBubble(event, true);
- DOM.eventPreventDefault(event);
- }
- }
-
- public void onMouseMove(Event event) {
- switch (orientation) {
- case ORIENTATION_HORIZONTAL:
- final int x = DOM.eventGetClientX(event);
- onHorizontalMouseMove(x);
- break;
- case ORIENTATION_VERTICAL:
- default:
- final int y = DOM.eventGetClientY(event);
- onVerticalMouseMove(y);
- break;
- }
- iLayout();
- // TODO Check if this is needed
- client.runDescendentsLayout(this);
-
- }
-
- private void onHorizontalMouseMove(int x) {
- int newX = origX + x - origMouseX;
- if (newX < 0) {
- newX = 0;
- }
- if (newX + getSplitterSize() > getOffsetWidth()) {
- newX = getOffsetWidth() - getSplitterSize();
- }
- DOM.setStyleAttribute(splitter, "left", newX + "px");
- updateSplitPosition(newX);
- }
-
- private void onVerticalMouseMove(int y) {
- int newY = origY + y - origMouseY;
- if (newY < 0) {
- newY = 0;
- }
-
- if (newY + getSplitterSize() > getOffsetHeight()) {
- newY = getOffsetHeight() - getSplitterSize();
- }
- DOM.setStyleAttribute(splitter, "top", newY + "px");
- updateSplitPosition(newY);
- }
-
- public void onMouseUp(Event event) {
- DOM.releaseCapture(getElement());
- if (BrowserInfo.get().isGecko()) {
- hideDraggingCurtain();
- }
- resizing = false;
- onMouseMove(event);
- }
-
- /**
- * Used in FF to avoid losing mouse capture when pointer is moved on an
- * iframe.
- */
- private void showDraggingCurtain() {
- if (draggingCurtain == null) {
- draggingCurtain = DOM.createDiv();
- DOM.setStyleAttribute(draggingCurtain, "position", "absolute");
- DOM.setStyleAttribute(draggingCurtain, "top", "0px");
- DOM.setStyleAttribute(draggingCurtain, "left", "0px");
- DOM.setStyleAttribute(draggingCurtain, "width", "100%");
- DOM.setStyleAttribute(draggingCurtain, "height", "100%");
- DOM.setStyleAttribute(draggingCurtain, "zIndex", ""
- + VToolkitOverlay.Z_INDEX);
- DOM.appendChild(RootPanel.getBodyElement(), draggingCurtain);
- }
- }
-
- /**
- * Hides dragging curtain
- */
- private void hideDraggingCurtain() {
- if (draggingCurtain != null) {
- DOM.removeChild(RootPanel.getBodyElement(), draggingCurtain);
- draggingCurtain = null;
- }
- }
-
- private int splitterSize = -1;
-
- private int getSplitterSize() {
- if (splitterSize < 0) {
- if (isAttached()) {
- switch (orientation) {
- case ORIENTATION_HORIZONTAL:
- splitterSize = DOM.getElementPropertyInt(splitter,
- "offsetWidth");
- break;
-
- default:
- splitterSize = DOM.getElementPropertyInt(splitter,
- "offsetHeight");
- break;
- }
- }
- }
- return splitterSize;
- }
-
- @Override
- public void setHeight(String height) {
- if (this.height.equals(height)) {
- return;
- }
-
- this.height = height;
- super.setHeight(height);
- if (!rendering && client != null) {
- iLayout();
- client.runDescendentsLayout(this);
- }
- }
-
- @Override
- public void setWidth(String width) {
- if (this.width.equals(width)) {
- return;
- }
-
- this.width = width;
- super.setWidth(width);
- if (!rendering && client != null) {
- iLayout();
- client.runDescendentsLayout(this);
- }
- }
-
- public RenderSpace getAllocatedSpace(Widget child) {
- if (child == firstChild) {
- return firstRenderSpace;
- } else if (child == secondChild) {
- return secondRenderSpace;
- }
-
- return null;
- }
-
- public boolean hasChildComponent(Widget component) {
- return (component != null && (component == firstChild || component == secondChild));
- }
-
- public void replaceChildComponent(Widget oldComponent, Widget newComponent) {
- if (oldComponent == firstChild) {
- setFirstWidget(newComponent);
- } else if (oldComponent == secondChild) {
- setSecondWidget(newComponent);
- }
- }
-
- public boolean requestLayout(Set<Paintable> child) {
- if (height != null && width != null) {
- /*
- * If the height and width has been specified the child components
- * cannot make the size of the layout change
- */
-
- return true;
- }
-
- if (renderInformation.updateSize(getElement())) {
- return false;
- } else {
- return true;
- }
-
- }
-
- public void updateCaption(Paintable component, UIDL uidl) {
- // TODO Implement caption handling
- }
-
- /**
- * Updates the new split position back to server.
- *
- * @param pos
- * The new position of the split handle.
- */
- private void updateSplitPosition(int pos) {
- // We always send pixel values to server
- client.updateVariable(id, "position", pos, immediate);
- }
-
- private void setStylenames() {
- final String splitterSuffix = (orientation == ORIENTATION_HORIZONTAL ? "-hsplitter"
- : "-vsplitter");
- final String firstContainerSuffix = "-first-container";
- final String secondContainerSuffix = "-second-container";
- String lockedSuffix = "";
-
- String splitterStyle = CLASSNAME + splitterSuffix;
- String firstStyle = CLASSNAME + firstContainerSuffix;
- String secondStyle = CLASSNAME + secondContainerSuffix;
-
- if (locked) {
- splitterStyle = CLASSNAME + splitterSuffix + "-locked";
- lockedSuffix = "-locked";
- }
- for (int i = 0; i < componentStyleNames.length; i++) {
- splitterStyle += " " + CLASSNAME + splitterSuffix + "-"
- + componentStyleNames[i] + lockedSuffix;
- firstStyle += " " + CLASSNAME + firstContainerSuffix + "-"
- + componentStyleNames[i];
- secondStyle += " " + CLASSNAME + secondContainerSuffix + "-"
- + componentStyleNames[i];
- }
- DOM.setElementProperty(splitter, "className", splitterStyle);
- DOM.setElementProperty(firstContainer, "className", firstStyle);
- DOM.setElementProperty(secondContainer, "className", secondStyle);
- }
- }
|