/*
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.server.headlessclient.dataui;
import java.awt.Color;
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Insets;
import java.awt.Point;
import java.awt.Rectangle;
import java.util.ArrayList;
import java.util.List;
import javax.swing.border.Border;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import org.apache.wicket.Component;
import org.apache.wicket.IRequestTarget;
import org.apache.wicket.Page;
import org.apache.wicket.RequestCycle;
import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.markup.MarkupStream;
import org.apache.wicket.markup.html.IHeaderResponse;
import org.apache.wicket.markup.html.WebMarkupContainer;
import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.markup.html.internal.HtmlHeaderContainer;
import org.apache.wicket.model.Model;
import com.servoy.j2db.BasicFormController;
import com.servoy.j2db.FormController;
import com.servoy.j2db.IApplication;
import com.servoy.j2db.IForm;
import com.servoy.j2db.IScriptExecuter;
import com.servoy.j2db.dataprocessing.IDisplayRelatedData;
import com.servoy.j2db.dataprocessing.IFoundSetInternal;
import com.servoy.j2db.dataprocessing.IRecordInternal;
import com.servoy.j2db.dataprocessing.ISwingFoundSet;
import com.servoy.j2db.dataprocessing.RelatedFoundSet;
import com.servoy.j2db.dataprocessing.SortColumn;
import com.servoy.j2db.persistence.StaticContentSpecLoader;
import com.servoy.j2db.persistence.TabPanel;
import com.servoy.j2db.scripting.FormScope;
import com.servoy.j2db.server.headlessclient.MainPage;
import com.servoy.j2db.server.headlessclient.PageContributor;
import com.servoy.j2db.server.headlessclient.WebForm;
import com.servoy.j2db.server.headlessclient.yui.YUILoader;
import com.servoy.j2db.ui.IComponent;
import com.servoy.j2db.ui.IFormLookupPanel;
import com.servoy.j2db.ui.IFormUI;
import com.servoy.j2db.ui.IProviderStylePropertyChanges;
import com.servoy.j2db.ui.ISplitPane;
import com.servoy.j2db.ui.IStylePropertyChanges;
import com.servoy.j2db.ui.ISupportSecuritySettings;
import com.servoy.j2db.ui.ISupportSimulateBounds;
import com.servoy.j2db.ui.ISupportSimulateBoundsProvider;
import com.servoy.j2db.ui.ISupportWebBounds;
import com.servoy.j2db.ui.scripting.RuntimeSplitPane;
import com.servoy.j2db.util.IStyleSheet;
import com.servoy.j2db.util.Utils;
/**
* This class represents a split pane in the web client
*
* @author gboros
*/
public class WebSplitPane extends WebMarkupContainer implements ISplitPane, IDisplayRelatedData, IProviderStylePropertyChanges, ISupportSecuritySettings,
ISupportWebBounds, ISupportWebTabSeq, ListSelectionListener, IWebFormContainer, ISupportSimulateBoundsProvider, IComponentToRequestAttacher
{
private final IApplication application;
private final int orient;
private Color background;
private Border border;
private Font font;
private Color foreground;
private Point location = new Point(0, 0);
private Dimension size = new Dimension(0, 0);
private String name;
private String tooltip;
private boolean opaque;
private boolean accessible = true;
private final List<ISwingFoundSet> related = new ArrayList<ISwingFoundSet>();
private double dividerLocation;
private int dividerSize = 5;
private boolean continuousLayout;
private double resizeWeight;
private int leftFormMinSize, rightFormMinSize;
protected IRecordInternal parentData;
private final List<String> allRelationNames = new ArrayList<String>(2);
private final WebMarkupContainer splitter;
private final WebMarkupContainer[] splitComponents = new WebMarkupContainer[2];
private final WebTabHolder[] webTabs = new WebTabHolder[2];
private final boolean[] paneChanged = new boolean[] { false, false };
private int tabSequenceIndex = ISupportWebTabSeq.DEFAULT;
private int leftPanelLastTabIndex = ISupportWebTabSeq.DEFAULT;
private boolean sizeChanged = false;
private String onDividerChangeMethodCmd;
private IScriptExecuter scriptExecutor;
private final RuntimeSplitPane scriptable;
private final AbstractServoyDefaultAjaxBehavior dividerUpdater = new AbstractServoyDefaultAjaxBehavior()
{
@Override
public void renderHead(IHeaderResponse response)
{
super.renderHead(response);
if (sizeChanged)
{
sizeChanged = false;
response.renderOnLoadJavascript("wicketAjaxGet('" + getCallbackUrl() + "&anchor=true')"); //$NON-NLS-1$ //$NON-NLS-2$
}
}
@Override
protected void respond(AjaxRequestTarget target)
{
if (getComponent().getRequest().getParameter("location") != null) //$NON-NLS-1$
{
setDividerLocationInternal(Utils.getAsInteger(getComponent().getRequest().getParameter("location"))); //$NON-NLS-1$
}
if (getComponent().getRequest().getParameter("changed") != null && orient == TabPanel.SPLIT_HORIZONTAL) //$NON-NLS-1$
{
// rerender for tableview header
WebSplitPane.this.visitChildren(WebCellBasedView.class, new Component.IVisitor<WebCellBasedView>()
{
public Object component(WebCellBasedView component)
{
component.getStylePropertyChanges().setChanged();
return IVisitor.CONTINUE_TRAVERSAL_BUT_DONT_GO_DEEPER;
}
});
}
if (getComponent().getRequest().getParameter("anchor") != null) //$NON-NLS-1$
{
Page page = findPage();
if (page instanceof MainPage && ((MainPage)page).getController() != null)
{
if (Utils.getAsBoolean(((MainPage)page).getController().getApplication().getRuntimeProperties().get("enableAnchors"))) //$NON-NLS-1$
{
target.appendJavascript("layoutEntirePage();"); //$NON-NLS-1$
}
}
target.appendJavascript("Servoy.Resize.onWindowResize();"); //$NON-NLS-1$
}
}
};
public WebSplitPane(IApplication application, RuntimeSplitPane scriptable, String name, int orient)
{
super(name);
this.application = application;
this.orient = orient;
setOutputMarkupPlaceholderTag(true);
add(StyleAttributeModifierModel.INSTANCE);
add(TooltipAttributeModifier.INSTANCE);
add(dividerUpdater);
splitter = new WebMarkupContainer("splitter"); //$NON-NLS-1$
splitter.setOutputMarkupId(true);
splitComponents[0] = new WebMarkupContainer("websplit_left"); //$NON-NLS-1$
splitComponents[0].setOutputMarkupId(true);
splitComponents[1] = new WebMarkupContainer("websplit_right"); //$NON-NLS-1$
splitComponents[1].setOutputMarkupId(true);
splitComponents[0].add(new Label("webform", new Model<String>(""))); //$NON-NLS-1$ //$NON-NLS-2$
splitComponents[1].add(new Label("webform", new Model<String>(""))); //$NON-NLS-1$ //$NON-NLS-2$
splitter.add(splitComponents[0]);
add(splitter);
add(splitComponents[1]);
this.scriptable = scriptable;
((ChangesRecorder)scriptable.getChangesRecorder()).setDefaultBorderAndPadding(null, TemplateGenerator.DEFAULT_LABEL_PADDING);
}
public final RuntimeSplitPane getScriptObject()
{
return scriptable;
}
public Color getBackground()
{
return background;
}
public Border getBorder()
{
return border;
}
public Font getFont()
{
return font;
}
public Color getForeground()
{
return foreground;
}
public Point getLocation()
{
return location;
}
public String getName()
{
return name;
}
public Dimension getSize()
{
return size;
}
public String getToolTipText()
{
return tooltip;
}
public boolean isOpaque()
{
return opaque;
}
public void setBackground(Color background)
{
this.background = background;
}
public void setBorder(Border border)
{
this.border = border;
}
public void setComponentEnabled(final boolean enabled)
{
if (accessible)
{
super.setEnabled(enabled);
visitChildren(IComponent.class, new IVisitor<Component>()
{
public Object component(Component component)
{
if (component instanceof IComponent)
{
((IComponent)component).setComponentEnabled(enabled);
}
else
{
component.setEnabled(enabled);
}
return CONTINUE_TRAVERSAL;
}
});
getStylePropertyChanges().setChanged();
}
}
public void setComponentVisible(boolean visible)
{
if (viewable)
{
setVisible(visible);
}
}
public void setCursor(Cursor cursor)
{
}
public void setFont(Font font)
{
this.font = font;
}
public void setForeground(Color foreground)
{
this.foreground = foreground;
}
public void setLocation(Point location)
{
this.location = location;
}
public void setName(String n)
{
name = n;
}
public void setOpaque(boolean opaque)
{
this.opaque = opaque;
}
public void setSize(Dimension size)
{
if (this.size != null)
{
for (int tabIdx = 0; tabIdx < 2; tabIdx++)
{
if (webTabs[tabIdx] != null && webTabs[tabIdx].getPanel().isReady())
{
webTabs[tabIdx].getPanel().getWebForm().setFormWidth(0);
}
}
}
this.size = size;
}
public void setToolTipText(String tooltip)
{
this.tooltip = Utils.stringIsEmpty(tooltip) ? null : tooltip;
}
public String[] getAllRelationNames()
{
String[] retval = new String[allRelationNames.size()];
for (int i = 0; i < retval.length; i++)
{
Object relationName = allRelationNames.get(i);
if (relationName != null)
{
retval[i] = relationName.toString();
}
}
return retval;
}
public List<SortColumn> getDefaultSort()
{
// cant return anything because the splitpane shows 2 forms, so which one to get?
return null;
}
public String getSelectedRelationName()
{
return null;
}
public void notifyVisible(boolean visible, List<Runnable> invokeLaterRunnables)
{
for (int tabIdx = 0; tabIdx < 2; tabIdx++)
{
notifyVisibleForm(visible, tabIdx, invokeLaterRunnables);
}
}
private boolean notifyVisibleForm(boolean visible, int tabIdx, List<Runnable> invokeLaterRunnables)
{
if (webTabs[tabIdx] != null)
{
WebTabFormLookup fl = webTabs[tabIdx].getPanel();
FormController controller = fl.getWebForm().getController();
//this is not needed when closing
if (visible)
{
if (parentData != null) showFoundSet(fl, parentData, controller.getDefaultSortColumns());
// Test if current one is there
if (fl.isReady())
{
if (splitComponents[tabIdx].get(fl.getWebForm().getId()) != null)
{
// replace it
splitComponents[tabIdx].replace(fl.getWebForm());
}
else
{
// else add it
splitComponents[tabIdx].add(fl.getWebForm());
}
FormController fc = fl.getWebForm().getController();
if (tabIdx == 1 && webTabs[0] != null) fc.recomputeTabSequence(leftPanelLastTabIndex);
else fc.recomputeTabSequence(tabSequenceIndex);
}
}
return controller.notifyVisible(visible, invokeLaterRunnables);
}
return false;
}
public void setRecord(IRecordInternal parentState, boolean stopEditing)
{
parentData = parentState;
for (int tabIdx = 0; tabIdx < 2; tabIdx++)
{
if (webTabs[tabIdx] != null)
{
WebTabFormLookup fl = webTabs[tabIdx].getPanel();
showFoundSet(fl, parentState, fl.getDefaultSort(parentData != null || fl.isReady()));
}
}
}
public boolean isCurrentForm(IFormUI formUI)
{
for (int tabIdx = 0; tabIdx < 2; tabIdx++)
{
if (webTabs[tabIdx] != null && webTabs[tabIdx].getPanel().getWebForm() == formUI)
{
return true;
}
}
return false;
}
public void recomputeTabSequence()
{
for (int tabIdx = 0; tabIdx < 2; tabIdx++)
{
if (webTabs[tabIdx] != null && webTabs[tabIdx].getPanel().getWebForm() != null)
{
webTabs[tabIdx].getPanel().getWebForm().getController().recomputeTabSequence(tabSequenceIndex);
}
}
}
public boolean isReadOnly()
{
boolean isReadOnly = true;
for (int tabIdx = 0; tabIdx < 2; tabIdx++)
{
isReadOnly = isReadOnly && (webTabs[tabIdx] != null ? webTabs[tabIdx].getPanel().isReadOnly() : false);
}
return isReadOnly;
}
public void setValidationEnabled(boolean mode)
{
}
public boolean stopUIEditing(boolean looseFocus)
{
boolean stopUIEditing = true;
for (int tabIdx = 0; tabIdx < 2; tabIdx++)
{
if (webTabs[tabIdx] != null && webTabs[tabIdx].getPanel().isReady())
{
stopUIEditing = stopUIEditing && webTabs[tabIdx].getPanel().getWebForm().getController().stopUIEditing(true);
} // else there is nothing there that could be edited (avoid creating forms again with getWebForm() when the app. is shutting down)
}
return stopUIEditing;
}
public void destroy()
{
deregisterSelectionListeners();
//TODO should deregister related foundsets??
}
public IStylePropertyChanges getStylePropertyChanges()
{
return scriptable.getChangesRecorder();
}
public void setAccessible(boolean b)
{
if (!b) setComponentEnabled(b);
accessible = b;
}
private boolean viewable = true;
public void setViewable(boolean b)
{
if (!b) setComponentVisible(b);
this.viewable = b;
}
public boolean isViewable()
{
return viewable;
}
public Insets getPaddingAndBorder()
{
return ((ChangesRecorder)getStylePropertyChanges()).getPaddingAndBorder(size.height, border, new Insets(0, 0, 0, 0), 0, null);
}
public Rectangle getWebBounds()
{
Dimension d = ((ChangesRecorder)getStylePropertyChanges()).calculateWebSize(size.width, size.height, border, new Insets(0, 0, 0, 0), 0, null);
return new Rectangle(location, d);
}
public void valueChanged(ListSelectionEvent e)
{
if (parentData != null)
{
if (webTabs[0] != null)
{
WebTabFormLookup panel = webTabs[0].getPanel();
showFoundSet(panel, parentData, panel.getDefaultSort(true));
}
if (webTabs[1] != null)
{
WebTabFormLookup panel = webTabs[1].getPanel();
showFoundSet(panel, parentData, panel.getDefaultSort(true));
}
}
}
private void showFoundSet(WebTabFormLookup flp, IRecordInternal parentState, List<SortColumn> sort)
{
deregisterSelectionListeners();
if (!flp.isReady()) return;
FormController fp = flp.getWebForm().getController();
if (fp != null && flp.getRelationName() != null)
{
IFoundSetInternal relatedFoundset = parentState == null ? null : parentState.getRelatedFoundSet(flp.getRelationName(), sort);
registerSelectionListeners(parentState, flp.getRelationName());
fp.loadData(relatedFoundset, null);
}
}
private void registerSelectionListeners(IRecordInternal parentState, String relationName)
{
String[] parts = relationName.split("\\."); //$NON-NLS-1$
IRecordInternal currentRecord = parentState;
for (int i = 0; currentRecord != null && i < parts.length - 1; i++)
{
IFoundSetInternal fs = currentRecord.getRelatedFoundSet(parts[i]);
if (fs instanceof ISwingFoundSet)
{
related.add((ISwingFoundSet)fs);
((ISwingFoundSet)fs).getSelectionModel().addListSelectionListener(this);
}
currentRecord = (fs == null) ? null : fs.getRecord(fs.getSelectedIndex());
}
}
private void deregisterSelectionListeners()
{
for (ISwingFoundSet fs : related)
{
fs.getSelectionModel().removeListSelectionListener(this);
}
related.clear();
}
@Override
protected void onRender(MarkupStream markupStream)
{
super.onRender(markupStream);
getStylePropertyChanges().setRendered();
}
public StringBuilder getDividerLocationJSSetter(boolean forceLayoutIfAnchored)
{
String dim, pos;
if (orient == TabPanel.SPLIT_HORIZONTAL)
{
dim = "Width"; //$NON-NLS-1$
pos = "left"; //$NON-NLS-1$
}
else
{
dim = "Height"; //$NON-NLS-1$
pos = "top"; //$NON-NLS-1$
}
StringBuilder resizeScript = new StringBuilder("var dividerSize = ").append(dividerSize).append(";"); //$NON-NLS-1$ //$NON-NLS-2$
resizeScript.append("var dividerLocation = ").append(dividerLocation).append(";"); //$NON-NLS-1$ //$NON-NLS-2$
resizeScript.append("var newDividerLocation = dividerLocation;"); //$NON-NLS-1$
resizeScript.append("if(dividerLocation < 1) { newDividerLocation = (YAHOO.util.Dom.get('").append(getMarkupId()).append("').offset").append(dim).append( //$NON-NLS-1$ //$NON-NLS-2$
"-").append(getDividerSize()).append(")*dividerLocation;}"); //$NON-NLS-1$ //$NON-NLS-2$
resizeScript.append("if(newDividerLocation < ").append(leftFormMinSize).append(") { newDividerLocation = ").append(leftFormMinSize).append(";};"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
resizeScript.append("if(dividerLocation != newDividerLocation) { wicketAjaxGet('").append(dividerUpdater.getCallbackUrl()).append( //$NON-NLS-1$
forceLayoutIfAnchored ? "&anchor=true" : "").append("&location=' + newDividerLocation);}"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
resizeScript.append("var splitter = YAHOO.util.Dom.get('").append(splitter.getMarkupId()).append("');"); //$NON-NLS-1$ //$NON-NLS-2$
resizeScript.append("YAHOO.util.Dom.setStyle(splitter, '").append(dim.toLowerCase()).append("', newDividerLocation + dividerSize + 'px');"); //$NON-NLS-1$ //$NON-NLS-2$
resizeScript.append("var left = YAHOO.util.Dom.get('").append(splitComponents[0].getMarkupId()).append("');"); //$NON-NLS-1$ //$NON-NLS-2$
resizeScript.append("YAHOO.util.Dom.setStyle(left, '").append(dim.toLowerCase()).append("', newDividerLocation + 'px');"); //$NON-NLS-1$ //$NON-NLS-2$
resizeScript.append("var right = YAHOO.util.Dom.get('").append(splitComponents[1].getMarkupId()).append("');"); //$NON-NLS-1$ //$NON-NLS-2$
resizeScript.append("YAHOO.util.Dom.setStyle(right, '").append(pos).append("', newDividerLocation + dividerSize + 'px');"); //$NON-NLS-1$ //$NON-NLS-2$
return resizeScript;
}
public String getSplitScripting()
{
String dim, dim_o, pos;
if (orient == TabPanel.SPLIT_HORIZONTAL)
{
dim = "Width"; //$NON-NLS-1$
dim_o = "height"; //$NON-NLS-1$
pos = "left"; //$NON-NLS-1$
}
else
{
dim = "Height"; //$NON-NLS-1$
dim_o = "width"; //$NON-NLS-1$
pos = "top"; //$NON-NLS-1$
}
StringBuilder resizeScript = getDividerLocationJSSetter(false);
resizeScript.append("var resize = new YAHOO.util.Resize(splitter, { min").append(dim).append(": ").append(dividerSize + leftFormMinSize).append(", max").append(dim).append(": splitter.offsetParent.offset").append(dim).append(" - ").append(rightFormMinSize).append(", ").append(continuousLayout ? "" : "proxy: true, "); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$ //$NON-NLS-8$
resizeScript.append("handles: ['").append(orient == TabPanel.SPLIT_HORIZONTAL ? "r" : "b").append("']});"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
resizeScript.append("YAHOO.util.Dom.setStyle(splitter, '").append(dim_o).append("', '');"); //$NON-NLS-1$ //$NON-NLS-2$
String dividerBg = null;
if (!isOpaque())
{
dividerBg = IStyleSheet.COLOR_TRANSPARENT;
}
else if (background != null)
{
dividerBg = Integer.toHexString(background.getRGB());
dividerBg = "#" + dividerBg.substring(2, dividerBg.length()); //$NON-NLS-1$
}
dim = dim.toLowerCase();
resizeScript.append("var splitterDivs = splitter.getElementsByTagName('div');"); //$NON-NLS-1$
resizeScript.append(
"for(var x = 0; x < splitterDivs.length; x++) { if(splitterDivs[x].parentNode == splitter && splitterDivs[x].id.match('yui') != null) { ").append( //$NON-NLS-1$
"YAHOO.util.Dom.setStyle(splitterDivs[x], '").append(dim).append("', '").append(dividerSize).append("px');").append(dividerBg != null ? "YAHOO.util.Dom.setStyle(splitterDivs[x], 'background-color', '" + dividerBg + "');" : "").append("break; } }; "); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$
if (!continuousLayout)
{
resizeScript.append("YAHOO.util.Dom.setStyle(resize.getProxyEl(), '").append(dim_o).append("', '100%');"); //$NON-NLS-1$ //$NON-NLS-2$
resizeScript.append("resize.on('startResize', function(ev) {"); //$NON-NLS-1$
resizeScript.append("YAHOO.util.Dom.setStyle(splitter, '").append(dim_o).append("', '');"); //$NON-NLS-1$ //$NON-NLS-2$
resizeScript.append("YAHOO.util.Dom.setStyle(this.getProxyEl(), '").append(dim_o).append("', '100%');"); //$NON-NLS-1$ //$NON-NLS-2$
resizeScript.append("YAHOO.util.Dom.setStyle(this.getProxyEl(), 'border', 'none');"); //$NON-NLS-1$
resizeScript.append("YAHOO.util.Dom.setStyle(this.getProxyEl(), 'padding', 0);"); //$NON-NLS-1$
resizeScript.append(
"this.getProxyEl().innerHTML = '<div style = \"filter: alpha(opacity=50); opacity: 0.5; -moz-opacity: 0.5; position: absolute; left: 0; right: 0; top: 0; bottom: 0; border-").append(orient == TabPanel.SPLIT_HORIZONTAL ? "right" : "bottom").append( //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
":").append(dividerSize).append("px solid ").append(dividerBg != null ? dividerBg : "#7D98B8").append("\"></div>';"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
resizeScript.append("});"); //$NON-NLS-1$
}
resizeScript.append("var dividerMoveTimer;"); //$NON-NLS-1$
resizeScript.append("resize.on('resize', function(ev) {"); //$NON-NLS-1$
resizeScript.append("var d = ev.").append(dim).append(";"); //$NON-NLS-1$ //$NON-NLS-2$
resizeScript.append("YAHOO.util.Dom.setStyle(splitter, '").append(dim_o).append("', '');"); //$NON-NLS-1$ //$NON-NLS-2$
resizeScript.append("var newLeftSize = parseInt(YAHOO.util.Dom.getStyle(splitter, '").append(dim).append("'), 10);"); //$NON-NLS-1$ //$NON-NLS-2$
resizeScript.append("YAHOO.util.Dom.setStyle(left, '").append(dim).append("', (newLeftSize - ").append(dividerSize).append(") + 'px');"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
resizeScript.append("YAHOO.util.Dom.setStyle(right, '").append(pos).append("', d + 'px');"); //$NON-NLS-1$ //$NON-NLS-2$
resizeScript.append("clearTimeout(dividerMoveTimer);"); //$NON-NLS-1$
resizeScript.append("dividerMoveTimer = setTimeout(function() {wicketAjaxGet('").append(dividerUpdater.getCallbackUrl()).append("&anchor=true").append("&changed=true").append("&location=' + (newLeftSize - ").append(dividerSize).append("));}, 200);"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$
resizeScript.append("});"); //$NON-NLS-1$
resizeScript.append("resize.on('endResize', function(ev) {"); //$NON-NLS-1$
resizeScript.append("var newLeftSize = parseInt(YAHOO.util.Dom.getStyle(splitter, '").append(dim).append("'), 10);"); //$NON-NLS-1$ //$NON-NLS-2$
resizeScript.append("YAHOO.util.Dom.setStyle(splitter, '").append(dim_o).append("', '');"); //$NON-NLS-1$ //$NON-NLS-2$
resizeScript.append("wicketAjaxGet('").append(dividerUpdater.getCallbackUrl()).append("&anchor=true").append("&changed=true").append("&location=' + (newLeftSize - ").append(dividerSize).append("));"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$
resizeScript.append("});"); //$NON-NLS-1$
boolean useAnchors = Utils.getAsBoolean(application.getRuntimeProperties().get("enableAnchors")); //$NON-NLS-1$
if (useAnchors)
{
String splitId = getMarkupId();
resizeScript.append("\nif(typeof(splitPanes) != \"undefined\")\n").append("{\n"); //$NON-NLS-1$ //$NON-NLS-2$
resizeScript.append("splitPanes['").append(splitId).append("'] = new Array();\n"); //$NON-NLS-1$ //$NON-NLS-2$
resizeScript.append("splitPanes['").append(splitId).append("']['orient'] = '").append(orient == TabPanel.SPLIT_HORIZONTAL ? "h" : "v").append("';\n"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$
resizeScript.append("splitPanes['").append(splitId).append("']['resize'] = resize;\n"); //$NON-NLS-1$ //$NON-NLS-2$
resizeScript.append("splitPanes['").append(splitId).append("']['splitter'] = splitter;\n"); //$NON-NLS-1$ //$NON-NLS-2$
resizeScript.append("splitPanes['").append(splitId).append("']['left'] = left;\n"); //$NON-NLS-1$ //$NON-NLS-2$
resizeScript.append("splitPanes['").append(splitId).append("']['right'] = right;\n"); //$NON-NLS-1$ //$NON-NLS-2$
resizeScript.append("splitPanes['").append(splitId).append("']['currentSize'] = splitter.offsetParent.offset").append(orient == TabPanel.SPLIT_HORIZONTAL ? "Width" : "Height").append(";\n"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$
resizeScript.append("splitPanes['").append(splitId).append("']['resizeWeight'] = ").append(resizeWeight).append(";\n"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
resizeScript.append("splitPanes['").append(splitId).append("']['dividerSize'] = ").append(dividerSize).append(";\n"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
resizeScript.append("splitPanes['").append(splitId).append("']['leftMin'] = ").append(leftFormMinSize).append(";\n"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
resizeScript.append("splitPanes['").append(splitId).append("']['rightMin'] = ").append(rightFormMinSize).append(";\n"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
resizeScript.append("splitPanes['").append(splitId).append("']['callback'] = '").append(dividerUpdater.getCallbackUrl()).append("';\n"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
resizeScript.append("}\n"); //$NON-NLS-1$
// even the PageContributor may do the layout, it can happen that it is doing before
// we set the divider, as both the layout script & divider script are just added with wicket
// renderOnLoadJavascript, but we don't know the order they are added;
resizeScript.append("layoutEntirePage();\n"); //$NON-NLS-1$
resizeScript.append("Servoy.Resize.onWindowResize();\n"); //$NON-NLS-1$
}
return resizeScript.toString();
}
@Override
public void renderHead(HtmlHeaderContainer container)
{
super.renderHead(container);
IHeaderResponse headerResponse = container.getHeaderResponse();
YUILoader.renderResize(headerResponse);
headerResponse.renderOnLoadJavascript(getSplitScripting());
}
public int getAbsoluteFormLocationY()
{
WebDataRenderer parent = findParent(WebDataRenderer.class);
if (parent != null)
{
return parent.getYOffset() + getLocation().y;
}
return getLocation().y;
}
public void setReadOnly(boolean b)
{
for (int tabIdx = 0; tabIdx < 2; tabIdx++)
{
if (webTabs[tabIdx] != null) webTabs[tabIdx].getPanel().setReadOnly(b);
}
}
public void setLeftForm(IFormLookupPanel flp)
{
allRelationNames.add(0, flp == null ? null : flp.getRelationName());
webTabs[0] = new WebTabHolder(flp.getFormName(), flp, null, null);
}
public IFormLookupPanel getLeftForm()
{
return webTabs[0] != null ? webTabs[0].getPanel() : null;
}
public void setRightForm(IFormLookupPanel flp)
{
allRelationNames.add(allRelationNames.size() > 0 ? 1 : 0, flp == null ? null : flp.getRelationName());
webTabs[1] = new WebTabHolder(flp.getFormName(), flp, null, null);
}
public IFormLookupPanel getRightForm()
{
return webTabs[1] != null ? webTabs[1].getPanel() : null;
}
public IFormUI[] getChildForms()
{
IFormUI leftForm = null;
if (webTabs[0] != null)
{
leftForm = webTabs[0].getPanel().getWebForm();
if (leftForm != null && ((Component)leftForm).getParent() == null)
{
leftForm = null;
}
}
IFormUI rightForm = null;
if (webTabs[1] != null)
{
rightForm = webTabs[1].getPanel().getWebForm();
if (rightForm != null && ((Component)rightForm).getParent() == null)
{
rightForm = null;
}
}
return leftForm != null || rightForm != null ? new IFormUI[] { leftForm, rightForm } : null;
}
public IFormLookupPanel createFormLookupPanel(String tabname, String relationName, String formName)
{
return new WebTabFormLookup(tabname, relationName, formName, this, application);
}
public FormScope getForm(boolean bLeftForm)
{
int i = bLeftForm ? 0 : 1;
if (webTabs[i] != null) return webTabs[i].getPanel().getWebForm().getController().getFormScope();
return null;
}
private void setDividerLocationInternal(double newDividerLocation)
{
if (Math.abs(dividerLocation - newDividerLocation) > Double.MIN_VALUE)
{
dividerLocation = newDividerLocation;
if (onDividerChangeMethodCmd != null && scriptExecutor != null)
{
scriptExecutor.executeFunction(onDividerChangeMethodCmd, new Object[] { new Integer(-1) }, false, WebSplitPane.this, false,
StaticContentSpecLoader.PROPERTY_ONCHANGEMETHODID.getPropertyName(), true);
}
}
}
public void setDividerLocation(double newDividerLocation)
{
if (newDividerLocation < 0) return;
setDividerLocationInternal(newDividerLocation);
sizeChanged = true;
}
public void setRuntimeDividerLocation(double locationPos)
{
if (locationPos < 0) return;
setDividerLocationInternal(locationPos);
IRequestTarget requestTarget = RequestCycle.get().getRequestTarget();
MainPage page = (MainPage)findPage();
if (requestTarget instanceof AjaxRequestTarget && page != null)
{
((PageContributor)page.getPageContributor()).addSplitPaneToUpdatedDivider(this);
if (page.getController() != null && Utils.getAsBoolean(page.getController().getApplication().getRuntimeProperties().get("enableAnchors"))) //$NON-NLS-1$
{
((AjaxRequestTarget)requestTarget).appendJavascript("layoutEntirePage();"); //$NON-NLS-1$
}
((AjaxRequestTarget)requestTarget).appendJavascript("Servoy.Resize.onWindowResize();"); //$NON-NLS-1$
}
else sizeChanged = true;
}
public double getDividerLocation()
{
return dividerLocation;
}
public void setDividerSize(int size)
{
dividerSize = size < 0 ? 0 : size;
sizeChanged = true;
}
public int getDividerSize()
{
return dividerSize;
}
public double getResizeWeight()
{
return resizeWeight;
}
public void setResizeWeight(double resizeWeight)
{
this.resizeWeight = resizeWeight;
}
public boolean getContinuousLayout()
{
return continuousLayout;
}
public void setContinuousLayout(boolean b)
{
continuousLayout = b;
}
public void setFormMinSize(boolean bLeftForm, int minSize)
{
if (bLeftForm)
{
leftFormMinSize = minSize;
}
else
{
rightFormMinSize = minSize;
}
}
public int getFormMinSize(boolean bLeftForm)
{
return bLeftForm ? leftFormMinSize : rightFormMinSize;
}
public boolean setForm(boolean bLeftForm, Object form, Object relation)
{
FormController f = null;
String fName = null;
boolean readOnly = false;
if (form instanceof FormController)
{
f = (FormController)form;
readOnly = f.isReadOnly();
}
if (form instanceof BasicFormController.JSForm)
{
f = (FormController)((BasicFormController.JSForm)form).getFormPanel();
readOnly = f.isReadOnly();
}
if (f != null) fName = f.getName();
if (form instanceof String) fName = (String)form;
if (fName != null)
{
String tabname = fName;
RelatedFoundSet relatedFs = null;
String relationName = null;
if (relation instanceof RelatedFoundSet)
{
relatedFs = (RelatedFoundSet)relation;
}
else if (relation instanceof String)
{
relationName = (String)relation;
}
if (relatedFs != null)
{
relationName = relatedFs.getRelationName();
if (f != null && !relatedFs.getDataSource().equals(f.getDataSource()))
{
return false;
}
// TODO do this check to check if the parent table has this relation? How to get the parent table
// Table parentTable = null;
// application.getSolution().getRelations(Solution.SOLUTION+Solution.MODULES, parentTable, true, false);
}
IFormLookupPanel replacedForm = bLeftForm ? getLeftForm() : getRightForm();
if (replacedForm != null)
{
List<Runnable> invokeLaterRunnables = new ArrayList<Runnable>(0);
boolean bNotifyVisibleForm = notifyVisibleForm(false, bLeftForm ? 0 : 1, invokeLaterRunnables);
Utils.invokeLater(application, invokeLaterRunnables);
if (!bNotifyVisibleForm) return false;
}
WebTabFormLookup flp = (WebTabFormLookup)createFormLookupPanel(tabname, relationName, fName);
if (f != null) flp.setReadOnly(readOnly);
if (bLeftForm) setLeftForm(flp);
else setRightForm(flp);
if (relatedFs != null)
{
FormController fp = flp.getWebForm().getController();
if (fp != null && flp.getRelationName() != null && flp.getRelationName().equals(relationName))
{
fp.loadData(relatedFs, null);
}
}
List<Runnable> invokeLaterRunnables = new ArrayList<Runnable>(0);
boolean bNotifyVisibleForm = notifyVisibleForm(true, bLeftForm ? 0 : 1, invokeLaterRunnables);
Utils.invokeLater(application, invokeLaterRunnables);
if (bNotifyVisibleForm)
{
paneChanged[bLeftForm ? 0 : 1] = true;
}
return bNotifyVisibleForm;
}
else if (form == null)
{
IFormLookupPanel replacedForm = bLeftForm ? getLeftForm() : getRightForm();
if (replacedForm != null)
{
List<Runnable> invokeLaterRunnables = new ArrayList<Runnable>(0);
boolean bNotifyVisibleForm = notifyVisibleForm(false, bLeftForm ? 0 : 1, invokeLaterRunnables);
Utils.invokeLater(application, invokeLaterRunnables);
if (!bNotifyVisibleForm) return false;
}
splitComponents[bLeftForm ? 0 : 1].replace(new Label("webform", new Model<String>("")));
webTabs[bLeftForm ? 0 : 1] = null;
paneChanged[bLeftForm ? 0 : 1] = true;
return true;
}
return false;
}
public void setTabSequenceIndex(int tabIndex)
{
this.tabSequenceIndex = tabIndex;
}
public int getTabSequenceIndex()
{
return tabSequenceIndex;
}
public void setFormLastTabIndex(WebForm form, int lastTabIndex)
{
if (webTabs[0] != null && form.equals(webTabs[0].getPanel().getWebForm())) leftPanelLastTabIndex = lastTabIndex;
}
public void notifyResized()
{
for (int i = 0; i < 2; i++)
{
if (webTabs[i] != null && webTabs[i].getPanel().isReady())
{
WebForm webForm = webTabs[i].getPanel().getWebForm();
FormController controller = webForm.getController();
if (controller != null && webForm.isFormWidthHeightChanged())
{
controller.notifyResized();
webForm.clearFormWidthHeightChangedFlag();
}
}
}
}
/*
* (non-Javadoc)
*
* @see com.servoy.j2db.ui.ISplitPane#setOnDividerChangeMethodCmd(java.lang.String)
*/
public void setOnDividerChangeMethodCmd(String onDividerChangeMethodCmd)
{
this.onDividerChangeMethodCmd = onDividerChangeMethodCmd;
}
/*
* (non-Javadoc)
*
* @see com.servoy.j2db.ui.ISplitPane#addScriptExecuter(com.servoy.j2db.IScriptExecuter)
*/
public void addScriptExecuter(IScriptExecuter el)
{
this.scriptExecutor = el;
}
public ISupportSimulateBounds getBoundsProvider()
{
return findParent(ISupportSimulateBounds.class);
}
/*
* (non-Javadoc)
*
* @see com.servoy.j2db.ui.ITabPanel#setTabLayoutPolicy(int)
*/
public void setTabLayoutPolicy(int scroll_tab_layout)
{
// IGNORE
}
/*
* (non-Javadoc)
*
* @see com.servoy.j2db.ui.ITabPanel#addTab(java.lang.String, int, com.servoy.j2db.ui.IFormLookupPanel, java.lang.String)
*/
public void addTab(String text, int iconMediaId, IFormLookupPanel flp, String tooltip)
{
// IGNORE
}
/*
* (non-Javadoc)
*
* @see com.servoy.j2db.ui.ITabPanel#setTabForegroundAt(int, java.awt.Color)
*/
public void setTabForegroundAt(int index, Color fg)
{
// IGNORE
}
/*
* (non-Javadoc)
*
* @see com.servoy.j2db.ui.ITabPanel#setTabBackgroundAt(int, java.awt.Color)
*/
public void setTabBackgroundAt(int index, Color bg)
{
// IGNORE
}
/*
* (non-Javadoc)
*
* @see com.servoy.j2db.ui.ITabPanel#setTabEnabledAt(int, boolean)
*/
public void setTabEnabledAt(int index, boolean enabled)
{
IFormLookupPanel form = index == 0 ? getLeftForm() : index == 1 ? getRightForm() : null;
if (form instanceof WebTabFormLookup) ((WebTabFormLookup)form).getWebForm().setEnabled(enabled);
}
/*
* (non-Javadoc)
*
* @see com.servoy.j2db.ui.ITabPanel#setOnTabChangeMethodCmd(java.lang.String, java.lang.Object[])
*/
public void setOnTabChangeMethodCmd(String onTabChangeMethodCmd, Object[] onTabChangeArgs)
{
// IGNORE
}
/*
* (non-Javadoc)
*
* @see com.servoy.j2db.ui.ITabPanel#removeTabAt(int)
*/
public boolean removeTabAt(int index)
{
return false;
}
/*
* (non-Javadoc)
*
* @see com.servoy.j2db.ui.ITabPanel#removeAllTabs()
*/
public boolean removeAllTabs()
{
return false;
}
/*
* (non-Javadoc)
*
* @see com.servoy.j2db.ui.ITabPanel#addTab(com.servoy.j2db.IForm, java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String,
* java.lang.String, java.lang.String, java.lang.String, com.servoy.j2db.dataprocessing.RelatedFoundSet, int)
*/
public boolean addTab(IForm formController, String formName, String tabname, String tabText, String tooltip, String iconURL, String fg, String bg,
String relationName, RelatedFoundSet relatedFs, int tabIndex)
{
return false;
}
/*
* (non-Javadoc)
*
* @see com.servoy.j2db.ui.ITabPanel#setTabTextAt(int, java.lang.String)
*/
public void setTabTextAt(int i, String text)
{
// IGNORE
}
/*
* (non-Javadoc)
*
* @see com.servoy.j2db.ui.ITabPanel#getTabTextAt(int)
*/
public String getTabTextAt(int i)
{
return null;
}
/*
* (non-Javadoc)
*
* @see com.servoy.j2db.ui.ITabPanel#setMnemonicAt(int, int)
*/
public void setMnemonicAt(int i, int mnemonic)
{
// IGNORE
}
/*
* (non-Javadoc)
*
* @see com.servoy.j2db.ui.ITabPanel#getMnemonicAt(int)
*/
public int getMnemonicAt(int i)
{
// TODO Auto-generated method stub
return 0;
}
/*
* (non-Javadoc)
*
* @see com.servoy.j2db.ui.ITabPanel#getTabNameAt(int)
*/
public String getTabNameAt(int i)
{
IFormLookupPanel form = i == 0 ? getLeftForm() : i == 1 ? getRightForm() : null;
return form != null ? form.getName() : null;
}
/*
* (non-Javadoc)
*
* @see com.servoy.j2db.ui.ITabPanel#getTabFormNameAt(int)
*/
public String getTabFormNameAt(int i)
{
IFormLookupPanel form = i == 0 ? getLeftForm() : i == 1 ? getRightForm() : null;
return form != null ? form.getFormName() : null;
}
/*
* (non-Javadoc)
*
* @see com.servoy.j2db.ui.ITabPanel#setTabIndex(int)
*/
public void setTabIndex(int index)
{
// IGNORE
}
/*
* (non-Javadoc)
*
* @see com.servoy.j2db.ui.ITabPanel#setTabIndex(java.lang.String)
*/
public void setTabIndex(String name)
{
// IGNORE
}
/*
* (non-Javadoc)
*
* @see com.servoy.j2db.ui.ITabPanel#isTabEnabledAt(int)
*/
public boolean isTabEnabledAt(int index)
{
IFormLookupPanel form = index == 0 ? getLeftForm() : index == 1 ? getRightForm() : null;
if (form instanceof WebTabFormLookup) return ((WebTabFormLookup)form).getWebForm().isEnabled();
return false;
}
/*
* (non-Javadoc)
*
* @see com.servoy.j2db.ui.ITabPanel#getTabIndex()
*/
public int getTabIndex()
{
return 0;
}
/*
* (non-Javadoc)
*
* @see com.servoy.j2db.ui.ITabPanel#getMaxTabIndex()
*/
public int getMaxTabIndex()
{
return 1;
}
/*
* (non-Javadoc)
*
* @see com.servoy.j2db.ui.ITabPanel#setHorizontalAlignment(int)
*/
public void setHorizontalAlignment(int alignment)
{
// IGNORE
}
public boolean isParentContainerChanged()
{
final boolean[] isParentContainerChanged = { false };
visitParents(IProviderStylePropertyChanges.class, new IVisitor<Component>()
{
@Override
public Object component(Component component)
{
if (((IProviderStylePropertyChanges)component).getStylePropertyChanges().isChanged())
{
isParentContainerChanged[0] = true;
return IVisitor.STOP_TRAVERSAL;
}
return IVisitor.CONTINUE_TRAVERSAL;
}
});
return isParentContainerChanged[0];
}
public void attachComponents(AjaxRequestTarget target)
{
if (!((ChangesRecorder)scriptable.getChangesRecorder()).isChanged())
{
if (!isParentContainerChanged() && (paneChanged[0] || paneChanged[1]))
{
if (paneChanged[0] && paneChanged[1])
{
target.addComponent(WebSplitPane.this);
}
else if (paneChanged[0])
{
target.addComponent(splitComponents[0]);
}
else
{
target.addComponent(splitComponents[1]);
}
target.appendJavascript(getSplitScripting());
}
}
paneChanged[0] = false;
paneChanged[1] = false;
}
@Override
public void uiRecreated()
{
recomputeTabSequence();
}
}