/* 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.BorderLayout; import java.awt.Color; import java.awt.Component; import java.awt.Container; import java.awt.Cursor; import java.awt.Dimension; import java.awt.Font; import java.awt.Frame; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; import java.awt.KeyEventDispatcher; import java.awt.KeyboardFocusManager; import java.awt.Toolkit; import java.awt.Window; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.InputEvent; import java.awt.event.KeyAdapter; import java.awt.event.KeyEvent; import java.awt.event.MouseAdapter; import java.awt.event.MouseMotionAdapter; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.awt.event.WindowListener; import java.awt.print.PageFormat; import java.io.DataInputStream; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.lang.reflect.Constructor; import java.lang.reflect.Method; import java.net.MalformedURLException; import java.net.URL; import java.net.URLStreamHandler; import java.rmi.Remote; import java.rmi.RemoteException; import java.rmi.registry.LocateRegistry; import java.rmi.registry.Registry; import java.rmi.server.UnicastRemoteObject; import java.security.PrivilegedExceptionAction; import java.util.ArrayList; import java.util.Calendar; import java.util.Collection; import java.util.Date; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Locale; import java.util.Map; import java.util.Map.Entry; import java.util.Properties; import java.util.ResourceBundle; import java.util.Stack; import java.util.TimeZone; import java.util.concurrent.ScheduledExecutorService; import javax.security.auth.Subject; import javax.security.auth.callback.Callback; import javax.security.auth.callback.CallbackHandler; import javax.security.auth.callback.NameCallback; import javax.security.auth.callback.PasswordCallback; import javax.security.auth.callback.TextOutputCallback; import javax.security.auth.callback.UnsupportedCallbackException; import javax.security.auth.login.LoginContext; import javax.security.auth.login.LoginException; import javax.swing.AbstractAction; import javax.swing.Action; import javax.swing.ActionMap; import javax.swing.BorderFactory; import javax.swing.BoxLayout; import javax.swing.ButtonGroup; import javax.swing.Icon; import javax.swing.ImageIcon; import javax.swing.InputMap; import javax.swing.JButton; import javax.swing.JComponent; import javax.swing.JDialog; import javax.swing.JFormattedTextField.AbstractFormatter; import javax.swing.JFormattedTextField.AbstractFormatterFactory; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JLayeredPane; import javax.swing.JMenu; import javax.swing.JMenuBar; import javax.swing.JMenuItem; import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JRadioButtonMenuItem; import javax.swing.JRootPane; import javax.swing.JToolBar; import javax.swing.KeyStroke; import javax.swing.LookAndFeel; import javax.swing.RepaintManager; import javax.swing.SwingConstants; import javax.swing.SwingUtilities; import javax.swing.ToolTipManager; import javax.swing.UIDefaults; import javax.swing.UIManager; import javax.swing.UIManager.LookAndFeelInfo; import javax.swing.WindowConstants; import javax.swing.border.BevelBorder; import javax.swing.border.Border; import javax.swing.plaf.FontUIResource; import javax.swing.plaf.InputMapUIResource; import javax.swing.plaf.metal.MetalLookAndFeel; import javax.swing.plaf.metal.MetalTheme; import javax.swing.text.DefaultFormatter; import javax.swing.text.DefaultFormatterFactory; import javax.swing.text.MaskFormatter; import com.servoy.j2db.ApplicationException; import com.servoy.j2db.BeanManager; import com.servoy.j2db.ClientRepository; import com.servoy.j2db.ClientState; import com.servoy.j2db.Credentials; import com.servoy.j2db.FormController; import com.servoy.j2db.FormManager; import com.servoy.j2db.IApplication; import com.servoy.j2db.IBasicFormManager; import com.servoy.j2db.IBeanManager; import com.servoy.j2db.IDataRendererFactory; import com.servoy.j2db.IFormManagerInternal; import com.servoy.j2db.ILAFManager; import com.servoy.j2db.IMessagesCallback; import com.servoy.j2db.IModeManager; import com.servoy.j2db.IProvideFormName; import com.servoy.j2db.ISmartClientApplication; import com.servoy.j2db.J2DBGlobals; import com.servoy.j2db.LAFManager; import com.servoy.j2db.MediaURLStreamHandler; import com.servoy.j2db.Messages; import com.servoy.j2db.MessagesResourceBundle; import com.servoy.j2db.RuntimeWindowManager; import com.servoy.j2db.SwingModeManager; import com.servoy.j2db.cmd.ICmdManager; import com.servoy.j2db.component.ComponentFactory; import com.servoy.j2db.dataprocessing.FoundSetManager; import com.servoy.j2db.dataprocessing.GlobalEditEvent; import com.servoy.j2db.dataprocessing.IDisplay; import com.servoy.j2db.dataprocessing.IGlobalEditListener; import com.servoy.j2db.dataprocessing.IInfoListener; import com.servoy.j2db.dataprocessing.IUserClient; import com.servoy.j2db.dataprocessing.PrototypeState; import com.servoy.j2db.dataprocessing.SwingFoundSetFactory; import com.servoy.j2db.dataprocessing.TagResolver; import com.servoy.j2db.gui.CustomColorChooserDialog; import com.servoy.j2db.gui.GlobalAutoScrollerFocusListener; import com.servoy.j2db.gui.JDateChooser; import com.servoy.j2db.gui.JFontChooser; import com.servoy.j2db.gui.LoginDialog; import com.servoy.j2db.persistence.IActiveSolutionHandler; import com.servoy.j2db.persistence.IRepository; import com.servoy.j2db.persistence.RepositoryException; import com.servoy.j2db.persistence.Solution; import com.servoy.j2db.persistence.SolutionMetaData; import com.servoy.j2db.persistence.Style; import com.servoy.j2db.plugins.IClientPluginAccess; import com.servoy.j2db.plugins.PluginManager; import com.servoy.j2db.preference.ApplicationPreferences; import com.servoy.j2db.preference.GeneralPanel; import com.servoy.j2db.preference.LFPreferencePanel; import com.servoy.j2db.preference.LocalePreferences; import com.servoy.j2db.preference.PreferencePanel; import com.servoy.j2db.preference.ServicePanel; import com.servoy.j2db.query.AbstractBaseQuery; import com.servoy.j2db.scripting.IExecutingEnviroment; import com.servoy.j2db.scripting.ScriptEngine; import com.servoy.j2db.scripting.StartupArguments; import com.servoy.j2db.server.shared.IApplicationServer; import com.servoy.j2db.server.shared.IApplicationServerAccess; import com.servoy.j2db.server.shared.RemoteActiveSolutionHandler; import com.servoy.j2db.smart.cmd.CmdAbout; import com.servoy.j2db.smart.cmd.CmdBrowseMode; import com.servoy.j2db.smart.cmd.CmdClose; import com.servoy.j2db.smart.cmd.CmdCopy; import com.servoy.j2db.smart.cmd.CmdCut; import com.servoy.j2db.smart.cmd.CmdDeleteAllRecord; import com.servoy.j2db.smart.cmd.CmdDeleteRecord; import com.servoy.j2db.smart.cmd.CmdDuplicateRecord; import com.servoy.j2db.smart.cmd.CmdExit; import com.servoy.j2db.smart.cmd.CmdExtendFind; import com.servoy.j2db.smart.cmd.CmdFindAll; import com.servoy.j2db.smart.cmd.CmdFindMode; import com.servoy.j2db.smart.cmd.CmdHelp; import com.servoy.j2db.smart.cmd.CmdHistoryBack; import com.servoy.j2db.smart.cmd.CmdHistoryForward; import com.servoy.j2db.smart.cmd.CmdInvertRecords; import com.servoy.j2db.smart.cmd.CmdLogout; import com.servoy.j2db.smart.cmd.CmdManager; import com.servoy.j2db.smart.cmd.CmdNewRecord; import com.servoy.j2db.smart.cmd.CmdNextRecord; import com.servoy.j2db.smart.cmd.CmdOmitRecord; import com.servoy.j2db.smart.cmd.CmdOpenSolution; import com.servoy.j2db.smart.cmd.CmdPageSetup; import com.servoy.j2db.smart.cmd.CmdPaste; import com.servoy.j2db.smart.cmd.CmdPerformFind; import com.servoy.j2db.smart.cmd.CmdPrevRecord; import com.servoy.j2db.smart.cmd.CmdPreviewMode; import com.servoy.j2db.smart.cmd.CmdReCopyValues; import com.servoy.j2db.smart.cmd.CmdReduceFind; import com.servoy.j2db.smart.cmd.CmdSaveData; import com.servoy.j2db.smart.cmd.CmdSelectAll; import com.servoy.j2db.smart.cmd.CmdShowOmitRecords; import com.servoy.j2db.smart.cmd.CmdShowPreferences; import com.servoy.j2db.smart.cmd.CmdSort; import com.servoy.j2db.smart.cmd.CmdStopSearchFindAll; import com.servoy.j2db.smart.cmd.CmdViewAsForm; import com.servoy.j2db.smart.cmd.CmdViewAsList; import com.servoy.j2db.smart.cmd.MenuEditAction; import com.servoy.j2db.smart.cmd.MenuExportAction; import com.servoy.j2db.smart.cmd.MenuFileAction; import com.servoy.j2db.smart.cmd.MenuHelpAction; import com.servoy.j2db.smart.cmd.MenuImportAction; import com.servoy.j2db.smart.cmd.MenuSelectAction; import com.servoy.j2db.smart.cmd.MenuViewAction; import com.servoy.j2db.smart.dataui.DataField; import com.servoy.j2db.smart.dataui.DataRendererFactory; import com.servoy.j2db.smart.dataui.DataTextArea; import com.servoy.j2db.smart.dataui.SwingItemFactory; import com.servoy.j2db.smart.plugins.ClientPluginManager; import com.servoy.j2db.smart.plugins.SmartClientPluginAccessProvider; import com.servoy.j2db.ui.IComponent; import com.servoy.j2db.ui.IFormUI; import com.servoy.j2db.ui.ItemFactory; import com.servoy.j2db.util.Ad; import com.servoy.j2db.util.BrowserLauncher; import com.servoy.j2db.util.Debug; import com.servoy.j2db.util.ExtendableURLStreamHandlerFactory; import com.servoy.j2db.util.OrientationApplier; import com.servoy.j2db.util.Pair; import com.servoy.j2db.util.PersistHelper; import com.servoy.j2db.util.RendererParentWrapper; import com.servoy.j2db.util.ServoyException; import com.servoy.j2db.util.ServoyScheduledExecutor; import com.servoy.j2db.util.Settings; import com.servoy.j2db.util.SortedList; import com.servoy.j2db.util.SwingHelper; import com.servoy.j2db.util.Text; import com.servoy.j2db.util.Utils; import com.servoy.j2db.util.gui.ActionCheckBoxMenuItem; import com.servoy.j2db.util.gui.ActionMenuItem; import com.servoy.j2db.util.gui.ActionRadioMenuItem; import com.servoy.j2db.util.gui.IPropertyEditorDialog; import com.servoy.j2db.util.gui.JDK131ProgressBar; import com.servoy.j2db.util.gui.JMenuAlwaysEnabled; import com.servoy.j2db.util.gui.OverlapRepaintManager; import com.servoy.j2db.util.rmi.IRMIClientSocketFactoryFactory; import com.servoy.j2db.util.rmi.IReconnectListener; import com.servoy.j2db.util.toolbar.IToolbarPanel; import com.servoy.j2db.util.toolbar.Toolbar; import com.servoy.j2db.util.toolbar.ToolbarButton; import com.servoy.j2db.util.toolbar.ToolbarPanel; /** * This class is the main entry point and makes the actual swing client application * * @author jblok */ public class J2DBClient extends ClientState implements ISmartClientApplication, IGlobalEditListener, IInfoListener, IReconnectListener, IMessagesCallback, IProvideFormName { protected JFrame frame; protected JRootPane rootPane; // root pane from applet or frame(above) public static final int BUTTON_SPACING = 5; public static final int COMPONENT_SPACING = 10; public static final int menuShortcutKeyMask = Toolkit.getDefaultToolkit().getMenuShortcutKeyMask(); private ItemFactory itemFactory; /** * Some font settings */ public static final Font smallFont = new Font("SansSerif", Font.PLAIN, 10); // SansSerif //$NON-NLS-1$ public static final Font defaultFont = new Font("SansSerif", Font.PLAIN, 11); // SansSerif //$NON-NLS-1$ // public Font boldFont = new Font("Dialog", Font.BOLD, 12); public static final Font bigFont = new Font("SansSerif", Font.PLAIN, 12); // SansSerif //$NON-NLS-1$ /** * Managers */ private CmdManager cmdManager; private volatile IBeanManager beanManager; private volatile ILAFManager lafManager; private RuntimeWindowManager jsWindowManager; protected Icon empty; private Icon overwrite; private Icon insert; private Icon editing; private Icon transaction; private Icon locking; private Icon data_change; protected JLabel statusLabel; private JLabel editLabel; private JLabel insertModeLabel; private JLabel transactionLabel; private JLabel lockLabel; private JLabel dataChangeLabel; private JLabel sslLabel; private JDK131ProgressBar statusProgessBar; private JMenuBar menuBar; private JMenu import_Menu; private JMenu export_Menu; private final FlashDataChange flashDataChange = new FlashDataChange(); private volatile ServoyScheduledExecutor scheduledExecutorService; /** * Toolbars */ protected ToolbarPanel toolbarsPanel; /** * Declaration of the Dialogs */ private ApplicationPreferences ap = null; private SelectSolutionDialog selectSolutionDialog = null; private IRMIClientSocketFactoryFactory rmiFactoryFactory; /** * Decl. of the application name */ protected static String splashImage = "images/splashclient.png"; //$NON-NLS-1$ public JMenu getImportMenu() { return import_Menu; } public JMenu getExportMenu() { return export_Menu; } public JFrame getMainApplicationFrame() { return frame; } public String getApplicationName() { return "Servoy Client"; //$NON-NLS-1$ } public void updateUI(int millisec) { int remainingTime = millisec; FormController currentForm = (FormController)getFormManager().getCurrentForm(); if (currentForm != null) { currentForm.getFormUI().updateFormUI(); } long endTime = System.currentTimeMillis() + remainingTime; try { do { SwingHelper.dispatchEvents(remainingTime); remainingTime = (int)(endTime - System.currentTimeMillis()); if (remainingTime <= 0 || millisec <= 20) // we could do here time <= 0 but if user just wants a short UI update if needed - and not to really waste time in this call he can do updateUI(1 - 20) which will run at most X ms of events but could finish earlier, if there is nothing to be painted... { break; } try { Thread.sleep(Math.min(40, remainingTime)); remainingTime = (int)(endTime - System.currentTimeMillis()); } catch (InterruptedException e) { // ignore } } while (remainingTime > 0); } catch (Exception ex) { Debug.error(ex); } } public String getDisplayApplicationName() { String appName = getApplicationName(); if (!appName.endsWith("Developer")) //$NON-NLS-1$ { boolean branding = Utils.getAsBoolean(settings.getProperty("servoy.branding", "false")); //$NON-NLS-1$ //$NON-NLS-2$ String appTitle = settings.getProperty("servoy.branding.windowtitle"); //$NON-NLS-1$ if (branding && appTitle != null) { appName = appTitle; } } return appName; } public int getApplicationType() { return CLIENT; } /* * (non-Javadoc) * * @see com.servoy.j2db.IApplication#getOSName() */ public String getClientOSName() { return System.getProperty("os.name"); //$NON-NLS-1$ } public int getClientPlatform() { return Utils.getPlatform(); } @Override protected IActiveSolutionHandler createActiveSolutionHandler() { return new RemoteActiveSolutionHandler(getApplicationServer(), this); } @Override public IRepository getRepository() { ClientRepository repo = (ClientRepository)super.getRepository(); // always a non-null ClientRepository, see createRepository() if (repo.getDelegate() == null) { // try connect underlying repository IApplicationServerAccess asa = getApplicationServerAccess(); if (asa != null) { try { repo.setDelegate(asa.getRepository()); } catch (RemoteException e) { Debug.error(e); } } } return repo; } /** * Wrap the repository with a client-side repository wrapper that sets the repository in root objects transmitted over RMI. */ @Override protected IRepository createRepository() throws RemoteException { IRepository repo = super.createRepository(); if (repo instanceof ClientRepository) { return repo; } // when super createRepo returns null the delegate repository will be updated in getRepository return new ClientRepository(repo); } @Override public boolean haveRepositoryAccess() { // always a non-null ClientRepository, see createRepository() return ((ClientRepository)getRepository()).getDelegate() != null; } @Override public ScheduledExecutorService getScheduledExecutor() { if (scheduledExecutorService == null) { synchronized (J2DBGlobals.class) { if (scheduledExecutorService == null) { scheduledExecutorService = new ServoyScheduledExecutor(2, 7, 4) { @Override protected void beforeExecute(Thread t, Runnable r) { super.beforeExecute(t, r); J2DBGlobals.setServiceProvider(J2DBClient.this); } @Override protected void afterExecute(Runnable r, Throwable t) { super.afterExecute(r, t); J2DBGlobals.setServiceProvider(null); } }; } } } return scheduledExecutorService; } /** * Starting point */ @SuppressWarnings("nls") public static void main(final String[] args) { String userTimeZone = System.getProperty("user.timezone"); // Bug around java when downloading the first time (pack or gzip seems to alter the timezone and don't set it back) if (userTimeZone != null && !userTimeZone.equals(TimeZone.getDefault().getID())) { TimeZone timeZone = TimeZone.getTimeZone(userTimeZone); if (userTimeZone.equals(timeZone.getID())) { TimeZone.setDefault(timeZone); } } boolean toggleTracing = false; StartupArguments arguments = new StartupArguments(args); Iterator<Entry<String, Object>> iterator = arguments.entrySet().iterator(); while (iterator.hasNext()) { Entry<String, Object> arg = iterator.next(); if (arg.getKey().startsWith("system.property.")) { System.setProperty(arg.getKey().substring(16), (String)arg.getValue()); } if (arg.getKey().equals("tracing") && arg.getValue().equals("true")) { toggleTracing = true; } } if (toggleTracing) Debug.toggleTracing(); if (Boolean.getBoolean("servoy.usejaas")) { final boolean[] loginShown = new boolean[1]; System.setProperty("javax.security.auth.useSubjectCredsOnly", "true"); try { Debug.log("creating context"); LoginContext lc = new LoginContext("ServoyClient", new CallbackHandler() { public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException { Debug.log("handle call back"); String loginName = null; String passwordString = null; for (Callback callback : callbacks) { if (callback instanceof TextOutputCallback) { final TextOutputCallback textOutputCallback = (TextOutputCallback)callback; switch (textOutputCallback.getMessageType()) { case TextOutputCallback.INFORMATION : Debug.log(textOutputCallback.getMessage()); break; case TextOutputCallback.WARNING : Debug.warn(textOutputCallback.getMessage()); break; case TextOutputCallback.ERROR : Debug.error(textOutputCallback.getMessage()); break; default : throw new IOException("Unsupported message type: " + textOutputCallback.getMessageType()); } } else if (callback instanceof NameCallback) { final NameCallback nameCallback = (NameCallback)callback; if (loginName == null) { LoginDialog ld = new LoginDialog((Frame)null, null, "Sign on", false, true); Object[] credentials = ld.showDialog(null); if (credentials != null && credentials.length == 2) { loginName = (String)credentials[0]; passwordString = (String)credentials[1]; } if (loginName == null) { loginName = ""; passwordString = ""; } loginShown[0] = true; } nameCallback.setName(loginName); } else if (callback instanceof PasswordCallback) { final PasswordCallback passwordCallback = (PasswordCallback)callback; if (passwordString == null) { LoginDialog ld = new LoginDialog((Frame)null, null, "Sign on", false, true); Object[] credentials = ld.showDialog(null); if (credentials != null && credentials.length == 2) { loginName = (String)credentials[0]; passwordString = (String)credentials[1]; } if (passwordString == null) { loginName = ""; passwordString = ""; } loginShown[0] = true; } passwordCallback.setPassword(passwordString.toCharArray()); } else { throw new UnsupportedCallbackException(callback, "Unrecognized Callback"); } } } }); Debug.log("context created"); boolean loggedIn = true; try { lc.login(); } catch (LoginException e) { Debug.log("login failed", e); loggedIn = false; } if (loggedIn) { Subject.doAsPrivileged(lc.getSubject(), new PrivilegedExceptionAction<Void>() { public Void run() throws Exception { mainImpl(args); return null; } }, null); } else { mainImpl(args); } } catch (Exception e) { Debug.log("context creation failed", e); if (loginShown[0]) { JOptionPane.showMessageDialog(null, "Couldnt login", "Login failed", JOptionPane.ERROR_MESSAGE); } mainImpl(args); } } else { mainImpl(args); } } private static void mainImpl(final String[] args) { Runnable main = new Runnable() { public void run() { // init application AbstractBaseQuery.initialize(); // make sure query domain mapping is installed J2DBClient base = new J2DBClient(); base.startupApplication(args); } }; //Special flag on request of customers/plugin makers to start a SWT bridge especially for macOSX if class is present boolean useDJNativeSwing = Utils.getAsBoolean(System.getProperty("javaws.useDJNativeSwing", "false")); //$NON-NLS-1$ //$NON-NLS-2$ Class< ? > djNativeSwingClazz = null; if (useDJNativeSwing) { try { djNativeSwingClazz = Class.forName("chrriis.dj.nativeswing.swtimpl.NativeInterface"); //$NON-NLS-1$ djNativeSwingClazz.getMethod("initialize").invoke(null); //$NON-NLS-1$ SwingUtilities.invokeLater(main); // workarround for mac to prevent dead locks with system property -XstartOnFirstThread djNativeSwingClazz.getMethod("runEventPump").invoke(null); //$NON-NLS-1$ } catch (Throwable ex) { Debug.error(ex); main.run(); } } else { main.run(); } } /** * Main application constructor */ protected J2DBClient() { this(true); } /** * Main application constructor */ protected J2DBClient(boolean setSingletonServiceProvider) { super(); //security check: when run as this class instance it must run under webstart for security! if (getClass() == J2DBClient.class && !(WebStart.isRunningWebStart() && WebStart.getWebStartURL() != null)) { throw new IllegalStateException(); } getClientInfo().setApplicationType(getApplicationType()); if (setSingletonServiceProvider) J2DBGlobals.setSingletonServiceProvider(this); } protected boolean getAppleScreenMenuBar() { return true; } @SuppressWarnings("nls") protected void startupApplication(String[] args) { try { logStartUp(); startupArguments = args; handleArguments(args); // set some props // ie. for full gc timing 6 mins (1 minutes == default) System.setProperty("sun.rmi.dgc.client.gcInterval", "360000"); // System.setProperty("java.rmi.server.codebase", "");//disable any rmi classloading System.setProperty("apple.laf.useScreenMenuBar", Boolean.toString(getAppleScreenMenuBar())); // if no mrj.version (this is in java 1.7), set the mrj.version from java 1.6 // as MRJAdapter depends on this if (Utils.isAppleMacOS() && System.getProperty("mrj.version") == null) System.setProperty("mrj.version", "1070.1.6.0_45-451"); UIManager.put("TabbedPane.contentOpaque", Boolean.FALSE); // The "TabbedPane.tabsOpaque" should not be set. If we set it, then the tabs (the little handles // that are used for switching between forms) become transparent in some L&F (for example Windows Classic) // which is not desired. Also, settting this property does not help with the gray stripe that appears // behind the tabs on Windows. That stripe only goes away if the tabpanel is made transparent. //UIManager.put("TabbedPane.tabsOpaque", Boolean.FALSE); Object originalHighlight = UIManager.get("TabbedPane.highlight"); if (originalHighlight instanceof Color) UIManager.put("TabbedPane.highlight", ((Color)originalHighlight).darker()); //offset from white a bit since white is most used background initSecurityManager(); initSettings(); initRMISocketFactory(); setLookAndFeel(); createMainPanel(); applicationSetup(); applicationInit(); if (applicationServerInit()) { serverInit(); selectAndOpenSolution(); // the select dialog is shown. } } catch (Exception ex) { Debug.error("Fatal Exception"); Debug.error(ex); } } protected void initSettings() throws Exception { // overload settings from disk boolean uses_client_installer = (System.getProperty("servoy.server_url") != null); //$NON-NLS-1$ settings = Settings.getInstance(); if (!uses_client_installer) { ((Settings)settings).loadFromServer(getServerURL()); // no disk loading needed for client, rely on webstart } else { //is special case for cytrix users, using a shared disk, to prevent webstarts installs File file = new File(System.getProperty("user.dir"), Settings.FILE_NAME); //$NON-NLS-1$ ((Settings)settings).loadFromFile(file); } } protected void initSecurityManager() throws SecurityException { System.setSecurityManager(null);// seems still needed for javaws(http://forum.java.sun.com/thread.jsp?thread=71233&forum=38&message=507926) } protected void initStreamHandlerFactory() { extendableURLStreamHandlerFactory = new ExtendableURLStreamHandlerFactory(); extendableURLStreamHandlerFactory.addStreamHandler("media", new MediaURLStreamHandler()); //$NON-NLS-1$ try { URL.setURLStreamHandlerFactory(extendableURLStreamHandlerFactory); } catch (Throwable ex) { Debug.error(ex); } } protected void initRMISocketFactory() { URL webstartbase = getServerURL(); String rmiFactory = settings.getProperty("SocketFactory.rmiClientFactory", "com.servoy.j2db.rmi.DefaultClientSocketFactoryFactory"); //$NON-NLS-1$ //$NON-NLS-2$ try { Class< ? > cls = Class.forName(rmiFactory.trim()); Constructor< ? > constructor = cls.getConstructor(new Class[] { URL.class, ISmartClientApplication.class, Properties.class, IReconnectListener.class }); rmiFactoryFactory = (IRMIClientSocketFactoryFactory)constructor.newInstance(new Object[] { webstartbase, this, getSettings(), this }); Debug.trace("IRMISocketFactoryFactory instantiated: " + cls); //$NON-NLS-1$ } catch (Exception e) { Debug.error("couldn't instantiate the rmi socketfactory", e); //$NON-NLS-1$ } } protected ExtendableURLStreamHandlerFactory extendableURLStreamHandlerFactory; protected MainPanel mainPanel; private LoadingUIEffects loadingUIEffects; protected void createMainPanel() { // init the frame frame = new JFrame(); frame.addWindowFocusListener(new WindowAdapter() { @Override public void windowGainedFocus(WindowEvent e) { if (getFormManager() != null) ((FormManager)getFormManager()).setCurrentContainer(null, null); } }); rootPane = frame.getRootPane(); InputMap im = rootPane.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW); im.put(KeyStroke.getKeyStroke(KeyEvent.VK_T, InputEvent.SHIFT_DOWN_MASK + InputEvent.CTRL_DOWN_MASK + InputEvent.ALT_DOWN_MASK), "enabletracing"); //$NON-NLS-1$ ActionMap am = rootPane.getActionMap(); am.put("enabletracing", new AbstractAction() //$NON-NLS-1$ { private static final long serialVersionUID = 1L; public void actionPerformed(ActionEvent e) { Debug.toggleTracing(); } }); frame.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE); frame.setName(IApplication.APP_WINDOW_NAME); frame.getContentPane().setLayout(new BorderLayout()); frame.setTitle(getDisplayApplicationName()); String branding = getSettings().getProperty("servoy.branding", "false"); //$NON-NLS-1$ //$NON-NLS-2$ String windowicon = getSettings().getProperty("servoy.branding.windowicon"); //$NON-NLS-1$ if (branding.equals("true") && windowicon != null && Utils.isSwingClient(getApplicationType())) //$NON-NLS-1$ { URL webstartUrl = getServerURL(); try { String windowiconFile = null; String path = webstartUrl.getPath(); if (!path.equals("") && path.endsWith("/")) { windowiconFile = path.substring(0, path.length() - 1) + windowicon; } else windowiconFile = windowicon; URL url = new URL(webstartUrl.getProtocol(), webstartUrl.getHost(), webstartUrl.getPort(), windowiconFile); frame.setIconImage(new ImageIcon(url).getImage()); } catch (MalformedURLException ex) { Debug.error("Error loading the window icon image", ex); //$NON-NLS-1$ frame.setIconImage(loadImage("windowicon.png").getImage()); //$NON-NLS-1$ } } else { frame.setIconImage(loadImage("windowicon.png").getImage()); //$NON-NLS-1$ } mainPanel = new MainPanel(this, null); mainPanel.setPreferredSize(new Dimension(Settings.INITIAL_CLIENT_WIDTH, Settings.INITIAL_CLIENT_HEIGHT)); frame.getContentPane().add(mainPanel, BorderLayout.CENTER); frame.pack(); Debug.trace("Main frame packed"); //$NON-NLS-1$ // block when visible Component glassPane = rootPane.getGlassPane(); glassPane.addMouseListener(new MouseAdapter() { }); glassPane.addMouseMotionListener(new MouseMotionAdapter() { }); glassPane.addKeyListener(new KeyAdapter() { }); } public void addURLStreamHandler(String protocolName, URLStreamHandler handler) { if (protocolName != null && !"http".equals(protocolName) && !"media".equals(protocolName)) //$NON-NLS-1$ //$NON-NLS-2$ { extendableURLStreamHandlerFactory.addStreamHandler(protocolName, handler); } } protected void installShutdownHook() { Runtime.getRuntime().addShutdownHook(new Thread() { @Override public void run() { if (isConnected() && frame != null) { Debug.error("Client closes abnormally, trying to unbind the client from the server'"); //$NON-NLS-1$ //de register myself try { unRegisterClient(getClientID()); unBindUserClient(); } catch (Exception e) { Debug.error(e);// incase server is dead } } } }); } @Override protected void applicationSetup() { installShutdownHook(); KeyboardFocusManager.getCurrentKeyboardFocusManager().addPropertyChangeListener(new GlobalAutoScrollerFocusListener()); // create status JPanel statusPanel = createStatusPanel(); String showStatusBar = settings.getProperty("servoy.smartclient.showStatusBar"); //$NON-NLS-1$ if (showStatusBar != null && showStatusBar.equals("false")) statusPanel.setVisible(false); //$NON-NLS-1$ mainPanel.add(statusPanel, BorderLayout.SOUTH); // first set the default locale if set. String str = getSettings().getProperty("locale.default"); //$NON-NLS-1$ Locale loc = PersistHelper.createLocale(str); if (loc != null) { Locale.setDefault(loc); } TimeZone defaultTimeZone = TimeZone.getDefault(); if (defaultTimeZone != null) //can this happen? { str = getSettings().getProperty("timezone.default", defaultTimeZone.getID()); //$NON-NLS-1$ TimeZone tz = TimeZone.getTimeZone(str); if (tz != null) { getClientInfo().setTimeZone(tz); TimeZone.setDefault(tz); } } super.applicationSetup(); jsWindowManager = createJSWindowManager(); cmdManager = createCmdManager(); // load all the actions Map<String, Action> actions = getActions(); // load the toolbars toolbarsPanel = new ToolbarPanel(Settings.INITIAL_CLIENT_WIDTH - 200); mainPanel.add(toolbarsPanel, BorderLayout.NORTH); fillToolbar(actions); String showToolBar = settings.getProperty("servoy.smartclient.showToolBar"); //$NON-NLS-1$ if (showToolBar != null && showToolBar.equals("false")) toolbarsPanel.setVisible(false); //$NON-NLS-1$ // load menu JMenuBar menu = createMenuBar(actions); String showMenuBar = settings.getProperty("servoy.smartclient.showMenuBar"); //$NON-NLS-1$ if (showMenuBar != null && showMenuBar.equals("false")) menu.setVisible(false); //$NON-NLS-1$ frame.setJMenuBar(menu); ((SwingRuntimeWindow)jsWindowManager.getWindow(null)).setJMenuBar(menu); if (Utils.isAppleMacOS()) { attachAppleMenu(actions); } setMainFrameInitialBounds(); showSolutionLoading(true); } protected LoadingUIEffects createLoadingUIEffects() { return new LoadingUIEffects(this, mainPanel); } @Override public void showSolutionLoading(boolean loading) { getLoadingUIEffects().showSolutionLoading(loading); } protected LoadingUIEffects getLoadingUIEffects() { if (loadingUIEffects == null) loadingUIEffects = createLoadingUIEffects(); return loadingUIEffects; } /** * @param actions */ protected void fillToolbar(Map<String, Action> actions) { toolbarsPanel.clear(); SortedList<Toolbar.ToolbarKey> sortedList = new SortedList<Toolbar.ToolbarKey>(); createToolBars(sortedList, actions); int offsetRow = 0; if (sortedList.size() > 0) { offsetRow = sortedList.get(0).getRow(); if (offsetRow == -1) offsetRow = 0; } for (int i = 0; i < sortedList.size(); i++) { Toolbar.ToolbarKey key = sortedList.get(i); if (toolbarsPanel.getToolBar(key.getToolbar().getName()) == null) { if ("edit".equals(key.getToolbar().getName())) //$NON-NLS-1$ { fillBrowseToolbar(key.getToolbar(), actions); } toolbarsPanel.addToolbar(key.getToolbar(), key.getRow() - offsetRow); toolbarsPanel.setToolbarVisible(key.getToolbar().getName(), key.isVisible()); } } } protected void setMainFrameInitialBounds() { SwingUtilities.invokeLater(new Runnable() { public void run() { if (!Settings.getInstance().loadBounds(frame)) { Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); frame.setLocation(screenSize.width / 2 - Settings.INITIAL_CLIENT_WIDTH / 2, screenSize.height / 2 - Settings.INITIAL_CLIENT_HEIGHT / 2); } } }); } @Override protected boolean applicationInit() { try { blockGUI(Messages.getString("servoy.client.status.application.setup")); //$NON-NLS-1$ initStreamHandlerFactory(); super.applicationInit(); // repaint manager that handles repaint for overlapping components properly (if a component // below other components is repainted, the components on top of it will be repainted too) RepaintManager current = RepaintManager.currentManager(frame); if (!(current instanceof OverlapRepaintManager)) { if (current != null && current.getClass() != RepaintManager.class) { Debug.log("Overwriting a none default RepaintManager: " + current.getClass() + " with our overlay repaint manager"); } RepaintManager.setCurrentManager(new OverlapRepaintManager()); } // Add the windows listener WindowListener l = new WindowAdapter() { @Override public void windowClosing(WindowEvent e) { shutDown(false); } }; frame.addWindowListener(l); // register top level keystrokes registerKeyStrokes(rootPane); return true; } finally { releaseGUI(); } } protected ILAFManager createLAFManager() { return new LAFManager(); } @Override protected void createPluginManager() { pluginManager = new ClientPluginManager(this); pluginAccess = createClientPluginAccessProvider(); getScheduledExecutor().execute(new Runnable() { public void run() { getPluginManager().init(); ((PluginManager)getPluginManager()).initClientPlugins(J2DBClient.this, (IClientPluginAccess)getPluginAccess()); ((FoundSetManager)getFoundSetManager()).setColumnManangers(getPluginManager().getColumnValidatorManager(), getPluginManager().getColumnConverterManager(), getPluginManager().getUIConverterManager()); } }); } protected SmartClientPluginAccessProvider createClientPluginAccessProvider() { return new SmartClientPluginAccessProvider(this); } protected IBeanManager createBeanManager() { return new BeanManager(); } protected CmdManager createCmdManager() { return new CmdManager(this); } @Override protected IModeManager createModeManager() { return new SwingModeManager(this); } @Override protected IBasicFormManager createFormManager() { return new SwingFormManager(this, mainPanel); } protected void createToolBars(SortedList<Toolbar.ToolbarKey> list, Map<String, Action> actions) { int editPlace = Integer.parseInt(settings.getProperty("toolbar.edit.row", "0")); //$NON-NLS-1$ //$NON-NLS-2$ int editIndex = Integer.parseInt(settings.getProperty("toolbar.edit.row.index", "0")); //$NON-NLS-1$ //$NON-NLS-2$ boolean editVisible = settings.getProperty("toolbar.edit", "true").equals("true"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ int textPlace = Integer.parseInt(settings.getProperty("toolbar.text.row", "0")); //$NON-NLS-1$ //$NON-NLS-2$ int textIndex = Integer.parseInt(settings.getProperty("toolbar.text.row.index", "1")); //$NON-NLS-1$ //$NON-NLS-2$ boolean textVisible = settings.getProperty("toolbar.text", "true").equals("true"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ Toolbar browseToolbar = new Toolbar("edit", Messages.getString("servoy.edittoolbar.label"), true); //$NON-NLS-1$//$NON-NLS-2$ list.add(new Toolbar.ToolbarKey(editPlace, editIndex, editVisible, browseToolbar)); list.add(new Toolbar.ToolbarKey(textPlace, textIndex, textVisible, new TextToolbar(this, actions))); } public IToolbarPanel getToolbarPanel() { return toolbarsPanel; } public JComponent getEditLabel()// used for rendering by printing { return editLabel; } /** * updates the insert mode icon for the given display * * @param display */ public void updateInsertModeIcon(IDisplay display) { Icon icon = empty; if (display instanceof DataField) { DataField field = (DataField)display; AbstractFormatterFactory formatterFactory = field.getFormatterFactory(); if (formatterFactory instanceof DefaultFormatterFactory) { DefaultFormatterFactory factory = ((DefaultFormatterFactory)formatterFactory); AbstractFormatter editFormatter = factory.getEditFormatter(); if (editFormatter == null) editFormatter = factory.getDefaultFormatter(); if (editFormatter instanceof DefaultFormatter && !(editFormatter instanceof MaskFormatter)) { if (((DefaultFormatter)editFormatter).getOverwriteMode()) { icon = overwrite; } else { icon = insert; } } } } else if (display instanceof DataTextArea) { if (((DataTextArea)display).getOverwriteMode()) { icon = overwrite; } else { icon = insert; } } insertModeLabel.setIcon(icon); } protected JPanel createStatusPanel() { Color darkShadow = UIManager.getColor("controlShadow"); //$NON-NLS-1$ Color lightShadow = UIManager.getColor("controlLtHighlight"); //$NON-NLS-1$ JPanel status = new JPanel(); status.setName("statusbar"); //$NON-NLS-1$ Border border = BorderFactory.createBevelBorder(BevelBorder.LOWERED, lightShadow, status.getBackground(), darkShadow, status.getBackground()); // set the status statusLabel = new JLabel(); // statusLabel.setFont(smallFont); statusLabel.setText(Messages.getString("servoy.general.status.ready")); //$NON-NLS-1$ statusLabel.setAlignmentX(Component.RIGHT_ALIGNMENT); statusLabel.setAlignmentY(Component.BOTTOM_ALIGNMENT); statusLabel.setBorder(BorderFactory.createCompoundBorder(border, BorderFactory.createEmptyBorder(0, 2, 0, 0)));// BorderFactory.createEtchedBorder()); statusLabel.setMinimumSize(new Dimension(100, 18)); statusLabel.setPreferredSize(new Dimension(4000, 18)); empty = loadImage("empty.gif"); //$NON-NLS-1$ editing = loadImage("editing.gif"); //$NON-NLS-1$ overwrite = loadImage("overwrite.png"); //$NON-NLS-1$ insert = loadImage("insert.png"); //$NON-NLS-1$ transaction = loadImage("transaction.gif"); //$NON-NLS-1$ locking = loadImage("lock.gif"); //$NON-NLS-1$ data_change = loadImage("data_change.gif"); //$NON-NLS-1$ sslLabel = new JLabel(empty, SwingConstants.TRAILING); // sslLabel.setFont(smallFont); sslLabel.setToolTipText(Messages.getString("servoy.client.ssllabel.tooltip")); //$NON-NLS-1$ sslLabel.setAlignmentX(Component.RIGHT_ALIGNMENT); sslLabel.setAlignmentY(Component.BOTTOM_ALIGNMENT); if (rmiFactoryFactory != null && rmiFactoryFactory.usingSSL()) { sslLabel.setText("SSL"); //$NON-NLS-1$ sslLabel.setIcon(null); sslLabel.setBorder(BorderFactory.createCompoundBorder(border, BorderFactory.createEmptyBorder(0, 2, 0, 0)));// BorderFactory.createEtchedBorder()); } else { sslLabel.setMinimumSize(new Dimension(18, 18)); sslLabel.setPreferredSize(new Dimension(18, 18)); sslLabel.setBorder(border);// BorderFactory.createEtchedBorder()); } insertModeLabel = new JLabel(empty, SwingConstants.TRAILING); insertModeLabel.setAlignmentX(Component.RIGHT_ALIGNMENT); insertModeLabel.setAlignmentY(Component.BOTTOM_ALIGNMENT); insertModeLabel.setBorder(border);// BorderFactory.createEtchedBorder()); insertModeLabel.setMinimumSize(new Dimension(18, 18)); insertModeLabel.setPreferredSize(new Dimension(18, 18)); editLabel = new JLabel(empty, SwingConstants.TRAILING); editLabel.setToolTipText(Messages.getString("servoy.client.editlabel.tooltip")); //$NON-NLS-1$ editLabel.setAlignmentX(Component.RIGHT_ALIGNMENT); editLabel.setAlignmentY(Component.BOTTOM_ALIGNMENT); editLabel.setBorder(border);// BorderFactory.createEtchedBorder()); editLabel.setMinimumSize(new Dimension(18, 18)); editLabel.setPreferredSize(new Dimension(18, 18)); transactionLabel = new JLabel(empty, SwingConstants.TRAILING); transactionLabel.setToolTipText(Messages.getString("servoy.client.transactionlabel.tooltip")); //$NON-NLS-1$ transactionLabel.setAlignmentX(Component.RIGHT_ALIGNMENT); transactionLabel.setAlignmentY(Component.BOTTOM_ALIGNMENT); transactionLabel.setBorder(border);// BorderFactory.createEtchedBorder()); transactionLabel.setMinimumSize(new Dimension(18, 18)); transactionLabel.setPreferredSize(new Dimension(18, 18)); lockLabel = new JLabel(empty, SwingConstants.TRAILING); lockLabel.setToolTipText(Messages.getString("servoy.client.locklabel.tooltip")); //$NON-NLS-1$ lockLabel.setAlignmentX(Component.RIGHT_ALIGNMENT); lockLabel.setAlignmentY(Component.BOTTOM_ALIGNMENT); lockLabel.setBorder(border);// BorderFactory.createEtchedBorder()); lockLabel.setMinimumSize(new Dimension(18, 18)); lockLabel.setPreferredSize(new Dimension(18, 18)); dataChangeLabel = new JLabel(empty, SwingConstants.TRAILING); dataChangeLabel.setToolTipText(Messages.getString("servoy.client.datachangelabel.tooltip")); //$NON-NLS-1$ dataChangeLabel.setAlignmentX(Component.RIGHT_ALIGNMENT); dataChangeLabel.setAlignmentY(Component.BOTTOM_ALIGNMENT); dataChangeLabel.setBorder(border);// BorderFactory.createEtchedBorder()); dataChangeLabel.setMinimumSize(new Dimension(18, 18)); dataChangeLabel.setPreferredSize(new Dimension(18, 18)); statusProgessBar = new JDK131ProgressBar(); statusProgessBar.setMaximumSize(new Dimension(100, 18)); statusProgessBar.setPreferredSize(new Dimension(100, 18)); statusProgessBar.setMinimumSize(new Dimension(100, 18)); statusProgessBar.setBorder(border);// BorderFactory.createEtchedBorder()); statusProgessBar.setStringPainted(false); statusProgessBar.setAlignmentX(Component.RIGHT_ALIGNMENT); statusProgessBar.setAlignmentY(Component.BOTTOM_ALIGNMENT); status.setLayout(new BoxLayout(status, BoxLayout.X_AXIS)); status.add(statusLabel); status.add(editLabel); status.add(insertModeLabel); status.add(transactionLabel); status.add(lockLabel); status.add(dataChangeLabel); status.add(sslLabel); status.add(statusProgessBar); status.setBorder(BorderFactory.createEmptyBorder(1, 0, 0, 0)); return status; } private void registerKeyStrokes(JRootPane rp) { ActionListener actionListener2 = new ActionListener() { public void actionPerformed(ActionEvent actionEvent) { // Debug.showConsole(); } }; KeyStroke stroke2 = KeyStroke.getKeyStroke(KeyEvent.VK_4, InputEvent.SHIFT_MASK | InputEvent.CTRL_MASK); rp.registerKeyboardAction(actionListener2, stroke2, JComponent.WHEN_IN_FOCUSED_WINDOW); } @Override public void shutDown(boolean force) { // hide try { if (getSolution() != null) { if (!closeSolution(force, null) && !force) return; // getFlattenedSolution().setSolution(null); } } catch (Exception ex) { Debug.error(ex); } if (toolbarsPanel.getToolBar("edit") != null) //$NON-NLS-1$ { settings.setProperty("toolbar.edit", toolbarsPanel.getToolBar("edit").isVisible() ? "true" : "false"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ settings.setProperty("toolbar.edit.row", Integer.toString(toolbarsPanel.getToolBarRow("edit"))); //$NON-NLS-1$ //$NON-NLS-2$ settings.setProperty("toolbar.edit.row.index", Integer.toString(toolbarsPanel.getToolbarRowIndex("edit"))); //$NON-NLS-1$ //$NON-NLS-2$ } if (toolbarsPanel.getToolBar("text") != null) //$NON-NLS-1$ { settings.setProperty("toolbar.text", toolbarsPanel.getToolBar("text").isVisible() ? "true" : "false"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ settings.setProperty("toolbar.text.row", Integer.toString(toolbarsPanel.getToolBarRow("text"))); //$NON-NLS-1$ //$NON-NLS-2$ settings.setProperty("toolbar.text.row.index", Integer.toString(toolbarsPanel.getToolbarRowIndex("text"))); //$NON-NLS-1$ //$NON-NLS-2$ } if (frame != null) { frame.setVisible(false); } super.shutDown(force); if (scheduledExecutorService != null) { scheduledExecutorService.shutdownNow(); scheduledExecutorService = null; } if (rmiFactoryFactory != null) { rmiFactoryFactory.close(); } //clear the frame if (frame != null) { frame.dispose(); frame = null; } invokeLater(new Runnable() { public void run() { // Exit really hard here!! exitHard(0); } }); } protected void exitHard(int status) { System.exit(status); } @Override protected void saveSettings() { try { Settings.getInstance().saveBounds(frame); ((Settings)settings).save(); } catch (Exception ex) { Debug.error(ex); } } public ImageIcon loadImage(String name) { java.net.URL iconUrl = ClientState.class.getResource("images/" + name); //$NON-NLS-1$ if (iconUrl != null) { return new ImageIcon(iconUrl, iconUrl.toExternalForm().intern()); } else { java.net.URL iconUrl2 = J2DBClient.class.getResource("images/error.gif"); //$NON-NLS-1$ if (iconUrl2 != null) { return new ImageIcon(iconUrl2, iconUrl2.toExternalForm().intern()); } else { return null; } } } public ILAFManager getLAFManager() { return lafManager; } /** * Set the look and feel (platform dep. or indep.) */ @SuppressWarnings("nls") protected void setLookAndFeel() { try { String allowLAFWindowDecoration = settings.getProperty("servoy.smartclient.allowLAFWindowDecoration"); if (allowLAFWindowDecoration != null && allowLAFWindowDecoration.equals("true")) { //Allow LAF's to control the JFrame and JDialog chrome JFrame.setDefaultLookAndFeelDecorated(true); JDialog.setDefaultLookAndFeelDecorated(true); //Settings aboive might cause flicker while resizing, see: //https://substance.dev.java.net/docs/faq.html, question 17 //http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=5079688 if (Utils.getPlatform() == Utils.PLATFORM_WINDOWS && System.getProperty("sun.awt.noerasebackground") == null) { System.setProperty("sun.awt.noerasebackground", "true"); } } // in case we use alloy System.setProperty("alloy.isLookAndFeelFrameDecoration", "true"); String defaultLAFClassName = UIManager.getSystemLookAndFeelClassName(); String lnf = settings.getProperty("selectedlnf", defaultLAFClassName); boolean isRunningWebStart = WebStart.isRunningWebStart(); URL webstartbase = null; if (isRunningWebStart) { webstartbase = getServerURL(); lnf = settings.getProperty(webstartbase.getHost() + webstartbase.getPort() + "_selectedlnf", lnf); } // Users may have set the lnf to spaces in the properties file if (lnf.trim().length() == 0) { lnf = defaultLAFClassName; } lafManager = createLAFManager(); lafManager.init(); // test if selected lnf is loaded through the lafManager List<LookAndFeelInfo> lst = lafManager.getLAFInfos(this); boolean found = false; for (int i = 0; i < lst.size(); i++) { UIManager.LookAndFeelInfo info = lst.get(i); if (info.getClassName().equals(lnf)) { found = true; break; } } if (!found) { lnf = defaultLAFClassName; } putClientProperty(LookAndFeelInfo.class.getName(), lnf); String font = settings.getProperty("font"); if (isRunningWebStart) { font = settings.getProperty(webstartbase.getHost() + webstartbase.getPort() + "_font", font); } Font dfltFont = PersistHelper.createFont(font); if (dfltFont == null) { if (!Utils.isAppleMacOS()) { Font fnt = (Font)UIManager.getDefaults().get("MenuItem.font"); if (fnt != null) { dfltFont = fnt; if (dfltFont.isBold()) dfltFont = dfltFont.deriveFont(Font.PLAIN); } else { dfltFont = PersistHelper.createFont("Tahoma", Font.PLAIN, 11); } } } replaceCtrlShortcutsWithMacShortcuts(); if (dfltFont != null) putClientProperty(Font.class.getName(), dfltFont); } catch (Exception e) { Debug.error(e); } } protected void replaceCtrlShortcutsWithMacShortcuts() { if (Utils.isAppleMacOS() && UIManager.getLookAndFeel().getClass().getName().toUpperCase().indexOf("AQUA") < 0) { for (Object keyObj : UIManager.getLookAndFeelDefaults().keySet()) { String key = keyObj.toString(); if (key.contains("InputMap")) { Object val = UIManager.getLookAndFeelDefaults().get(key); if (val instanceof InputMapUIResource) { InputMapUIResource map = (InputMapUIResource)val; KeyStroke[] allKeys = map.allKeys(); if (allKeys != null) for (KeyStroke keyStroke : allKeys) { int modifiers = keyStroke.getModifiers(); if ((modifiers & InputEvent.CTRL_MASK) > 0) { modifiers -= InputEvent.CTRL_DOWN_MASK; modifiers -= InputEvent.CTRL_MASK; modifiers += InputEvent.META_DOWN_MASK + InputEvent.META_MASK; KeyStroke k = KeyStroke.getKeyStroke(keyStroke.getKeyCode(), modifiers); Object mapVal = map.get(keyStroke); map.remove(keyStroke); map.put(k, mapVal); } } } } } } } public String getUserProperty(String name) { if (name == null) return null; return ((Settings)getSettings()).getUserProperty(Settings.USER, name); } public String[] getUserPropertyNames() { List<String> retval = new ArrayList<String>(); Iterator<Object> it = getSettings().keySet().iterator(); while (it.hasNext()) { String key = (String)it.next(); if (key.startsWith(Settings.USER)) { retval.add(key.substring(Settings.USER.length())); } } return retval.toArray(new String[retval.size()]); } public void setUserProperty(String name, String value) { if (name == null) return; ((Settings)getSettings()).setUserProperty(Settings.USER, name, value); } public Object getClientProperty(Object name) { if (name == null) return null; if (LookAndFeelInfo.class.getName().equals(name)) { LookAndFeel lnf = UIManager.getLookAndFeel(); return lnf == null ? null : lnf.getClass().getName(); } else if (USE_SYSTEM_PRINT_DIALOG.equals(name)) { return getSettings().get(USE_SYSTEM_PRINT_DIALOG); } else if (TOOLTIP_INITIAL_DELAY.equals(name)) { return new Integer(ToolTipManager.sharedInstance().getInitialDelay()); } else if (TOOLTIP_DISMISS_DELAY.equals(name)) { return new Integer(ToolTipManager.sharedInstance().getDismissDelay()); } else { UIDefaults uiDefaults = UIManager.getDefaults(); if (Font.class.getName().equals(name)) { Object f = uiDefaults.get("MenuItem.font"); //$NON-NLS-1$ if (f == null) return null; if (f != uiDefaults.get("Menu.font")) return null; //$NON-NLS-1$ if (f != uiDefaults.get("RadioButtonMenuItem.font")) return null; //$NON-NLS-1$ if (f != uiDefaults.get("CheckBoxMenuItem.font")) return null; //$NON-NLS-1$ if (f != uiDefaults.get("ComboBox.font")) return null; //$NON-NLS-1$ if (f != uiDefaults.get("RadioButton.font")) return null; //$NON-NLS-1$ if (f != uiDefaults.get("CheckBox.font")) return null; //$NON-NLS-1$ if (f != uiDefaults.get("Button.font")) return null; //$NON-NLS-1$ if (f != uiDefaults.get("Label.font")) return null; //$NON-NLS-1$ if (f != uiDefaults.get("TabbedPane.font")) return null; //$NON-NLS-1$ if (f != uiDefaults.get("Panel.font")) return null; //$NON-NLS-1$ if (f != uiDefaults.get("TitledBorder.font")) return null; //$NON-NLS-1$ if (f != uiDefaults.get("List.font")) return null; //$NON-NLS-1$ if (f != uiDefaults.get("Table.font")) return null; //$NON-NLS-1$ if (f != uiDefaults.get("TableHeader.font")) return null; //$NON-NLS-1$ if (f != uiDefaults.get("Tree.font")) return null; //$NON-NLS-1$ if (f != uiDefaults.get("TextArea.font")) return null; //$NON-NLS-1$ if (f != uiDefaults.get("PasswordField.font")) return null; //$NON-NLS-1$ if (f != uiDefaults.get("TextField.font")) return null; //$NON-NLS-1$ if (f != uiDefaults.get("FormattedTextField.font")) return null; //$NON-NLS-1$ return f; } else { return uiDefaults.get(name.toString()); } } } public boolean putClientProperty(Object name, Object value) { if (name == null) return false; try { boolean mustSetFont = true; if (LookAndFeelInfo.class.getName().equals(name)) { LookAndFeel laf = lafManager.createInstance(value.toString()); if (laf != null) { if (laf instanceof MetalLookAndFeel) { UIManager.setLookAndFeel(laf); String themeName = getSettings().getProperty("lnf.theme", "com.servoy.j2db.util.gui.DefaultTheme"); //$NON-NLS-1$ //$NON-NLS-2$ if (WebStart.isRunningWebStart()) { URL webstartbase = getServerURL(); themeName = settings.getProperty(webstartbase.getHost() + webstartbase.getPort() + "_lnf.theme", themeName); //$NON-NLS-1$ } if (themeName != null && themeName.length() != 0) { MetalTheme theme = lafManager.createThemeInstance(themeName); if (theme != null) { MetalLookAndFeel.setCurrentTheme(theme); mustSetFont = false; } } } UIManager.setLookAndFeel(laf);// yes, this is the second time if there is a methalTHeme but this is only it works replaceCtrlShortcutsWithMacShortcuts(); } } UIDefaults uiDefaults = UIManager.getDefaults(); if (Font.class.getName().equals(name) && mustSetFont) { Font font = (Font)value; if (font != null && !(font instanceof FontUIResource)) { font = new FontUIResource(font); } uiDefaults.put("MenuItem.font", font); //$NON-NLS-1$ uiDefaults.put("Menu.font", font); //$NON-NLS-1$ uiDefaults.put("RadioButtonMenuItem.font", font); //$NON-NLS-1$ uiDefaults.put("CheckBoxMenuItem.font", font); //$NON-NLS-1$ uiDefaults.put("ComboBox.font", font); //$NON-NLS-1$ uiDefaults.put("RadioButton.font", font); //$NON-NLS-1$ uiDefaults.put("CheckBox.font", font); //$NON-NLS-1$ uiDefaults.put("Button.font", font); //$NON-NLS-1$ uiDefaults.put("Label.font", font); // Was BIG_FONT //$NON-NLS-1$ uiDefaults.put("TabbedPane.font", font); //$NON-NLS-1$ uiDefaults.put("Panel.font", font); //$NON-NLS-1$ uiDefaults.put("TitledBorder.font", font); //$NON-NLS-1$ uiDefaults.put("List.font", font); //$NON-NLS-1$ uiDefaults.put("Table.font", font); //$NON-NLS-1$ uiDefaults.put("TableHeader.font", font); //$NON-NLS-1$ uiDefaults.put("Tree.font", font); //$NON-NLS-1$ uiDefaults.put("TextArea.font", font); //$NON-NLS-1$ uiDefaults.put("PasswordField.font", font); //$NON-NLS-1$ uiDefaults.put("TextField.font", font); //$NON-NLS-1$ uiDefaults.put("FormattedTextField.font", font); //$NON-NLS-1$ } else if (LookAndFeelInfo.class.getName().equals(name) && frame != null) { uiDefaults.put("ToolTip.hideAccelerator", Boolean.TRUE); //$NON-NLS-1$ ToolTipManager.sharedInstance().setDismissDelay(8000); SwingUtilities.updateComponentTreeUI(frame); if (ap != null) { SwingUtilities.updateComponentTreeUI(ap); } Iterator<Window> windows = dialogs.values().iterator(); while (windows.hasNext()) { Window window = windows.next(); SwingUtilities.updateComponentTreeUI(window); } } else if (USE_SYSTEM_PRINT_DIALOG.equals(name)) { getSettings().put(USE_SYSTEM_PRINT_DIALOG, value.toString()); } else if (TOOLTIP_INITIAL_DELAY.equals(name)) { ToolTipManager.sharedInstance().setInitialDelay(((Number)value).intValue()); } else if (TOOLTIP_DISMISS_DELAY.equals(name)) { ToolTipManager.sharedInstance().setDismissDelay(((Number)value).intValue()); } else { uiDefaults.put(name.toString(), value); } } catch (Exception e) { Debug.error(e); return false; } return true; } protected RuntimeWindowManager createJSWindowManager() { return new SwingRuntimeWindowManager(this); } public RuntimeWindowManager getRuntimeWindowManager() { return jsWindowManager; } /** * Show the help private void showAppHelp() { // try // { // if (hb == null) // { // URL hsURL = new // * URL(WebStart.getWebStartURL(),"docs/help/client.hs");//developer/server.hs? // HelpSet hs = new HelpSet(null, hsURL); // hb = hs.createHelpBroker(); // } * // hb.setDisplayed(true); // } // catch (Exception ex) // { // Debug.error("Help not found\n" + ex); // return; // } } */ public IBeanManager getBeanManager() { if (beanManager == null) { beanManager = createBeanManager(); } return beanManager; } public ICmdManager getCmdManager() { return cmdManager; } @Override protected void registerListeners() { // Note:add order is important // 1 J2DBGlobals.addPropertyChangeListener(this, cmdManager); // register J2DBGlobals.addPropertyChangeListener(modeManager, cmdManager); // register // 2 super.registerListeners(); } @Override protected boolean startApplicationServerConnection() { try { applicationServer = connectApplicationServer(); } catch (Exception ex) { reportError(Messages.getString("servoy.client.error.finding.dataservice"), ex); //$NON-NLS-1$ } return applicationServer != null; } protected IApplicationServer connectApplicationServer() throws Exception { String name = IApplicationServer.class.getName(); String host = getServerURL().getHost(); int port = Utils.getAsInteger(settings.getProperty("usedRMIRegistryPort")); //$NON-NLS-1$ try { if (register == null) { register = LocateRegistry.getRegistry(host, port, rmiFactoryFactory.getRemoteClientSocketFactory()); } return (IApplicationServer)register.lookup(name); } catch (Exception e) { Debug.error("Error getting the service " + name + " from host " + host + ':' + port, e); //$NON-NLS-1$ //$NON-NLS-2$ throw e; } } private Registry register; // solution loading monitor protected boolean solutionLoading; protected Object solutionLoadingMutex = new Object(); @Override protected SolutionMetaData selectSolutionToLoad() throws RepositoryException { if (getSolution() != null) { int x = JOptionPane.showConfirmDialog(frame, Messages.getString("servoy.client.message.closeopensolution"), //$NON-NLS-1$ Messages.getString("servoy.general.confirm"), //$NON-NLS-1$ JOptionPane.OK_CANCEL_OPTION, JOptionPane.INFORMATION_MESSAGE); if (x != JOptionPane.OK_OPTION) { return null; } closeSolution(false, null); // always return, because openSolutionDialog method is called in closeSolution return null; } SwingHelper.dispatchEvents(100);// hide menu return super.selectSolutionToLoad(); } @Override public IFormManagerInternal getFormManager() { return (IFormManagerInternal)super.getFormManager(); } @Override protected void loadSolution(final SolutionMetaData solutionMeta) throws RepositoryException { // regular solution showSolutionLoading(true); invokeLater(new Runnable() { public void run() { try { blockGUI(Messages.getString("servoy.client.status.loadingsolution", new Object[] { solutionMeta.getName() })); //$NON-NLS-1$ loadSolutionsAndModules(solutionMeta); } catch (final Exception ex) { showSolutionLoading(false); invokeLater(new Runnable() { public void run() { reportError(Messages.getString("servoy.client.error.opensolution"), ex); //$NON-NLS-1$ } }); } finally { getScriptEngine(); releaseGUI(); } } }); } @Override protected SolutionMetaData showSolutionSelection(SolutionMetaData[] solutions) { if (selectSolutionDialog == null) { selectSolutionDialog = new SelectSolutionDialog(this); } showSolutionLoading(true); SolutionMetaData tmp = null; try { tmp = selectSolutionDialog.showDialog(solutions); } finally { if (tmp == null) showSolutionLoading(false); } return tmp; } @Override protected int getSolutionTypeFilter() { return super.getSolutionTypeFilter() | SolutionMetaData.SMART_CLIENT_ONLY; } @Override public boolean loadSolutionsAndModules(SolutionMetaData s) { boolean value = super.loadSolutionsAndModules(s); if (getSolution() != null) { OrientationApplier.setOrientationToAWTComponent(frame, getLocale(), getSolution().getTextOrientation()); } return value; } @Override protected void solutionLoaded(final Solution solution) { super.solutionLoaded(solution); invokeLater(new Runnable() { /** * @see java.lang.Runnable#run() */ public void run() { try { blockGUI(Messages.getString("servoy.client.status.initializing.solution")); //$NON-NLS-1$ setTitle(""); //$NON-NLS-1$ J2DBGlobals.firePropertyChange(J2DBClient.this, "solution", null, solution); //$NON-NLS-1$ handleArguments(null); // clear the loaded solution names. } finally { releaseGUI(); } } }); } @Override public boolean saveSolution() { // not impleneted in this class return true; } public void setTitle(String name) { String title = ""; //$NON-NLS-1$ String solutionTitle = getSolution().getTitleText(); if (solutionTitle == null) { title = getSolution().getName(); } else if (!solutionTitle.equals("<empty>")) //$NON-NLS-1$ { title = solutionTitle; } title = getI18NMessageIfPrefixed(title); if (name != null && !name.trim().equals("") && !"<empty>".equals(name)) //$NON-NLS-1$ //$NON-NLS-2$ { String i18nName = getI18NMessageIfPrefixed(name); FormController formController = (FormController)getFormManager().getCurrentForm(); if (formController != null) { String name2 = Text.processTags(i18nName, formController.getTagResolver()); if (name2 != null) i18nName = name2; } else { String name2 = Text.processTags(i18nName, TagResolver.createResolver(new PrototypeState(null))); if (name2 != null) i18nName = name2; } if (!i18nName.trim().equals("")) //$NON-NLS-1$ { if ("".equals(title)) //$NON-NLS-1$ { title += i18nName; } else { title += " - " + i18nName; //$NON-NLS-1$ } } } String appName = getDisplayApplicationName(); if (appName.endsWith("Developer")) //$NON-NLS-1$ { title = appName + " - " + title; //$NON-NLS-1$ } else { if (title.equals("")) //$NON-NLS-1$ { title = appName; } else { title += " - " + appName; //$NON-NLS-1$ } } frame.setTitle(title); } @Override protected void checkForActiveTransactions(boolean force) { if (foundSetManager != null) { if (foundSetManager.hasTransaction()) { int but = JOptionPane.CANCEL_OPTION; if (!force) { but = JOptionPane.showConfirmDialog( frame, Messages.getString("servoy.client.message.activetransaction"), Messages.getString("servoy.client.message.activetransaction.title"), JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE); //$NON-NLS-1$ //$NON-NLS-2$ } if (but == JOptionPane.OK_OPTION) { foundSetManager.commitTransaction(true, true); } else { foundSetManager.rollbackTransaction(true, false, true); } } } } @Override public boolean closeSolution(boolean force, Object[] args) { if (getSolution() == null || isClosing) return true; blockGUI(Messages.getString("servoy.client.status.closingsolution")); //$NON-NLS-1$ try { if (!super.closeSolution(force, args)) return false; if (frame != null) frame.setTitle(getDisplayApplicationName()); // delete all dialogs Iterator<Window> it = dialogs.values().iterator(); while (it.hasNext()) { Window element = it.next(); element.dispose(); } dialogs = new HashMap<String, Window>(); Collection<Style> userStyles = getFlattenedSolution().flushUserStyles(); if (userStyles != null) { for (Style style : userStyles) { ComponentFactory.flushStyle(this, style); } } setStatusText("", null); //$NON-NLS-1$ ComponentFactory.flushCachedItems(this); invokeLater(new Runnable()// make some stuff later null so its not created again { public void run() { editLabel.setIcon(empty); insertModeLabel.setIcon(empty); transactionLabel.setIcon(empty); lockLabel.setIcon(empty); dataChangeLabel.setIcon(empty); invokeLater(new Runnable() { public void run() { if (getSolution() == null && getClientInfo() != null) { // select new solution, run later because logout may trigger a login dialog as well handleClientUserUidChanged(null, getClientInfo().getUserUid()); } } }); } }); return true; } catch (Exception ex) { Debug.error(ex); return false; } finally { releaseGUI(); } } protected int blockCounter = 0; protected Stack<Pair<Color, String>> msgStack = new Stack<Pair<Color, String>>(); protected Pair<Color, String> lastOne; @Override public void blockGUI(final String reason) { synchronized (msgStack) { blockCounter++; if (msgStack.size() == 0) lastOne = new Pair<Color, String>(statusLabel.getForeground(), statusLabel.getText()); Runnable update = new Runnable() { public void run() { msgStack.push(new Pair<Color, String>(Color.BLACK, reason)); statusLabel.setForeground(Color.BLACK); statusLabel.setText(reason); if (blockCounter == 1) { frame.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); statusProgessBar.setIndeterminate(true); rootPane.getGlassPane().setVisible(true); rootPane.getGlassPane().setEnabled(true); } } }; if (isEventDispatchThread()) { update.run(); } else { invokeLater(update); } } } // Releases GUI interaction @Override public void releaseGUI() { synchronized (msgStack) { blockCounter--; if (blockCounter < 0) { Debug.error("releaseGUI to many times called"); //$NON-NLS-1$ blockCounter = 0; } else if (blockCounter >= 0) { Runnable update = new Runnable() { public void run() { msgStack.pop();// remove myown msg, to be able to show previous Pair<Color, String> p = null; if (msgStack.size() == 0) { p = lastOne; } else { p = msgStack.peek(); } statusLabel.setForeground(p.getLeft()); statusLabel.setText(p.getRight()); if (blockCounter == 0) { if (frame != null) frame.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); rootPane.getGlassPane().setEnabled(false); rootPane.getGlassPane().setVisible(false); statusProgessBar.setIndeterminate(false); } } }; if (isEventDispatchThread()) { update.run(); } else { invokeLater(update); } } } } @Override public void reportWarning(String s) { reportWarningInStatus(s); } public void reportWarningInStatus(final String s) { if (s == null) return; mainPanel.getToolkit().beep(); synchronized (msgStack) { if (msgStack.size() == 0) lastOne = new Pair<Color, String>(statusLabel.getForeground(), statusLabel.getText()); Runnable update = new Runnable() { public void run() { msgStack.push(new Pair<Color, String>(Color.RED, s)); statusLabel.setForeground(Color.RED); statusLabel.setText(s); } }; if (isEventDispatchThread()) { update.run(); } else { invokeLater(update); } } getScheduledExecutor().execute(new HideStatusText(3000 + (s.length() * 100))); } class HideStatusText implements Runnable { private final int sleepTime; HideStatusText(int slt) { sleepTime = slt; } public void run() { try { Thread.sleep(sleepTime); } catch (InterruptedException e) { Debug.error(e); } synchronized (msgStack) { Runnable update = new Runnable() { public void run() { msgStack.pop();// remove myown msg, to be able to show previous Pair<Color, String> p = null; if (msgStack.size() == 0) { p = lastOne; } else { p = msgStack.peek(); } statusLabel.setForeground(p.getLeft()); statusLabel.setText(p.getRight()); } }; invokeLater(update); } } } private void fillBrowseToolbar(JToolBar toolBar, Map<String, Action> actions) { JButton mi = null; Action action = null; action = actions.get("cmdopensolution"); //$NON-NLS-1$ if (action != null) { mi = new ToolbarButton(action); toolBar.add(mi); } action = actions.get("cmdprint"); //$NON-NLS-1$ if (action != null) { mi = new ToolbarButton(action); toolBar.add(mi); } /* * action = (Action) actions.get("cmdspell"); if (action != null) { mi = new ToolbarButton(action); toolBar.add(mi); } */ toolBar.addSeparator(); action = actions.get("cmdhistoryback"); //$NON-NLS-1$ if (action != null) { mi = new ToolbarButton(action); toolBar.add(mi); } action = actions.get("cmdhistoryforward"); //$NON-NLS-1$ if (action != null) { mi = new ToolbarButton(action); toolBar.add(mi); } toolBar.addSeparator(); action = actions.get("cmdnewrecord"); //$NON-NLS-1$ if (action != null) { mi = new ToolbarButton(action); toolBar.add(mi); } action = actions.get("cmddeleterecord"); //$NON-NLS-1$ if (action != null) { mi = new ToolbarButton(action); toolBar.add(mi); } toolBar.addSeparator(); action = actions.get("cmdsort"); //$NON-NLS-1$ if (action != null) { mi = new ToolbarButton(action); toolBar.add(mi); } } protected Map<String, Action> getActions() { HashMap<String, Action> table = new HashMap<String, Action>(); table.put("cmdopensolution", new CmdOpenSolution(this)); //$NON-NLS-1$ // table.put("cmdspell", new CmdSpell(this)); //$NON-NLS-1$ table.put("cmdnewrecord", new CmdNewRecord(this)); //$NON-NLS-1$ table.put("cmdduplicaterecord", new CmdDuplicateRecord(this)); //$NON-NLS-1$ table.put("cmddeleterecord", new CmdDeleteRecord(this)); //$NON-NLS-1$ table.put("cmddeleteallrecord", new CmdDeleteAllRecord(this)); //$NON-NLS-1$ table.put("cmdsort", new CmdSort(this)); //$NON-NLS-1$ table.put("cmdclose", new CmdClose(this)); //$NON-NLS-1$ table.put("cmdpagesetup", new CmdPageSetup(this)); //$NON-NLS-1$ // table.put("cmdprint", new CmdPrint(this)); //$NON-NLS-1$ table.put("cmdundo", cmdManager.getUndoAction()); //$NON-NLS-1$ table.put("cmdredo", cmdManager.getRedoAction()); //$NON-NLS-1$ table.put("cmdcut", new CmdCut(this)); //$NON-NLS-1$ table.put("cmdcopy", new CmdCopy(this)); //$NON-NLS-1$ table.put("cmdpaste", new CmdPaste(this)); //$NON-NLS-1$ table.put("cmdselectall", new CmdSelectAll(this)); //$NON-NLS-1$ table.put("cmdshowpreferences", new CmdShowPreferences(this)); //$NON-NLS-1$ table.put("cmdbrowsemode", new CmdBrowseMode(this)); //$NON-NLS-1$ table.put("cmdfindmode", new CmdFindMode(this)); //$NON-NLS-1$ table.put("cmdperformfind", new CmdPerformFind(this)); //$NON-NLS-1$ table.put("cmdreducefind", new CmdReduceFind(this)); //$NON-NLS-1$ table.put("cmdextendfind", new CmdExtendFind(this)); //$NON-NLS-1$ table.put("cmdpreviewmode", new CmdPreviewMode(this)); //$NON-NLS-1$ table.put("cmdfindall", new CmdFindAll(this)); //$NON-NLS-1$ table.put("cmdstopsearchfindall", new CmdStopSearchFindAll(this)); //$NON-NLS-1$ table.put("cmdsavedata", new CmdSaveData(this)); //$NON-NLS-1$ // table.put("cmdreplace", new CmdReplace(this)); //$NON-NLS-1$ table.put("cmdhelp", new CmdHelp(this)); //$NON-NLS-1$ // table.put("cmdhelpcontents", new CmdHelpContents(this)); //$NON-NLS-1$ table.put("cmdabout", new CmdAbout(this)); //$NON-NLS-1$ table.put("cmdexit", new CmdExit(this)); //$NON-NLS-1$ table.put("cmdviewasform", new CmdViewAsForm(this)); //$NON-NLS-1$ table.put("cmdviewaslist", new CmdViewAsList(this)); //$NON-NLS-1$ // table.put("cmdviewastable", new CmdViewAsTable(this)); //$NON-NLS-1$ table.put("cmdomitrecord", new CmdOmitRecord(this)); //$NON-NLS-1$ table.put("cmdrevertrecords", new CmdInvertRecords(this)); //$NON-NLS-1$ table.put("cmdshowomitrecords", new CmdShowOmitRecords(this)); //$NON-NLS-1$ table.put("cmdrecopyvalues", new CmdReCopyValues(this)); //$NON-NLS-1$ Action action = new CmdHistoryBack(this); rootPane.registerKeyboardAction(action, (KeyStroke)action.getValue(Action.ACCELERATOR_KEY), JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT); table.put("cmdhistoryback", action); //$NON-NLS-1$ action = new CmdHistoryForward(this); rootPane.registerKeyboardAction(action, (KeyStroke)action.getValue(Action.ACCELERATOR_KEY), JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT); table.put("cmdhistoryforward", action); //$NON-NLS-1$ table.put("cmdnextrecord", new CmdNextRecord(this)); //$NON-NLS-1$ table.put("cmdprevrecord", new CmdPrevRecord(this)); //$NON-NLS-1$ table.put("cmdlogout", new CmdLogout(this)); //$NON-NLS-1$ table.put("menuimportaction", new MenuImportAction(this)); //$NON-NLS-1$ table.put("menuexportaction", new MenuExportAction(this)); //$NON-NLS-1$ return table; } /** * create the menu bar */ protected JMenuBar createMenuBar(Map<String, Action> actions) { // MenuBar // menuBar = new JMenuBar(); if (menuBar == null) { menuBar = new JMenuBar(); } else { menuBar.removeAll(); } // menuBar.setBorder(BorderFactory.createEmptyBorder()); // menuBar.setMargin(new Insets(10,10,10,10)); // menuBar.getAccessibleContext().setAccessibleName("Swing menus"); // menuBar.add(Box.createRigidArea(new Dimension(10,10))); // File Menu JMenu file = menuBar.add(new JMenuAlwaysEnabled(new MenuFileAction(this))); //file.setOpaque(false); // file.setEnabled(!runsInApplet); JMenuItem mi = null; Action action = null; action = actions.get("releaseformpanels"); //$NON-NLS-1$ if (action != null) { mi = new ActionMenuItem(action); file.add(mi); } action = actions.get("cmdopensolution"); //$NON-NLS-1$ if (action != null) { mi = new ActionMenuItem(action); file.add(mi); } action = actions.get("cmdclose"); //$NON-NLS-1$ if (action != null) { mi = new ActionMenuItem(action); file.add(mi); file.addSeparator(); } action = actions.get("cmdsolutionsettings"); //$NON-NLS-1$ if (action != null) { mi = new ActionMenuItem(action); file.add(mi); file.addSeparator(); } action = actions.get("cmdpagesetup"); //$NON-NLS-1$ if (action != null) { mi = new ActionMenuItem(action); file.add(mi); } file.add(((SwingModeManager)modeManager).getPreviewModeMenuItem(actions)); file.addSeparator(); action = actions.get("menuimportaction"); //$NON-NLS-1$ if (action != null) { if (import_Menu == null) { import_Menu = new JMenuAlwaysEnabled(action); } file.add(import_Menu); } action = actions.get("menuexportaction"); //$NON-NLS-1$ if (action != null) { if (export_Menu == null) { export_Menu = new JMenuAlwaysEnabled(action); } file.add(export_Menu); } file.addSeparator(); action = actions.get("cmdlogout"); //$NON-NLS-1$ if (action != null) { mi = new ActionMenuItem(action); file.add(mi); } action = actions.get("cmdexit"); //$NON-NLS-1$ if (action != null) { mi = new ActionMenuItem(action); file.add(mi); } // Edit Menu JMenu edit = menuBar.add(new JMenuAlwaysEnabled(new MenuEditAction(this))); // edit.setOpaque(false); action = actions.get("cmdundo"); //$NON-NLS-1$ if (action != null) { mi = new ActionMenuItem(action); edit.add(mi); } action = actions.get("cmdredo"); //$NON-NLS-1$ if (action != null) { mi = new ActionMenuItem(action); edit.add(mi); } edit.addSeparator(); action = actions.get("cmdcopy"); //$NON-NLS-1$ if (action != null) { mi = new ActionMenuItem(action); edit.add(mi); } action = actions.get("cmdcut"); //$NON-NLS-1$ if (action != null) { mi = new ActionMenuItem(action); edit.add(mi); } action = actions.get("cmdpaste"); //$NON-NLS-1$ if (action != null) { mi = new ActionMenuItem(action); edit.add(mi); } edit.addSeparator(); action = actions.get("cmdselectall"); //$NON-NLS-1$ if (action != null) { mi = new ActionMenuItem(action); edit.add(mi); } edit.addSeparator(); action = actions.get("cmdshowpreferences"); //$NON-NLS-1$ if (action != null) { mi = new ActionMenuItem(action); edit.add(mi); } // Mode Menu JMenu mode = menuBar.add(new JMenuAlwaysEnabled(new MenuViewAction(this))); // mode.setOpaque(false); // mode.add(modeManager.getBrowseModeMenuItem(actions)); ButtonGroup bg = new ButtonGroup(); JRadioButtonMenuItem mi1 = null; JRadioButtonMenuItem mi2 = null; JRadioButtonMenuItem mi3 = null; action = actions.get("cmdviewasform"); //$NON-NLS-1$ if (action != null) { mi1 = new ActionRadioMenuItem(action); mode.add(mi1); bg.add(mi1); } action = actions.get("cmdviewaslist"); //$NON-NLS-1$ if (action != null) { mi2 = new ActionRadioMenuItem(action); mode.add(mi2); bg.add(mi2); } action = actions.get("cmdviewastable"); //$NON-NLS-1$ if (action != null) { mi3 = new ActionRadioMenuItem(action); mode.add(mi3); bg.add(mi3); } ((SwingFormManager)formManager).setViews(new JRadioButtonMenuItem[] { mi1, mi2, mi3 }); ButtonGroup bg1 = new ButtonGroup(); action = actions.get("cmdbasicfilter"); //$NON-NLS-1$ if (action != null) { mode.addSeparator(); mi = new ActionRadioMenuItem(action); mode.add(mi); bg1.add(mi); } action = actions.get("cmdadvancedfilter"); //$NON-NLS-1$ if (action != null) { mi = new ActionRadioMenuItem(action); mode.add(mi); bg1.add(mi); } action = actions.get("cmdwebfilter"); //$NON-NLS-1$ if (action != null) { mi = new ActionCheckBoxMenuItem(action); mode.add(mi); } action = actions.get("cmdshowrulers"); //$NON-NLS-1$ if (action != null) { mode.addSeparator(); mi = new ActionCheckBoxMenuItem(action); mode.add(mi); } action = actions.get("cmdshowgrid"); //$NON-NLS-1$ if (action != null) { mi = new ActionCheckBoxMenuItem(action); mode.add(mi); } action = actions.get("cmdsnaptogrid"); //$NON-NLS-1$ if (action != null) { mi = new ActionCheckBoxMenuItem(action); mode.add(mi); } mode.addSeparator(); JMenu toolbars = toolbarsPanel.getMenu(); mode.add(toolbars); // Select Menu JMenu select = menuBar.add(new JMenuAlwaysEnabled(new MenuSelectAction(this))); // select.setOpaque(false); select.add(((SwingModeManager)modeManager).getFindModeMenuItem(actions)); action = actions.get("cmdperformfind"); //$NON-NLS-1$ if (action != null) { mi = new ActionMenuItem(action); select.add(mi); } action = actions.get("cmdreducefind"); //$NON-NLS-1$ if (action != null) { mi = new ActionMenuItem(action); select.add(mi); } action = actions.get("cmdextendfind"); //$NON-NLS-1$ if (action != null) { mi = new ActionMenuItem(action); select.add(mi); } action = actions.get("cmdfindall"); //$NON-NLS-1$ if (action != null) { mi = new ActionMenuItem(action); select.add(mi); } select.addSeparator(); action = actions.get("cmdsavedata"); //$NON-NLS-1$ if (action != null) { mi = new ActionMenuItem(action); select.add(mi); } select.addSeparator(); action = actions.get("cmdnewrecord"); //$NON-NLS-1$ if (action != null) { mi = new ActionMenuItem(action); select.add(mi); } action = actions.get("cmdduplicaterecord"); //$NON-NLS-1$ if (action != null) { mi = new ActionMenuItem(action); select.add(mi); } action = actions.get("cmddeleterecord"); //$NON-NLS-1$ if (action != null) { mi = new ActionMenuItem(action); select.add(mi); } action = actions.get("cmddeleteallrecord"); //$NON-NLS-1$ if (action != null) { mi = new ActionMenuItem(action); select.add(mi); } select.addSeparator(); action = actions.get("cmdomitrecord"); //$NON-NLS-1$ if (action != null) { mi = new ActionMenuItem(action); select.add(mi); } action = actions.get("cmdshowomitrecords"); //$NON-NLS-1$ if (action != null) { mi = new ActionMenuItem(action); select.add(mi); } action = actions.get("cmdrevertrecords"); //$NON-NLS-1$ if (action != null) { mi = new ActionMenuItem(action); select.add(mi); } select.addSeparator(); action = actions.get("cmdprevrecord"); //$NON-NLS-1$ if (action != null) { mi = new ActionMenuItem(action); select.add(mi); } action = actions.get("cmdnextrecord"); //$NON-NLS-1$ if (action != null) { mi = new ActionMenuItem(action); select.add(mi); } select.addSeparator(); action = actions.get("cmdsort"); //$NON-NLS-1$ if (action != null) { mi = new ActionMenuItem(action); select.add(mi); } action = actions.get("cmdrecopyvalues"); //$NON-NLS-1$ if (action != null) { mi = new ActionMenuItem(action); select.add(mi); } action = actions.get("cmdreplace"); //$NON-NLS-1$ if (action != null) { mi = new ActionMenuItem(action); select.add(mi); } // Script Menu menuBar.add(((SwingFormManager)formManager).getScriptMenu()); // Script // Window Menu menuBar.add(((SwingFormManager)formManager).getWindowMenu()); // Help Menu JMenu help = menuBar.add(new JMenuAlwaysEnabled(new MenuHelpAction(this))); // help.setOpaque(false); action = actions.get("cmdhelp"); //$NON-NLS-1$ if (action != null) { mi = new ActionMenuItem(action); help.add(mi); } action = actions.get("cmdhelpcontents"); //$NON-NLS-1$ if (action != null) { mi = new ActionMenuItem(action); help.add(mi); } help.addSeparator(); action = actions.get("cmdsupport"); //$NON-NLS-1$ if (action != null) { mi = new ActionMenuItem(action); help.add(mi); } action = actions.get("cmdforum"); //$NON-NLS-1$ if (action != null) { mi = new ActionMenuItem(action); help.add(mi); } action = actions.get("cmdnewversioncheck"); //$NON-NLS-1$ if (action != null) { mi = new ActionMenuItem(action); help.add(mi); help.addSeparator(); } action = actions.get("cmdabout"); //$NON-NLS-1$ if (action != null) { mi = new ActionMenuItem(action); help.add(mi); } return menuBar; } protected void attachAppleMenu(Map<String, Action> actions) { Object appleObject; try { Class< ? > clazz = Class.forName("net.roydesign.app.Application"); //$NON-NLS-1$ Method mi = clazz.getMethod("getInstance", (Class[])null); //$NON-NLS-1$ appleObject = mi.invoke(null, (Object[])null); Action action = actions.get("cmdabout"); //$NON-NLS-1$ if (action != null) { Method m = clazz.getMethod("getAboutJMenuItem", (Class[])null); //$NON-NLS-1$ JMenuItem a_about = (JMenuItem)m.invoke(appleObject, (Object[])null); a_about.addActionListener(action); } action = actions.get("cmdexit"); //$NON-NLS-1$ if (action != null) { Method m = clazz.getMethod("getQuitJMenuItem", (Class[])null); //$NON-NLS-1$ JMenuItem a_about = (JMenuItem)m.invoke(appleObject, (Object[])null); a_about.addActionListener(action); } action = actions.get("cmdshowpreferences"); //$NON-NLS-1$ if (action != null) { Method m = clazz.getMethod("getPreferencesJMenuItem", (Class[])null); //$NON-NLS-1$ JMenuItem a_about = (JMenuItem)m.invoke(appleObject, (Object[])null); a_about.addActionListener(action); } } catch (Throwable e) { Debug.error(e); } } /** * Show the application dialog */ public void showAppPrefs() { if (ap == null) { blockGUI(Messages.getString("servoy.client.status.loading.preferencepanels")); //$NON-NLS-1$ SwingHelper.dispatchEvents(300);// show cursor / hide menu try { ap = new ApplicationPreferences(this); // Load all default tabs loadPreferecesPanels(ap); // Load plugins tabs ((ClientPluginManager)pluginManager).addPreferenceTabs(ap); ap.pack(); ap.setLocationRelativeTo(mainPanel); } finally { releaseGUI(); } } ap.setVisible(true); } protected PreferencePanel createGeneralPanel() { return new GeneralPanel(this); } protected void loadPreferecesPanels(ApplicationPreferences appPrefs) { appPrefs.addPreferenceTab(createGeneralPanel()); appPrefs.addPreferenceTab(new LFPreferencePanel(this)); appPrefs.addPreferenceTab(new LocalePreferences(this)); addServicePreferencesTab(appPrefs); } @SuppressWarnings("nls") protected void addServicePreferencesTab(ApplicationPreferences appPrefs) { String rmiFactory = settings.getProperty("SocketFactory.rmiClientFactory", "com.servoy.j2db.rmi.DefaultClientSocketFactoryFactory"); if (rmiFactory == null || rmiFactory.endsWith("com.servoy.j2db.rmi.DefaultClientSocketFactoryFactory")) { appPrefs.addPreferenceTab(new ServicePanel(this)); } } @Override public void logout(final Object[] solution_to_open_args) { if (getClientInfo().getUserUid() != null) { if (getSolution() == null) { super.logout(solution_to_open_args); } else { // close solution first invokeLater(new Runnable() { public void run() { boolean doLogOut = getClientInfo().getUserUid() != null; if (getSolution() != null) { doLogOut = closeSolution(false, solution_to_open_args); } if (doLogOut) { Action action = getCmdManager().getRegisteredAction("cmdlogout"); //$NON-NLS-1$ if (action != null) { action.setEnabled(false); } if (getSolution() == null) { // calls super.logout() logout(solution_to_open_args); } } } }); } } } @Override public String authenticate(Credentials credentials) throws RepositoryException { String jsreturn = super.authenticate(credentials); if (getClientInfo().getUserUid() != null) { // successfully logged in // store name URL serverURL = getServerURL(); getSettings().setProperty(serverURL.getHost() + serverURL.getPort() + "lastLoggedinUserName", getClientInfo().getUserName()); //$NON-NLS-1$ Action action = getCmdManager().getRegisteredAction("cmdlogout"); //$NON-NLS-1$ if (action != null) { action.setEnabled(true); } } return jsreturn; } private LoginDialog loginDialog; @Override public void showDefaultLogin() { Runnable r = new Runnable() { public void run() { if (loginDialog != null) { return; // already showing login dialog } try { while (getClientInfo().getUserUid() == null) { URL serverURL = getServerURL(); String name = getSettings().getProperty( serverURL.getHost() + serverURL.getPort() + "lastLoggedinUserName", System.getProperty("user.name")); //$NON-NLS-1$ //$NON-NLS-2$ if (loginDialog == null) { loginDialog = createLoginDialog(); } Object[] name_password = loginDialog.showDialog(name); dispatchEventsToHideDialog(); // hide dialog if (name_password == null || name_password.length < 2 || name_password[0] == null || name_password[1] == null) { // user hit cancel showSolutionLoading(false); return; } authenticate(null, null, new Object[] { name_password[0].toString(), name_password[1].toString() }); if (getClientInfo().getUserUid() == null) { JOptionPane.showMessageDialog(frame, Messages.getString("servoy.client.message.loginfailed"), //$NON-NLS-1$ Messages.getString("servoy.client.message.loginfailed.title"), //$NON-NLS-1$ JOptionPane.ERROR_MESSAGE); } } handleClientUserUidChanged(null, getClientInfo().getUserUid()); if (!isShutDown() && solutionRoot.isMainSolutionLoaded() && (getClientInfo().getUserUid() != null || !solutionRoot.getSolution().requireAuthentication())) { solutionLoaded(getSolution()); } } catch (Exception e) { reportError(Messages.getString("servoy.client.message.loginfailed"), e); //$NON-NLS-1$ } finally { if (loginDialog != null) { loginDialog.dispose(); loginDialog = null; } } } }; invokeLater(r); } protected void dispatchEventsToHideDialog() { SwingHelper.dispatchEvents(250); } @Override public void clearLoginForm() { Action action = getCmdManager().getRegisteredAction("cmdlogout"); //$NON-NLS-1$ if (action != null) { action.setEnabled(true); } super.clearLoginForm(); } public void setStatusProgress(int progress) { statusProgessBar.setValue(progress); } public void setStatusText(String statusText, String toolTip) { String text = (statusText.trim().length() == 0) ? READY : statusText; statusLabel.setForeground(Color.BLACK); statusLabel.setText(text); statusLabel.setToolTipText(toolTip); lastOne = new Pair<Color, String>(Color.BLACK, text); } private AboutDialog ad; public void showAboutDialog() { if (ad == null) { ad = new AboutDialog(this); ad.addWindowListener(new WindowAdapter() { @Override public void windowClosing(WindowEvent e) { ad = null; } @Override public void windowClosed(WindowEvent e) { ad = null; } }); ad.setLocationRelativeTo(frame); ad.setVisible(true); } else { ad.toFront(); } } public void looseFocus() { getMainApplicationFrame().getContentPane().requestFocus(); } public void reportInfo(String message) { reportInfo(frame, message, Messages.getString("servoy.general.info")); //$NON-NLS-1$ } public void reportInfo(Component parentComponent, String message, String title) { JOptionPane.showMessageDialog(parentComponent, message, title, JOptionPane.INFORMATION_MESSAGE); } @Override public void reportError(String message, Object detail) { Window window = (Window)getRuntimeWindowManager().getCurrentWindowWrappedObject(); if (window == null || !window.isVisible()) { window = getMainApplicationFrame(); } reportError(window, message, detail); } public void reportError(Component parentComponent, String message, Object detail) { // test if it is a Repository Exception with Client not register status code. if (!testClientRegistered(detail)) { if (Debug.tracing()) { if (detail instanceof Throwable) { Debug.trace("client is not registered, waiting for a reconnect", (Throwable)detail); //$NON-NLS-1$ } else { Debug.trace("client is not registered, waiting for a reconnect"); //$NON-NLS-1$ } } return; } if (detail instanceof Throwable) { Debug.error(message, (Throwable)detail); } else { Debug.error(detail); } mainPanel.getToolkit().beep(); String dialogMessage = message; if (dialogMessage == null) dialogMessage = ""; //$NON-NLS-1$ else if (dialogMessage.length() > 100) { dialogMessage = dialogMessage.substring(0, 100) + "..."; //$NON-NLS-1$ } JOptionPane.showMessageDialog(parentComponent, dialogMessage, Messages.getString("servoy.general.error"), JOptionPane.ERROR_MESSAGE); //$NON-NLS-1$ SwingHelper.dispatchEvents(100);// hide the dialog } public void setPageFormat(PageFormat pf) { pageFormat = pf; settings.setProperty("pageformat", PersistHelper.createPageFormatString(pf)); //$NON-NLS-1$ } private PageFormat pageFormat = null; public PageFormat getPageFormat() { if (pageFormat == null) { pageFormat = PersistHelper.createPageFormat(settings.getProperty("pageformat")); //$NON-NLS-1$ if (pageFormat == null) { pageFormat = new PageFormat(); } } return pageFormat; } private HashMap<String, Window> dialogs = new HashMap<String, Window>(); public void registerWindow(String name, Window d) { Window removed = null; if (d != null) { removed = dialogs.put(name, d); } else { removed = dialogs.remove(name); } if (removed != null && d != removed) { removed.dispose(); } } public Window getWindow(String name) { return dialogs.get(name); } @Override protected IExecutingEnviroment createScriptEngine() { return new ScriptEngine(this); } @Override protected void createFoundSetManager() { foundSetManager = new FoundSetManager(this, new SwingFoundSetFactory()); ((FoundSetManager)foundSetManager).setInfoListener(this); foundSetManager.init(); ((FoundSetManager)foundSetManager).getEditRecordList().addEditListener(this); } private int getRmiExportPort() throws Exception { URL base = getServerURL(); URL url = new URL(base, "servoy-rmi-portserver"); //$NON-NLS-1$ DataInputStream is = new DataInputStream((InputStream)url.getContent()); int port = is.readInt(); is.close(); return port; } @Override protected void bindUserClient() { try { int port = exportObject(userClient); Debug.trace("RMI export succeeded on port: " + port); getClientInfo().setHostPort(port); } catch (RemoteException e) { Debug.error(e); } } private int rmiExportPort = -1; /** * @return * @throws RemoteException */ public synchronized int exportObject(Remote object) throws RemoteException { int counter = 0; while (counter++ < 100) { try { if (rmiExportPort == -1) { rmiExportPort = getRmiExportPort(); } UnicastRemoteObject.exportObject(object, rmiExportPort, rmiFactoryFactory.getClientSocketFactory(), rmiFactoryFactory.getServerSocketFactory()); counter = -1; break; } catch (Exception e) { // set the port on -1 and try again. rmiExportPort = -1; } } if (counter != -1) { Debug.error("Couldnt export object with port from server, trying to do on anonym port"); rmiExportPort = 0; UnicastRemoteObject.exportObject(object, rmiExportPort, rmiFactoryFactory.getClientSocketFactory(), rmiFactoryFactory.getServerSocketFactory()); } return rmiExportPort; } @Override protected void unBindUserClient() throws Exception { if (userClient != null) { try { Debug.trace("Unexporting userclient"); int counter = 1; while (!UnicastRemoteObject.unexportObject(userClient, false)) { Debug.trace("Unexporting userclient not yet successful for " + counter + " time"); if (isRunningRemote() && counter < 5) { counter++; // Let the server be able to clean it up. synchronized (this) { this.wait(1000); } } else { UnicastRemoteObject.unexportObject(userClient, true); break; } } } catch (Exception e) { Debug.error(e); } } } public void output(Object msg, int level) { if (level == ERROR || level == FATAL) { System.err.println(msg); } else { System.out.println(msg); } } protected void showAd() { getScheduledExecutor().execute(new Runnable() { public void run() { final Object[] adsInfo = Ad.getAdInfo(); final int w = Utils.getAsInteger(adsInfo[1]); final int h = Utils.getAsInteger(adsInfo[2]); if (w > 50 && h > 50) { J2DBClient.this.invokeLater(new Runnable() { public void run() { URL url = (URL)adsInfo[0]; int t = Utils.getAsInteger(adsInfo[3]); JPanel comp = new InfoPanel(J2DBClient.this, url, t); comp.setSize(w, h); comp.setLocation((frame.getWidth() - comp.getWidth()) - 30, 60); frame.getRootPane().getLayeredPane().add(comp, JLayeredPane.MODAL_LAYER); } }); } } }); } @Override protected boolean registerClient(IUserClient uc) throws Exception { boolean registered = false; try { registered = super.registerClient(uc); if (!registered) { showAd(); } } catch (final ApplicationException e) { invokeAndWait(new Runnable() { public void run() { if (e.getErrorCode() == ServoyException.NO_LICENSE) { JOptionPane.showMessageDialog(frame, Messages.getString("servoy.license.notrialleft"), Messages.getString("servoy.license.label"), JOptionPane.ERROR_MESSAGE); exitHard(1); } else if (e.getErrorCode() == ServoyException.MAINTENANCE_MODE) { JOptionPane.showMessageDialog(frame, Messages.getString("servoy.maintenance.clientRegisterForbidden"), //$NON-NLS-1$ Messages.getString("servoy.maintenance.label"), JOptionPane.ERROR_MESSAGE); exitHard(1); } else if (e.getErrorCode() == ServoyException.InternalCodes.INVALID_RMI_SERVER_CONNECTION) { JOptionPane.showMessageDialog(frame, e.getMessage(), Messages.getString("servoy.general.error"), JOptionPane.ERROR_MESSAGE); //$NON-NLS-1$ exitHard(1); } } }); } return registered; } /** * @see com.servoy.j2db.dataprocessing.IGlobalEditListener#editChange(com.servoy.j2db.dataprocessing.GlobalEditEvent) */ public void editChange(final GlobalEditEvent e) { if (SwingUtilities.isEventDispatchThread()) { if (e.isEditing()) { editLabel.setIcon(editing); } else { editLabel.setIcon(empty); } } else { SwingUtilities.invokeLater(new Runnable() { public void run() { if (e.isEditing()) { editLabel.setIcon(editing); } else { editLabel.setIcon(empty); } } }); } } public void showTransactionStatus(boolean b) { if (b) { transactionLabel.setIcon(transaction); } else { transactionLabel.setIcon(empty); } } public void showLocksStatus(boolean b) { if (b) { lockLabel.setIcon(locking); } else { lockLabel.setIcon(empty); } } public void showDataChange()// blink for 1 seconds { synchronized (flashDataChange) { flashDataChange.setHideTime(System.currentTimeMillis() + 1000); if (!flashDataChange.isRunning()) { flashDataChange.setRunning(true); getScheduledExecutor().execute(flashDataChange); } } } class FlashDataChange implements Runnable { private static final long flashTime = 400; private long hideTime; private boolean visible; private boolean running; void setHideTime(long hideTime) { this.hideTime = hideTime; } void setRunning(boolean running) { this.running = running; } boolean isRunning() { return running; } public void run() { visible = true; dataChangeLabel.setIcon(data_change); while (true) { synchronized (this) { if (System.currentTimeMillis() > hideTime) { running = false; dataChangeLabel.setIcon(empty); visible = false; break; } } try { Thread.sleep(visible ? flashTime : flashTime / 2); } catch (InterruptedException e) { // Ignore (this is really not worth logging). } if (visible) { dataChangeLabel.setIcon(empty); } else { dataChangeLabel.setIcon(data_change); } visible = !visible; } } } /* * @see com.servoy.j2db.IMessagesCallback#refresh() */ public void messagesLoaded() { for (String jre_key : Messages.JRE_DEFAULT_KEYS) { String message = Messages.getString(jre_key); if (!Messages.JRE_DEFAULT_KEY_VALUE.equals(message)) UIManager.put(jre_key, message); } if (getCmdManager() != null) { ((CmdManager)getCmdManager()).i18nRefresh(); } ClientState.READY = Messages.getString("servoy.general.status.ready"); } /* * @see IServiceProvider#setLocale(Locale) */ public void setLocale(Locale locale) { Locale old = Locale.getDefault(); if (!old.equals(locale)) { Locale.setDefault(locale); Messages.loadInternal(this, getFoundSetManager()); J2DBGlobals.firePropertyChange(this, "locale", old, locale); } } public Locale getLocale() { return Locale.getDefault(); } public TimeZone getTimeZone() { return TimeZone.getDefault(); } public synchronized void setTimeZone(TimeZone zone) { if (getTimeZone().equals(zone)) return; TimeZone old = getTimeZone(); TimeZone.setDefault(zone); J2DBGlobals.firePropertyChange(this, "timeZone", old, zone); //$NON-NLS-1$ } /* * @see IServiceProvider#getI18NMessage(String,Object[]) */ public String getI18NMessage(String i18nKey, Object[] array) { if (array != null && array.length != 0) { return Messages.getString(i18nKey, array); } return Messages.getString(i18nKey); } public String getI18NMessage(String i18nKey) { return Messages.getString(i18nKey); } public void setI18NMessage(String key, String value) { Messages.setI18nScriptingMessage(key, value); } /* * @see IServiceProvider#getI18NMessageIfPrefixed(String,Object[]) */ public String getI18NMessageIfPrefixed(String i18nKey) { return Messages.getStringIfPrefix(i18nKey); } private String i18nColumnName; private String[] i18nColunmValue; public void setI18NMessagesFilter(String columnname, String[] value) { this.i18nColumnName = columnname; this.i18nColunmValue = value; refreshI18NMessages(); } public String getI18NColumnNameFilter() { return i18nColumnName; } public String[] getI18NColumnValueFilter() { return i18nColunmValue; } public ResourceBundle getResourceBundle(Locale locale) { return new MessagesResourceBundle(this, locale == null ? getLocale() : locale, i18nColumnName, i18nColunmValue, getSolution().getSolutionID()); } /* * @see com.servoy.j2db.ClientState#refreshI18NMessages() */ @Override public void refreshI18NMessages() { Messages.loadInternal(this, getFoundSetManager()); } @Override public boolean isRunningRemote() { return WebStart.isRunningWebStart(); } @Override public URL getServerURL() { String server_url = System.getProperty("servoy.server_url"); //$NON-NLS-1$ if (server_url != null) { try { return new URL(server_url); } catch (MalformedURLException e) { Debug.error(e); } } return WebStart.getWebStartURL(); } private JDialog disconnectDialog; private IDataRendererFactory< ? > dataRenderFactory; /* * @see disconnectFromServer() */ private void closeDisconnectDialog() { if (!isConnected()) { int option = JOptionPane.showConfirmDialog(disconnectDialog, Messages.getString("servoy.client.serverdisconnect.optionpane.question"), //$NON-NLS-1$ Messages.getString("servoy.client.serverdisconnect.optionpane.title"), JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE); //$NON-NLS-1$ if (option == JOptionPane.YES_OPTION) { saveSettings(); exitHard(1); } } } public boolean isConnected() { return rmiFactoryFactory == null || rmiFactoryFactory.isConnected(); } /** * @see com.servoy.j2db.ClientState#testClientRegistered(Object) */ @Override protected boolean testClientRegistered(Object exception) { Object ex = exception; while (ex instanceof Exception && !(ex instanceof ServoyException)) { ex = ((Exception)ex).getCause(); } if (isConnected() && ex instanceof ServoyException && (((ServoyException)ex).getErrorCode() == ServoyException.InternalCodes.CLIENT_NOT_REGISTERED || ((ServoyException)ex).getErrorCode() == ServoyException.InternalCodes.INVALID_RMI_SERVER_CONNECTION)) { if (rmiFactoryFactory != null) { if (!reconnecting) { Debug.error("Test exception, calling disconnect in thread: " + Thread.currentThread().getName(), (Exception)exception); rmiFactoryFactory.disconnect(); return false; } } else { reconnectedToServer(); } disconnectedFromServer(); return false; } return isConnected(); } /* * @see com.servoy.j2db.util.rmi.IReconnectListener#disconnected() */ public void disconnectedFromServer() { if (disconnectDialog == null) { disconnectDialog = new JDialog(this.getMainApplicationFrame(), Messages.getString("servoy.client.serverdisconnect.dialog.title"), true); disconnectDialog.setPreferredSize(new Dimension(400, 80)); disconnectDialog.setLayout(new GridBagLayout()); GridBagConstraints gbc = new GridBagConstraints(); gbc.gridx = 0; gbc.gridy = 0; gbc.anchor = GridBagConstraints.NORTH; disconnectDialog.getContentPane().add(new JLabel(Messages.getString("servoy.client.serverdisconnect.dialog.label")), gbc); // for Linux, a button is also added so that the user can close the disconnect dialog; the action is the same as for window close gbc.gridx = 0; gbc.gridy = 1; gbc.anchor = GridBagConstraints.SOUTH; JButton cancelButton = new JButton(Messages.getString("servoy.button.close")); //$NON-NLS-1$ cancelButton.setFont(new Font("arial", Font.PLAIN, 11)); cancelButton.setPreferredSize(new Dimension(100, 20)); cancelButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent event) { closeDisconnectDialog(); } }); disconnectDialog.add(cancelButton, gbc); disconnectDialog.addWindowListener(new WindowAdapter() { @Override public void windowClosing(WindowEvent e) { closeDisconnectDialog(); } }); disconnectDialog.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE); disconnectDialog.pack(); } Runnable dialogShower = new Runnable() { public void run() { if (!isConnected()) { if (Debug.tracing()) { Debug.trace("Setting disconnect dialog to true."); } disconnectDialog.setLocationRelativeTo(getMainApplicationFrame()); disconnectDialog.setVisible(true); } } }; if (isEventDispatchThread()) { dialogShower.run(); } else { invokeLater(dialogShower); } } private volatile boolean reconnecting; /* * @see com.servoy.j2db.util.rmi.IReconnectListener#reconnect() */ public void reconnectedToServer() { if (reconnecting) return; getScheduledExecutor().execute(new Runnable() { @SuppressWarnings("nls") public void run() { if (reconnecting) return; reconnecting = true; final String prevClientId = getClientInfo().getClientId(); try { if (Debug.tracing()) { Debug.trace(Thread.currentThread().getName() + ", Reconnecting to the server, unexporting the current client"); } try { // Try to force unexport the object. UnicastRemoteObject.unexportObject(userClient, true); } catch (Exception e1) { // ignore if not } // Create new clientinfo object. So that it can have different // addresses.. getClientInfo().initHostInfo(); // recreate the UserClient createUserClient(); bindUserClient(); try { registerClient(userClient); } catch (Exception e) { if (isConnected()) { // Remote client object no longer exists on app server, must have been restarted Debug.error("Error reregistering client", e); invokeAndWait(new Runnable() { public void run() { JOptionPane.showMessageDialog(getMainApplicationFrame(), Messages.getString("servoy.client.message.error.registerclient"), Messages.getString("servoy.client.message.clientregister"), JOptionPane.ERROR_MESSAGE); exitHard(1); } }); } else { reconnecting = false; disconnectedFromServer(); reconnectedToServer(); return; } } } finally { reconnecting = false; } if (prevClientId == null || !prevClientId.equals(getClientInfo().getClientId())) { Runnable closeAndLogout = new Runnable() { public void run() { JOptionPane.showMessageDialog(disconnectDialog, Messages.getString("servoy.client.serverdisconnect.restarting.solution"), Messages.getString("servoy.client.serverdisconnect.restarting.solution.title"), JOptionPane.INFORMATION_MESSAGE); if (Debug.tracing()) { Debug.trace("Client reconnected with id " + getClientID() + " from id " + prevClientId); } if (Debug.tracing()) { Debug.trace("Setting disconnect dialog to false."); } disconnectDialog.setVisible(false); closeSolution(true, startupArguments); // logout to make sure the login solution is reloaded in case the main solution needs state from the login solution logout(null); } }; if (((FoundSetManager)getFoundSetManager()).hasLocks(null) || ((FoundSetManager)getFoundSetManager()).hasTransaction() || ((FoundSetManager)getFoundSetManager()).hasClientDataSources()) { try { getDataServer().logMessage("Client reconnected with id " + getClientID() + " from id " + prevClientId + ", client needs to restart"); } catch (Exception ex) { // ignore } invokeLater(closeAndLogout); return; } // if logged in, login again if (getClientInfo().getUserUid() != null) { try { authenticate(new Credentials(getClientInfo().getClientId(), getClientInfo().getAuthenticatorType(), getClientInfo().getAuthenticatorMethod(), getClientInfo().getJsCredentials())); } catch (RepositoryException e) { Debug.error(e); } if (getClientInfo().getUserUid() == null) { try { getDataServer().logMessage( "Client reconnected with id " + getClientID() + " from id " + prevClientId + ", relogin with old credentials failed, restarting client"); } catch (Exception ex) { // ignore } invokeLater(closeAndLogout); return; } } try { ((FoundSetManager)getFoundSetManager()).registerClientTables(null); } catch (Exception e) { if (isConnected()) { // Remote client object no longer exists on app server, must have been restarted Debug.error("Error reregistering client", e); //$NON-NLS-1$ invokeAndWait(new Runnable() { public void run() { JOptionPane.showMessageDialog(getMainApplicationFrame(), Messages.getString("servoy.client.message.error.registerclient"), Messages.getString("servoy.client.message.clientregister"), JOptionPane.ERROR_MESSAGE); exitHard(1); } }); } else { disconnectedFromServer(); reconnectedToServer(); return; } } ((FoundSetManager)getFoundSetManager()).flushCachedDatabaseData(null); } if (Debug.tracing()) { Debug.trace("Client reconnected with id " + getClientID() + " from id " + prevClientId); } invokeLater(new Runnable() { public void run() { if (Debug.tracing()) { Debug.trace("Setting disconnect dialog to false."); } disconnectDialog.setVisible(false); } }); } }); } public boolean isEventDispatchThread() { return SwingUtilities.isEventDispatchThread(); } @Override protected void doInvokeLater(Runnable r) { SwingUtilities.invokeLater(r); } public void invokeAndWait(Runnable r) { if (isEventDispatchThread()) { r.run(); } else { try { SwingUtilities.invokeAndWait(r); } catch (Exception e) { Debug.error("Error calling invoke an wait for a runnable", e); } } } @Override public void activateSolutionMethod(String globalMethodName, StartupArguments argumentsScope) { try { ((IClientPluginAccess)getPluginAccess()).executeMethod(null, globalMethodName, new Object[] { argumentsScope.getFirstArgument(), argumentsScope.toJSMap() }, true); getMainApplicationFrame().toFront(); } catch (Exception e) { Debug.error(e); } } /** * @see com.servoy.j2db.IApplication#getItemFactory() */ public ItemFactory getItemFactory() { if (itemFactory == null) { itemFactory = new SwingItemFactory(this); } return itemFactory; } public IDataRendererFactory< ? > getDataRenderFactory() { if (dataRenderFactory == null) { dataRenderFactory = new DataRendererFactory(); } return dataRenderFactory; } /** * @see com.servoy.j2db.IApplication#isHeadless() */ public boolean isHeadless() { return false; } public RendererParentWrapper getPrintingRendererParent() { return new RendererParentWrapper(getEditLabel()); } public boolean showURL(String url, String target, String target_options, int timeout, boolean closeDialogs) { // mail to doesn't work in showUrl through webstart if (WebStart.isRunningWebStart() && url.toLowerCase().startsWith("http")) { try { return WebStart.showURL(new URL(url)); } catch (Exception ex) { Debug.error(ex); // Service is not supported? } } try { BrowserLauncher.openURL(url); return true; } catch (Throwable e)//catch all for apple mac { Debug.error(e); WebStart.setClipboardContent(url); reportWarningInStatus("If running in client this url is shown in browser: " + url + " ,the url is pasted on your clipboard"); return false; } } public Dimension getScreenSize() { try { int height = Toolkit.getDefaultToolkit().getScreenSize().height; int width = Toolkit.getDefaultToolkit().getScreenSize().width; return new Dimension(width, height); } catch (Exception e) { Debug.trace("Ignore, assume headless exc: " + e.getMessage()); } return new Dimension(0, 0); } protected LoginDialog createLoginDialog() { return new LoginDialog(frame, this); } public String showI18NDialog(String preselect_key, String preselect_language) { I18NDialog sfd = (I18NDialog)getWindow("I18NDialog_main"); //$NON-NLS-1$ JFrame window = getMainApplicationFrame(); if (sfd == null || sfd.getOwner() != window) { if (sfd != null) sfd.setVisible(false); sfd = new I18NDialog(this, window, true); registerWindow("I18NDialog_main", sfd); } else { sfd.setEndUser(true); } sfd.setModal(true); String i18nkey = sfd.showDialog(preselect_key, preselect_language); sfd.setModal(false); if (i18nkey != null && i18nkey.length() != 0) { return i18nkey; } return null; } public Date showCalendar(String pattern, Date date) { JDateChooser chooser = (JDateChooser)getWindow("JDateChooser"); //$NON-NLS-1$ Window windowParent = getMainApplicationFrame(); if (chooser == null || SwingUtilities.getWindowAncestor(chooser) != windowParent) { if (chooser != null) { chooser.dispose(); chooser = null; registerWindow("JDateChooser", chooser); } String dateFormat = TagResolver.getFormatString(Date.class, getSettings()); chooser = new JDateChooser((JFrame)windowParent, getI18NMessage("servoy.dateChooser.selectDate"), //$NON-NLS-1$ dateFormat); registerWindow("JDateChooser", chooser); } if (date != null) { Calendar cal = chooser.getSelectedDate(); cal.setTime(date); chooser.updateCalendar(cal); } if (chooser.showDialog(pattern) == JDateChooser.ACCEPT_OPTION) { Calendar selectedDate = chooser.getSelectedDate(); return selectedDate.getTime(); } return null; } private Window getUserWindow(String windowName) { Window w = null; if (windowName == null) { // no name specified; use default dialog if it is showing, or else the main application window w = getWindow(IFormManagerInternal.USER_WINDOW_PREFIX + FormManager.DEFAULT_DIALOG_NAME); if (w == null || (!w.isShowing())) { w = getMainApplicationFrame(); } } else { // we use the window with the given name, if found w = getWindow(IFormManagerInternal.USER_WINDOW_PREFIX + windowName); } return w; } public void beep() { Toolkit.getDefaultToolkit().beep(); } public void setClipboardContent(String string) { WebStart.setClipboardContent(string); } public String getClipboardString() { return WebStart.getClipboardString(); } private KeyEventDispatcher dispatcher = null; public void setNumpadEnterAsFocusNextEnabled(boolean enabled) { if (dispatcher == null) { dispatcher = new KeyEventDispatcher() { public boolean dispatchKeyEvent(KeyEvent e) { if (e.getKeyLocation() == KeyEvent.KEY_LOCATION_NUMPAD && e.getKeyCode() == 10) //numpad enter key { e.setKeyChar('\t'); e.setKeyCode(9); } return false; } }; } if (enabled) { KeyboardFocusManager.getCurrentKeyboardFocusManager().addKeyEventDispatcher(dispatcher); } else { KeyboardFocusManager.getCurrentKeyboardFocusManager().removeKeyEventDispatcher(dispatcher); dispatcher = null; } } // special hack for FixedJTable private int paintTableImmediately = 0; public void setPaintTableImmediately(boolean b) { if (b) paintTableImmediately--; else paintTableImmediately++; } public int getPaintTableImmediately() { return paintTableImmediately; } public String showColorChooser(String originalColor) { Color org = PersistHelper.createColor(originalColor); CustomColorChooserDialog ccd = (CustomColorChooserDialog)getWindow("CustomColorChooserDialog"); //$NON-NLS-1$ if (ccd == null || ccd.getOwner() != getMainApplicationFrame()) { ccd = new CustomColorChooserDialog(getMainApplicationFrame(), this); registerWindow("CustomColorChooserDialog", ccd); } Color c = ccd.showDialog(org); if (c != null) { return PersistHelper.createColorString(c); } return null; } public String showFontChooser(String fontString) { Font font = PersistHelper.createFont(fontString); JFontChooser chooser = new JFontChooser(getMainApplicationFrame(), font); int but = chooser.showDialog(getMainApplicationFrame(), getI18NMessage("servoy.fontchooser.title"), false); //$NON-NLS-1$ if (but == IPropertyEditorDialog.OK_OPTION) { Font f = chooser.getSelectedFont(); if (f != null) { return PersistHelper.createFontString(f); } } return null; } // these methods are added because this class extends JPanel which is serializable private void writeObject(ObjectOutputStream stream) throws IOException { throw new IOException("A Servoy client is not serializable"); //$NON-NLS-1$ } private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException { throw new IOException("A Servoy client is not serializable"); //$NON-NLS-1$ } private boolean isFormElementsEditableInFindMode = true; /* * @see com.servoy.j2db.IApplication#setFormElementsEditableInFindMode(boolean) */ public void setFormElementsEditableInFindMode(boolean editable) { isFormElementsEditableInFindMode = editable; } /* * @see com.servoy.j2db.IApplication#isFormElementsEditableInFindMode() */ public boolean isFormElementsEditableInFindMode() { return isFormElementsEditableInFindMode; } @Override public String getFormNameFor(IComponent component) { if (component instanceof Component) { Container parent = ((Component)component).getParent(); while (!(parent instanceof IFormUI)) { parent = parent.getParent(); } return ((IFormUI)parent).getController().getName(); } return ""; } }