package com.eas.bound;
import java.util.logging.Level;
import java.util.logging.Logger;
import com.eas.core.Utils;
import com.eas.menu.HasComponentPopupMenu;
import com.eas.menu.PlatypusPopupMenu;
import com.eas.ui.HasBinding;
import com.eas.ui.HasCustomEditing;
import com.eas.ui.HasEventsExecutor;
import com.eas.ui.HasJsFacade;
import com.eas.ui.HasJsName;
import com.eas.ui.HasJsValue;
import com.eas.ui.HasOnRender;
import com.eas.ui.HasOnSelect;
import com.eas.ui.PublishedCell;
import com.eas.ui.events.EventsExecutor;
import com.eas.ui.events.HasHideHandlers;
import com.eas.ui.events.HasShowHandlers;
import com.eas.ui.events.HideEvent;
import com.eas.ui.events.HideHandler;
import com.eas.ui.events.ShowEvent;
import com.eas.ui.events.ShowHandler;
import com.eas.widgets.WidgetsUtils;
import com.eas.widgets.boxes.DecoratorBox;
import com.google.gwt.core.client.JavaScriptObject;
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.logical.shared.ValueChangeEvent;
import com.google.gwt.event.logical.shared.ValueChangeHandler;
import com.google.gwt.event.shared.HandlerRegistration;
import com.google.gwt.user.client.ui.HasName;
import com.google.gwt.user.client.ui.HasText;
import com.google.gwt.user.client.ui.HasValue;
public abstract class ModelDecoratorBox<T> extends DecoratorBox<T> implements HasJsFacade, HasJsValue, HasText, HasCustomEditing, HasBinding, HasOnRender, HasOnSelect, HasComponentPopupMenu,
HasEventsExecutor, HasShowHandlers, HasHideHandlers, HasResizeHandlers {
protected EventsExecutor eventsExecutor;
protected PlatypusPopupMenu menu;
protected String name;
protected JavaScriptObject published;
protected JavaScriptObject onRender;
protected JavaScriptObject onSelect;
protected boolean editable = true;
protected boolean selectOnly;
//
protected boolean settingValue;
// binding
protected JavaScriptObject data;
protected String field;
public ModelDecoratorBox(HasValue<T> aDecorated) {
super(aDecorated);
}
@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 String getJsName() {
return name;
}
@Override
public void setJsName(String aValue) {
name = aValue;
if(decorated instanceof HasName){
((HasName)decorated).setName(aValue);
}
}
@Override
public JavaScriptObject getPublished() {
return published;
}
@Override
public void setPublished(JavaScriptObject aValue) {
published = aValue;
if (published != null) {
publish(this, published);
}
}
@Override
public boolean isEditable() {
return editable;
}
protected abstract void setReadonly(boolean aValue);
protected abstract boolean isReadonly();
@Override
public void setEditable(boolean aValue) {
if (editable != aValue) {
editable = aValue;
setReadonly(!editable || selectOnly);
}
}
@Override
public boolean isSelectOnly() {
return selectOnly;
}
@Override
public void setSelectOnly(boolean aValue) {
if (selectOnly != aValue) {
selectOnly = aValue;
setReadonly(!editable || selectOnly);
}
}
public JavaScriptObject getOnSelect() {
return onSelect;
}
public void setOnSelect(JavaScriptObject aValue) {
if (onSelect != aValue) {
onSelect = aValue;
setSelectButtonVisible(onSelect != null);
}
}
public JavaScriptObject getOnRender() {
return onRender;
}
public void setOnRender(JavaScriptObject aValue) {
if (aValue != onRender) {
onRender = aValue;
}
}
protected PublishedCell cellToRender;
public abstract T convert(Object aValue);
public void setValue(T value, boolean fireEvents) {
settingValue = true;
try {
super.setValue(value, fireEvents);
try {
if (onRender != null && data != null && field != null && !field.isEmpty()) {
cellToRender = WidgetsUtils.calcStandalonePublishedCell(published, onRender, data, field, getText(), cellToRender);
}
if (cellToRender != null) {
if (cellToRender.getDisplayCallback() == null) {
cellToRender.setDisplayCallback(new Runnable() {
@Override
public void run() {
cellToRender.styleToElement(getElement());
}
});
}
cellToRender.styleToElement(getElement());
}
} catch (Exception ex) {
Logger.getLogger(ModelDecoratorBox.class.getName()).log(Level.SEVERE, ex.getMessage(), ex);
}
} finally {
settingValue = false;
}
}
@Override
protected void clearValue() {
setValue(null, true);
}
@Override
protected void selectValue() {
try {
Utils.executeScriptEventVoid(published, onSelect, published);
} catch (Exception ex) {
Logger.getLogger(WidgetsUtils.class.getName()).log(Level.SEVERE, ex.getMessage(), ex);
}
}
protected HandlerRegistration boundToData;
protected HandlerRegistration boundToValue;
protected boolean settingValueFromJs;
protected boolean settingValueToJs;
protected void bind() {
if (data != null && field != null && !field.isEmpty()) {
boundToData = Utils.listenPath(data, field, new Utils.OnChangeHandler() {
@Override
public void onChange(JavaScriptObject anEvent) {
rebind();
}
});
Object oData = Utils.getPathData(data, field);
try {
setJsValue(oData);
} catch (Exception e) {
e.printStackTrace();
}
ValueChangeHandler<T> valueChangeHandler = new ValueChangeHandler<T>() {
@Override
public void onValueChange(ValueChangeEvent<T> event) {
if (!settingValueFromJs) {
settingValueToJs = true;
try {
Utils.setPathData(data, field, Utils.toJs(event.getValue()));
} finally {
settingValueToJs = false;
}
}
}
};
boundToValue = addValueChangeHandler(valueChangeHandler);
}else{
try {
setJsValue(null);
} catch (Exception e) {
e.printStackTrace();
}
}
}
protected void unbind() {
if (boundToData != null) {
boundToData.removeHandler();
boundToData = null;
}
if (boundToValue != null) {
boundToValue.removeHandler();
boundToValue = null;
}
}
protected void rebind(){
if (!settingValueToJs) {
settingValueFromJs = true;
try {
try {
Object pathData = Utils.getPathData(data, field);
setJsValue(pathData);
} catch (Exception e) {
e.printStackTrace();
}
} finally {
settingValueFromJs = false;
}
}
}
@Override
public JavaScriptObject getData() {
return data;
}
@Override
public void setData(JavaScriptObject aValue) {
if (data != aValue) {
unbind();
data = aValue;
bind();
}
}
@Override
public String getField() {
return field;
}
@Override
public void setField(String aValue) {
if (field == null ? aValue != null : !field.equals(aValue)) {
unbind();
field = aValue;
bind();
}
}
private static native void publish(HasJsFacade aWidget, JavaScriptObject aPublished)/*-{
Object.defineProperty(aPublished, "onSelect", {
get : function() {
return aWidget.@com.eas.ui.HasOnSelect::getOnSelect()();
},
set : function(aValue) {
aWidget.@com.eas.ui.HasOnSelect::setOnSelect(Lcom/google/gwt/core/client/JavaScriptObject;)(aValue);
}
});
Object.defineProperty(aPublished, "onRender", {
get : function() {
return aWidget.@com.eas.ui.HasOnRender::getOnRender()();
},
set : function(aValue) {
aWidget.@com.eas.ui.HasOnRender::setOnRender(Lcom/google/gwt/core/client/JavaScriptObject;)(aValue);
}
});
Object.defineProperty(aPublished, "editable", {
get : function() {
return aWidget.@com.eas.ui.HasCustomEditing::isEditable()();
},
set : function(aValue) {
aWidget.@com.eas.ui.HasCustomEditing::setEditable(Z)(!!aValue);
}
});
Object.defineProperty(aPublished, "nullable", {
get : function() {
return aWidget.@com.eas.widgets.boxes.DecoratorBox::isNullable()();
},
set : function(aValue) {
aWidget.@com.eas.widgets.boxes.DecoratorBox::setNullable(Z)(!!aValue);
}
});
Object.defineProperty(aPublished, "selectOnly", {
get : function() {
return aWidget.@com.eas.ui.HasCustomEditing::isSelectOnly()();
},
set : function(aValue) {
aWidget.@com.eas.ui.HasCustomEditing::setSelectOnly(Z)(!!aValue);
}
});
Object.defineProperty(aPublished, "data", {
get : function() {
return aWidget.@com.eas.ui.HasBinding::getData()();
},
set : function(aValue) {
aWidget.@com.eas.ui.HasBinding::setData(Lcom/google/gwt/core/client/JavaScriptObject;)(aValue);
}
});
Object.defineProperty(aPublished, "field", {
get : function() {
return aWidget.@com.eas.ui.HasBinding::getField()();
},
set : function(aValue) {
aWidget.@com.eas.ui.HasBinding::setField(Ljava/lang/String;)(aValue != null ? '' + aValue : null);
}
});
}-*/;
}