/*
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.smart;
import java.awt.Container;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.print.PrinterJob;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import javax.swing.Action;
import javax.swing.JComponent;
import javax.swing.JMenu;
import javax.swing.JRadioButtonMenuItem;
import javax.swing.JSeparator;
import com.servoy.j2db.BasicFormController;
import com.servoy.j2db.FlattenedSolution;
import com.servoy.j2db.FormController;
import com.servoy.j2db.FormManager;
import com.servoy.j2db.IFormUIInternal;
import com.servoy.j2db.IMainContainer;
import com.servoy.j2db.IModeManager;
import com.servoy.j2db.ISmartClientApplication;
import com.servoy.j2db.ISwingFormManager;
import com.servoy.j2db.Messages;
import com.servoy.j2db.cmd.ICmdManager;
import com.servoy.j2db.dataprocessing.IFoundSetInternal;
import com.servoy.j2db.persistence.Form;
import com.servoy.j2db.persistence.ScriptMethod;
import com.servoy.j2db.persistence.ScriptVariable;
import com.servoy.j2db.persistence.Solution;
import com.servoy.j2db.printing.PrintPreview;
import com.servoy.j2db.scripting.FunctionDefinition;
import com.servoy.j2db.smart.cmd.MenuMethodsAction;
import com.servoy.j2db.smart.scripting.ScriptMenuItem;
import com.servoy.j2db.util.SwingHelper;
import com.servoy.j2db.util.Utils;
import com.servoy.j2db.util.gui.JMenuAlwaysEnabled;
public class SwingFormManager extends FormManager implements ISwingFormManager, ActionListener
{
protected Map formUser; // FormUIController -> Container
// Map thats stores containers that er in printpreview: IMainContainer -> PrintPreviewHolder
protected Map printPreviews;
protected WindowMenuDialog windowMenuDialog;
private JMenu scriptMenu;
public SwingFormManager(ISmartClientApplication app, IMainContainer mainContainer)
{
super(app, mainContainer);
windowMenuDialog = new WindowMenuDialog(app, this);
formUser = new HashMap();
printPreviews = new HashMap();
}
public JComponent getFormPanel(String name, Container parent)
{
return (JComponent)getFormController(name, parent).getFormUI();
}
public void actionPerformed(ActionEvent e)
{
final String name = e.getActionCommand();
getApplication().invokeLater(new Runnable()
{
public void run()
{
if (getApplication().getSolution() != null)
{
try
{
getApplication().blockGUI(Messages.getString("servoy.formManager.showingForm")); //$NON-NLS-1$
SwingHelper.dispatchEvents(100);
// //save any outstanding change
// IForm dm = getCurrentForm();
// if (dm != null) dm.saveData();//make sure all data is saved on close();
// Form f = (Form)windowMenuDialog.getFormController(name);
switch (getApplication().getModeManager().getMode())
{
case IModeManager.PREVIEW_MODE :
// this does not work.
// removePreview();
// showPreview(f);
// break;
//
case IModeManager.FIND_MODE :
case IModeManager.EDIT_MODE :
((FormManager)getApplication().getFormManager()).showFormInMainPanel(name);
}
}
finally
{
getApplication().releaseGUI();
}
}
}
});
}
public JMenu getScriptMenu()
{
if (scriptMenu == null)
{
scriptMenu = new JMenuAlwaysEnabled(new MenuMethodsAction(getApplication()));
}
return scriptMenu;
}
//return the window menu
public JMenu getWindowMenu()
{
return windowMenuDialog.getWindowMenu();
}
@Override
public void addForm(Form form, boolean selected)
{
super.addForm(form, selected);
if (getApplication().getFlattenedSolution().formCanBeInstantiated(form))
{
JRadioButtonMenuItem mi = windowMenuDialog.addForm(form);
if (mi != null) mi.setSelected(selected);
}
}
/**
* @see com.servoy.j2db.FormManager#removeForm(com.servoy.j2db.persistence.Form)
*/
@Override
public boolean removeForm(Form form)
{
if (super.removeForm(form))
{
windowMenuDialog.removeForm(form);
return true;
}
return false;
}
@Override
protected void selectFormMenuItem(Form form)
{
if (currentContainer == getMainContainer(null))
{
windowMenuDialog.selectForm(currentContainer.getController().getForm());
}
}
/**
* @see com.servoy.j2db.FormManager#makeSolutionSettings(com.servoy.j2db.persistence.Solution)
*/
@Override
protected void makeSolutionSettings(Solution s)
{
// have to do this when security.login() is used.
windowMenuDialog.destroy();
super.makeSolutionSettings(s);
if (getCurrentForm() instanceof FormController)
{
windowMenuDialog.selectForm(((FormController)getCurrentForm()).getForm());
}
}
protected boolean getShowFormsAllInWindowMenu()
{
return false;
}
@Override
public void removeAllFormPanels()
{
super.removeAllFormPanels();
if (scriptMenu != null)
{
scriptMenu.removeAll();
}
}
@Override
protected void handleModeChange(int oldmode, int newmode)
{
if (scriptMenu != null)
{
scriptMenu.setEnabled(newmode == IModeManager.EDIT_MODE);
}
super.handleModeChange(oldmode, newmode);
}
/**
* @param f
*/
public void synchViewMenu(int view)
{
if (views != null)
{
boolean enableViewButtons = false;
if (view < views.length)
{
enableViewButtons = true;
JRadioButtonMenuItem mi2 = views[view];
if (mi2 != null && !mi2.isSelected())
{
mi2.setSelected(true);
}
}
for (JRadioButtonMenuItem element : views)
{
if (element != null) element.setEnabled(enableViewButtons);
}
}
}
/**
* @param f
*/
@Override
public void enableCmds(boolean enable)
{
Form currentMainShowingForm = null;
if (currentContainer != null)
{
// only enable command on the current container. They must be enabled else commands are disabled or not
// disabled based on the main container. Now they will be set to enabled based on who has the focus
//if (currentContainer != getMainContainer(null) ||
if (currentContainer.getController() == null) return;
currentMainShowingForm = currentContainer.getController().getForm();
}
if (enable && currentMainShowingForm == null) return;
boolean findMode = false; // see also CmdManager.ableFormRelatedDataEditActions - the actions that are not used in there
// but are in here should make use of findMode here - so as not to be enabled in find mode
if (currentMainShowingForm != null) findMode = currentContainer.getController().isInFindMode();
ICmdManager cm = getApplication().getCmdManager();
Action a = null;
a = cm.getRegisteredAction("cmdnewrecord"); //$NON-NLS-1$
if (a != null) a.setEnabled(enable && currentMainShowingForm.getOnNewRecordCmdMethodID() >= 0);
a = cm.getRegisteredAction("cmdduplicaterecord"); //$NON-NLS-1$
if (a != null) a.setEnabled(enable && currentMainShowingForm.getOnDuplicateRecordCmdMethodID() >= 0);
a = cm.getRegisteredAction("cmddeleterecord"); //$NON-NLS-1$
if (a != null) a.setEnabled(enable && currentMainShowingForm.getOnDeleteRecordCmdMethodID() >= 0);
a = cm.getRegisteredAction("cmddeleteallrecord"); //$NON-NLS-1$
if (a != null) a.setEnabled(enable && !findMode && currentMainShowingForm.getOnDeleteAllRecordsCmdMethodID() >= 0);
a = cm.getRegisteredAction("cmdfindmode"); //$NON-NLS-1$
if (a != null) a.setEnabled(enable && !findMode && currentMainShowingForm.getOnFindCmdMethodID() >= 0);
a = cm.getRegisteredAction("cmdfindall"); //$NON-NLS-1$
if (a != null) a.setEnabled(enable && currentMainShowingForm.getOnShowAllRecordsCmdMethodID() >= 0);
a = cm.getRegisteredAction("cmdomitrecord"); //$NON-NLS-1$
if (a != null) a.setEnabled(enable && !findMode && currentMainShowingForm.getOnOmitRecordCmdMethodID() >= 0);
a = cm.getRegisteredAction("cmdshowomitrecords"); //$NON-NLS-1$
if (a != null) a.setEnabled(enable && !findMode && currentMainShowingForm.getOnShowOmittedRecordsCmdMethodID() >= 0);
a = cm.getRegisteredAction("cmdrevertrecords"); //$NON-NLS-1$
if (a != null) a.setEnabled(enable && !findMode && currentMainShowingForm.getOnInvertRecordsCmdMethodID() >= 0);
a = cm.getRegisteredAction("cmdpreviewmode"); //$NON-NLS-1$
if (a != null) a.setEnabled(enable && !findMode && currentMainShowingForm.getOnPrintPreviewCmdMethodID() >= 0);
a = cm.getRegisteredAction("cmdsort"); //$NON-NLS-1$
if (a != null) a.setEnabled(enable && !findMode && currentMainShowingForm.getOnSortCmdMethodID() >= 0);
a = cm.getRegisteredAction("cmdnextrecord"); //$NON-NLS-1$
if (a != null) a.setEnabled(enable && currentMainShowingForm.getOnNextRecordCmdMethodID() >= 0);
a = cm.getRegisteredAction("cmdprevrecord"); //$NON-NLS-1$
if (a != null) a.setEnabled(enable && currentMainShowingForm.getOnPreviousRecordCmdMethodID() >= 0);
}
// fill the scripts menu
@Override
public void fillScriptMenu()
{
JMenu menu = getScriptMenu();
// Remove old script methods.
menu.removeAll();
FlattenedSolution sol = getApplication().getFlattenedSolution();
if (sol.getSolution() == null) return;
List<ScriptMenuItem> globalMenus = new ArrayList<ScriptMenuItem>();
int menuCount = 1;
Iterator<ScriptMethod> globalMethods = sol.getScriptMethods(true);
while (globalMethods.hasNext())
{
ScriptMethod sm = globalMethods.next();
ScriptMenuItem item = getScriptMenuItem(sm, new FunctionDefinition(ScriptVariable.SCOPES_DOT_PREFIX + sm.getScopeName(), sm.getName()), menuCount);
if (item != null)
{
globalMenus.add(item);
if (menuCount > 0 && menuCount < 9)
{
menuCount++;
}
else
{
menuCount = -1;
}
// just break after 50, doesn't make sense to have more in the menu..
if (globalMenus.size() > 50) break;
}
}
JMenu globalMenu = menu;
if (globalMenus.size() > 20)// if big create sub menu for global methods
{
globalMenu = new JMenu(Messages.getString("servoy.formManager.menuGlobalMethods"));
menu.add(globalMenu);
}
Iterator<ScriptMenuItem> it = globalMenus.iterator();
while (it.hasNext())
{
ScriptMenuItem item = it.next();
globalMenu.add(item);
}
boolean insertSeparator = menu.getMenuComponentCount() > 0;
FormController fp = getCurrentMainShowingFormController();
if (fp != null)
{
int nformmethods = 0;
Form form = fp.getForm();
Iterator<ScriptMethod> formMethods = form.getScriptMethods(true);
while (formMethods.hasNext())
{
ScriptMethod sm = formMethods.next();
ScriptMenuItem item = getScriptMenuItem(sm, new FunctionDefinition(form.getName(), sm.getName()), -1);
if (item != null)
{
if (insertSeparator)
{
menu.add(new JSeparator());
insertSeparator = false;
}
nformmethods++;
menu.add(item);
}
}
if (form.getDataSource() != null)
{
insertSeparator |= nformmethods > 0;
Iterator<ScriptMethod> foundsetMethods = fp.getApplication().getFlattenedSolution().getFoundsetMethods(fp.getDataSource(), true);
while (foundsetMethods.hasNext())
{
ScriptMethod sm = foundsetMethods.next();
ScriptMenuItem item = getScriptMenuItem(sm, new FunctionDefinition(form.getName(), sm.getName()), -1);
if (item != null)
{
if (insertSeparator)
{
menu.add(new JSeparator());
insertSeparator = false;
}
menu.add(item);
}
}
}
}
menu.setEnabled(menu.getMenuComponentCount() > 0);
}
/**
* Method showScriptInMenu.
*
* @param sm
* @return boolean
*/
protected ScriptMenuItem getScriptMenuItem(ScriptMethod sm, FunctionDefinition functionDefinition, int autoSortcut)
{
if (sm.getShowInMenu())
{
return new ScriptMenuItem(getApplication(), functionDefinition, sm.getName(), autoSortcut);
}
return null;
}
private JRadioButtonMenuItem[] views = null;
public void setViews(JRadioButtonMenuItem[] viewbuttons)
{
views = viewbuttons;
}
//uninit
@Override
protected void destroySolutionSettings()
{
super.destroySolutionSettings();
windowMenuDialog.destroy();
if (scriptMenu != null)
{
getScriptMenu().removeAll();
}
formUser = new HashMap();
printPreviews = new HashMap();
}
@Override
protected void removeFormUser(BasicFormController fp)
{
Container user = (Container)formUser.remove(fp);
if (user != null)
{
user.remove((Container)fp.getFormUI());
}
}
@Override
protected boolean checkAndUpdateFormUser(FormController fp, Object parentContainer)
{
Container c = (Container)parentContainer;
boolean isNewUser = false;
Container user = (Container)formUser.get(fp);
if (user == null)
{
formUser.put(fp, c);//register new user
isNewUser = true;
}
else if (!c.equals(user) || ((Container)fp.getFormUI()).getParent() == null)
{
// register first then remove (else 2 times remove with FormLookupPanel)
formUser.put(fp, c);//register new user
user.remove(((Container)fp.getFormUI()));
isNewUser = true;
}
return isNewUser;
}
@Override
public void showPreview(final FormController afp, final IFoundSetInternal foundset, int zoomFactor, final PrinterJob printJob)
{
removePreview();
final FormController fc = currentContainer.getController();
if (fc != null)
{
List invokeLaterRunnables = new ArrayList();
boolean ok = fc.notifyVisible(false, invokeLaterRunnables);
Utils.invokeLater(getApplication(), invokeLaterRunnables);
if (!ok)
{
return;//cannot hide...so skip preview
}
}
showFormInMainPanel(afp.getName(), currentContainer, null, true, null);
getApplication().getModeManager().setMode(IModeManager.PREVIEW_MODE);
boolean isNewUser = checkAndUpdateFormUser(afp, currentContainer);
if (isNewUser)
{
IFormUIInternal ui = afp.getFormUI();
currentContainer.add(ui, afp.getName());
}
try
{
final PrintPreview printPreview = new PrintPreview((ISmartClientApplication)getApplication(), afp, foundset, zoomFactor, printJob);
Runnable r = new Runnable()
{
public void run()
{
printPreviews.put(currentContainer, new PrintPreviewHolder(printPreview, fc));
currentContainer.add(printPreview, "@preview"); //$NON-NLS-1$
currentContainer.show("@preview"); //$NON-NLS-1$
//handle navigator propertly
List invokeLaterRunnables = new ArrayList();
afp.showNavigator(invokeLaterRunnables);
Utils.invokeLater(getApplication(), invokeLaterRunnables);
printPreview.showPages();
}
};
getApplication().invokeLater(r);
}
catch (Exception ex)
{
getApplication().reportError(Messages.getString("servoy.formManager.error.PrintPreview"), ex); //$NON-NLS-1$
}
}
@Override
protected FormController removePreview()
{
return removePreview(currentContainer);
}
protected FormController removePreview(IMainContainer container)
{
PrintPreviewHolder printPreviewHolder = (PrintPreviewHolder)printPreviews.remove(container);
if (printPreviewHolder != null)
{
container.remove(printPreviewHolder.printPreview);
printPreviewHolder.printPreview.destroy();
return printPreviewHolder.formBeforePrintPreview;
}
//currentMainShowingForm
return container.getController();//just return current
}
@Override
protected boolean isShowingPrintPreview()
{
return (printPreviews.containsKey(currentContainer));
}
@Override
public IFormUIInternal getFormUI(FormController formController)
{
return new SwingForm(formController);
}
@Override
public IMainContainer getOrCreateMainContainer(String name)
{
IMainContainer container = getMainContainer(name);
if (container == null)
{
container = new MainPanel(getApplication(), name);
containers.put(name, container);
}
return container;
}
private class PrintPreviewHolder
{
private final PrintPreview printPreview;
private final FormController formBeforePrintPreview;
private PrintPreviewHolder(PrintPreview printPreview, FormController formBeforePrintPreview)
{
this.printPreview = printPreview;
this.formBeforePrintPreview = formBeforePrintPreview;
}
}
}