package com.eas.widgets;
import java.util.HashMap;
import java.util.Map;
import com.eas.core.HasPublished;
import com.eas.core.XElement;
import com.eas.menu.HasComponentPopupMenu;
import com.eas.menu.PlatypusPopupMenu;
import com.eas.ui.HasEventsExecutor;
import com.eas.ui.HasJsFacade;
import com.eas.ui.MarginConstraints;
import com.eas.ui.PublishedAbsoluteConstraints;
import com.eas.ui.PublishedMarginConstraints;
import com.eas.ui.events.AddEvent;
import com.eas.ui.events.AddHandler;
import com.eas.ui.events.EventsExecutor;
import com.eas.ui.events.HasAddHandlers;
import com.eas.ui.events.HasHideHandlers;
import com.eas.ui.events.HasRemoveHandlers;
import com.eas.ui.events.HasShowHandlers;
import com.eas.ui.events.HideEvent;
import com.eas.ui.events.HideHandler;
import com.eas.ui.events.RemoveEvent;
import com.eas.ui.events.RemoveHandler;
import com.eas.ui.events.ShowEvent;
import com.eas.ui.events.ShowHandler;
import com.eas.widgets.containers.AnchorsPanel;
import com.google.gwt.core.client.JavaScriptObject;
import com.google.gwt.dom.client.Element;
import com.google.gwt.event.dom.client.ContextMenuEvent;
import com.google.gwt.event.dom.client.ContextMenuHandler;
import com.google.gwt.event.logical.shared.HasResizeHandlers;
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.user.client.ui.HasEnabled;
import com.google.gwt.user.client.ui.Widget;
import com.google.gwt.dom.client.Style;
public class MarginsPane extends AnchorsPanel implements HasLayers, HasPublished, HasJsFacade, HasEnabled, HasComponentPopupMenu,
HasEventsExecutor, HasShowHandlers, HasHideHandlers, HasResizeHandlers, HasAddHandlers, HasRemoveHandlers, HasChildrenPosition {
protected EventsExecutor eventsExecutor;
protected PlatypusPopupMenu menu;
protected boolean enabled = true;
protected String name;
protected JavaScriptObject published;
protected Map<Widget, MarginConstraints> constraints = new HashMap<>();
public MarginsPane() {
super();
getElement().getStyle().setOverflow(Style.Overflow.HIDDEN);
getElement().getStyle().setPosition(Style.Position.RELATIVE);
}
@Override
public HandlerRegistration addAddHandler(AddHandler handler) {
return addHandler(handler, AddEvent.getType());
}
@Override
public HandlerRegistration addRemoveHandler(RemoveHandler handler) {
return addHandler(handler, RemoveEvent.getType());
}
@Override
public HandlerRegistration addResizeHandler(ResizeHandler handler) {
return addHandler(handler, ResizeEvent.getType());
}
@Override
public void onResize() {
super.onResize();
if (isAttached()) {
ResizeEvent.fire(this, getElement().getOffsetWidth(), getElement().getOffsetHeight());
}
}
@Override
public HandlerRegistration addHideHandler(HideHandler handler) {
return addHandler(handler, HideEvent.getType());
}
@Override
public HandlerRegistration addShowHandler(ShowHandler handler) {
return addHandler(handler, ShowEvent.getType());
}
@Override
public void setVisible(boolean visible) {
boolean oldValue = isVisible();
super.setVisible(visible);
if (oldValue != visible) {
if (visible) {
ShowEvent.fire(this, this);
} else {
HideEvent.fire(this, this);
}
}
}
@Override
public EventsExecutor getEventsExecutor() {
return eventsExecutor;
}
@Override
public void setEventsExecutor(EventsExecutor aExecutor) {
eventsExecutor = aExecutor;
}
@Override
public PlatypusPopupMenu getPlatypusPopupMenu() {
return menu;
}
protected HandlerRegistration menuTriggerReg;
@Override
public void setPlatypusPopupMenu(PlatypusPopupMenu aMenu) {
if (menu != aMenu) {
if (menuTriggerReg != null)
menuTriggerReg.removeHandler();
menu = aMenu;
if (menu != null) {
menuTriggerReg = super.addDomHandler(new ContextMenuHandler() {
@Override
public void onContextMenu(ContextMenuEvent event) {
event.preventDefault();
event.stopPropagation();
menu.setPopupPosition(event.getNativeEvent().getClientX(), event.getNativeEvent().getClientY());
menu.show();
}
}, ContextMenuEvent.getType());
}
}
}
@Override
public boolean isEnabled() {
return enabled;
}
@Override
public void setEnabled(boolean aValue) {
boolean oldValue = enabled;
enabled = aValue;
if (!oldValue && enabled) {
getElement().<XElement> cast().unmask();
} else if (oldValue && !enabled) {
getElement().<XElement> cast().disabledMask();
}
}
@Override
public String getJsName() {
return name;
}
@Override
public void setJsName(String aValue) {
name = aValue;
}
protected void applyConstraints(Widget aWidget, MarginConstraints aConstraints) {
constraints.put(aWidget, aConstraints);
MarginConstraints.Margin left = aConstraints.getLeft();
MarginConstraints.Margin top = aConstraints.getTop();
MarginConstraints.Margin right = aConstraints.getRight();
MarginConstraints.Margin bottom = aConstraints.getBottom();
MarginConstraints.Margin width = aConstraints.getWidth();
MarginConstraints.Margin height = aConstraints.getHeight();
// horizontal
if (left != null && width != null)
right = null;
if (left != null && right != null) {
setWidgetLeftRight(aWidget, left.value, left.unit, right.value, right.unit);
} else if (left == null && right != null) {
assert width != null : "left may be absent in presence of width and right";
setWidgetRightWidth(aWidget, right.value, right.unit, width.value, width.unit);
} else if (right == null && left != null) {
assert width != null : "right may be absent in presence of width and left";
setWidgetLeftWidth(aWidget, left.value, left.unit, width.value, width.unit);
} else {
assert false : "At least left with width, right with width or both (without width) must present";
}
// vertical
if (top != null && height != null)
bottom = null;
if (top != null && bottom != null) {
setWidgetTopBottom(aWidget, top.value, top.unit, bottom.value, bottom.unit);
} else if (top == null && bottom != null) {
assert height != null : "top may be absent in presence of height and bottom";
setWidgetBottomHeight(aWidget, bottom.value, bottom.unit, height.value, height.unit);
} else if (bottom == null && top != null) {
assert height != null : "bottom may be absent in presence of height and top";
setWidgetTopHeight(aWidget, top.value, top.unit, height.value, height.unit);
} else {
assert false : "At least top with height, bottom with height or both (without height) must present";
}
aWidget.getElement().getStyle().setMargin(0, Style.Unit.PX);
if (isAttached()) {
forceLayout();
}
}
public void add(Widget aChild, PublishedMarginConstraints aConstraints) {
super.add(aChild);
MarginConstraints anchors = new MarginConstraints();
int h = 0;
int v = 0;
String left = aConstraints.getLeft();
if (left != null && !left.isEmpty()) {
anchors.setLeft(MarginConstraints.Margin.parse(left));
h++;
}
String right = aConstraints.getRight();
if (right != null && !right.isEmpty()) {
anchors.setRight(MarginConstraints.Margin.parse(right));
h++;
}
String width = aConstraints.getWidth();
if (width != null && !width.isEmpty()) {
anchors.setWidth(MarginConstraints.Margin.parse(width));
h++;
}
String top = aConstraints.getTop();
if (top != null && !top.isEmpty()) {
anchors.setTop(MarginConstraints.Margin.parse(top));
v++;
}
String bottom = aConstraints.getBottom();
if (bottom != null && !bottom.isEmpty()) {
anchors.setBottom(MarginConstraints.Margin.parse(bottom));
v++;
}
String height = aConstraints.getHeight();
if (height != null && !height.isEmpty()) {
anchors.setHeight(MarginConstraints.Margin.parse(height));
v++;
}
if (h < 2)
throw new IllegalArgumentException("There are must be at least two horizontal values in anchors.");
if (v < 2)
throw new IllegalArgumentException("There are must be at least two vertical values in anchors.");
applyConstraints(aChild, anchors);
}
public void add(Widget aChild, PublishedAbsoluteConstraints aConstraints) {
MarginConstraints anchors = new MarginConstraints();
String left = aConstraints != null && aConstraints.getLeft() != null ? aConstraints.getLeft() : "0";
if (left != null && !left.isEmpty()) {
anchors.setLeft(MarginConstraints.Margin.parse(left));
}
String width = aConstraints != null && aConstraints.getWidth() != null ? aConstraints.getWidth() : "10";
if (width != null && !width.isEmpty()) {
anchors.setWidth(MarginConstraints.Margin.parse(width));
}
String top = aConstraints != null && aConstraints.getTop() != null ? aConstraints.getTop() : "0";
if (top != null && !top.isEmpty()) {
anchors.setTop(MarginConstraints.Margin.parse(top));
}
String height = aConstraints != null && aConstraints.getHeight() != null ? aConstraints.getHeight() : "10";
if (height != null && !height.isEmpty()) {
anchors.setHeight(MarginConstraints.Margin.parse(height));
}
add(aChild);
applyConstraints(aChild, anchors);
}
public void add(Widget aChild, MarginConstraints anchors) {
add(aChild);
applyConstraints(aChild, anchors);
}
@Override
public void add(Widget widget) {
super.add(widget);
AddEvent.fire(this, widget);
}
@Override
public boolean remove(Widget w) {
constraints.remove(w);
boolean res = super.remove(w);
if (res) {
RemoveEvent.fire(this, w);
}
return res;
}
@Override
public void clear() {
super.clear();
constraints.clear();
}
public void ajustWidth(Widget layouted, int aValue) {
MarginConstraints anchors = constraints.get(layouted);
int containerWidth = layouted.getParent().getOffsetWidth();
if (anchors.getWidth() != null) {
anchors.getWidth().setPlainValue(aValue, containerWidth);
} else if (anchors.getLeft() != null && anchors.getRight() != null) {
anchors.getRight().setPlainValue(containerWidth - layouted.getElement().getParentElement().getOffsetLeft() - aValue, containerWidth);
}
applyConstraints(layouted, anchors);
}
public void ajustHeight(Widget layouted, int aValue) {
MarginConstraints anchors = constraints.get(layouted);
int containerHeight = layouted.getParent().getElement().getOffsetHeight();
if (anchors.getHeight() != null) {
anchors.getHeight().setPlainValue(aValue, containerHeight);
} else if (anchors.getTop() != null && anchors.getBottom() != null) {
anchors.getBottom().setPlainValue(containerHeight - layouted.getElement().getParentElement().getOffsetTop() - aValue, containerHeight);
}
applyConstraints(layouted, anchors);
}
public void ajustLeft(Widget layouted, int aValue) {
MarginConstraints anchors = constraints.get(layouted);
int containerWidth = layouted.getParent().getElement().getOffsetWidth();
int childWidth = layouted.getElement().getParentElement().getOffsetWidth();
if (anchors.getLeft() != null && anchors.getWidth() != null) {
anchors.getLeft().setPlainValue(aValue, containerWidth);
} else if (anchors.getWidth() != null && anchors.getRight() != null) {
anchors.getRight().setPlainValue(containerWidth - aValue - childWidth, containerWidth);
} else if (anchors.getLeft() != null && anchors.getRight() != null) {
anchors.getLeft().setPlainValue(aValue, containerWidth);
anchors.getRight().setPlainValue(containerWidth - aValue - childWidth, containerWidth);
}
applyConstraints(layouted, anchors);
}
public void ajustTop(Widget layouted, int aValue) {
MarginConstraints anchors = constraints.get(layouted);
int containerHeight = layouted.getParent().getElement().getOffsetHeight();
int childHeight = layouted.getElement().getParentElement().getOffsetHeight();
if (anchors.getTop() != null && anchors.getHeight() != null) {
anchors.getTop().setPlainValue(aValue, containerHeight);
} else if (anchors.getHeight() != null && anchors.getBottom() != null) {
anchors.getBottom().setPlainValue(containerHeight - aValue - childHeight, containerHeight);
} else if (anchors.getTop() != null && anchors.getBottom() != null) {
anchors.getTop().setPlainValue(aValue, containerHeight);
anchors.getBottom().setPlainValue(containerHeight - aValue - childHeight, containerHeight);
}
applyConstraints(layouted, anchors);
}
@Override
public void toFront(Widget aWidget) {
if (aWidget != null) {
getElement().insertBefore(aWidget.getElement().getParentNode(), getElement().getLastChild()); // exclude
// last
// element
}
}
@Override
public void toFront(Widget aWidget, int aCount) {
if (aWidget != null && aCount > 0) {
XElement container = getElement().cast();
Element widgetElement = aWidget.getElement().getParentElement();
int index = container.getChildIndex(widgetElement);
if (index < 0 || (index + aCount) >= container.getChildCount() - 1) {// exclude
// last
// element
getElement().insertBefore(widgetElement, container.getLastChild());
} else {
getElement().insertAfter(widgetElement, container.getChild(index + aCount));
}
}
}
@Override
public void toBack(Widget aWidget) {
if (aWidget != null) {
getElement().insertFirst(aWidget.getElement().getParentElement());
}
}
@Override
public void toBack(Widget aWidget, int aCount) {
if (aWidget != null && aCount > 0) {
XElement container = getElement().cast();
Element widgetElement = aWidget.getElement().getParentElement();
int index = container.getChildIndex(widgetElement);
if (index < 0 || (index - aCount) < 0) {
getElement().insertFirst(widgetElement);
} else {
getElement().insertBefore(widgetElement, container.getChild(index - aCount));
}
}
}
@Override
public JavaScriptObject getPublished() {
return published;
}
@Override
public void setPublished(JavaScriptObject aValue) {
published = aValue;
}
@Override
public int getTop(Widget aWidget) {
assert aWidget.getParent() == this : "widget should be a child of this container";
return aWidget.getElement().getParentElement().getOffsetTop();
}
@Override
public int getLeft(Widget aWidget) {
assert aWidget.getParent() == this : "widget should be a child of this container";
return aWidget.getElement().getParentElement().getOffsetLeft();
}
}