/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package com.eas.window;
import com.google.gwt.core.client.GWT;
import com.google.gwt.dom.client.Element;
import com.google.gwt.dom.client.Style;
import com.google.gwt.event.dom.client.MouseEvent;
import com.google.gwt.resources.client.ClientBundle;
import com.google.gwt.resources.client.CssResource;
import com.google.gwt.user.client.ui.ProvidesResize;
import com.google.gwt.user.client.ui.RequiresResize;
import com.google.gwt.user.client.ui.SimplePanel;
import com.google.gwt.user.client.ui.Widget;
/**
*
* @author mg
*/
public class DraggablePanel extends SimplePanel implements RequiresResize, ProvidesResize {
protected interface Resources extends ClientBundle {
static final Resources instance = GWT.create(Resources.class);
public ResizableStyles resizable();
}
protected interface ResizableStyles extends CssResource {
public String contentDecor();
public String horizontalDecor();
public String northDecor();
public String southDecor();
public String verticalDecor();
public String westDecor();
public String eastDecor();
public String cornerDecor();
public String northWestDecor();
public String northEastDecor();
public String southWestDecor();
public String southEastDecor();
}
protected static ResizableStyles styles = Resources.instance.resizable();
protected abstract class DraggableWidgetDecoration extends DraggableDecoration {
private boolean mouseDragged;
public DraggableWidgetDecoration(String... aClasses) {
super(aClasses);
}
@Override
protected void mousePressed() {
focus();
}
@Override
protected void mouseDragged() {
if(!mouseDragged){
mouseDragged = true;
beginResizing();
}
}
@Override
protected void mouseReleased() {
mouseDragged = false;
endResizing();
}
@Override
protected Widget getMovableTarget() {
return DraggablePanel.this.getMovableTarget();
}
@Override
protected Widget getResizableTarget() {
return DraggablePanel.this.getWidget();
}
}
protected DraggableDecoration n = new DraggableWidgetDecoration(styles.horizontalDecor(), styles.northDecor(), "horizontal-decor", "north-decor") {
@Override
protected boolean changeTarget(Widget aMovableTarget, Widget aResizableTarget, int dx, int dy, MouseEvent<?> aEvent) {
if (isNresizable()) {
double newTop = targetScrollTop + dy;
aMovableTarget.getElement().getStyle().setTop(newTop >= 0 ? newTop : 0, Style.Unit.PX);
if (newTop >= 0) {
aResizableTarget.getElement().getStyle().setHeight(targetHeight - dy, Style.Unit.PX);
/*
if (aResizableTarget instanceof RequiresResize) {
((RequiresResize) aResizableTarget).onResize();
}
*/
}
return true;
} else {
return false;
}
}
};
protected DraggableDecoration s = new DraggableWidgetDecoration(styles.horizontalDecor(), styles.southDecor(), "horizontal-decor", "south-decor") {
@Override
protected boolean changeTarget(Widget aMovableTarget, Widget aResizableTarget, int dx, int dy, MouseEvent<?> aEvent) {
if (isSresizable()) {
aResizableTarget.getElement().getStyle().setHeight(targetHeight + dy, Style.Unit.PX);
/*
if (aResizableTarget instanceof RequiresResize) {
((RequiresResize) aResizableTarget).onResize();
}
*/
return true;
} else {
return false;
}
}
};
protected DraggableDecoration w = new DraggableWidgetDecoration(styles.verticalDecor(), styles.westDecor(), "vertical-decor", "west-decor") {
@Override
protected boolean changeTarget(Widget aMovableTarget, Widget aResizableTarget, int dx, int dy, MouseEvent<?> aEvent) {
if (isWresizable()) {
double newLeft = targetScrollLeft + dx;
aMovableTarget.getElement().getStyle().setLeft(newLeft >= 0 ? newLeft : 0, Style.Unit.PX);
if (newLeft >= 0) {
aResizableTarget.getElement().getStyle().setWidth(targetWidth - dx, Style.Unit.PX);
/*
if (aResizableTarget instanceof RequiresResize) {
((RequiresResize) aResizableTarget).onResize();
}
*/
}
return true;
} else {
return false;
}
}
};
protected DraggableDecoration e = new DraggableWidgetDecoration(styles.verticalDecor(), styles.eastDecor(), "vertical-decor", "east-decor") {
@Override
protected boolean changeTarget(Widget aMovableTarget, Widget aResizableTarget, int dx, int dy, MouseEvent<?> aEvent) {
if (isEresizable()) {
aResizableTarget.getElement().getStyle().setWidth(targetWidth + dx, Style.Unit.PX);
/*
if (aResizableTarget instanceof RequiresResize) {
((RequiresResize) aResizableTarget).onResize();
}
*/
return true;
} else {
return false;
}
}
};
protected DraggableDecoration nw = new DraggableWidgetDecoration(styles.cornerDecor(), styles.northWestDecor(), "corner-decor", "north-west-decor") {
@Override
protected boolean changeTarget(Widget aMovableTarget, Widget aResizableTarget, int dx, int dy, MouseEvent<?> aEvent) {
n.assignMouseState(nw);
n.changeTarget(aMovableTarget, aResizableTarget, dx, dy, aEvent);
w.assignMouseState(nw);
w.changeTarget(aMovableTarget, aResizableTarget, dx, dy, aEvent);
return true;
}
};
protected DraggableDecoration ne = new DraggableWidgetDecoration(styles.cornerDecor(), styles.northEastDecor(), "corner-decor", "north-east-decor") {
@Override
protected boolean changeTarget(Widget aMovableTarget, Widget aResizableTarget, int dx, int dy, MouseEvent<?> aEvent) {
n.assignMouseState(ne);
n.changeTarget(aMovableTarget, aResizableTarget, dx, dy, aEvent);
e.assignMouseState(ne);
e.changeTarget(aMovableTarget, aResizableTarget, dx, dy, aEvent);
return true;
}
};
protected DraggableDecoration sw = new DraggableWidgetDecoration(styles.cornerDecor(), styles.southWestDecor(), "corner-decor", "south-west-decor") {
@Override
protected boolean changeTarget(Widget aMovableTarget, Widget aResizableTarget, int dx, int dy, MouseEvent<?> aEvent) {
s.assignMouseState(sw);
s.changeTarget(aMovableTarget, aResizableTarget, dx, dy, aEvent);
w.assignMouseState(sw);
w.changeTarget(aMovableTarget, aResizableTarget, dx, dy, aEvent);
return true;
}
};
protected DraggableDecoration se = new DraggableWidgetDecoration(styles.cornerDecor(), styles.southEastDecor(), "corner-decor", "south-east-decor") {
@Override
protected boolean changeTarget(Widget aMovableTarget, Widget aResizableTarget, int dx, int dy, MouseEvent<?> aEvent) {
s.assignMouseState(se);
s.changeTarget(aMovableTarget, aResizableTarget, dx, dy, aEvent);
e.assignMouseState(se);
e.changeTarget(aMovableTarget, aResizableTarget, dx, dy, aEvent);
return true;
}
};
protected final SimplePanel content = new SimplePanel();
protected boolean undecorated;
protected boolean resizable = true;
public DraggablePanel() {
super();
init();
}
public DraggablePanel(boolean undecorated) {
super();
this.undecorated = undecorated;
init();
}
protected void init() {
styles.ensureInjected();
super.setWidget(content);
}
protected void beginResizing() {
}
protected void endResizing() {
onResize();
}
@Override
public Widget getWidget() {
return content.getWidget();
}
@Override
public void setWidget(Widget w) {
content.setWidget(w);
onResize();
}
@Override
public boolean isVisible() {
return super.isVisible() && !"hidden".equals(getElement().getStyle().getProperty("visibility"));
}
public boolean isUndecorated() {
return undecorated;
}
public void setUndecorated(boolean aValue) {
boolean oldValue = undecorated;
undecorated = aValue;
if (oldValue && !undecorated) {
decorate();
} else if (!oldValue && undecorated) {
undecorate();
}
}
public boolean isResizable() {
return resizable;
}
public void setResizable(boolean aValue) {
resizable = aValue;
updateDecorCursors();
}
public void setPosition(double aLeft, double aTop) {
Element elem = getMovableTarget().getElement();
elem.getStyle().setLeft(aLeft, Style.Unit.PX);
elem.getStyle().setTop(aTop, Style.Unit.PX);
elem.getStyle().setPosition(Style.Position.ABSOLUTE);
}
public void setSize(double aWidth, double aHeight) {
if (getWidget() != null) {
Element elem = getWidget().getElement();
elem.getStyle().setWidth(aWidth, Style.Unit.PX);
elem.getStyle().setHeight(aHeight, Style.Unit.PX);
onResize();
}
}
@Override
public void setWidth(String width) {
if (getWidget() != null) {
getWidget().setWidth(width);
if (isAttached()) {
onResize();
}
}
}
@Override
public void setHeight(String height) {
if (getWidget() != null) {
getWidget().setHeight(height);
if (isAttached()) {
onResize();
}
}
}
protected void decorate() {
content.getElement().addClassName(styles.contentDecor());
Element topElement = getElement();
// Physical attach
topElement.appendChild(n.getElement());
topElement.appendChild(s.getElement());
topElement.appendChild(w.getElement());
topElement.appendChild(e.getElement());
topElement.appendChild(nw.getElement());
topElement.appendChild(ne.getElement());
topElement.appendChild(sw.getElement());
topElement.appendChild(se.getElement());
// Logical attach
adopt(e);
adopt(w);
adopt(n);
adopt(s);
adopt(nw);
adopt(ne);
adopt(sw);
adopt(se);
}
protected void undecorate() {
// Logical detach
orphan(e);
orphan(w);
orphan(n);
orphan(s);
orphan(nw);
orphan(ne);
orphan(sw);
orphan(se);
// Physical detach
e.getElement().removeFromParent();
w.getElement().removeFromParent();
n.getElement().removeFromParent();
s.getElement().removeFromParent();
nw.getElement().removeFromParent();
ne.getElement().removeFromParent();
sw.getElement().removeFromParent();
se.getElement().removeFromParent();
content.getElement().removeClassName(styles.contentDecor());
}
@Override
protected void onAttach() {
super.onAttach();
if (!n.isAttached()) {
n.onAttach();
}
if (!s.isAttached()) {
s.onAttach();
}
if (!e.isAttached()) {
e.onAttach();
}
if (!w.isAttached()) {
w.onAttach();
}
if (!ne.isAttached()) {
ne.onAttach();
}
if (!se.isAttached()) {
se.onAttach();
}
if (!nw.isAttached()) {
nw.onAttach();
}
if (!sw.isAttached()) {
sw.onAttach();
}
onResize();
}
@Override
protected void onDetach() {
super.onDetach();
if (n.isAttached()) {
n.onDetach();
}
if (s.isAttached()) {
s.onDetach();
}
if (e.isAttached()) {
e.onDetach();
}
if (w.isAttached()) {
w.onDetach();
}
if (ne.isAttached()) {
ne.onDetach();
}
if (se.isAttached()) {
se.onDetach();
}
if (nw.isAttached()) {
nw.onDetach();
}
if (sw.isAttached()) {
sw.onDetach();
}
}
protected boolean isNresizable() {
return resizable;
}
protected boolean isSresizable() {
return resizable;
}
protected boolean isWresizable() {
return resizable;
}
protected boolean isEresizable() {
return resizable;
}
protected void updateDecorCursors() {
if (isNresizable()) {
n.getElement().getStyle().clearCursor();
} else {
n.getElement().getStyle().setCursor(Style.Cursor.DEFAULT);
}
if (isSresizable()) {
s.getElement().getStyle().clearCursor();
} else {
s.getElement().getStyle().setCursor(Style.Cursor.DEFAULT);
}
if (isEresizable()) {
e.getElement().getStyle().clearCursor();
} else {
e.getElement().getStyle().setCursor(Style.Cursor.DEFAULT);
}
if (isWresizable()) {
w.getElement().getStyle().clearCursor();
} else {
w.getElement().getStyle().setCursor(Style.Cursor.DEFAULT);
}
if (isNresizable() && isWresizable()) {
nw.getElement().getStyle().clearCursor();
} else if (isNresizable()) {
nw.getElement().getStyle().setCursor(Style.Cursor.N_RESIZE);
} else if (isWresizable()) {
nw.getElement().getStyle().setCursor(Style.Cursor.W_RESIZE);
} else {
nw.getElement().getStyle().setCursor(Style.Cursor.DEFAULT);
}
if (isNresizable() && isEresizable()) {
ne.getElement().getStyle().clearCursor();
} else if (isNresizable()) {
ne.getElement().getStyle().setCursor(Style.Cursor.N_RESIZE);
} else if (isEresizable()) {
ne.getElement().getStyle().setCursor(Style.Cursor.E_RESIZE);
} else {
ne.getElement().getStyle().setCursor(Style.Cursor.DEFAULT);
}
if (isSresizable() && isEresizable()) {
se.getElement().getStyle().clearCursor();
} else if (isSresizable()) {
se.getElement().getStyle().setCursor(Style.Cursor.S_RESIZE);
} else if (isEresizable()) {
se.getElement().getStyle().setCursor(Style.Cursor.E_RESIZE);
} else {
se.getElement().getStyle().setCursor(Style.Cursor.DEFAULT);
}
if (isSresizable() && isWresizable()) {
sw.getElement().getStyle().clearCursor();
} else if (isSresizable()) {
sw.getElement().getStyle().setCursor(Style.Cursor.S_RESIZE);
} else if (isWresizable()) {
sw.getElement().getStyle().setCursor(Style.Cursor.W_RESIZE);
} else {
sw.getElement().getStyle().setCursor(Style.Cursor.DEFAULT);
}
}
protected Widget getMovableTarget() {
return this;
}
protected void focus() {
// no op here. Descendants may put some code here
}
@Override
public void onResize() {
if (getWidget() instanceof RequiresResize) {
((RequiresResize) getWidget()).onResize();
}
}
}