/*
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;
import java.awt.Rectangle;
import java.awt.print.PrinterJob;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.apache.wicket.IPageMap;
import org.apache.wicket.MarkupContainer;
import org.apache.wicket.PageMap;
import org.apache.wicket.RequestCycle;
import org.apache.wicket.Session;
import com.servoy.j2db.BasicFormController;
import com.servoy.j2db.FormController;
import com.servoy.j2db.FormManager;
import com.servoy.j2db.IApplication;
import com.servoy.j2db.IFormUIInternal;
import com.servoy.j2db.IMainContainer;
import com.servoy.j2db.dataprocessing.FoundSet;
import com.servoy.j2db.dataprocessing.IFoundSetInternal;
import com.servoy.j2db.persistence.Form;
import com.servoy.j2db.persistence.Solution;
import com.servoy.j2db.server.headlessclient.dataui.IWebFormContainer;
import com.servoy.j2db.smart.SwingForm;
import com.servoy.j2db.util.Debug;
import com.servoy.j2db.util.ServoyException;
import com.servoy.j2db.util.Settings;
import com.servoy.j2db.util.Utils;
/**
* A {@link FormManager} implementation that is used in the webclient.
*
* @author jcompagner
*/
public class WebFormManager extends FormManager
{
private final int maxForms;
private final ResourceReferences globalResourceReferences = new ResourceReferences();
@SuppressWarnings("nls")
public WebFormManager(IApplication app, IMainContainer mainp)
{
super(app, mainp);
int max = Utils.getAsInteger(Settings.getInstance().getProperty("servoy.max.webforms.loaded", "128"), false);
maxForms = max == 0 ? 128 : max;
}
public ResourceReferences getGlobalResourceReferences()
{
return globalResourceReferences;
}
/*
* (non-Javadoc)
*
* @see com.servoy.j2db.FormManager#makeSolutionSettings(com.servoy.j2db.persistence.Solution)
*/
@Override
protected void makeSolutionSettings(Solution s)
{
super.makeSolutionSettings(s);
if (getCurrentContainer() instanceof MainPage)
{
// store the minimum version of the current main container loading
// this new solution. So that it can't go past it again when using
// the back button in the browser
((MainPage)getCurrentContainer()).storeMinVersion();
}
}
@Override
protected int getMaxFormsLoaded()
{
return maxForms;
}
@Override
public IFormUIInternal getFormUI(FormController formController)
{
if (Utils.getAsBoolean(getApplication().getRuntimeProperties().get("isPrinting"))) //$NON-NLS-1$
{
return new SwingForm(formController);
}
return new WebForm(formController);
}
protected void addIPersistListenerHook()
{
}
@Override
protected boolean checkAndUpdateFormUser(FormController fp, Object parentContainer)
{
if (parentContainer instanceof MainPage)
{
return ((MainPage)parentContainer).getController() != fp;
}
return true;
}
@Override
protected void enableCmds(boolean enable)
{
}
@Override
public void fillScriptMenu()
{
}
public void synchViewMenu(int viewType)
{
}
protected void removeIPersistListenerHook()
{
}
@Override
protected void selectFormMenuItem(Form form)
{
}
@Override
protected boolean isShowingPrintPreview()
{
// Web Printing doesn't have to show the forms, it prints to PDF,t hat code sits in
// WebForm.print(boolean showDialogs, boolean printCurrentRecordOnly, boolean showPrinterSelectDialog, PrinterJob printerJob)
return false;
}
@Override
protected FormController removePreview()
{
// Web Printing doesn't have to show the forms, it prints to PDF,t hat code sits in
// WebForm.print(boolean showDialogs, boolean printCurrentRecordOnly, boolean showPrinterSelectDialog, PrinterJob printerJob)
return null;
}
@Override
public void showPreview(FormController afp, IFoundSetInternal foundset, int zoomFactor, PrinterJob printJob)
{
// Web Printing doesn't have to show the forms, it prints to PDF,t hat code sits in
// WebForm.print(boolean showDialogs, boolean printCurrentRecordOnly, boolean showPrinterSelectDialog, PrinterJob printerJob)
}
@Override
protected void removeFormUser(BasicFormController fp)
{
}
public void reload(FormController[] fcontrollers)
{
HashSet<MainPage> mainPages = new HashSet<MainPage>();
for (FormController fc : fcontrollers)
{
WebForm formUI = (WebForm)fc.getFormUI();
MainPage mp = formUI.findParent(MainPage.class);
if (mp != null && mainPages.add(mp))
{
mp.setVersioned(false);
mp.setMainPageSwitched();
}
}
String navigatorName = null;
Set<MainPage> parents = new HashSet<MainPage>();
for (FormController fp : fcontrollers)
{
if (fp != null)
{
boolean formVisible = fp.isFormVisible();
FoundSet foundset = fp.getFormModel();
WebForm wf = (WebForm)fp.getFormUI();
MarkupContainer wfParent = wf.getParent();
boolean refresh = false;
//datasource has changed, but foundset has not
if (foundset != null && !Utils.equalObjects(foundset.getDataSource(), fp.getDataSource()))
{
try
{
foundset = (FoundSet)(getApplication()).getFoundSetManager().getSharedFoundSet(fp.getDataSource());
foundset.loadAllRecords();
refresh = true;
}
catch (ServoyException e)
{
Debug.error("Failed to reload foundset.", e); //$NON-NLS-1$
}
}
MainPage page = wf.findParent(MainPage.class);
try
{
if (page != null)
{
page.setTempRemoveMainForm(true);
}
fp.destroy();
}
finally
{
if (page != null)
{
page.setTempRemoveMainForm(false);
}
}
while (wfParent != null && !(wfParent instanceof IWebFormContainer) && !(wfParent.getParent() instanceof MainPage) &&
!(wfParent.getParent() instanceof WebForm))
{
wfParent = wfParent.getParent();
}
if (wfParent instanceof IWebFormContainer)
{
if (formVisible)
{
FormController fc = leaseFormPanel(fp.getName());
if (fc != null)
{
// form was deleted in developer?
fc.loadData(foundset, null);
if (refresh) fc.recreateUI();
List<Runnable> runnables = new ArrayList<Runnable>();
((IWebFormContainer)wfParent).notifyVisible(true, runnables);
Utils.invokeLater(getApplication(), runnables);
}
}
}
else if (wfParent != null)
{
WebForm parentWF = wfParent.findParent(WebForm.class);
if (parentWF != null)
{
if (!Arrays.asList(fcontrollers).contains(parentWF.getController())) parentWF.getController().destroy();
}
else
{
MainPage parent = wfParent.findParent(MainPage.class);
if (parent != null && !parents.contains(parent))
{
parents.add(parent);
if (parent.getNavigator() == fp)
{
navigatorName = fp.getName();
FormController navigator = getFormController(navigatorName, parent);
if (navigator != null)
{
List<Runnable> invokeLaterRunnables = new ArrayList<Runnable>();
navigator.notifyVisible(true, invokeLaterRunnables);
Utils.invokeLater(getApplication(), invokeLaterRunnables);
parent.setNavigator(navigator);
//parent.triggerBrowserRequestIfNeeded(); // FIXME: this is needed here but currently does nothing because the request target is not yet set
}
}
FormController previousMainShowingForm = (parent != null ? parent.getController() : null);
if (previousMainShowingForm != null)
{
FormController previousNavigator = parent.getNavigator();
parent.setController(null);
// navigator is not re-applied so apply it manually
int navigatorID = previousMainShowingForm.getForm().getNavigatorID();
if (navigatorID == Form.NAVIGATOR_IGNORE || (previousNavigator != null && previousNavigator.getForm().getID() == navigatorID))
{
parent.setNavigator(previousNavigator);
}
else if (navigatorID > 0)
{
Form newNavigator = application.getFlattenedSolution().getForm(navigatorID);
if (newNavigator != null)
{
parent.setNavigator(leaseFormPanel(newNavigator.getName()));
}
}
showFormInMainPanel(previousMainShowingForm.getName(), parent, null, true, null);
// parent.triggerBrowserRequestIfNeeded(); // FIXME: this is needed here but currently does nothing because the request target is not yet set
}
}
}
}
}
}
for (MainPage mainPage : mainPages)
{
mainPage.setVersioned(true);
}
}
public void reload()
{
FormController[] array = createdFormControllers.values().toArray(new FormController[0]);
createdFormControllers.clear();
leaseHistory.clear();
reload(array);
}
@Override
public void showFormInDialog(String formName, Rectangle bounds, String title, boolean resizeble, boolean showTextToolbar, boolean closeAll, boolean modal,
String windowName)
{
// with old implementation, non-modal dialogs in WC were actually separate browser windows; keep it compatible with new implementation
if (modal)
{
super.showFormInDialog(formName, bounds, title, resizeble, showTextToolbar, closeAll, modal, windowName);
}
else
{
super.showFormInFrame(formName, bounds, title, resizeble, showTextToolbar, windowName);
}
}
/**
* @see com.servoy.j2db.FormManager#getOrCreateMainContainer(java.lang.String)
*/
@Override
public IMainContainer getOrCreateMainContainer(String nm)
{
String name = nm;
if (name != null && name.trim().length() == 0)
{
// blank names would make PageMap throw an exception or generate JS errors
name = "blank_name"; //$NON-NLS-1$
}
IMainContainer container = getMainContainer(name);
if (container == null)
{
WebClient wc = (WebClient)getApplication();
IPageMap pageMap = PageMap.forName(name);
container = new MainPage(wc, pageMap);
containers.put(name, container);
}
return container;
}
@Override
protected void destroyContainer(IMainContainer container)
{
if (container instanceof MainPage)
{
((MainPage)container).close();
}
super.destroyContainer(container);
}
/*
* (non-Javadoc)
*
* @see com.servoy.j2db.FormManager#destroySolutionSettings()
*/
@Override
protected void destroySolutionSettings()
{
super.destroySolutionSettings();
if (RequestCycle.get() != null) Session.get().setMetaData(Session.PAGEMAP_ACCESS_MDK, null); // reset all pagemap accesses.
}
}