/*
This file belongs to the Servoy development and deployment environment, Copyright (C) 1997-2010 Servoy BV
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU Affero General Public License as published by the Free
Software Foundation; either version 3 of the License, or (at your option) any
later version.
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License along
with this program; if not, see http://www.gnu.org/licenses or write to the Free
Software Foundation,Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
*/
package com.servoy.j2db.scripting.solutionmodel;
import java.awt.Point;
import java.util.Iterator;
import org.mozilla.javascript.Function;
import org.mozilla.javascript.annotations.JSFunction;
import org.mozilla.javascript.annotations.JSGetter;
import org.mozilla.javascript.annotations.JSSetter;
import com.servoy.base.persistence.IMobileProperties;
import com.servoy.base.solutionmodel.IBaseSMMethod;
import com.servoy.base.solutionmodel.IBaseSMValueList;
import com.servoy.base.solutionmodel.mobile.IMobileSMField;
import com.servoy.j2db.IApplication;
import com.servoy.j2db.persistence.Field;
import com.servoy.j2db.persistence.GraphicalComponent;
import com.servoy.j2db.persistence.RepositoryException;
import com.servoy.j2db.persistence.ScriptMethod;
import com.servoy.j2db.persistence.StaticContentSpecLoader;
import com.servoy.j2db.persistence.ValueList;
import com.servoy.j2db.solutionmodel.ISMField;
import com.servoy.j2db.solutionmodel.ISMMethod;
import com.servoy.j2db.util.PersistHelper;
import com.servoy.j2db.util.UUID;
import com.servoy.j2db.util.Utils;
// Documented via JSFieldWithConstants
// JSFieldWithConstants was introduced to prevent the duplication of constants like JSRadios.PASSWORD == JSField.PASSWORD
public class JSField extends JSComponent<Field> implements ISMField, IMobileSMField
{
private final IApplication application;
// support constants
public JSField()
{
this(null, null, null, false);
}
public JSField(IJSParent< ? > parent, Field field, IApplication application, boolean isNew)
{
super(parent, field, isNew);
this.application = application;
}
public static JSField createField(IJSParent< ? > parent, Field field, IApplication application, boolean isNew)
{
if (field == null)
{
return null;
}
return application.getScriptEngine().getSolutionModifier().createField(parent, field, isNew);
}
/**
* @clonedesc com.servoy.base.persistence.IBaseFieldCommon#getDataProviderID()
*
* @sample
* // Normally the dataprovider is specified when a component is created.
* var field = form.newField('parent_table_text', JSField.TEXT_FIELD, 10, 40, 100, 20);
* // But it can be modified later if needed.
* field.dataProviderID = 'parent_table_id';
*/
@JSGetter
public String getDataProviderID()
{
return getBaseComponent(false).getDataProviderID();
}
@JSSetter
public void setDataProviderID(String arg)
{
getBaseComponent(true).setDataProviderID(arg);
}
/**
* @clonedesc com.servoy.base.persistence.IBaseGraphicalComponentCommon#getDisplaysTags()
*
* @sample
* var field = form.newField('parent_table_text', JSField.TEXT_FIELD, 10, 40, 100, 20);
* field.displaysTags = true;
*/
@JSGetter
public boolean getDisplaysTags()
{
return getBaseComponent(false).getDisplaysTags();
}
@JSSetter
public void setDisplaysTags(boolean arg)
{
getBaseComponent(true).setDisplaysTags(arg);
}
/**
* @clonedesc com.servoy.base.persistence.IBaseFieldCommon#getDisplayType()
*
* @sample
* // The display type is specified when the field is created.
* var cal = form.newField('my_table_date', JSField.CALENDAR, 10, 10, 100, 20);
* // But it can be changed if needed.
* cal.dataProviderID = 'my_table_text';
* cal.displayType = JSField.TEXT_FIELD;
*/
@JSGetter
public int getDisplayType()
{
return getBaseComponent(false).getDisplayType();
}
@JSSetter
public void setDisplayType(int arg)
{
getBaseComponent(true).setDisplayType(arg);
}
/**
* @clonedesc com.servoy.j2db.persistence.Field#getEditable()
*
* @sample
* var field = form.newField('my_table_text', JSField.TEXT_FIELD, 10, 10, 100, 20);
* field.editable = false;
*/
@JSGetter
public boolean getEditable()
{
return getBaseComponent(false).getEditable();
}
@JSSetter
public void setEditable(boolean arg)
{
getBaseComponent(true).setEditable(arg);
}
/**
* @clonedesc com.servoy.base.persistence.IBaseFieldCommon#getFormat()
*
* @sample
* var field = form.newField('my_table_number', JSField.TEXT_FIELD, 10, 10, 100, 20);
* field.format = '$#.00';
*/
@JSGetter
public String getFormat()
{
return getBaseComponent(false).getFormat();
}
@JSSetter
public void setFormat(String arg)
{
getBaseComponent(true).setFormat(arg);
}
/**
* @sameas com.servoy.j2db.scripting.solutionmodel.JSGraphicalComponent#getHorizontalAlignment()
*/
@JSGetter
public int getHorizontalAlignment()
{
return getBaseComponent(false).getHorizontalAlignment();
}
@JSSetter
public void setHorizontalAlignment(int arg)
{
getBaseComponent(true).setHorizontalAlignment(arg);
}
/**
* @sameas com.servoy.j2db.scripting.solutionmodel.JSGraphicalComponent#getMargin()
*/
@JSGetter
public String getMargin()
{
return PersistHelper.createInsetsString(getBaseComponent(false).getMargin());
}
@JSSetter
public void setMargin(String margin)
{
getBaseComponent(true).setMargin(PersistHelper.createInsets(margin));
}
/**
* @clonedesc com.servoy.j2db.persistence.Field#getScrollbars()
*
* @sample
* var noScrollbars = form.newField('my_table_text', JSField.TEXT_AREA, 10, 10, 100, 100);
* noScrollbars.scrollbars = SM_SCROLLBAR.HORIZONTAL_SCROLLBAR_NEVER | SM_SCROLLBAR.VERTICAL_SCROLLBAR_NEVER;
* var neededScrollbars = form.newField('my_table_text', JSField.TEXT_AREA, 120, 10, 100, 100);
* neededScrollbars.scrollbars = SM_SCROLLBAR.HORIZONTAL_SCROLLBAR_AS_NEEDED | SM_SCROLLBAR.VERTICAL_SCROLLBAR_AS_NEEDED;
* var alwaysScrollbars = form.newField('my_table_text', JSField.TEXT_AREA, 230, 10, 100, 100);
* alwaysScrollbars.scrollbars = SM_SCROLLBAR.HORIZONTAL_SCROLLBAR_ALWAYS | SM_SCROLLBAR.VERTICAL_SCROLLBAR_ALWAYS;
*/
@JSGetter
public int getScrollbars()
{
return getBaseComponent(false).getScrollbars();
}
@JSSetter
public void setScrollbars(int arg)
{
getBaseComponent(true).setScrollbars(arg);
}
/**
* @clonedesc com.servoy.j2db.persistence.Field#getSelectOnEnter()
*
* @sample
* // Create two fields and set one of them to have "selectOnEnter" true. As you tab
* // through the fields you can notice how the text inside the second field gets
* // automatically selected when the field receives focus.
* var fieldNoSelect = form.newField('my_table_text', JSField.TEXT_FIELD, 10, 10, 100, 20);
* var fieldSelect = form.newField('my_table_text', JSField.TEXT_FIELD, 10, 40, 100, 20);
* fieldSelect.selectOnEnter = true;
*/
@JSGetter
public boolean getSelectOnEnter()
{
return getBaseComponent(false).getSelectOnEnter();
}
@JSSetter
public void setSelectOnEnter(boolean arg)
{
getBaseComponent(true).setSelectOnEnter(arg);
}
/**
* @sameas com.servoy.j2db.scripting.solutionmodel.JSGraphicalComponent#getTabSeq()
*/
@JSGetter
public int getTabSeq()
{
return getBaseComponent(false).getTabSeq();
}
@JSSetter
public void setTabSeq(int arg)
{
getBaseComponent(true).setTabSeq(arg);
}
/**
* @deprecated As of release 4.1, replaced by getTitleText()
*/
@Deprecated
public String js_getText()
{
return getBaseComponent(false).getText();
}
/**
* @clonedesc com.servoy.j2db.persistence.Field#getText()
*
* @sample
* var form = solutionModel.newForm('someForm', 'db:/example_data/my_table', null, false, 640, 480);
* var field = form.newField('my_table_number', JSField.TEXT_FIELD, 10, 10, 100, 20);
* field.titleText = 'Column Title';
* form.view = JSForm.LOCKED_TABLE_VIEW;
* forms['someForm'].controller.show()
*/
@JSGetter
public String getTitleText()
{
return getBaseComponent(false).getText();
}
@JSSetter
public void setTitleText(String arg)
{
getBaseComponent(true).setText(arg);
}
/**
* @sameas com.servoy.j2db.scripting.solutionmodel.JSGraphicalComponent#getToolTipText()
*/
@JSGetter
public String getToolTipText()
{
return getBaseComponent(false).getToolTipText();
}
@JSSetter
public void setToolTipText(String arg)
{
getBaseComponent(true).setToolTipText(arg);
}
/**
* @clonedesc com.servoy.base.persistence.IBaseFieldCommon#getPlaceholderText()
*
* @sample
* field.placeholderText = 'Search';
*/
@JSGetter
public String getPlaceholderText()
{
return getBaseComponent(false).getPlaceholderText();
}
@JSSetter
public void setPlaceholderText(String arg)
{
getBaseComponent(true).setPlaceholderText(arg);
}
/**
* @clonedesc com.servoy.base.persistence.IBaseField#getValuelistID()
*
* @sample
* var vlist = solutionModel.newValueList('options', JSValueList.CUSTOM_VALUES);
* vlist.customValues = "one\ntwo\nthree\nfour";
* var cmb = form.newField('my_table_options', JSField.COMBOBOX, 10, 100, 100, 20);
* cmb.valuelist = vlist;
*/
@JSGetter
public JSValueList getValuelist()
{
ValueList vl = application.getFlattenedSolution().getValueList(getBaseComponent(false).getValuelistID());
if (vl != null)
{
return new JSValueList(vl, application, false);
}
return null;
}
@JSSetter
public void setValuelist(IBaseSMValueList valuelist)
{
if (valuelist == null)
{
getBaseComponent(true).setValuelistID(0);
}
else
{
getBaseComponent(true).setValuelistID(((JSValueList)valuelist).getValueList().getID());
}
}
/**
* @clonedesc com.servoy.j2db.scripting.solutionmodel.JSGraphicalComponent#getVerticalAlignment()
* @sampleas com.servoy.j2db.scripting.solutionmodel.JSGraphicalComponent#getVerticalAlignment()
*
* @deprecated not used (is ignored) on fields
*/
@Deprecated
public int js_getVerticalAlignment()
{
return getBaseComponent(false).getVerticalAlignment();
}
/**
* @deprecated As of release 4.1, replaced by setOnAction(JSMethod).
*/
@Deprecated
public void js_setOnActionMethod(Function function)
{
ScriptMethod scriptMethod = JSForm.getScriptMethod(function, application.getFlattenedSolution());
if (scriptMethod != null)
{
getBaseComponent(true).setOnActionMethodID(scriptMethod.getID());
}
else
{
getBaseComponent(true).setOnActionMethodID(0);
}
}
/**
* @deprecated As of release 4.1, replaced by setOnDataChange(JSMethod).
*/
@Deprecated
public void js_setOnDataChangeMethod(Function function)
{
ScriptMethod scriptMethod = JSForm.getScriptMethod(function, application.getFlattenedSolution());
if (scriptMethod != null)
{
getBaseComponent(true).setOnDataChangeMethodID(scriptMethod.getID());
}
else
{
getBaseComponent(true).setOnDataChangeMethodID(0);
}
}
/**
* @deprecated As of release 4.1, replaced by setOnFocusGained(JSMethod).
*/
@Deprecated
public void js_setOnFocusGainedMethod(Function function)
{
ScriptMethod scriptMethod = JSForm.getScriptMethod(function, application.getFlattenedSolution());
if (scriptMethod != null)
{
getBaseComponent(true).setOnFocusGainedMethodID(scriptMethod.getID());
}
else
{
getBaseComponent(true).setOnFocusGainedMethodID(0);
}
}
/**
* @deprecated As of release 4.1, replaced by setOnFocusLost(JSMethod).
*/
@Deprecated
public void js_setOnFocusLostMethod(Function function)
{
ScriptMethod scriptMethod = JSForm.getScriptMethod(function, application.getFlattenedSolution());
if (scriptMethod != null)
{
getBaseComponent(true).setOnFocusLostMethodID(scriptMethod.getID());
}
else
{
getBaseComponent(true).setOnFocusLostMethodID(0);
}
}
@Deprecated
public void js_setText(String arg)
{
getBaseComponent(true).setText(arg);
}
@Deprecated
public void js_setVerticalAlignment(int arg)
{
getBaseComponent(true).setVerticalAlignment(arg);
}
/**
* @clonedesc com.servoy.base.persistence.IBaseGraphicalComponent#getOnActionMethodID()
*
* @sample
* var doNothingMethod = form.newMethod('function doNothing() { application.output("Doing nothing."); }');
* var onClickMethod = form.newMethod('function onClick(event) { application.output("I was clicked at " + event.getTimestamp()); }');
* var onDoubleClickMethod = form.newMethod('function onDoubleClick(event) { application.output("I was double-clicked at " + event.getTimestamp()); }');
* var onRightClickMethod = form.newMethod('function onRightClick(event) { application.output("I was right-clicked at " + event.getTimestamp()); }');
* // At creation the button has the 'doNothing' method as onClick handler, but we'll change that later.
* var btn = form.newButton('I am a button', 10, 40, 200, 20, doNothingMethod);
* btn.onAction = onClickMethod;
* btn.onDoubleClick = onDoubleClickMethod;
* btn.onRightClick = onRightClickMethod;
*/
@JSGetter
public JSMethod getOnAction()
{
return getEventHandler(application, StaticContentSpecLoader.PROPERTY_ONACTIONMETHODID);
}
@JSSetter
public void setOnAction(IBaseSMMethod method)
{
setEventHandler(application, StaticContentSpecLoader.PROPERTY_ONACTIONMETHODID, (JSMethod)method);
}
/**
* @clonedesc com.servoy.base.persistence.IBaseField#getOnDataChangeMethodID()
*
* @sample
* var form = solutionModel.newForm('someForm', 'db:/example_data/parent_table', null, false, 620, 300);
* var onDataChangeMethod = form.newMethod('function onDataChange(oldValue, newValue, event) { application.output("Data changed from " + oldValue + " to " + newValue + " at " + event.getTimestamp()); }');
* var field = form.newField('parent_table_text', JSField.TEXT_FIELD, 10, 10, 100, 20);
* field.onDataChange = onDataChangeMethod;
* forms['someForm'].controller.show();
*/
@JSGetter
public JSMethod getOnDataChange()
{
return getEventHandler(application, StaticContentSpecLoader.PROPERTY_ONDATACHANGEMETHODID);
}
@JSSetter
public void setOnDataChange(IBaseSMMethod method)
{
setEventHandler(application, StaticContentSpecLoader.PROPERTY_ONDATACHANGEMETHODID, (JSMethod)method);
}
/**
* @clonedesc com.servoy.j2db.persistence.Field#getOnRenderMethodID()
*
* @sample
* field.onRender = form.newMethod('function onRender(event) { event.getElement().bgcolor = \'#00ff00\' }');
*/
@JSGetter
public JSMethod getOnRender()
{
return getEventHandler(application, StaticContentSpecLoader.PROPERTY_ONRENDERMETHODID);
}
@JSSetter
public void setOnRender(ISMMethod method)
{
setEventHandler(application, StaticContentSpecLoader.PROPERTY_ONRENDERMETHODID, (JSMethod)method);
}
/**
* @sameas com.servoy.j2db.scripting.solutionmodel.JSGraphicalComponent#getOnRightClick()
*/
@JSGetter
public JSMethod getOnRightClick()
{
return getEventHandler(application, StaticContentSpecLoader.PROPERTY_ONRIGHTCLICKMETHODID);
}
@JSSetter
public void setOnRightClick(ISMMethod method)
{
setEventHandler(application, StaticContentSpecLoader.PROPERTY_ONRIGHTCLICKMETHODID, (JSMethod)method);
}
/**
* @clonedesc com.servoy.j2db.persistence.Field#getOnFocusGainedMethodID()
*
* @sample
* var form = solutionModel.newForm('someForm', 'db:/example_data/parent_table', null, false, 620, 300);
* var onFocusLostMethod = form.newMethod('function onFocusLost(event) { application.output("Focus lost at " + event.getTimestamp()); }');
* var onFocusGainedMethod = form.newMethod('function onFocusGained(event) { application.output("Focus gained at " + event.getTimestamp()); }');
* var field = form.newField('parent_table_text', JSField.TEXT_FIELD, 10, 10, 100, 20);
* field.onFocusGained = onFocusGainedMethod;
* field.onFocusLost = onFocusLostMethod;
* forms['someForm'].controller.show()
*/
@JSGetter
public JSMethod getOnFocusGained()
{
return getEventHandler(application, StaticContentSpecLoader.PROPERTY_ONFOCUSGAINEDMETHODID);
}
@JSSetter
public void setOnFocusGained(IBaseSMMethod method)
{
setEventHandler(application, StaticContentSpecLoader.PROPERTY_ONFOCUSGAINEDMETHODID, (JSMethod)method);
}
/**
* @clonedesc com.servoy.j2db.persistence.Field#getOnFocusLostMethodID()
*
* @sampleas getOnFocusGained()
*/
@JSGetter
public JSMethod getOnFocusLost()
{
return getEventHandler(application, StaticContentSpecLoader.PROPERTY_ONFOCUSLOSTMETHODID);
}
@JSSetter
public void setOnFocusLost(IBaseSMMethod method)
{
setEventHandler(application, StaticContentSpecLoader.PROPERTY_ONFOCUSLOSTMETHODID, (JSMethod)method);
}
@Override
@JSFunction
public JSTitle getTitle()
{
return new JSTitle(getJSParent(), getTitleForComponent(this), false);
}
public static GraphicalComponent getTitleForComponent(JSComponent< ? > comp)
{
JSForm parentForm = (JSForm)comp.getJSParent();
String cGroup = comp.getGroupID();
if (cGroup != null)
{
Iterator<GraphicalComponent> comps = parentForm.getSupportChild().getGraphicalComponents();
for (GraphicalComponent gc : Utils.iterate(comps))
{
if (cGroup.equals(gc.getGroupID()))
{
// I guess the following if might as well not be; the location thing is for legacy solutions (before the COMPONENT_TITLE existed)
if (Boolean.TRUE.equals(gc.getCustomMobileProperty(IMobileProperties.COMPONENT_TITLE.propertyName)) || gc.getLocation().y < comp.getY() ||
(gc.getLocation().y == comp.getY() && gc.getLocation().x < comp.getX()))
{
return gc;
}
}
}
}
if (cGroup == null)
{
comp.setGroupID(cGroup = UUID.randomUUID().toString());
}
parentForm.checkModification();
GraphicalComponent titleLabel;
try
{
titleLabel = parentForm.getSupportChild().createNewGraphicalComponent(new Point(comp.getX(), comp.getY()));
}
catch (RepositoryException e)
{
// should not happen
throw new RuntimeException(e);
}
titleLabel.setGroupID(cGroup);
titleLabel.putCustomMobileProperty(IMobileProperties.COMPONENT_TITLE.propertyName, Boolean.TRUE);
return titleLabel;
}
/**
* @see com.servoy.j2db.scripting.solutionmodel.JSComponent#toString()
*/
@Override
public String toString()
{
return "Field: " + getBaseComponent(false).getName(); //$NON-NLS-1$
}
}