Package com.sencha.gxt.widget.core.client

Source Code of com.sencha.gxt.widget.core.client.SplitBar$SplitBarAppearance

/**
* Sencha GXT 3.0.0 - Sencha for GWT
* Copyright(c) 2007-2012, Sencha, Inc.
* licensing@sencha.com
*
* http://www.sencha.com/products/gxt/license/
*/
package com.sencha.gxt.widget.core.client;

import com.google.gwt.core.client.GWT;
import com.google.gwt.dom.client.Style.Cursor;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.DoubleClickEvent;
import com.google.gwt.event.dom.client.DoubleClickHandler;
import com.google.gwt.event.dom.client.HasClickHandlers;
import com.google.gwt.event.dom.client.HasDoubleClickHandlers;
import com.google.gwt.event.logical.shared.AttachEvent;
import com.google.gwt.event.logical.shared.ResizeEvent;
import com.google.gwt.event.logical.shared.ResizeHandler;
import com.google.gwt.event.shared.HandlerRegistration;
import com.google.gwt.safehtml.shared.SafeHtmlBuilder;
import com.google.gwt.user.client.Event;
import com.sencha.gxt.core.client.Style.Direction;
import com.sencha.gxt.core.client.Style.LayoutRegion;
import com.sencha.gxt.core.client.dom.XDOM;
import com.sencha.gxt.core.client.dom.XElement;
import com.sencha.gxt.core.client.resources.CommonStyles;
import com.sencha.gxt.core.client.util.DelayedTask;
import com.sencha.gxt.core.client.util.Rectangle;
import com.sencha.gxt.core.shared.event.GroupingHandlerRegistration;
import com.sencha.gxt.fx.client.DragCancelEvent;
import com.sencha.gxt.fx.client.DragEndEvent;
import com.sencha.gxt.fx.client.DragHandler;
import com.sencha.gxt.fx.client.DragMoveEvent;
import com.sencha.gxt.fx.client.DragStartEvent;
import com.sencha.gxt.fx.client.Draggable;
import com.sencha.gxt.widget.core.client.event.HideEvent;
import com.sencha.gxt.widget.core.client.event.HideEvent.HideHandler;
import com.sencha.gxt.widget.core.client.event.MoveEvent;
import com.sencha.gxt.widget.core.client.event.MoveEvent.MoveHandler;
import com.sencha.gxt.widget.core.client.event.SelectEvent;
import com.sencha.gxt.widget.core.client.event.SelectEvent.HasSelectHandlers;
import com.sencha.gxt.widget.core.client.event.SelectEvent.SelectHandler;
import com.sencha.gxt.widget.core.client.event.ShowEvent;
import com.sencha.gxt.widget.core.client.event.ShowEvent.ShowHandler;
import com.sencha.gxt.widget.core.client.event.SplitBarDragEvent;
import com.sencha.gxt.widget.core.client.event.SplitBarDragEvent.HasSplitBarDragHandlers;
import com.sencha.gxt.widget.core.client.event.SplitBarDragEvent.SplitBarDragHandler;

/**
* Creates a draggable splitter on the side of a widget.
*/
public class SplitBar extends Component implements HasClickHandlers, HasDoubleClickHandlers, HasSplitBarDragHandlers,
    HasSelectHandlers {

  @SuppressWarnings("javadoc")
  public interface SplitBarAppearance {
    String miniClass(Direction direction);

    String miniSelector();

    void onMiniOver(XElement mini, boolean over);

    String proxyClass();

    void render(SafeHtmlBuilder sb, LayoutRegion region);
  }

  private class Handler implements AttachEvent.Handler, ResizeHandler, MoveHandler, HideHandler, ShowHandler {

    @Override
    public void onAttachOrDetach(AttachEvent event) {
      if (event.isAttached()) {
        onHandleAttach();
      } else {
        onHandleDetach();
      }
    }

    @Override
    public void onHide(HideEvent event) {
      onHandleHide(event);
    }

    @Override
    public void onMove(MoveEvent event) {
      delay.delay(10);
    }

    @Override
    public void onResize(ResizeEvent event) {
      delay.delay(10);
    }

    @Override
    public void onShow(ShowEvent event) {
      onHandleShow(event);
    }
  }

  private boolean autoSize = true;
  private int yOffset = 0;
  private int xOffset = 0;

  private int minSize = 10;
  private int maxSize = 2000;

  private int handleWidth = 5;
  private int barWidth = 2;
  private XElement resizeEl, miniEl;
  private Component resizeWidget;
  private Component containerWidget;
  private Draggable draggable;
  private Rectangle startBounds;
  private DelayedTask delay;
  protected LayoutRegion region;

  private GroupingHandlerRegistration handlerRegistration;
  private boolean collapsible;
  private final SplitBarAppearance appearance;
  private boolean disableDragging;

  /**
   * Creates a split for bar for the specified layout region and target.
   *
   * @param region the layout region
   * @param target the split bar container
   */
  public SplitBar(LayoutRegion region, Component target) {
    this(GWT.<SplitBarAppearance> create(SplitBarAppearance.class), region, target);
  }

  /**
   * Creates a new split bar.
   *
   * @param style the bar location
   * @param resizeWidget the widget being resized
   * @param container the widget the split bar proxy will be sized to
   */
  public SplitBar(LayoutRegion style, Component resizeWidget, Component container) {
    this(style, resizeWidget);
    this.containerWidget = container;
    draggable.setContainer(container);
  }

  /**
   * Creates a new split bar with the specified appearance
   *
   * @param appearance the split bar appearance
   * @param region the bar location
   * @param resizeWidget the widget being resized
   */
  public SplitBar(SplitBarAppearance appearance, LayoutRegion region, Component resizeWidget) {
    this.appearance = appearance;
    this.region = region;
    this.resizeWidget = resizeWidget;
    this.resizeEl = resizeWidget.getElement();

    SafeHtmlBuilder builder = new SafeHtmlBuilder();
    this.appearance.render(builder, region);

    setElement(XDOM.create(builder.toSafeHtml()));

    setAllowTextSelection(false);
    getElement().makePositionable(true);

    Handler handler = new Handler();
    handlerRegistration = new GroupingHandlerRegistration();
    handlerRegistration.add(resizeWidget.addAttachHandler(handler));
    handlerRegistration.add(resizeWidget.addMoveHandler(handler));
    handlerRegistration.add(resizeWidget.addResizeHandler(handler));
    handlerRegistration.add(resizeWidget.addHideHandler(handler));
    handlerRegistration.add(resizeWidget.addShowHandler(handler));

    draggable = new Draggable(this);
    draggable.setUpdateZIndex(false);
    draggable.setStartDragDistance(0);
    draggable.setProxyStyle(appearance.proxyClass());

    DragHandler dragHandler = new DragHandler() {
      @Override
      public void onDragCancel(DragCancelEvent event) {
        onCancelDrag(event);
      }

      @Override
      public void onDragEnd(DragEndEvent event) {
        onEndDrag(event);
      }

      @Override
      public void onDragMove(DragMoveEvent event) {

      }

      @Override
      public void onDragStart(DragStartEvent event) {
        onStartDrag(event);
      }
    };

    draggable.addDragHandler(dragHandler);

    if (resizeWidget.isAttached()) {
      onHandleAttach();
    }

    delay = new DelayedTask() {

      @Override
      public void onExecute() {
        sync();
      }
    };

    sinkEvents(Event.ONCLICK | Event.ONMOUSEOVER | Event.ONMOUSEOUT);
  }

  @Override
  public HandlerRegistration addClickHandler(ClickHandler handler) {
    return addDomHandler(handler, ClickEvent.getType());
  }

  @Override
  public HandlerRegistration addDoubleClickHandler(DoubleClickHandler handler) {
    return addDomHandler(handler, DoubleClickEvent.getType());
  }

  @Override
  public HandlerRegistration addSelectHandler(SelectHandler handler) {
    return addHandler(handler, SelectEvent.getType());
  }

  @Override
  public HandlerRegistration addSplitBarDragHandler(SplitBarDragHandler handler) {
    return addHandler(handler, SplitBarDragEvent.getType());
  }

  /**
   * Prevents the split bar from being dragged.
   */
  public void disableDragging() {
    if (!disableDragging) {
      disableDragging = true;
      draggable.release();
      getElement().getStyle().setCursor(Cursor.DEFAULT);
    }
  }

  /**
   * Returns the split bar appearance.
   *
   * @return the split bar appearance
   */
  public SplitBarAppearance getAppearance() {
    return appearance;
  }

  /**
   * Returns the bar width.
   *
   * @return the bar width
   */
  public int getBarWidth() {
    return barWidth;
  }

  /**
   * Returns the container widget.
   *
   * @return the container widget
   */
  public Component getContainer() {
    return containerWidget;
  }

  /**
   * Returns the split bar's draggable instance.
   *
   * @return the draggable instance
   */
  public Draggable getDraggable() {
    return draggable;
  }

  /**
   * Returns the handle width.
   *
   * @return the handle width
   */
  public int getHandleWidth() {
    return handleWidth;
  }

  /**
   * Returns the maximum size.
   *
   * @return the max size
   */
  public int getMaxSize() {
    return maxSize;
  }

  /**
   * @return the minSize
   */
  public int getMinSize() {
    return minSize;
  }

  /**
   * Returns the resize widget.
   *
   * @return the resize widget
   */
  public Component getTargetWidget() {
    return resizeWidget;
  }

  /**
   * Returns the x offset.
   *
   * @return the x offset value
   */
  public int getXOffset() {
    return xOffset;
  }

  /**
   * Returns the y offset.
   *
   * @return the y offset
   */
  public int getYOffset() {
    return yOffset;
  }

  /**
   * Returns the auto size state.
   *
   * @return true if auto size is enabled
   */
  public boolean isAutoSize() {
    return autoSize;
  }

  /**
   * Return true if the mini-collapse tool is enabled.
   *
   * @return true if mini-collapse enabled
   */
  public boolean isCollapsible() {
    return collapsible;
  }

  @Override
  public void onBrowserEvent(Event event) {
    super.onBrowserEvent(event);
    switch (event.getTypeInt()) {
      case Event.ONCLICK:
        onClick(event);
        break;
      case Event.ONMOUSEOVER:
        onMouseOver(event);
        break;

      case Event.ONMOUSEOUT:
        onMouseOut(event);
        break;
    }
  }

  /**
   * Removes the split bar from the resize widget.
   */
  public void release() {
    handlerRegistration.removeHandler();

    removeSplitBar();
    draggable.release();
  }

  /**
   * True to update the size of the the resize widget after a drag operation
   * using a proxy (defaults to true).
   *
   * @param autoSize the auto size state
   */
  public void setAutoSize(boolean autoSize) {
    this.autoSize = autoSize;
  }

  /**
   * Sets the width of drag proxy during resizing (defaults to 2).
   *
   * @param barWidth the bar width
   */
  public void setBarWidth(int barWidth) {
    this.barWidth = barWidth;
  }

  /**
   * True to show a mini-collapse tool in the split bar (defaults to false).
   * When clicked, the collapse event is fired.
   *
   * @param collapsible true to add the mini-collapse tool
   */
  public void setCollapsible(boolean collapsible) {
    this.collapsible = collapsible;
    if (miniEl == null) {
      miniEl = XElement.createElement("div");
      miniEl.setClassName(CommonStyles.get().nodrag() + " " + appearance.miniClass(Direction.LEFT));
      getElement().appendChild(miniEl);

    }
    miniEl.setDisplayed(collapsible);
  }

  /**
   * Sets the width of the drag handles (defaults to 5).
   *
   * @param handleWidth the handle width
   */
  public void setHandleWidth(int handleWidth) {
    this.handleWidth = handleWidth;
  }

  /**
   * Sets the maximum size of the resize widget (defaults to 2000).
   *
   * @param maxSize the maximum size
   */
  public void setMaxSize(int maxSize) {
    this.maxSize = maxSize;
  }

  /**
   * Sets he minimum size of the resize widget (defaults to 10).
   *
   * @param minSize the minimum size
   */
  public void setMinSize(int minSize) {
    this.minSize = minSize;
  }

  /**
   * The amount of pixels the bar should be offset to the left (defaults to 0).
   *
   * @param x the xOffset to set
   */
  public void setXOffset(int x) {
    this.xOffset = x;
  }

  /**
   * Sets the amount of pixels the bar should be offset to the top (defaults to
   * 0).
   *
   * @param y the yOffset to set
   */
  public void setYOffset(int y) {
    this.yOffset = y;
  }

  /**
   * Updates the spitbar's bounds to match the target widget.
   */
  public void sync() {
    if (!isAttached() || !resizeWidget.isAttached()) {
      return;
    }

    Rectangle rect = resizeEl.getBounds();
    int x = rect.getX();
    int y = rect.getY();

    // if (!GXT.isBorderBox()) {
    // y -= resizeEl.getFrameWidth(Side.TOP);
    // x -= resizeEl.getFrameWidth(Side.LEFT);
    // }

    y = Math.max(y, 0);

    int w = rect.getWidth();
    int h = rect.getHeight();

    switch (region) {
      case SOUTH:
        getElement().setBounds(x + getXOffset(), y + h + getYOffset(), w, getHandleWidth(), false);
        break;
      case WEST:
        getElement().setBounds(x - getHandleWidth() + getYOffset(), y + getXOffset(), getHandleWidth(), h, false);
        break;
      case NORTH:
        getElement().setBounds(x + getXOffset(), y - getHandleWidth() + getYOffset(), w, getHandleWidth(), false);
        break;
      case EAST:
        getElement().setBounds(Math.max(0, x + w + getXOffset()), y + getYOffset(), getHandleWidth(), h, false);
        break;
    }

  }

  /**
   * Sets the visual style indicating the direction of the mini collapse tool.
   *
   * @param direction the collapse direction
   */
  public void updateMini(Direction direction) {
    if (miniEl != null) {
      miniEl.setClassName(CommonStyles.get().nodrag() + " " + appearance.miniClass(direction));
    }
  }

  protected void onClick(Event event) {
    XElement target = event.getEventTarget().<XElement> cast();
    if (target == miniEl) {
      event.stopPropagation();
      onMiniClick();
    }
  }

  protected void onHandleAttach() {
    if (!disabled) {
      resizeWidget.getParent().getElement().appendChild(getElement());
      ComponentHelper.doAttach(SplitBar.this);
      sync();
    }
  }

  protected void onHandleDetach() {
    if (!disabled) {
      removeSplitBar();
    }
  }

  protected void onHandleHide(HideEvent event) {
    hide();
  }

  protected void onHandleShow(ShowEvent event) {
    show();
    sync();
  }

  protected void onMiniClick() {
    fireEvent(new SelectEvent());
  }

  protected void onMouseOut(Event event) {
    if (event.getEventTarget().cast() == miniEl) {
      appearance.onMiniOver(miniEl, false);
    }
  }

  protected void onMouseOver(Event event) {
    if (event.getEventTarget().cast() == miniEl) {
      appearance.onMiniOver(miniEl, true);
    }
  }

  protected void removeSplitBar() {
    ComponentHelper.doDetach(this);
    getElement().removeFromParent();
  }

  private void onCancelDrag(DragCancelEvent be) {
    resizeWidget.enableEvents();
    sync();
  }

  private void onEndDrag(DragEndEvent bee) {
    int x = bee.getX();
    int y = bee.getY();
    int width = resizeWidget.getOffsetWidth();
    int height = resizeWidget.getOffsetHeight();

    int diffY = y - startBounds.getY();
    int diffX = x - startBounds.getX();

    resizeWidget.enableEvents();

    int size = 0;

    switch (region) {
      case NORTH: {
        size = height - diffY;
        if (autoSize) {
          resizeEl.setY(y);
          resizeEl.setHeight(height);
        }
        break;
      }
      case SOUTH: {
        size = height + diffY;
        if (autoSize) {
          resizeWidget.setHeight(diffY);
        }
        break;
      }
      case WEST: {
        size = width - diffX;
        if (autoSize) {
          getElement().setX(x);
          resizeWidget.setWidth(width - diffX);
        }
        break;
      }
      case EAST: {
        size = width + diffX;
        if (autoSize) {
          resizeWidget.setWidth(size);
        }
        break;
      }
    }
    fireEvent(new SplitBarDragEvent(false, size));
  }

  private void onStartDrag(DragStartEvent de) {
    // adjust width of proxy
    if (region == LayoutRegion.WEST || region == LayoutRegion.EAST) {
      de.setWidth(getBarWidth());
    } else {
      de.setHeight(getBarWidth());
    }

    fireEvent(new SplitBarDragEvent(true, 0));

    resizeWidget.enableEvents();

    if (containerWidget != null) {
      switch (region) {
        case WEST:
        case EAST:
          int h = containerWidget.getOffsetHeight(true);
          de.setHeight(h);
          break;
        case NORTH:
        case SOUTH:
          int w = containerWidget.getOffsetWidth(true);
          de.setWidth(w);
          break;
      }
    }
    startBounds = new Rectangle();
    startBounds.setY(de.getY());
    startBounds.setX(de.getX());

    boolean v = region == LayoutRegion.WEST || region == LayoutRegion.EAST;
    int size;
    if (v) {
      size = resizeEl.getOffsetWidth();
    } else {
      size = resizeEl.getOffsetHeight();
    }

    int c1 = size - getMinSize();
    if (size < getMinSize()) {
      c1 = 0;
    }
    int c2 = Math.max(getMaxSize() - size, 0);
    if (v) {
      draggable.setConstrainVertical(true);
      draggable.setXConstraint(region == LayoutRegion.WEST ? c2 : c1, region == LayoutRegion.WEST ? c1 : c2);
    } else {
      draggable.setConstrainHorizontal(true);
      draggable.setYConstraint(region == LayoutRegion.NORTH ? c2 : c1, region == LayoutRegion.NORTH ? c1 : c2);
    }
  }

}
TOP

Related Classes of com.sencha.gxt.widget.core.client.SplitBar$SplitBarAppearance

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.