From f2e3722df9676436680afc0f1991e91e1696fb99 Mon Sep 17 00:00:00 2001 From: Marc Englund Date: Mon, 19 Nov 2007 14:03:05 +0000 Subject: [PATCH] MASS REFORMAT. According to http://toolkit.intra.itmill.com/trac/itmilltoolkit/wiki/CodingConventions svn changeset:2864/svn branch:trunk --- src/com/itmill/toolkit/Application.java | 1983 +++---- src/com/itmill/toolkit/data/Buffered.java | 505 +- .../toolkit/data/BufferedValidatable.java | 22 +- src/com/itmill/toolkit/data/Container.java | 1410 ++--- src/com/itmill/toolkit/data/Item.java | 314 +- src/com/itmill/toolkit/data/Property.java | 736 +-- src/com/itmill/toolkit/data/Validatable.java | 168 +- src/com/itmill/toolkit/data/Validator.java | 276 +- .../itmill/toolkit/data/util/BeanItem.java | 216 +- .../util/ContainerHierarchicalWrapper.java | 1177 ++-- .../data/util/ContainerOrderedWrapper.java | 1002 ++-- .../data/util/FilesystemContainer.java | 1639 +++--- .../data/util/HierarchicalContainer.java | 532 +- .../toolkit/data/util/IndexedContainer.java | 3319 +++++------ .../toolkit/data/util/MethodProperty.java | 1528 ++--- .../toolkit/data/util/ObjectProperty.java | 667 +-- .../toolkit/data/util/PropertysetItem.java | 562 +- .../toolkit/data/util/QueryContainer.java | 1163 ++-- .../data/validator/CompositeValidator.java | 499 +- .../toolkit/data/validator/NullValidator.java | 160 +- .../data/validator/StringLengthValidator.java | 324 +- src/com/itmill/toolkit/demo/BrowserDemo.java | 89 +- .../toolkit/demo/BufferedComponents.java | 103 +- src/com/itmill/toolkit/demo/CachingDemo.java | 80 +- src/com/itmill/toolkit/demo/Calc.java | 209 +- .../itmill/toolkit/demo/CustomLayoutDemo.java | 220 +- src/com/itmill/toolkit/demo/FilterSelect.java | 123 +- src/com/itmill/toolkit/demo/HelloWorld.java | 47 +- .../itmill/toolkit/demo/KeyboardShortcut.java | 196 +- src/com/itmill/toolkit/demo/LayoutDemo.java | 226 +- src/com/itmill/toolkit/demo/ModalWindow.java | 125 +- .../itmill/toolkit/demo/NotificationDemo.java | 122 +- src/com/itmill/toolkit/demo/Parameters.java | 156 +- .../toolkit/demo/QueryContainerDemo.java | 317 +- src/com/itmill/toolkit/demo/SelectDemo.java | 88 +- src/com/itmill/toolkit/demo/TableDemo.java | 322 +- .../itmill/toolkit/demo/TreeFilesystem.java | 140 +- .../toolkit/demo/TreeFilesystemContainer.java | 112 +- .../itmill/toolkit/demo/UpgradingSample.java | 263 +- .../itmill/toolkit/demo/WindowedDemos.java | 112 +- .../toolkit/demo/colorpicker/ColorPicker.java | 98 +- .../colorpicker/ColorPickerApplication.java | 74 +- .../gwt/client/ColorPickerWidgetSet.java | 26 +- .../gwt/client/ui/GwtColorPicker.java | 145 +- .../gwt/client/ui/IColorPicker.java | 109 +- .../demo/reservation/CalendarDemo.java | 170 +- .../demo/reservation/CalendarField.java | 597 +- .../toolkit/demo/reservation/GoogleMap.java | 424 +- .../reservation/ReservationApplication.java | 651 +-- .../ResourceNotAvailableException.java | 6 +- .../reservation/ResourceSelectorPanel.java | 184 +- .../toolkit/demo/reservation/SampleDB.java | 1048 ++-- .../gwt/client/ReservationWidgetSet.java | 48 +- .../gwt/client/ui/ICalendarField.java | 497 +- .../reservation/gwt/client/ui/IGoogleMap.java | 158 +- .../demo/util/SampleCalendarDatabase.java | 283 +- .../toolkit/demo/util/SampleDatabase.java | 293 +- .../toolkit/demo/util/SampleDirectory.java | 98 +- src/com/itmill/toolkit/event/Action.java | 284 +- src/com/itmill/toolkit/event/EventRouter.java | 273 +- .../itmill/toolkit/event/ListenerMethod.java | 990 ++-- .../toolkit/event/MethodEventSource.java | 251 +- .../itmill/toolkit/event/ShortcutAction.java | 190 +- .../launcher/ITMillToolkitDesktopMode.java | 323 +- .../launcher/ITMillToolkitHostedMode.java | 246 +- .../launcher/ITMillToolkitWebMode.java | 264 +- .../launcher/util/BrowserLauncher.java | 137 +- .../toolkit/service/ApplicationContext.java | 144 +- .../toolkit/service/FileTypeResolver.java | 684 +-- .../toolkit/terminal/ApplicationResource.java | 82 +- .../toolkit/terminal/ClassResource.java | 299 +- .../terminal/CompositeErrorMessage.java | 304 +- .../toolkit/terminal/DownloadStream.java | 360 +- .../itmill/toolkit/terminal/ErrorMessage.java | 118 +- .../toolkit/terminal/ExternalResource.java | 98 +- .../itmill/toolkit/terminal/FileResource.java | 252 +- .../itmill/toolkit/terminal/KeyMapper.java | 160 +- .../toolkit/terminal/PaintException.java | 48 +- .../itmill/toolkit/terminal/PaintTarget.java | 644 +-- .../itmill/toolkit/terminal/Paintable.java | 215 +- .../toolkit/terminal/ParameterHandler.java | 48 +- src/com/itmill/toolkit/terminal/Resource.java | 12 +- .../itmill/toolkit/terminal/Scrollable.java | 140 +- src/com/itmill/toolkit/terminal/Sizeable.java | 296 +- .../toolkit/terminal/StreamResource.java | 374 +- .../itmill/toolkit/terminal/SystemError.java | 204 +- src/com/itmill/toolkit/terminal/Terminal.java | 78 +- .../toolkit/terminal/ThemeResource.java | 135 +- .../itmill/toolkit/terminal/URIHandler.java | 46 +- .../itmill/toolkit/terminal/UploadStream.java | 50 +- .../itmill/toolkit/terminal/UserError.java | 246 +- .../toolkit/terminal/VariableOwner.java | 175 +- .../gwt/client/ApplicationConnection.java | 1088 ++-- .../toolkit/terminal/gwt/client/Console.java | 8 +- .../terminal/gwt/client/Container.java | 76 +- .../gwt/client/ContainerResizedListener.java | 16 +- .../terminal/gwt/client/DateLocale.java | 107 +- .../terminal/gwt/client/DateTimeService.java | 473 +- .../terminal/gwt/client/DebugConsole.java | 114 +- .../gwt/client/LocaleNotLoadedException.java | 14 +- .../terminal/gwt/client/LocaleService.java | 327 +- .../terminal/gwt/client/NullConsole.java | 16 +- .../terminal/gwt/client/Paintable.java | 2 +- .../terminal/gwt/client/StyleConstants.java | 10 +- .../toolkit/terminal/gwt/client/UIDL.java | 862 +-- .../toolkit/terminal/gwt/client/Util.java | 132 +- .../terminal/gwt/client/WidgetSet.java | 40 +- .../terminal/gwt/client/ui/Action.java | 94 +- .../terminal/gwt/client/ui/AlignmentInfo.java | 132 +- .../terminal/gwt/client/ui/CalendarEntry.java | 226 +- .../terminal/gwt/client/ui/CalendarPanel.java | 831 +-- .../terminal/gwt/client/ui/ICheckBox.java | 176 +- .../gwt/client/ui/ICustomComponent.java | 46 +- .../terminal/gwt/client/ui/ICustomLayout.java | 842 +-- .../terminal/gwt/client/ui/IDateField.java | 357 +- .../gwt/client/ui/IDateFieldCalendar.java | 20 +- .../terminal/gwt/client/ui/IExpandLayout.java | 364 +- .../terminal/gwt/client/ui/IFilterSelect.java | 38 +- .../toolkit/terminal/gwt/client/ui/IForm.java | 49 +- .../terminal/gwt/client/ui/ILabel.java | 69 +- .../client/ui/IOrderedLayoutHorizontal.java | 6 +- .../gwt/client/ui/IOrderedLayoutVertical.java | 6 +- .../terminal/gwt/client/ui/IPanel.java | 281 +- .../gwt/client/ui/IPasswordField.java | 6 +- .../gwt/client/ui/IProgressIndicator.java | 88 +- .../terminal/gwt/client/ui/ISlider.java | 902 +-- .../terminal/gwt/client/ui/ISplitPanel.java | 662 +-- .../gwt/client/ui/ISplitPanelHorizontal.java | 6 +- .../gwt/client/ui/ISplitPanelVertical.java | 6 +- .../terminal/gwt/client/ui/ITablePaging.java | 785 +-- .../terminal/gwt/client/ui/ITabsheet.java | 423 +- .../gwt/client/ui/ITabsheetPanel.java | 156 +- .../terminal/gwt/client/ui/ITextField.java | 175 +- .../terminal/gwt/client/ui/ITextualDate.java | 427 +- .../gwt/client/ui/IUnknownComponent.java | 41 +- .../terminal/gwt/client/ui/IUpload.java | 219 +- .../toolkit/terminal/gwt/client/ui/IView.java | 288 +- .../terminal/gwt/client/ui/IWindow.java | 716 +-- .../terminal/gwt/client/ui/MarginInfo.java | 99 +- .../terminal/gwt/client/ui/MenuItem.java | 299 +- .../gwt/client/ui/ShortcutActionHandler.java | 259 +- .../toolkit/terminal/gwt/client/ui/Table.java | 6 +- .../toolkit/terminal/gwt/client/ui/Time.java | 500 +- .../terminal/gwt/client/ui/TreeAction.java | 86 +- .../terminal/gwt/client/ui/TreeImages.java | 30 +- .../client/ui/richtextarea/IRichTextArea.java | 78 +- .../ui/richtextarea/RichTextToolbar.java | 789 +-- .../terminal/gwt/client/util/DateLocale.java | 94 +- .../terminal/gwt/client/util/Pattern.java | 302 +- .../gwt/client/util/SimpleDateFormat.java | 301 +- .../gwt/client/util/SimpleDateParser.java | 302 +- .../gwt/server/CommunicationManager.java | 2088 +++---- .../terminal/gwt/server/HttpUploadStream.java | 144 +- .../terminal/gwt/server/JsonPaintTarget.java | 2075 +++---- .../gwt/server/WebApplicationContext.java | 513 +- .../terminal/gwt/server/WebBrowser.java | 161 +- .../terminal/web/ApplicationServlet.java | 14 +- .../itmill/toolkit/tests/BasicRandomTest.java | 847 +-- .../toolkit/tests/RandomLayoutStress.java | 319 +- .../itmill/toolkit/tests/TableSelectTest.java | 216 +- src/com/itmill/toolkit/tests/TestBench.java | 355 +- .../toolkit/tests/TestCaptionWrapper.java | 293 +- .../tests/TestComponentsAndLayouts.java | 799 +-- .../itmill/toolkit/tests/TestDateField.java | 70 +- .../toolkit/tests/TestForAlignments.java | 100 +- ...cationLayoutThatUsesWholeBrosersSpace.java | 73 +- .../tests/TestForBasicApplicationLayout.java | 166 +- .../tests/TestForChildComponentRendering.java | 130 +- .../tests/TestForContainerFilterable.java | 142 +- ...tForGridLayoutChildComponentRendering.java | 146 +- .../tests/TestForMultipleStyleNames.java | 96 +- .../toolkit/tests/TestForNativeWindowing.java | 217 +- .../tests/TestForPreconfiguredComponents.java | 338 +- .../toolkit/tests/TestForRichTextEditor.java | 53 +- ...ablesInitialColumnWidthLogicRendering.java | 185 +- .../itmill/toolkit/tests/TestForTrees.java | 281 +- .../itmill/toolkit/tests/TestForUpload.java | 603 +- .../toolkit/tests/TestForWindowOpen.java | 56 +- .../toolkit/tests/TestForWindowing.java | 94 +- src/com/itmill/toolkit/tests/TestIFrames.java | 44 +- .../tests/TestSetVisibleAndCaching.java | 112 +- .../itmill/toolkit/tests/TestSplitPanel.java | 24 +- .../toolkit/tests/UsingObjectsInSelect.java | 192 +- .../toolkit/tests/featurebrowser/Feature.java | 352 +- .../tests/featurebrowser/FeatureBrowser.java | 608 +- .../featurebrowser/FeatureBuffering.java | 138 +- .../tests/featurebrowser/FeatureButton.java | 108 +- .../featurebrowser/FeatureContainers.java | 144 +- .../featurebrowser/FeatureCustomLayout.java | 127 +- .../featurebrowser/FeatureDateField.java | 164 +- .../tests/featurebrowser/FeatureEmbedded.java | 153 +- .../tests/featurebrowser/FeatureForm.java | 317 +- .../featurebrowser/FeatureGridLayout.java | 121 +- .../tests/featurebrowser/FeatureItems.java | 130 +- .../tests/featurebrowser/FeatureLabel.java | 123 +- .../tests/featurebrowser/FeatureLink.java | 79 +- .../featurebrowser/FeatureOrderedLayout.java | 125 +- .../tests/featurebrowser/FeaturePanel.java | 109 +- .../featurebrowser/FeatureParameters.java | 280 +- .../featurebrowser/FeatureProperties.java | 140 +- .../tests/featurebrowser/FeatureSelect.java | 145 +- .../tests/featurebrowser/FeatureTabSheet.java | 115 +- .../tests/featurebrowser/FeatureTable.java | 353 +- .../featurebrowser/FeatureTextField.java | 111 +- .../tests/featurebrowser/FeatureTree.java | 303 +- .../tests/featurebrowser/FeatureUpload.java | 241 +- .../tests/featurebrowser/FeatureUtil.java | 40 +- .../featurebrowser/FeatureValidators.java | 130 +- .../tests/featurebrowser/FeatureWindow.java | 255 +- .../featurebrowser/FeaturesApplication.java | 43 +- .../tests/featurebrowser/IntroBasic.java | 114 +- .../tests/featurebrowser/IntroComponents.java | 90 +- .../featurebrowser/IntroDataHandling.java | 112 +- .../tests/featurebrowser/IntroDataModel.java | 116 +- .../featurebrowser/IntroItemContainers.java | 114 +- .../tests/featurebrowser/IntroLayouts.java | 118 +- .../tests/featurebrowser/IntroTerminal.java | 54 +- .../tests/featurebrowser/IntroWelcome.java | 292 +- .../tests/featurebrowser/PropertyPanel.java | 972 ++-- .../tests/magi/DefaultButtonExample.java | 149 +- .../toolkit/tests/magi/EmbeddedButton.java | 61 +- .../itmill/toolkit/tests/magi/MyUploader.java | 106 +- .../itmill/toolkit/tests/magi/SSNField.java | 168 +- .../toolkit/tests/magi/SelectExample.java | 202 +- .../toolkit/tests/magi/TableExample.java | 84 +- .../itmill/toolkit/tests/magi/TheButton.java | 32 +- .../itmill/toolkit/tests/magi/TheButtons.java | 45 +- .../toolkit/tests/magi/TheButtons2.java | 43 +- .../toolkit/tests/magi/TheButtons3.java | 58 +- .../toolkit/tests/magi/WindowOpener.java | 123 +- .../itmill/toolkit/ui/AbstractComponent.java | 1834 +++--- .../ui/AbstractComponentContainer.java | 327 +- src/com/itmill/toolkit/ui/AbstractField.java | 1856 +++--- src/com/itmill/toolkit/ui/AbstractLayout.java | 358 +- .../itmill/toolkit/ui/BaseFieldFactory.java | 158 +- src/com/itmill/toolkit/ui/Button.java | 581 +- src/com/itmill/toolkit/ui/Component.java | 744 +-- .../itmill/toolkit/ui/ComponentContainer.java | 416 +- .../itmill/toolkit/ui/CustomComponent.java | 915 +-- src/com/itmill/toolkit/ui/CustomLayout.java | 383 +- src/com/itmill/toolkit/ui/Embedded.java | 1054 ++-- src/com/itmill/toolkit/ui/ExpandLayout.java | 202 +- src/com/itmill/toolkit/ui/Field.java | 150 +- src/com/itmill/toolkit/ui/FieldFactory.java | 96 +- src/com/itmill/toolkit/ui/Form.java | 1736 +++--- src/com/itmill/toolkit/ui/FormLayout.java | 6 +- src/com/itmill/toolkit/ui/GridLayout.java | 1993 +++---- src/com/itmill/toolkit/ui/Label.java | 974 ++-- src/com/itmill/toolkit/ui/Layout.java | 45 +- src/com/itmill/toolkit/ui/Link.java | 496 +- src/com/itmill/toolkit/ui/OptionGroup.java | 40 +- src/com/itmill/toolkit/ui/OrderedLayout.java | 633 ++- src/com/itmill/toolkit/ui/Panel.java | 1097 ++-- .../itmill/toolkit/ui/ProgressIndicator.java | 426 +- src/com/itmill/toolkit/ui/RichTextArea.java | 13 +- src/com/itmill/toolkit/ui/Slider.java | 858 +-- src/com/itmill/toolkit/ui/SplitPanel.java | 484 +- src/com/itmill/toolkit/ui/TabSheet.java | 1155 ++-- src/com/itmill/toolkit/ui/Table.java | 5047 ++++++++--------- src/com/itmill/toolkit/ui/TextField.java | 829 +-- src/com/itmill/toolkit/ui/Tree.java | 1902 ++++--- src/com/itmill/toolkit/ui/TwinColSelect.java | 76 +- src/com/itmill/toolkit/ui/Upload.java | 1505 ++--- src/com/itmill/toolkit/ui/Window.java | 2507 ++++---- 264 files changed, 50187 insertions(+), 48860 deletions(-) diff --git a/src/com/itmill/toolkit/Application.java b/src/com/itmill/toolkit/Application.java index 42412569e9..1ae6dd98d7 100644 --- a/src/com/itmill/toolkit/Application.java +++ b/src/com/itmill/toolkit/Application.java @@ -28,13 +28,8 @@ package com.itmill.toolkit; -import com.itmill.toolkit.service.ApplicationContext; -import com.itmill.toolkit.terminal.*; -import com.itmill.toolkit.ui.AbstractComponent; -import com.itmill.toolkit.ui.Component; -import com.itmill.toolkit.ui.Window; -import com.itmill.toolkit.ui.Component.Focusable; - +import java.net.MalformedURLException; +import java.net.URL; import java.util.Collection; import java.util.Collections; import java.util.Enumeration; @@ -46,8 +41,20 @@ import java.util.LinkedList; import java.util.Locale; import java.util.Properties; import java.util.Random; -import java.net.MalformedURLException; -import java.net.URL; + +import com.itmill.toolkit.service.ApplicationContext; +import com.itmill.toolkit.terminal.ApplicationResource; +import com.itmill.toolkit.terminal.DownloadStream; +import com.itmill.toolkit.terminal.ErrorMessage; +import com.itmill.toolkit.terminal.ParameterHandler; +import com.itmill.toolkit.terminal.SystemError; +import com.itmill.toolkit.terminal.Terminal; +import com.itmill.toolkit.terminal.URIHandler; +import com.itmill.toolkit.terminal.VariableOwner; +import com.itmill.toolkit.ui.AbstractComponent; +import com.itmill.toolkit.ui.Component; +import com.itmill.toolkit.ui.Window; +import com.itmill.toolkit.ui.Component.Focusable; /** *

@@ -105,972 +112,996 @@ import java.net.URL; */ public abstract class Application implements URIHandler, Terminal.ErrorListener { - /** - * Random window name generator. - */ - private static Random nameGenerator = new Random(); - - /** - * Application context the application is running in. - */ - private ApplicationContext context; - - /** - * The current user or null if no user has logged in. - */ - private Object user; - - /** - * Mapping from window name to window instance. - */ - private Hashtable windows = new Hashtable(); - - /** - * Main window of the application. - */ - private Window mainWindow = null; - - /** - * The application's URL. - */ - private URL applicationUrl; - - /** - * Name of the theme currently used by the application. - */ - private String theme = null; - - /** - * Application status. - */ - private boolean applicationIsRunning = false; - - /** - * Application properties. - */ - private Properties properties; - - /** - * Default locale of the application. - */ - private Locale locale; - - /** - * List of listeners listening user changes. - */ - private LinkedList userChangeListeners = null; - - /** - * Window attach listeners. - */ - private LinkedList windowAttachListeners = null; - - /** - * Window detach listeners. - */ - private LinkedList windowDetachListeners = null; - - - /** - * Application resource mapping: key <-> resource. - */ - private Hashtable resourceKeyMap = new Hashtable(); - - private Hashtable keyResourceMap = new Hashtable(); - - private long lastResourceKeyNumber = 0; - - /** - * URL the user is redirected to on application close or null if application - * is just closed - */ - private String logoutURL = null; - - private Focusable pendingFocus; - - /** - *

- * Gets a window by name. Returns null if the application is - * not running or it does not contain a window corresponding to the name. - *

- * - *

- * Since version 5.0 all windows can be referenced by their names in url - * http://host:port/foo/bar/ where - * http://host:port/foo/ is the application url as returned - * by getURL() and bar is the name of the window. - *

- * - *

- * One should note that this method can, as a side effect create new windows - * if needed by the application. This can be achieved by overriding the - * default implementation. - *

- * - *

- * The method should return null if the window does not exists (and is not - * created as a side-effect) or if the application is not running anymore - *

. - * - * @param name - * the name of the window. - * @return the window associated with the given URI or null - */ - public Window getWindow(String name) { - - // For closed app, do not give any windows - if (!isRunning()) - return null; - - // Gets the window by name - Window window = (Window) windows.get(name); - - return window; - } - - /** - * Adds a new window to the application. - * - *

- * This implicitly invokes the - * {@link com.itmill.toolkit.ui.Window#setApplication(Application)} method. - *

- * - *

- * Note that all application-level windows can be accessed by their names in - * url http://host:port/foo/bar/ where - * http://host:port/foo/ is the application url as returned - * by getURL() and bar is the name of the window. Also note - * that not all windows should be added to application - one can also add - * windows inside other windows - these windows show as smaller windows - * inside those windows. - *

- * - * @param window - * the new Window to add. If the name of the - * window is null, an unique name is - * automatically given for the window. - * @throws IllegalArgumentException - * if a window with the same name as the new window already - * exists in the application. - * @throws NullPointerException - * if the given Window is null. - */ - public void addWindow(Window window) throws IllegalArgumentException, - NullPointerException { - - // Nulls can not be added to application - if (window == null) - return; - - // Gets the naming proposal from window - String name = window.getName(); - - // Checks that the application does not already contain - // window having the same name - if (name != null && windows.containsKey(name)) { - - // If the window is already added - if (window == windows.get(name)) - return; - - // Otherwise complain - throw new IllegalArgumentException("Window with name '" - + window.getName() - + "' is already present in the application"); - } - - // If the name of the window is null, the window is automatically named - if (name == null) { - boolean accepted = false; - while (!accepted) { - - // Try another name - name = String.valueOf(Math.abs(nameGenerator.nextInt())); - if (!windows.containsKey(name)) - accepted = true; - } - window.setName(name); - } - - // Adds the window to application - windows.put(name, window); - window.setApplication(this); - - fireWindowAttachEvent(window); - - // If no main window is set, declare the window to be main window - if (getMainWindow() == null) - setMainWindow(window); - } - - /** - * Send information to all listeners about new Windows associated with this - * application. - * - * @param window - */ - private void fireWindowAttachEvent(Window window) { - // Fires the window attach event - if (windowAttachListeners != null) { - Object[] listeners = windowAttachListeners.toArray(); - WindowAttachEvent event = new WindowAttachEvent(window); - for (int i = 0; i < listeners.length; i++) { - ((WindowAttachListener) listeners[i]).windowAttached(event); - } - } - } - - /** - * Removes the specified window from the application. - * - * @param window - * the window to be removed. - */ - public void removeWindow(Window window) { - if (window != null && windows.contains(window)) { - - // Removes the window from application - windows.remove(window.getName()); - - // If the window was main window, clear it - if (getMainWindow() == window) - setMainWindow(null); - - // Removes the application from window - if (window.getApplication() == this) - window.setApplication(null); - - fireWindowDetachEvent(window); - } - } - - private void fireWindowDetachEvent(Window window) { - // Fires the window detach event - if (windowDetachListeners != null) { - Object[] listeners = windowDetachListeners.toArray(); - WindowDetachEvent event = new WindowDetachEvent(window); - for (int i = 0; i < listeners.length; i++) { - ((WindowDetachListener) listeners[i]).windowDetached(event); - } - } - } - - /** - * Gets the user of the application. - * - * @return the User of the application. - */ - public Object getUser() { - return user; - } - - /** - *

- * Sets the user of the application instance. An application instance may - * have a user associated to it. This can be set in login procedure or - * application initialization. - *

- *

- * A component performing the user login procedure can assign the user - * property of the application and make the user object available to other - * components of the application. - *

- * - * @param user - * the new user. - */ - public void setUser(Object user) { - Object prevUser = this.user; - if (user != prevUser && (user == null || !user.equals(prevUser))) { - this.user = user; - if (userChangeListeners != null) { - Object[] listeners = userChangeListeners.toArray(); - UserChangeEvent event = new UserChangeEvent(this, user, - prevUser); - for (int i = 0; i < listeners.length; i++) { - ((UserChangeListener) listeners[i]) - .applicationUserChanged(event); - } - } - } - } - - /** - * Gets the URL of the application. - * - * @return the application's URL. - */ - public URL getURL() { - return applicationUrl; - } - - /** - * Ends the Application. In effect this will cause the application stop - * returning any windows when asked. - */ - public void close() { - applicationIsRunning = false; - } - - /** - * Starts the application on the given URL.After this call the application - * corresponds to the given URL and it will return windows when asked for - * them. - * - * @param applicationUrl - * the URL the application should respond to. - * @param applicationProperties - * the Application properties as specified by the adapter. - * @param context - * the context application will be running in. - * - */ - public void start(URL applicationUrl, Properties applicationProperties, - ApplicationContext context) { - this.applicationUrl = applicationUrl; - this.properties = applicationProperties; - this.context = context; - init(); - applicationIsRunning = true; - } - - /** - * Tests if the application is running or if it has been finished. - * - * @return true if the application is running, - * false if not. - */ - public boolean isRunning() { - return applicationIsRunning; - } - - /** - * Gets the set of windows contained by the application. - * - * @return the Unmodifiable collection of windows. - */ - public Collection getWindows() { - return Collections.unmodifiableCollection(windows.values()); - } - - /** - *

- * Main initializer of the application. The init method is - * called by the framework when the application is started, and it should - * perform whatever initialization operations the application needs, such as - * creating windows and adding components to them. - *

- */ - public abstract void init(); - - /** - * Gets the application's theme. The application's theme is the default - * theme used by all the windows in it that do not explicitly specify a - * theme. If the application theme is not explicitly set, the - * null is returned. - * - * @return the name of the application's theme. - */ - public String getTheme() { - return theme; - } - - /** - * Sets the application's theme. - *

- * Note that this theme can be overridden by the windows. null - * implies the default terminal theme. - *

- * - * @param theme - * the new theme for this application. - */ - public void setTheme(String theme) { - - // Collect list of windows not having the current or future theme - LinkedList toBeUpdated = new LinkedList(); - String myTheme = this.getTheme(); - for (Iterator i = getWindows().iterator(); i.hasNext();) { - Window w = (Window) i.next(); - String windowTheme = w.getTheme(); - if ((windowTheme == null) - || (!theme.equals(windowTheme) && windowTheme - .equals(myTheme))) { - toBeUpdated.add(w); - } - } - - // Updates the theme - this.theme = theme; - - // Ask windows to update themselves - for (Iterator i = toBeUpdated.iterator(); i.hasNext();) - ((Window) i.next()).requestRepaint(); - } - - /** - * Gets the mainWindow of the application. - * - * @return the main window. - */ - public Window getMainWindow() { - return mainWindow; - } - - /** - *

- * Sets the mainWindow. If the main window is not explicitly set, the main - * window defaults to first created window. Setting window as a main window - * of this application also adds the window to this application. - *

- * - * @param mainWindow - * the mainWindow to set. - */ - public void setMainWindow(Window mainWindow) { - - addWindow(mainWindow); - this.mainWindow = mainWindow; - } - - /** - * Returns an enumeration of all the names in this application. - * - * @return an enumeration of all the keys in this property list, including - * the keys in the default property list. - * - */ - public Enumeration getPropertyNames() { - return this.properties.propertyNames(); - } - - /** - * Searches for the property with the specified name in this application. - * This method returns null if the property is not found. - * - * @param name - * the name of the property. - * @return the value in this property list with the specified key value. - */ - public String getProperty(String name) { - return this.properties.getProperty(name); - } - - /** - * Adds new resource to the application. The resource can be accessed by the - * user of the application. - * - * @param resource - * the resource to add. - */ - public void addResource(ApplicationResource resource) { - - // Check if the resource is already mapped - if (resourceKeyMap.containsKey(resource)) - return; - - // Generate key - String key = String.valueOf(++lastResourceKeyNumber); - - // Add the resource to mappings - resourceKeyMap.put(resource, key); - keyResourceMap.put(key, resource); - } - - /** - * Removes the resource from the application. - * - * @param resource - * the resource to remove. - */ - public void removeResource(ApplicationResource resource) { - Object key = resourceKeyMap.get(resource); - if (key != null) { - resourceKeyMap.remove(resource); - keyResourceMap.remove(key); - } - } - - /** - * Gets the relative uri of the resource. - * - * @param resource - * the resource to get relative location. - * @return the relative uri of the resource. - */ - public String getRelativeLocation(ApplicationResource resource) { - - // Gets the key - String key = (String) resourceKeyMap.get(resource); - - // If the resource is not registered, return null - if (key == null) - return null; - - String filename = resource.getFilename(); - if (filename == null) - return "APP/" + key + "/"; - else - return "APP/" + key + "/" + filename; - } - - /* - * @see com.itmill.toolkit.terminal.URIHandler#handleURI(URL, String) - */ - public DownloadStream handleURI(URL context, String relativeUri) { - - // If the relative uri is null, we are ready - if (relativeUri == null) - return null; - - // Resolves the prefix - String prefix = relativeUri; - int index = relativeUri.indexOf('/'); - if (index >= 0) - prefix = relativeUri.substring(0, index); - - // Handles the resource requests - if (prefix.equals("APP")) { - - // Handles the resource request - int next = relativeUri.indexOf('/', index + 1); - if (next < 0) - return null; - String key = relativeUri.substring(index + 1, next); - ApplicationResource resource = (ApplicationResource) keyResourceMap - .get(key); - if (resource != null) - return resource.getStream(); - - // Resource requests override uri handling - return null; - } - - // If the uri is in some window, handle the window uri - Window window = getWindow(prefix); - if (window != null) { - URL windowContext; - try { - windowContext = new URL(context, prefix + "/"); - String windowUri = relativeUri.length() > prefix.length() + 1 ? relativeUri - .substring(prefix.length() + 1) - : ""; - return window.handleURI(windowContext, windowUri); - } catch (MalformedURLException e) { - return null; - } - } - - // If the uri was not pointing to a window, handle the - // uri in main window - window = getMainWindow(); - if (window != null) - return window.handleURI(context, relativeUri); - - return null; - } - - /** - * Gets the default locale for this application. - * - * @return the locale of this application. - */ - public Locale getLocale() { - if (this.locale != null) - return this.locale; - return Locale.getDefault(); - } - - /** - * Sets the default locale for this application. - * - * @param locale - * the Locale object. - * - */ - public void setLocale(Locale locale) { - this.locale = locale; - } - - /** - *

- * An event that characterizes a change in the current selection. - *

- * Application user change event sent when the setUser is called to change - * the current user of the application. - * - * @version - * @VERSION@ - * @since 3.0 - */ - public class UserChangeEvent extends java.util.EventObject { - - /** - * Serial generated by eclipse. - */ - private static final long serialVersionUID = 3544951069307188281L; - - /** - * New user of the application. - */ - private Object newUser; - - /** - * Previous user of the application. - */ - private Object prevUser; - - /** - * Constructor for user change event. - * - * @param source - * the application source. - * @param newUser - * the new User. - * @param prevUser - * the previous User. - */ - public UserChangeEvent(Application source, Object newUser, - Object prevUser) { - super(source); - this.newUser = newUser; - this.prevUser = prevUser; - } - - /** - * Gets the new user of the application. - * - * @return the new User. - */ - public Object getNewUser() { - return newUser; - } - - /** - * Gets the previous user of the application. - * - * @return the previous Toolkit user, if user has not changed ever on - * application it returns null - */ - public Object getPreviousUser() { - return prevUser; - } - - /** - * Gets the application where the user change occurred. - * - * @return the Application. - */ - public Application getApplication() { - return (Application) getSource(); - } - } - - /** - * The UserChangeListener interface for listening application - * user changes. - * - * @version - * @VERSION@ - * @since 3.0 - */ - public interface UserChangeListener extends EventListener { - - /** - * The applicationUserChanged method Invoked when the - * application user has changed. - * - * @param event - * the change event. - */ - public void applicationUserChanged(Application.UserChangeEvent event); - } - - /** - * Adds the user change listener. - * - * @param listener - * the user change listener to add. - */ - public void addListener(UserChangeListener listener) { - if (userChangeListeners == null) - userChangeListeners = new LinkedList(); - userChangeListeners.add(listener); - } - - /** - * Removes the user change listener. - * - * @param listener - * the user change listener to remove. - */ - public void removeListener(UserChangeListener listener) { - if (userChangeListeners == null) - return; - userChangeListeners.remove(listener); - if (userChangeListeners.isEmpty()) - userChangeListeners = null; - } - - /** - * Window detach event. - */ - public class WindowDetachEvent extends EventObject { - - /** - * Serial generated by eclipse. - */ - private static final long serialVersionUID = 3544669568644691769L; - - private Window window; - - /** - * Creates a event. - * - * @param window - * the Detached window. - */ - public WindowDetachEvent(Window window) { - super(Application.this); - this.window = window; - } - - /** - * Gets the detached window. - * - * @return the detached window. - */ - public Window getWindow() { - return window; - } - - /** - * Gets the application from which the window was detached. - * - * @return the Application. - */ - public Application getApplication() { - return (Application) getSource(); - } - } - - /** - * Window attach event. - */ - public class WindowAttachEvent extends EventObject { - - /** - * Serial generated by eclipse. - */ - private static final long serialVersionUID = 3977578104367822392L; - - private Window window; - - /** - * Creates a event. - * - * @param window - * the Attached window. - */ - public WindowAttachEvent(Window window) { - super(Application.this); - this.window = window; - } - - /** - * Gets the attached window. - * - * @return the attached window. - */ - public Window getWindow() { - return window; - } - - /** - * Gets the application to which the window was attached. - * - * @return the Application. - */ - public Application getApplication() { - return (Application) getSource(); - } - } - - /** - * Window attach listener interface. - */ - public interface WindowAttachListener { - - /** - * Window attached - * - * @param event - * the window attach event. - */ - public void windowAttached(WindowAttachEvent event); - } - - /** - * Window detach listener interface. - */ - public interface WindowDetachListener { - - /** - * Window detached. - * - * @param event - * the window detach event. - */ - public void windowDetached(WindowDetachEvent event); - } - - /** - * Adds the window attach listener. - * - * @param listener - * the window attach listener to add. - */ - public void addListener(WindowAttachListener listener) { - if (windowAttachListeners == null) - windowAttachListeners = new LinkedList(); - windowAttachListeners.add(listener); - } - - /** - * Adds the window detach listener. - * - * @param listener - * the window detach listener to add. - */ - public void addListener(WindowDetachListener listener) { - if (windowDetachListeners == null) - windowDetachListeners = new LinkedList(); - windowDetachListeners.add(listener); - } - - /** - * Removes the window attach listener. - * - * @param listener - * the window attach listener to remove. - */ - public void removeListener(WindowAttachListener listener) { - if (windowAttachListeners != null) { - windowAttachListeners.remove(listener); - if (windowAttachListeners.isEmpty()) - windowAttachListeners = null; - } - } - - /** - * Removes the window detach listener. - * - * @param listener - * the window detach listener to remove. - */ - public void removeListener(WindowDetachListener listener) { - if (windowDetachListeners != null) { - windowDetachListeners.remove(listener); - if (windowDetachListeners.isEmpty()) - windowDetachListeners = null; - } - } - - /** - * Returns the URL user is redirected to on application close.If the URL is - * null, the application is closed normally as defined by - * the application running environment. - *

- * Desktop application just closes the application window and - * web-application redirects the browser to application main URL. - *

- * - * @return the URL. - */ - public String getLogoutURL() { - return logoutURL; - } - - /** - * Sets the URL user is redirected to on application close. If the URL is - * null, the application is closed normally as defined by - * the application running environment: Desktop application just closes the - * application window and web-application redirects the browser to - * application main URL. - * - * @param logoutURL - * the logoutURL to set. - */ - public void setLogoutURL(String logoutURL) { - this.logoutURL = logoutURL; - } - - /** - *

- * Invoked by the terminal on any exception that occurs in application and - * is thrown by the setVariable to the terminal. The default - * implementation sets the exceptions as ComponentErrors to - * the component that initiated the exception. - *

- *

- * You can safely override this method in your application in order to - * direct the errors to some other destination (for example log). - *

- * - * @param event - * the change event. - * @see com.itmill.toolkit.terminal.Terminal.ErrorListener#terminalError(com.itmill.toolkit.terminal.Terminal.ErrorEvent) - */ - public void terminalError(Terminal.ErrorEvent event) { - - // Finds the original source of the error/exception - Object owner = null; - if (event instanceof VariableOwner.ErrorEvent) { - owner = ((VariableOwner.ErrorEvent) event).getVariableOwner(); - } else if (event instanceof URIHandler.ErrorEvent) { - owner = ((URIHandler.ErrorEvent) event).getURIHandler(); - } else if (event instanceof ParameterHandler.ErrorEvent) { - owner = ((ParameterHandler.ErrorEvent) event).getParameterHandler(); - } - - // Shows the error in AbstractComponent - if (owner instanceof AbstractComponent) { - Throwable e = event.getThrowable(); - if (e instanceof ErrorMessage) - ((AbstractComponent) owner).setComponentError((ErrorMessage) e); - else - ((AbstractComponent) owner) - .setComponentError(new SystemError(e)); - } - } - - /** - * Gets the application context. - *

- * The application context is the environment where the application is - * running in. - *

- * - * @return the application context. - */ - public ApplicationContext getContext() { - return context; - } - - public void setFocusedComponent(Focusable focusable) { - this.pendingFocus = focusable; - } - - /** - * Gets and nulls focused component in this window - * - * @return Focused component or null if none is focused. - */ - public Component.Focusable consumeFocus() { - Component.Focusable f = this.pendingFocus; - this.pendingFocus = null; - return f; - } + /** + * Random window name generator. + */ + private static Random nameGenerator = new Random(); + + /** + * Application context the application is running in. + */ + private ApplicationContext context; + + /** + * The current user or null if no user has logged in. + */ + private Object user; + + /** + * Mapping from window name to window instance. + */ + private Hashtable windows = new Hashtable(); + + /** + * Main window of the application. + */ + private Window mainWindow = null; + + /** + * The application's URL. + */ + private URL applicationUrl; + + /** + * Name of the theme currently used by the application. + */ + private String theme = null; + + /** + * Application status. + */ + private boolean applicationIsRunning = false; + + /** + * Application properties. + */ + private Properties properties; + + /** + * Default locale of the application. + */ + private Locale locale; + + /** + * List of listeners listening user changes. + */ + private LinkedList userChangeListeners = null; + + /** + * Window attach listeners. + */ + private LinkedList windowAttachListeners = null; + + /** + * Window detach listeners. + */ + private LinkedList windowDetachListeners = null; + + /** + * Application resource mapping: key <-> resource. + */ + private Hashtable resourceKeyMap = new Hashtable(); + + private Hashtable keyResourceMap = new Hashtable(); + + private long lastResourceKeyNumber = 0; + + /** + * URL the user is redirected to on application close or null if application + * is just closed + */ + private String logoutURL = null; + + private Focusable pendingFocus; + + /** + *

+ * Gets a window by name. Returns null if the application is + * not running or it does not contain a window corresponding to the name. + *

+ * + *

+ * Since version 5.0 all windows can be referenced by their names in url + * http://host:port/foo/bar/ where + * http://host:port/foo/ is the application url as returned + * by getURL() and bar is the name of the window. + *

+ * + *

+ * One should note that this method can, as a side effect create new windows + * if needed by the application. This can be achieved by overriding the + * default implementation. + *

+ * + *

+ * The method should return null if the window does not exists (and is not + * created as a side-effect) or if the application is not running anymore + *

. + * + * @param name + * the name of the window. + * @return the window associated with the given URI or null + */ + public Window getWindow(String name) { + + // For closed app, do not give any windows + if (!isRunning()) { + return null; + } + + // Gets the window by name + Window window = (Window) windows.get(name); + + return window; + } + + /** + * Adds a new window to the application. + * + *

+ * This implicitly invokes the + * {@link com.itmill.toolkit.ui.Window#setApplication(Application)} method. + *

+ * + *

+ * Note that all application-level windows can be accessed by their names in + * url http://host:port/foo/bar/ where + * http://host:port/foo/ is the application url as returned + * by getURL() and bar is the name of the window. Also note + * that not all windows should be added to application - one can also add + * windows inside other windows - these windows show as smaller windows + * inside those windows. + *

+ * + * @param window + * the new Window to add. If the name of the + * window is null, an unique name is + * automatically given for the window. + * @throws IllegalArgumentException + * if a window with the same name as the new window already + * exists in the application. + * @throws NullPointerException + * if the given Window is null. + */ + public void addWindow(Window window) throws IllegalArgumentException, + NullPointerException { + + // Nulls can not be added to application + if (window == null) { + return; + } + + // Gets the naming proposal from window + String name = window.getName(); + + // Checks that the application does not already contain + // window having the same name + if (name != null && windows.containsKey(name)) { + + // If the window is already added + if (window == windows.get(name)) { + return; + } + + // Otherwise complain + throw new IllegalArgumentException("Window with name '" + + window.getName() + + "' is already present in the application"); + } + + // If the name of the window is null, the window is automatically named + if (name == null) { + boolean accepted = false; + while (!accepted) { + + // Try another name + name = String.valueOf(Math.abs(nameGenerator.nextInt())); + if (!windows.containsKey(name)) { + accepted = true; + } + } + window.setName(name); + } + + // Adds the window to application + windows.put(name, window); + window.setApplication(this); + + fireWindowAttachEvent(window); + + // If no main window is set, declare the window to be main window + if (getMainWindow() == null) { + setMainWindow(window); + } + } + + /** + * Send information to all listeners about new Windows associated with this + * application. + * + * @param window + */ + private void fireWindowAttachEvent(Window window) { + // Fires the window attach event + if (windowAttachListeners != null) { + Object[] listeners = windowAttachListeners.toArray(); + WindowAttachEvent event = new WindowAttachEvent(window); + for (int i = 0; i < listeners.length; i++) { + ((WindowAttachListener) listeners[i]).windowAttached(event); + } + } + } + + /** + * Removes the specified window from the application. + * + * @param window + * the window to be removed. + */ + public void removeWindow(Window window) { + if (window != null && windows.contains(window)) { + + // Removes the window from application + windows.remove(window.getName()); + + // If the window was main window, clear it + if (getMainWindow() == window) { + setMainWindow(null); + } + + // Removes the application from window + if (window.getApplication() == this) { + window.setApplication(null); + } + + fireWindowDetachEvent(window); + } + } + + private void fireWindowDetachEvent(Window window) { + // Fires the window detach event + if (windowDetachListeners != null) { + Object[] listeners = windowDetachListeners.toArray(); + WindowDetachEvent event = new WindowDetachEvent(window); + for (int i = 0; i < listeners.length; i++) { + ((WindowDetachListener) listeners[i]).windowDetached(event); + } + } + } + + /** + * Gets the user of the application. + * + * @return the User of the application. + */ + public Object getUser() { + return user; + } + + /** + *

+ * Sets the user of the application instance. An application instance may + * have a user associated to it. This can be set in login procedure or + * application initialization. + *

+ *

+ * A component performing the user login procedure can assign the user + * property of the application and make the user object available to other + * components of the application. + *

+ * + * @param user + * the new user. + */ + public void setUser(Object user) { + Object prevUser = this.user; + if (user != prevUser && (user == null || !user.equals(prevUser))) { + this.user = user; + if (userChangeListeners != null) { + Object[] listeners = userChangeListeners.toArray(); + UserChangeEvent event = new UserChangeEvent(this, user, + prevUser); + for (int i = 0; i < listeners.length; i++) { + ((UserChangeListener) listeners[i]) + .applicationUserChanged(event); + } + } + } + } + + /** + * Gets the URL of the application. + * + * @return the application's URL. + */ + public URL getURL() { + return applicationUrl; + } + + /** + * Ends the Application. In effect this will cause the application stop + * returning any windows when asked. + */ + public void close() { + applicationIsRunning = false; + } + + /** + * Starts the application on the given URL.After this call the application + * corresponds to the given URL and it will return windows when asked for + * them. + * + * @param applicationUrl + * the URL the application should respond to. + * @param applicationProperties + * the Application properties as specified by the adapter. + * @param context + * the context application will be running in. + * + */ + public void start(URL applicationUrl, Properties applicationProperties, + ApplicationContext context) { + this.applicationUrl = applicationUrl; + properties = applicationProperties; + this.context = context; + init(); + applicationIsRunning = true; + } + + /** + * Tests if the application is running or if it has been finished. + * + * @return true if the application is running, + * false if not. + */ + public boolean isRunning() { + return applicationIsRunning; + } + + /** + * Gets the set of windows contained by the application. + * + * @return the Unmodifiable collection of windows. + */ + public Collection getWindows() { + return Collections.unmodifiableCollection(windows.values()); + } + + /** + *

+ * Main initializer of the application. The init method is + * called by the framework when the application is started, and it should + * perform whatever initialization operations the application needs, such as + * creating windows and adding components to them. + *

+ */ + public abstract void init(); + + /** + * Gets the application's theme. The application's theme is the default + * theme used by all the windows in it that do not explicitly specify a + * theme. If the application theme is not explicitly set, the + * null is returned. + * + * @return the name of the application's theme. + */ + public String getTheme() { + return theme; + } + + /** + * Sets the application's theme. + *

+ * Note that this theme can be overridden by the windows. null + * implies the default terminal theme. + *

+ * + * @param theme + * the new theme for this application. + */ + public void setTheme(String theme) { + + // Collect list of windows not having the current or future theme + LinkedList toBeUpdated = new LinkedList(); + String myTheme = getTheme(); + for (Iterator i = getWindows().iterator(); i.hasNext();) { + Window w = (Window) i.next(); + String windowTheme = w.getTheme(); + if ((windowTheme == null) + || (!theme.equals(windowTheme) && windowTheme + .equals(myTheme))) { + toBeUpdated.add(w); + } + } + + // Updates the theme + this.theme = theme; + + // Ask windows to update themselves + for (Iterator i = toBeUpdated.iterator(); i.hasNext();) { + ((Window) i.next()).requestRepaint(); + } + } + + /** + * Gets the mainWindow of the application. + * + * @return the main window. + */ + public Window getMainWindow() { + return mainWindow; + } + + /** + *

+ * Sets the mainWindow. If the main window is not explicitly set, the main + * window defaults to first created window. Setting window as a main window + * of this application also adds the window to this application. + *

+ * + * @param mainWindow + * the mainWindow to set. + */ + public void setMainWindow(Window mainWindow) { + + addWindow(mainWindow); + this.mainWindow = mainWindow; + } + + /** + * Returns an enumeration of all the names in this application. + * + * @return an enumeration of all the keys in this property list, including + * the keys in the default property list. + * + */ + public Enumeration getPropertyNames() { + return properties.propertyNames(); + } + + /** + * Searches for the property with the specified name in this application. + * This method returns null if the property is not found. + * + * @param name + * the name of the property. + * @return the value in this property list with the specified key value. + */ + public String getProperty(String name) { + return properties.getProperty(name); + } + + /** + * Adds new resource to the application. The resource can be accessed by the + * user of the application. + * + * @param resource + * the resource to add. + */ + public void addResource(ApplicationResource resource) { + + // Check if the resource is already mapped + if (resourceKeyMap.containsKey(resource)) { + return; + } + + // Generate key + String key = String.valueOf(++lastResourceKeyNumber); + + // Add the resource to mappings + resourceKeyMap.put(resource, key); + keyResourceMap.put(key, resource); + } + + /** + * Removes the resource from the application. + * + * @param resource + * the resource to remove. + */ + public void removeResource(ApplicationResource resource) { + Object key = resourceKeyMap.get(resource); + if (key != null) { + resourceKeyMap.remove(resource); + keyResourceMap.remove(key); + } + } + + /** + * Gets the relative uri of the resource. + * + * @param resource + * the resource to get relative location. + * @return the relative uri of the resource. + */ + public String getRelativeLocation(ApplicationResource resource) { + + // Gets the key + String key = (String) resourceKeyMap.get(resource); + + // If the resource is not registered, return null + if (key == null) { + return null; + } + + String filename = resource.getFilename(); + if (filename == null) { + return "APP/" + key + "/"; + } else { + return "APP/" + key + "/" + filename; + } + } + + /* + * @see com.itmill.toolkit.terminal.URIHandler#handleURI(URL, String) + */ + public DownloadStream handleURI(URL context, String relativeUri) { + + // If the relative uri is null, we are ready + if (relativeUri == null) { + return null; + } + + // Resolves the prefix + String prefix = relativeUri; + int index = relativeUri.indexOf('/'); + if (index >= 0) { + prefix = relativeUri.substring(0, index); + } + + // Handles the resource requests + if (prefix.equals("APP")) { + + // Handles the resource request + int next = relativeUri.indexOf('/', index + 1); + if (next < 0) { + return null; + } + String key = relativeUri.substring(index + 1, next); + ApplicationResource resource = (ApplicationResource) keyResourceMap + .get(key); + if (resource != null) { + return resource.getStream(); + } + + // Resource requests override uri handling + return null; + } + + // If the uri is in some window, handle the window uri + Window window = getWindow(prefix); + if (window != null) { + URL windowContext; + try { + windowContext = new URL(context, prefix + "/"); + String windowUri = relativeUri.length() > prefix.length() + 1 ? relativeUri + .substring(prefix.length() + 1) + : ""; + return window.handleURI(windowContext, windowUri); + } catch (MalformedURLException e) { + return null; + } + } + + // If the uri was not pointing to a window, handle the + // uri in main window + window = getMainWindow(); + if (window != null) { + return window.handleURI(context, relativeUri); + } + + return null; + } + + /** + * Gets the default locale for this application. + * + * @return the locale of this application. + */ + public Locale getLocale() { + if (locale != null) { + return locale; + } + return Locale.getDefault(); + } + + /** + * Sets the default locale for this application. + * + * @param locale + * the Locale object. + * + */ + public void setLocale(Locale locale) { + this.locale = locale; + } + + /** + *

+ * An event that characterizes a change in the current selection. + *

+ * Application user change event sent when the setUser is called to change + * the current user of the application. + * + * @version + * @VERSION@ + * @since 3.0 + */ + public class UserChangeEvent extends java.util.EventObject { + + /** + * Serial generated by eclipse. + */ + private static final long serialVersionUID = 3544951069307188281L; + + /** + * New user of the application. + */ + private Object newUser; + + /** + * Previous user of the application. + */ + private Object prevUser; + + /** + * Constructor for user change event. + * + * @param source + * the application source. + * @param newUser + * the new User. + * @param prevUser + * the previous User. + */ + public UserChangeEvent(Application source, Object newUser, + Object prevUser) { + super(source); + this.newUser = newUser; + this.prevUser = prevUser; + } + + /** + * Gets the new user of the application. + * + * @return the new User. + */ + public Object getNewUser() { + return newUser; + } + + /** + * Gets the previous user of the application. + * + * @return the previous Toolkit user, if user has not changed ever on + * application it returns null + */ + public Object getPreviousUser() { + return prevUser; + } + + /** + * Gets the application where the user change occurred. + * + * @return the Application. + */ + public Application getApplication() { + return (Application) getSource(); + } + } + + /** + * The UserChangeListener interface for listening application + * user changes. + * + * @version + * @VERSION@ + * @since 3.0 + */ + public interface UserChangeListener extends EventListener { + + /** + * The applicationUserChanged method Invoked when the + * application user has changed. + * + * @param event + * the change event. + */ + public void applicationUserChanged(Application.UserChangeEvent event); + } + + /** + * Adds the user change listener. + * + * @param listener + * the user change listener to add. + */ + public void addListener(UserChangeListener listener) { + if (userChangeListeners == null) { + userChangeListeners = new LinkedList(); + } + userChangeListeners.add(listener); + } + + /** + * Removes the user change listener. + * + * @param listener + * the user change listener to remove. + */ + public void removeListener(UserChangeListener listener) { + if (userChangeListeners == null) { + return; + } + userChangeListeners.remove(listener); + if (userChangeListeners.isEmpty()) { + userChangeListeners = null; + } + } + + /** + * Window detach event. + */ + public class WindowDetachEvent extends EventObject { + + /** + * Serial generated by eclipse. + */ + private static final long serialVersionUID = 3544669568644691769L; + + private Window window; + + /** + * Creates a event. + * + * @param window + * the Detached window. + */ + public WindowDetachEvent(Window window) { + super(Application.this); + this.window = window; + } + + /** + * Gets the detached window. + * + * @return the detached window. + */ + public Window getWindow() { + return window; + } + + /** + * Gets the application from which the window was detached. + * + * @return the Application. + */ + public Application getApplication() { + return (Application) getSource(); + } + } + + /** + * Window attach event. + */ + public class WindowAttachEvent extends EventObject { + + /** + * Serial generated by eclipse. + */ + private static final long serialVersionUID = 3977578104367822392L; + + private Window window; + + /** + * Creates a event. + * + * @param window + * the Attached window. + */ + public WindowAttachEvent(Window window) { + super(Application.this); + this.window = window; + } + + /** + * Gets the attached window. + * + * @return the attached window. + */ + public Window getWindow() { + return window; + } + + /** + * Gets the application to which the window was attached. + * + * @return the Application. + */ + public Application getApplication() { + return (Application) getSource(); + } + } + + /** + * Window attach listener interface. + */ + public interface WindowAttachListener { + + /** + * Window attached + * + * @param event + * the window attach event. + */ + public void windowAttached(WindowAttachEvent event); + } + + /** + * Window detach listener interface. + */ + public interface WindowDetachListener { + + /** + * Window detached. + * + * @param event + * the window detach event. + */ + public void windowDetached(WindowDetachEvent event); + } + + /** + * Adds the window attach listener. + * + * @param listener + * the window attach listener to add. + */ + public void addListener(WindowAttachListener listener) { + if (windowAttachListeners == null) { + windowAttachListeners = new LinkedList(); + } + windowAttachListeners.add(listener); + } + + /** + * Adds the window detach listener. + * + * @param listener + * the window detach listener to add. + */ + public void addListener(WindowDetachListener listener) { + if (windowDetachListeners == null) { + windowDetachListeners = new LinkedList(); + } + windowDetachListeners.add(listener); + } + + /** + * Removes the window attach listener. + * + * @param listener + * the window attach listener to remove. + */ + public void removeListener(WindowAttachListener listener) { + if (windowAttachListeners != null) { + windowAttachListeners.remove(listener); + if (windowAttachListeners.isEmpty()) { + windowAttachListeners = null; + } + } + } + + /** + * Removes the window detach listener. + * + * @param listener + * the window detach listener to remove. + */ + public void removeListener(WindowDetachListener listener) { + if (windowDetachListeners != null) { + windowDetachListeners.remove(listener); + if (windowDetachListeners.isEmpty()) { + windowDetachListeners = null; + } + } + } + + /** + * Returns the URL user is redirected to on application close.If the URL is + * null, the application is closed normally as defined by + * the application running environment. + *

+ * Desktop application just closes the application window and + * web-application redirects the browser to application main URL. + *

+ * + * @return the URL. + */ + public String getLogoutURL() { + return logoutURL; + } + + /** + * Sets the URL user is redirected to on application close. If the URL is + * null, the application is closed normally as defined by + * the application running environment: Desktop application just closes the + * application window and web-application redirects the browser to + * application main URL. + * + * @param logoutURL + * the logoutURL to set. + */ + public void setLogoutURL(String logoutURL) { + this.logoutURL = logoutURL; + } + + /** + *

+ * Invoked by the terminal on any exception that occurs in application and + * is thrown by the setVariable to the terminal. The default + * implementation sets the exceptions as ComponentErrors to + * the component that initiated the exception. + *

+ *

+ * You can safely override this method in your application in order to + * direct the errors to some other destination (for example log). + *

+ * + * @param event + * the change event. + * @see com.itmill.toolkit.terminal.Terminal.ErrorListener#terminalError(com.itmill.toolkit.terminal.Terminal.ErrorEvent) + */ + public void terminalError(Terminal.ErrorEvent event) { + + // Finds the original source of the error/exception + Object owner = null; + if (event instanceof VariableOwner.ErrorEvent) { + owner = ((VariableOwner.ErrorEvent) event).getVariableOwner(); + } else if (event instanceof URIHandler.ErrorEvent) { + owner = ((URIHandler.ErrorEvent) event).getURIHandler(); + } else if (event instanceof ParameterHandler.ErrorEvent) { + owner = ((ParameterHandler.ErrorEvent) event).getParameterHandler(); + } + + // Shows the error in AbstractComponent + if (owner instanceof AbstractComponent) { + Throwable e = event.getThrowable(); + if (e instanceof ErrorMessage) { + ((AbstractComponent) owner).setComponentError((ErrorMessage) e); + } else { + ((AbstractComponent) owner) + .setComponentError(new SystemError(e)); + } + } + } + + /** + * Gets the application context. + *

+ * The application context is the environment where the application is + * running in. + *

+ * + * @return the application context. + */ + public ApplicationContext getContext() { + return context; + } + + public void setFocusedComponent(Focusable focusable) { + pendingFocus = focusable; + } + + /** + * Gets and nulls focused component in this window + * + * @return Focused component or null if none is focused. + */ + public Component.Focusable consumeFocus() { + Component.Focusable f = pendingFocus; + pendingFocus = null; + return f; + } } \ No newline at end of file diff --git a/src/com/itmill/toolkit/data/Buffered.java b/src/com/itmill/toolkit/data/Buffered.java index ae0b4ee08d..94f7c3649e 100644 --- a/src/com/itmill/toolkit/data/Buffered.java +++ b/src/com/itmill/toolkit/data/Buffered.java @@ -67,253 +67,260 @@ import com.itmill.toolkit.terminal.SystemError; */ public interface Buffered { - /** - * Updates all changes since the previous commit to the data source. The - * value stored in the object will always be updated into the data source - * when commit is called. - * - * @throws SourceException - * if the operation fails because of an exception is thrown by - * the data source. The cause is included in the exception. - */ - public void commit() throws SourceException; - - /** - * Discards all changes since last commit. The object updates its value from - * the data source. - * - * @throws SourceException - * if the operation fails because of an exception is thrown by - * the data source. The cause is included in the exception. - */ - public void discard() throws SourceException; - - /** - * Tests if the object is in write-through mode. If the object is in - * write-through mode, all modifications to it will result in - * commit being called after the modification. - * - * @return true if the object is in write-through mode, - * false if it's not. - */ - public boolean isWriteThrough(); - - /** - * Sets the object's write-through mode to the specified status. When - * switching the write-through mode on, the commit operation - * will be performed. - * - * @param writeThrough - * Boolean value to indicate if the object should be in - * write-through mode after the call. - * @throws SourceException - * If the operation fails because of an exception is thrown by - * the data source. - * - */ - public void setWriteThrough(boolean writeThrough) throws SourceException; - - /** - * Tests if the object is in read-through mode. If the object is in - * read-through mode, retrieving its value will result in the value being - * first updated from the data source to the object. - *

- * The only exception to this rule is that when the object is not in - * write-through mode and it's buffer contains a modified value, the value - * retrieved from the object will be the locally modified value in the - * buffer which may differ from the value in the data source. - *

- * - * @return true if the object is in read-through mode, - * false if it's not. - */ - public boolean isReadThrough(); - - /** - * Sets the object's read-through mode to the specified status. When - * switching read-through mode on, the object's value is updated from the - * data source. - * - * @param readThrough - * Boolean value to indicate if the object should be in - * read-through mode after the call. - * - * @throws SourceException - * If the operation fails because of an exception is thrown by - * the data source. The cause is included in the exception. - */ - public void setReadThrough(boolean readThrough) throws SourceException; - - /** - * Tests if the value stored in the object has been modified since it was - * last updated from the data source. - * - * @return true if the value in the object has been modified - * since the last data source update, false if not. - */ - public boolean isModified(); - - /** - * An exception that signals that one or more exceptions occurred while a - * buffered object tried to access its data source or if there is a problem - * in processing a data source. - * - * @author IT Mill Ltd. - * @version - * @VERSION@ - * @since 3.0 - */ - public class SourceException extends RuntimeException implements - ErrorMessage { - - /** - * Serial generated by eclipse. - */ - private static final long serialVersionUID = 3256720671781630518L; - - /** Source class implementing the buffered interface */ - private Buffered source; - - /** Original cause of the source exception */ - private Throwable[] causes = {}; - - /** - * Creates a source exception that does not include a cause. - * - * @param source - * the source object implementing the Buffered interface. - */ - public SourceException(Buffered source) { - this.source = source; - } - - /** - * Creates a source exception from a cause exception. - * - * @param source - * the source object implementing the Buffered interface. - * @param cause - * the original cause for this exception. - */ - public SourceException(Buffered source, Throwable cause) { - this.source = source; - causes = new Throwable[] { cause }; - } - - /** - * Creates a source exception from multiple causes. - * - * @param source - * the source object implementing the Buffered interface. - * @param causes - * the original causes for this exception. - */ - public SourceException(Buffered source, Throwable[] causes) { - this.source = source; - this.causes = causes; - } - - /** - * Gets the cause of the exception. - * - * @return The cause for the exception. - * @throws MoreThanOneCauseException - * if there is more than one cause for the exception. This - * is possible if the commit operation triggers more than - * one error at the same time. - */ - public final Throwable getCause() { - if (causes.length == 0) - return null; - return causes[0]; - } - - /** - * Gets all the causes for this exception. - * - * @return throwables that caused this exception - */ - public final Throwable[] getCauses() { - return causes; - } - - /** - * Gets a source of the exception. - * - * @return the Buffered object which generated this exception. - */ - public Buffered getSource() { - return source; - } - - /** - * Gets the error level of this buffered source exception. The level of - * the exception is maximum error level of all the contained causes. - *

- * The causes that do not specify error level default to - * ERROR level. Also source exception without any causes - * are of level ERROR. - *

- * - * @see com.itmill.toolkit.terminal.ErrorMessage#getErrorLevel() - */ - public int getErrorLevel() { - - int level = Integer.MIN_VALUE; - - for (int i = 0; i < causes.length; i++) { - int causeLevel = (causes[i] instanceof ErrorMessage) ? ((ErrorMessage) causes[i]) - .getErrorLevel() - : ErrorMessage.ERROR; - if (causeLevel > level) - level = causeLevel; - } - - return level == Integer.MIN_VALUE ? ErrorMessage.ERROR : level; - } - - /* Documented in super interface */ - public void paint(PaintTarget target) throws PaintException { - target.startTag("error"); - int level = getErrorLevel(); - if (level > 0 && level <= ErrorMessage.INFORMATION) - target.addAttribute("level", "info"); - else if (level <= ErrorMessage.WARNING) - target.addAttribute("level", "warning"); - else if (level <= ErrorMessage.ERROR) - target.addAttribute("level", "error"); - else if (level <= ErrorMessage.CRITICAL) - target.addAttribute("level", "critical"); - else - target.addAttribute("level", "system"); - - // Paint all the exceptions - for (int i = 0; i < causes.length; i++) { - if (causes[i] instanceof ErrorMessage) - ((ErrorMessage) causes[i]).paint(target); - else - new SystemError(causes[i]).paint(target); - } - - target.endTag("error"); - - } - - /* Documented in super interface */ - public void addListener(RepaintRequestListener listener) { - } - - /* Documented in super interface */ - public void removeListener(RepaintRequestListener listener) { - } - - /* Documented in super interface */ - public void requestRepaint() { - } - - /* Documented in super interface */ - public void requestRepaintRequests() { - } - - } + /** + * Updates all changes since the previous commit to the data source. The + * value stored in the object will always be updated into the data source + * when commit is called. + * + * @throws SourceException + * if the operation fails because of an exception is thrown + * by the data source. The cause is included in the + * exception. + */ + public void commit() throws SourceException; + + /** + * Discards all changes since last commit. The object updates its value from + * the data source. + * + * @throws SourceException + * if the operation fails because of an exception is thrown + * by the data source. The cause is included in the + * exception. + */ + public void discard() throws SourceException; + + /** + * Tests if the object is in write-through mode. If the object is in + * write-through mode, all modifications to it will result in + * commit being called after the modification. + * + * @return true if the object is in write-through mode, + * false if it's not. + */ + public boolean isWriteThrough(); + + /** + * Sets the object's write-through mode to the specified status. When + * switching the write-through mode on, the commit operation + * will be performed. + * + * @param writeThrough + * Boolean value to indicate if the object should be in + * write-through mode after the call. + * @throws SourceException + * If the operation fails because of an exception is thrown + * by the data source. + * + */ + public void setWriteThrough(boolean writeThrough) throws SourceException; + + /** + * Tests if the object is in read-through mode. If the object is in + * read-through mode, retrieving its value will result in the value being + * first updated from the data source to the object. + *

+ * The only exception to this rule is that when the object is not in + * write-through mode and it's buffer contains a modified value, the value + * retrieved from the object will be the locally modified value in the + * buffer which may differ from the value in the data source. + *

+ * + * @return true if the object is in read-through mode, + * false if it's not. + */ + public boolean isReadThrough(); + + /** + * Sets the object's read-through mode to the specified status. When + * switching read-through mode on, the object's value is updated from the + * data source. + * + * @param readThrough + * Boolean value to indicate if the object should be in + * read-through mode after the call. + * + * @throws SourceException + * If the operation fails because of an exception is thrown + * by the data source. The cause is included in the + * exception. + */ + public void setReadThrough(boolean readThrough) throws SourceException; + + /** + * Tests if the value stored in the object has been modified since it was + * last updated from the data source. + * + * @return true if the value in the object has been modified + * since the last data source update, false if not. + */ + public boolean isModified(); + + /** + * An exception that signals that one or more exceptions occurred while a + * buffered object tried to access its data source or if there is a problem + * in processing a data source. + * + * @author IT Mill Ltd. + * @version + * @VERSION@ + * @since 3.0 + */ + public class SourceException extends RuntimeException implements + ErrorMessage { + + /** + * Serial generated by eclipse. + */ + private static final long serialVersionUID = 3256720671781630518L; + + /** Source class implementing the buffered interface */ + private Buffered source; + + /** Original cause of the source exception */ + private Throwable[] causes = {}; + + /** + * Creates a source exception that does not include a cause. + * + * @param source + * the source object implementing the Buffered interface. + */ + public SourceException(Buffered source) { + this.source = source; + } + + /** + * Creates a source exception from a cause exception. + * + * @param source + * the source object implementing the Buffered interface. + * @param cause + * the original cause for this exception. + */ + public SourceException(Buffered source, Throwable cause) { + this.source = source; + causes = new Throwable[] { cause }; + } + + /** + * Creates a source exception from multiple causes. + * + * @param source + * the source object implementing the Buffered interface. + * @param causes + * the original causes for this exception. + */ + public SourceException(Buffered source, Throwable[] causes) { + this.source = source; + this.causes = causes; + } + + /** + * Gets the cause of the exception. + * + * @return The cause for the exception. + * @throws MoreThanOneCauseException + * if there is more than one cause for the exception. + * This is possible if the commit operation triggers + * more than one error at the same time. + */ + public final Throwable getCause() { + if (causes.length == 0) { + return null; + } + return causes[0]; + } + + /** + * Gets all the causes for this exception. + * + * @return throwables that caused this exception + */ + public final Throwable[] getCauses() { + return causes; + } + + /** + * Gets a source of the exception. + * + * @return the Buffered object which generated this exception. + */ + public Buffered getSource() { + return source; + } + + /** + * Gets the error level of this buffered source exception. The level of + * the exception is maximum error level of all the contained causes. + *

+ * The causes that do not specify error level default to + * ERROR level. Also source exception without any causes + * are of level ERROR. + *

+ * + * @see com.itmill.toolkit.terminal.ErrorMessage#getErrorLevel() + */ + public int getErrorLevel() { + + int level = Integer.MIN_VALUE; + + for (int i = 0; i < causes.length; i++) { + int causeLevel = (causes[i] instanceof ErrorMessage) ? ((ErrorMessage) causes[i]) + .getErrorLevel() + : ErrorMessage.ERROR; + if (causeLevel > level) { + level = causeLevel; + } + } + + return level == Integer.MIN_VALUE ? ErrorMessage.ERROR : level; + } + + /* Documented in super interface */ + public void paint(PaintTarget target) throws PaintException { + target.startTag("error"); + int level = getErrorLevel(); + if (level > 0 && level <= ErrorMessage.INFORMATION) { + target.addAttribute("level", "info"); + } else if (level <= ErrorMessage.WARNING) { + target.addAttribute("level", "warning"); + } else if (level <= ErrorMessage.ERROR) { + target.addAttribute("level", "error"); + } else if (level <= ErrorMessage.CRITICAL) { + target.addAttribute("level", "critical"); + } else { + target.addAttribute("level", "system"); + } + + // Paint all the exceptions + for (int i = 0; i < causes.length; i++) { + if (causes[i] instanceof ErrorMessage) { + ((ErrorMessage) causes[i]).paint(target); + } else { + new SystemError(causes[i]).paint(target); + } + } + + target.endTag("error"); + + } + + /* Documented in super interface */ + public void addListener(RepaintRequestListener listener) { + } + + /* Documented in super interface */ + public void removeListener(RepaintRequestListener listener) { + } + + /* Documented in super interface */ + public void requestRepaint() { + } + + /* Documented in super interface */ + public void requestRepaintRequests() { + } + + } } diff --git a/src/com/itmill/toolkit/data/BufferedValidatable.java b/src/com/itmill/toolkit/data/BufferedValidatable.java index d7983a0d68..f5fd3566df 100644 --- a/src/com/itmill/toolkit/data/BufferedValidatable.java +++ b/src/com/itmill/toolkit/data/BufferedValidatable.java @@ -42,15 +42,15 @@ package com.itmill.toolkit.data; */ public interface BufferedValidatable extends Buffered, Validatable { - /** - * Tests if the invalid data is committed to datasource. The default is - * false. - */ - public boolean isInvalidCommitted(); - - /** - * Sets if the invalid data should be committed to datasource. The default - * is false. - */ - public void setInvalidCommitted(boolean isCommitted); + /** + * Tests if the invalid data is committed to datasource. The default is + * false. + */ + public boolean isInvalidCommitted(); + + /** + * Sets if the invalid data should be committed to datasource. The default + * is false. + */ + public void setInvalidCommitted(boolean isCommitted); } diff --git a/src/com/itmill/toolkit/data/Container.java b/src/com/itmill/toolkit/data/Container.java index 5d2ff27b57..d57ae6af30 100644 --- a/src/com/itmill/toolkit/data/Container.java +++ b/src/com/itmill/toolkit/data/Container.java @@ -75,704 +75,714 @@ import java.util.Collection; */ public interface Container { - /** - * Gets the Item with the given Item ID from the Container. If the Container - * does not contain the requested Item, null is returned. - * - * @param itemId - * ID of the Item to retrieve - * @return the Item with the given ID or null if the Item is - * not found in the Container - */ - public Item getItem(Object itemId); - - /** - * Gets the ID's of all Properties stored in the Container. The ID's are - * returned as a unmodifiable collection. - * - * @return unmodifiable collection of Property IDs - */ - public Collection getContainerPropertyIds(); - - /** - * Gets the ID's of all Items stored in the Container. The ID's are returned - * as a unmodifiable collection. - * - * @return unmodifiable collection of Item IDs - */ - public Collection getItemIds(); - - /** - * Gets the Property identified by the given itemId and propertyId from the - * Container. If the Container does not contain the Property, - * null is returned. - * - * @param itemId - * ID of the Item which contains the Property - * @param propertyId - * ID of the Property to retrieve - * @return Property with the given ID or null - */ - public Property getContainerProperty(Object itemId, Object propertyId); - - /** - * Gets the data type of all Properties identified by the given Property ID. - * - * @param propertyId - * ID identifying the Properties - * @return data type of the Properties - */ - public Class getType(Object propertyId); - - /** - * Gets the number of Items in the Container. - * - * @return number of Items in the Container - */ - public int size(); - - /** - * Tests if the Container contains the specified Item - * - * @param itemId - * ID the of Item to be tested - * @return boolean indicating if the Container holds the specified Item - */ - public boolean containsId(Object itemId); - - /** - * Creates a new Item with the given ID into the Container. The new - *

- * Item is returned, and it is ready to have its Properties modified. - * Returns null if the operation fails or the Container - * already contains a Item with the given ID. - *

- * - *

- * This functionality is optional. - *

- * - * @param itemId - * ID of the Item to be created - * @return Created new Item, or null in case of a failure - */ - public Item addItem(Object itemId) throws UnsupportedOperationException; - - /** - * Creates a new Item into the Container, and assign it an automatic ID. - * - *

- * The new ID is returned, or null if the operation fails. - * After a successful call you can use the - * {@link #getItem(Object ItemId) getItem}method to fetch the - * Item. - *

- * - *

- * This functionality is optional. - *

- * - * @return ID of the newly created Item, or null in case of a - * failure - */ - public Object addItem() throws UnsupportedOperationException; - - /** - * Removes the Item identified by ItemId from the Container. - * This functionality is optional. - * - * @param itemId - * ID of the Item to remove - * @return true if the operation succeeded, - * false if not - */ - public boolean removeItem(Object itemId) - throws UnsupportedOperationException; - - /** - * Adds a new Property to all Items in the Container. The Property ID, data - * type and default value of the new Property are given as parameters. - * - * This functionality is optional. - * - * @param propertyId - * ID of the Property - * @param type - * Data type of the new Property - * @param defaultValue - * The value all created Properties are initialized to - * @return true if the operation succeeded, - * false if not - */ - public boolean addContainerProperty(Object propertyId, Class type, - Object defaultValue) throws UnsupportedOperationException; - - /** - * Removes a Property specified by the given Property ID from the Container. - * Note that the Property will be removed from all Items in the Container. - * - * This functionality is optional. - * - * @param propertyId - * ID of the Property to remove - * @return true if the operation succeeded, - * false if not - */ - public boolean removeContainerProperty(Object propertyId) - throws UnsupportedOperationException; - - /** - * Removes all Items from the Container. - * - *

- * Note that Property ID and type information is preserved. This - * functionality is optional. - *

- * - * @return true if the operation succeeded, - * false if not - */ - public boolean removeAllItems() throws UnsupportedOperationException; - - /** - * Interface for Container classes whose Items can be traversed in order. - */ - public interface Ordered extends Container { - - /** - * Gets the ID of the Item following the Item that corresponds to - * itemId. If the given Item is the last or not found in - * the Container, null is returned. - * - * @param itemId - * ID of an Item in the Container - * @return ID of the next Item or null - */ - public Object nextItemId(Object itemId); - - /** - * Gets the ID of the Item preceding the Item that corresponds to - * itemId. If the given Item is the first or not found - * in the Container, null is returned. - * - * @param itemId - * ID of an Item in the Container - * @return ID of the previous Item or null - */ - public Object prevItemId(Object itemId); - - /** - * Gets the ID of the first Item in the Container. - * - * @return ID of the first Item in the Container - */ - public Object firstItemId(); - - /** - * Gets the ID of the last Item in the Container.. - * - * @return ID of the last Item in the Container - */ - public Object lastItemId(); - - /** - * Tests if the Item corresponding to the given Item ID is the first - * Item in the Container. - * - * @param itemId - * ID of an Item in the Container - * @return true if the Item is first in the Container, - * false if not - */ - public boolean isFirstId(Object itemId); - - /** - * Tests if the Item corresponding to the given Item ID is the last Item - * in the Container. - * - * @return true if the Item is last in the Container, - * false if not - */ - public boolean isLastId(Object itemId); - - /** - * Adds new item after the given item. - *

- * Adding an item after null item adds the item as first item of the - * ordered container. - *

- * - * @param previousItemId - * Id of the previous item in ordered container. - * @return Returns item id the the created new item or null if the - * operation fails. - */ - public Object addItemAfter(Object previousItemId) - throws UnsupportedOperationException; - - /** - * Adds new item after the given item. - *

- * Adding an item after null item adds the item as first item of the - * ordered container. - *

- * - * @param previousItemId - * Id of the previous item in ordered container. - * @param newItemId - * Id of the new item to be added. - * @return Returns new item or null if the operation fails. - */ - public Item addItemAfter(Object previousItemId, Object newItemId) - throws UnsupportedOperationException; - - } - - /** Interface for Container classes whose Items can be sorted. */ - public interface Sortable extends Ordered { - - /** - * Sort method. - * - * Sorts the container items. - * - * @param propertyId - * Array of container property IDs, which values are used to - * sort the items in container as primary, secondary, ... - * sorting criterion. All of the item IDs must be in the - * collection returned by - * getSortableContainerPropertyIds - * @param ascending - * Array of sorting order flags corresponding to each - * property ID used in sorting. If this array is shorter than - * propertyId array, ascending order is assumed for items - * where the order is not specified. Use true - * to sort in ascending order, false to use - * descending order. - */ - void sort(Object[] propertyId, boolean[] ascending); - - /** - * Gets the container property IDs, which can be used to sort the item. - * - * @return The sortable field ids. - */ - Collection getSortableContainerPropertyIds(); - - } - - /** Interface for Container classes whose Items can be indexed. */ - public interface Indexed extends Ordered { - - /** - * Gets the index of the Item corresponding to the itemId. The following - * is true for the returned index: 0 <= index < size(). - * - * @param itemId - * ID of an Item in the Container - * @return index of the Item, or -1 if the Container does not include - * the Item - */ - public int indexOfId(Object itemId); - - /** - * Gets the ID of an Item by an index number. - * - * @param index - * Index of the requested id in the Container - * @return ID of the Item in the given index - */ - public Object getIdByIndex(int index); - - /** - * Adds new item at given index. - *

- * The indexes of the item currently in the given position and all the - * following items are incremented. - *

- * - * @param index - * Index to add the new item. - * @return Returns item id the the created new item or null if the - * operation fails. - */ - public Object addItemAt(int index) throws UnsupportedOperationException; - - /** - * Adds new item at given index. - *

- * The indexes of the item currently in the given position and all the - * following items are incremented. - *

- * - * @param index - * Index to add the new item. - * @param newItemId - * Id of the new item to be added. - * @return Returns new item or null if the operation fails. - */ - public Item addItemAt(int index, Object newItemId) - throws UnsupportedOperationException; - - } - - /** - *

- * Interface for Container classes whose Items can be - * arranged hierarchically. This means that the Items in the container - * belong in a tree-like structure, with the following quirks: - *

- * - * - */ - public interface Hierarchical extends Container { - - /** - * Gets the IDs of all Items that are children of the specified Item. - * The returned collection is unmodifiable. - * - * @param itemId - * ID of the Item whose children the caller is interested in - * @return An unmodifiable {@link java.util.Collection collection} - * containing the IDs of all other Items that are children in - * the container hierarchy - */ - public Collection getChildren(Object itemId); - - /** - * Gets the ID of the parent Item of the specified Item. - * - * @param itemId - * ID of the Item whose parent the caller wishes to find out. - * @return the ID of the parent Item. Will be null if the - * specified Item is a root element. - */ - public Object getParent(Object itemId); - - /** - * Gets the IDs of all Items in the container that don't have a parent. - * Such items are called root Items. The returned - * collection is unmodifiable. - * - * @return An unmodifiable {@link java.util.Collection collection} - * containing IDs of all root elements of the container - */ - public Collection rootItemIds(); - - /** - *

- * Sets the parent of an Item. The new parent item must exist and be - * able to have children. ( - * canHaveChildren(newParentId) == true). It is also - * possible to detach a node from the hierarchy (and thus make it root) - * by setting the parent null. - *

- * - *

- * This operation is optional. - *

- * - * @param itemId - * ID of the item to be set as the child of the Item - * identified with newParentId - * @param newParentId - * ID of the Item that's to be the new parent of the Item - * identified with itemId - * @return true if the operation succeeded, - * false if not - */ - public boolean setParent(Object itemId, Object newParentId) - throws UnsupportedOperationException; - - /** - * Tests if the Item with given ID can have any children. If the - * Container also implements the Managed interface, the - * items created with newItem can have children by - * default. - * - * @param itemId - * ID of the Item in the container whose child capability is - * to be tested - * @return true if the specified Item exists in the - * Container and it can have children, false if - * it's not found from the container or it can't have children. - */ - public boolean areChildrenAllowed(Object itemId); - - /** - *

- * Sets the given Item's capability to have children. If the Item - * identified with itemId already has children and - * areChildrenAllowed is false this method fails and - * false is returned. - *

- *

- * The children must be first explicitly removed with - * {@link #setParent(Object itemId, Object newParentId)}or - * {@link com.itmill.toolkit.data.Container#removeItem(Object itemId)}. - *

- * - *

- * This operation is optional. If it is not implemented, the method - * always returns false. - *

- * - * @param itemId - * ID of the Item in the container whose child capability is - * to be set - * @param areChildrenAllowed - * boolean value specifying if the Item can have children or - * not - * @return true if the operation succeeded, - * false if not - */ - public boolean setChildrenAllowed(Object itemId, - boolean areChildrenAllowed) - throws UnsupportedOperationException; - - /** - * Tests if the Item specified with itemId is a root - * Item. The hierarchical container can have more than one root and must - * have at least one unless it is empty. The - * {@link #getParent(Object itemId)}method always returns - * null for root Items. - * - * @param itemId - * ID of the Item whose root status is to be tested - * @return true if the specified Item is a root, - * false if not - */ - public boolean isRoot(Object itemId); - - /** - *

- * Tests if the Item specified with itemId has any child - * Items, that is, is it a leaf Item. The - * {@link #getChildren(Object itemId)}method always returns - * null for leaf Items. - *

- * - *

- * Note that being a leaf does not imply whether or not an Item is - * allowed to have children. - *

. - * - * @param itemId - * ID of the Item whose leaf status is to be tested - * @return true if the specified Item is a leaf, - * false if not - */ - public boolean hasChildren(Object itemId); - } - - /** Interface is implemented by containers that allow reducing their visiblecontents with - * set of filters. - * - * When a set of filters are set, only items that match the filters are included in the - * visible contents of the container. Still new items that do not match filters can be - * added to the container. Multiple filters can be added and the container remembers the - * state of the filters. When multiple filters are added, all filters must match for - * an item to be visible in the container. - * - * @since 5.0 - */ - public interface Filterable extends Container { - - /** Add a filter for given property. - * - * Only items where given property for which toString() contains or starts - * with given filterString are visible in the container. - * - * @param propertyId Property for which the filter is applied to. - * @param filterString String that must match contents of the property - * @param ignoreCase Determine if the casing can be ignored when comparing strings. - * @param onlyMatchPrefix Only match prefixes; no other matches are included. - */ - public void addContainerFilter(Object propertyId, String filterString, boolean ignoreCase, boolean onlyMatchPrefix); - - /** Remove all filters from all properties. */ - public void removeAllContainerFilters(); - - /** Remove all filters from given property. */ - public void removeContainerFilters(Object propertyId); - } - - - /** - * Interface implemented by viewer classes capable of using a Container as a - * data source. - */ - public interface Viewer { - - /** - * Sets the Container that serves as the data source of the viewer. - * - * @param newDataSource - * The new data source Item - */ - public void setContainerDataSource(Container newDataSource); - - /** - * Gets the Container serving as the data source of the viewer. - * - * @return data source Container - */ - public Container getContainerDataSource(); - - } - - /** - *

- * Interface implemented by the editor classes supporting editing the - * Container. Implementing this interface means that the Container serving - * as the data source of the editor can be modified through it. - *

- *

- * Note that not implementing the Container.Editor interface - * does not restrict the class from editing the Container contents - * internally. - *

- */ - public interface Editor extends Container.Viewer { - - } - - /* Contents change event ******************************************* */ - - /** - * An Event object specifying the Container whose Item set - * has changed. Note that these events are triggered only through succesful - * calls to the newItem and removeAllItems - * methods in the Container.Managed interface. - */ - public interface ItemSetChangeEvent { - - /** - * Gets the Property where the event occurred. - * - * @return source of the event - */ - public Container getContainer(); - } - - /** Container Item set change listener interface. */ - public interface ItemSetChangeListener { - - /** - * Lets the listener know a Containers Item set has changed. - * - * @param event - * change event text - */ - public void containerItemSetChange(Container.ItemSetChangeEvent event); - } - - /** - * The interface for adding and removing ItemSetChangeEvent - * listeners. By implementing this interface a class explicitly announces - * that it will generate a ItemSetChangeEvent when its - * contents are modified. - *

- * Note: The general Java convention is not to explicitly declare that a - * class generates events, but to directly define the - * addListener and removeListener methods. - * That way the caller of these methods has no real way of finding out if - * the class really will send the events, or if it just defines the methods - * to be able to implement an interface. - *

- */ - public interface ItemSetChangeNotifier { - - /** - * Adds an Item set change listener for the object. - * - * @param listener - * listener to be added - */ - public void addListener(Container.ItemSetChangeListener listener); - - /** - * Removes the Item set change listener from the object. - * - * @param listener - * listener to be removed - */ - public void removeListener(Container.ItemSetChangeListener listener); - } - - /* Property set change event ******************************************** */ - - /** - * An Event object specifying the Container whose Property - * set has changed. - *

- * Note: These events are triggered only through succesful calls to the - * addProperty and removeProperty methods in - * the Container.Managed interface. - *

- */ - public interface PropertySetChangeEvent { - - /** - * Retrieves the Container whose contents have been modified. - * - * @return Source Container of the event. - */ - public Container getContainer(); - } - - /** - * The listener interface for receiving PropertySetChangeEvent - * objects. - */ - public interface PropertySetChangeListener { - - /** - * Notifies this listener that the Containers contents has changed. - * - * @param event - * Change event. - */ - public void containerPropertySetChange( - Container.PropertySetChangeEvent event); - } - - /** - *

- * The interface for adding and removing PropertySetChangeEvent - * listeners. By implementing this interface a class explicitly announces - * that it will generate a PropertySetChangeEvent when its - * contents are modified. - *

- *

- * Note that the general Java convention is not to explicitly declare that a - * class generates events, but to directly define the - * addListener and removeListener methods. - * That way the caller of these methods has no real way of finding out if - * the class really will send the events, or if it just defines the methods - * to be able to implement an interface. - *

- */ - public interface PropertySetChangeNotifier { - - /** - * Registers a new Property set change listener for this Container. - * - * @param listener - * The new Listener to be registered - */ - public void addListener(Container.PropertySetChangeListener listener); - - /** - * Removes a previously registered Property set change listener. - * - * @param listener - * Listener to be removed - */ - public void removeListener(Container.PropertySetChangeListener listener); - } + /** + * Gets the Item with the given Item ID from the Container. If the Container + * does not contain the requested Item, null is returned. + * + * @param itemId + * ID of the Item to retrieve + * @return the Item with the given ID or null if the Item is + * not found in the Container + */ + public Item getItem(Object itemId); + + /** + * Gets the ID's of all Properties stored in the Container. The ID's are + * returned as a unmodifiable collection. + * + * @return unmodifiable collection of Property IDs + */ + public Collection getContainerPropertyIds(); + + /** + * Gets the ID's of all Items stored in the Container. The ID's are returned + * as a unmodifiable collection. + * + * @return unmodifiable collection of Item IDs + */ + public Collection getItemIds(); + + /** + * Gets the Property identified by the given itemId and propertyId from the + * Container. If the Container does not contain the Property, + * null is returned. + * + * @param itemId + * ID of the Item which contains the Property + * @param propertyId + * ID of the Property to retrieve + * @return Property with the given ID or null + */ + public Property getContainerProperty(Object itemId, Object propertyId); + + /** + * Gets the data type of all Properties identified by the given Property ID. + * + * @param propertyId + * ID identifying the Properties + * @return data type of the Properties + */ + public Class getType(Object propertyId); + + /** + * Gets the number of Items in the Container. + * + * @return number of Items in the Container + */ + public int size(); + + /** + * Tests if the Container contains the specified Item + * + * @param itemId + * ID the of Item to be tested + * @return boolean indicating if the Container holds the specified Item + */ + public boolean containsId(Object itemId); + + /** + * Creates a new Item with the given ID into the Container. The new + *

+ * Item is returned, and it is ready to have its Properties modified. + * Returns null if the operation fails or the Container + * already contains a Item with the given ID. + *

+ * + *

+ * This functionality is optional. + *

+ * + * @param itemId + * ID of the Item to be created + * @return Created new Item, or null in case of a failure + */ + public Item addItem(Object itemId) throws UnsupportedOperationException; + + /** + * Creates a new Item into the Container, and assign it an automatic ID. + * + *

+ * The new ID is returned, or null if the operation fails. + * After a successful call you can use the + * {@link #getItem(Object ItemId) getItem}method to fetch the + * Item. + *

+ * + *

+ * This functionality is optional. + *

+ * + * @return ID of the newly created Item, or null in case of a + * failure + */ + public Object addItem() throws UnsupportedOperationException; + + /** + * Removes the Item identified by ItemId from the Container. + * This functionality is optional. + * + * @param itemId + * ID of the Item to remove + * @return true if the operation succeeded, + * false if not + */ + public boolean removeItem(Object itemId) + throws UnsupportedOperationException; + + /** + * Adds a new Property to all Items in the Container. The Property ID, data + * type and default value of the new Property are given as parameters. + * + * This functionality is optional. + * + * @param propertyId + * ID of the Property + * @param type + * Data type of the new Property + * @param defaultValue + * The value all created Properties are initialized to + * @return true if the operation succeeded, + * false if not + */ + public boolean addContainerProperty(Object propertyId, Class type, + Object defaultValue) throws UnsupportedOperationException; + + /** + * Removes a Property specified by the given Property ID from the Container. + * Note that the Property will be removed from all Items in the Container. + * + * This functionality is optional. + * + * @param propertyId + * ID of the Property to remove + * @return true if the operation succeeded, + * false if not + */ + public boolean removeContainerProperty(Object propertyId) + throws UnsupportedOperationException; + + /** + * Removes all Items from the Container. + * + *

+ * Note that Property ID and type information is preserved. This + * functionality is optional. + *

+ * + * @return true if the operation succeeded, + * false if not + */ + public boolean removeAllItems() throws UnsupportedOperationException; + + /** + * Interface for Container classes whose Items can be traversed in order. + */ + public interface Ordered extends Container { + + /** + * Gets the ID of the Item following the Item that corresponds to + * itemId. If the given Item is the last or not found in + * the Container, null is returned. + * + * @param itemId + * ID of an Item in the Container + * @return ID of the next Item or null + */ + public Object nextItemId(Object itemId); + + /** + * Gets the ID of the Item preceding the Item that corresponds to + * itemId. If the given Item is the first or not found + * in the Container, null is returned. + * + * @param itemId + * ID of an Item in the Container + * @return ID of the previous Item or null + */ + public Object prevItemId(Object itemId); + + /** + * Gets the ID of the first Item in the Container. + * + * @return ID of the first Item in the Container + */ + public Object firstItemId(); + + /** + * Gets the ID of the last Item in the Container.. + * + * @return ID of the last Item in the Container + */ + public Object lastItemId(); + + /** + * Tests if the Item corresponding to the given Item ID is the first + * Item in the Container. + * + * @param itemId + * ID of an Item in the Container + * @return true if the Item is first in the Container, + * false if not + */ + public boolean isFirstId(Object itemId); + + /** + * Tests if the Item corresponding to the given Item ID is the last Item + * in the Container. + * + * @return true if the Item is last in the Container, + * false if not + */ + public boolean isLastId(Object itemId); + + /** + * Adds new item after the given item. + *

+ * Adding an item after null item adds the item as first item of the + * ordered container. + *

+ * + * @param previousItemId + * Id of the previous item in ordered container. + * @return Returns item id the the created new item or null if the + * operation fails. + */ + public Object addItemAfter(Object previousItemId) + throws UnsupportedOperationException; + + /** + * Adds new item after the given item. + *

+ * Adding an item after null item adds the item as first item of the + * ordered container. + *

+ * + * @param previousItemId + * Id of the previous item in ordered container. + * @param newItemId + * Id of the new item to be added. + * @return Returns new item or null if the operation fails. + */ + public Item addItemAfter(Object previousItemId, Object newItemId) + throws UnsupportedOperationException; + + } + + /** Interface for Container classes whose Items can be sorted. */ + public interface Sortable extends Ordered { + + /** + * Sort method. + * + * Sorts the container items. + * + * @param propertyId + * Array of container property IDs, which values are used + * to sort the items in container as primary, secondary, + * ... sorting criterion. All of the item IDs must be in + * the collection returned by + * getSortableContainerPropertyIds + * @param ascending + * Array of sorting order flags corresponding to each + * property ID used in sorting. If this array is shorter + * than propertyId array, ascending order is assumed for + * items where the order is not specified. Use + * true to sort in ascending order, + * false to use descending order. + */ + void sort(Object[] propertyId, boolean[] ascending); + + /** + * Gets the container property IDs, which can be used to sort the item. + * + * @return The sortable field ids. + */ + Collection getSortableContainerPropertyIds(); + + } + + /** Interface for Container classes whose Items can be indexed. */ + public interface Indexed extends Ordered { + + /** + * Gets the index of the Item corresponding to the itemId. The following + * is true for the returned index: 0 <= index < size(). + * + * @param itemId + * ID of an Item in the Container + * @return index of the Item, or -1 if the Container does not include + * the Item + */ + public int indexOfId(Object itemId); + + /** + * Gets the ID of an Item by an index number. + * + * @param index + * Index of the requested id in the Container + * @return ID of the Item in the given index + */ + public Object getIdByIndex(int index); + + /** + * Adds new item at given index. + *

+ * The indexes of the item currently in the given position and all the + * following items are incremented. + *

+ * + * @param index + * Index to add the new item. + * @return Returns item id the the created new item or null if the + * operation fails. + */ + public Object addItemAt(int index) throws UnsupportedOperationException; + + /** + * Adds new item at given index. + *

+ * The indexes of the item currently in the given position and all the + * following items are incremented. + *

+ * + * @param index + * Index to add the new item. + * @param newItemId + * Id of the new item to be added. + * @return Returns new item or null if the operation fails. + */ + public Item addItemAt(int index, Object newItemId) + throws UnsupportedOperationException; + + } + + /** + *

+ * Interface for Container classes whose Items can be + * arranged hierarchically. This means that the Items in the container + * belong in a tree-like structure, with the following quirks: + *

+ * + * + */ + public interface Hierarchical extends Container { + + /** + * Gets the IDs of all Items that are children of the specified Item. + * The returned collection is unmodifiable. + * + * @param itemId + * ID of the Item whose children the caller is interested + * in + * @return An unmodifiable {@link java.util.Collection collection} + * containing the IDs of all other Items that are children in + * the container hierarchy + */ + public Collection getChildren(Object itemId); + + /** + * Gets the ID of the parent Item of the specified Item. + * + * @param itemId + * ID of the Item whose parent the caller wishes to find + * out. + * @return the ID of the parent Item. Will be null if the + * specified Item is a root element. + */ + public Object getParent(Object itemId); + + /** + * Gets the IDs of all Items in the container that don't have a parent. + * Such items are called root Items. The returned + * collection is unmodifiable. + * + * @return An unmodifiable {@link java.util.Collection collection} + * containing IDs of all root elements of the container + */ + public Collection rootItemIds(); + + /** + *

+ * Sets the parent of an Item. The new parent item must exist and be + * able to have children. ( + * canHaveChildren(newParentId) == true). It is also + * possible to detach a node from the hierarchy (and thus make it root) + * by setting the parent null. + *

+ * + *

+ * This operation is optional. + *

+ * + * @param itemId + * ID of the item to be set as the child of the Item + * identified with newParentId + * @param newParentId + * ID of the Item that's to be the new parent of the Item + * identified with itemId + * @return true if the operation succeeded, + * false if not + */ + public boolean setParent(Object itemId, Object newParentId) + throws UnsupportedOperationException; + + /** + * Tests if the Item with given ID can have any children. If the + * Container also implements the Managed interface, the + * items created with newItem can have children by + * default. + * + * @param itemId + * ID of the Item in the container whose child capability + * is to be tested + * @return true if the specified Item exists in the + * Container and it can have children, false if + * it's not found from the container or it can't have children. + */ + public boolean areChildrenAllowed(Object itemId); + + /** + *

+ * Sets the given Item's capability to have children. If the Item + * identified with itemId already has children and + * areChildrenAllowed is false this method fails and + * false is returned. + *

+ *

+ * The children must be first explicitly removed with + * {@link #setParent(Object itemId, Object newParentId)}or + * {@link com.itmill.toolkit.data.Container#removeItem(Object itemId)}. + *

+ * + *

+ * This operation is optional. If it is not implemented, the method + * always returns false. + *

+ * + * @param itemId + * ID of the Item in the container whose child capability + * is to be set + * @param areChildrenAllowed + * boolean value specifying if the Item can have children + * or not + * @return true if the operation succeeded, + * false if not + */ + public boolean setChildrenAllowed(Object itemId, + boolean areChildrenAllowed) + throws UnsupportedOperationException; + + /** + * Tests if the Item specified with itemId is a root + * Item. The hierarchical container can have more than one root and must + * have at least one unless it is empty. The + * {@link #getParent(Object itemId)}method always returns + * null for root Items. + * + * @param itemId + * ID of the Item whose root status is to be tested + * @return true if the specified Item is a root, + * false if not + */ + public boolean isRoot(Object itemId); + + /** + *

+ * Tests if the Item specified with itemId has any child + * Items, that is, is it a leaf Item. The + * {@link #getChildren(Object itemId)}method always returns + * null for leaf Items. + *

+ * + *

+ * Note that being a leaf does not imply whether or not an Item is + * allowed to have children. + *

. + * + * @param itemId + * ID of the Item whose leaf status is to be tested + * @return true if the specified Item is a leaf, + * false if not + */ + public boolean hasChildren(Object itemId); + } + + /** + * Interface is implemented by containers that allow reducing their + * visiblecontents with set of filters. + * + * When a set of filters are set, only items that match the filters are + * included in the visible contents of the container. Still new items that + * do not match filters can be added to the container. Multiple filters can + * be added and the container remembers the state of the filters. When + * multiple filters are added, all filters must match for an item to be + * visible in the container. + * + * @since 5.0 + */ + public interface Filterable extends Container { + + /** + * Add a filter for given property. + * + * Only items where given property for which toString() contains or + * starts with given filterString are visible in the container. + * + * @param propertyId + * Property for which the filter is applied to. + * @param filterString + * String that must match contents of the property + * @param ignoreCase + * Determine if the casing can be ignored when comparing + * strings. + * @param onlyMatchPrefix + * Only match prefixes; no other matches are included. + */ + public void addContainerFilter(Object propertyId, String filterString, + boolean ignoreCase, boolean onlyMatchPrefix); + + /** Remove all filters from all properties. */ + public void removeAllContainerFilters(); + + /** Remove all filters from given property. */ + public void removeContainerFilters(Object propertyId); + } + + /** + * Interface implemented by viewer classes capable of using a Container as a + * data source. + */ + public interface Viewer { + + /** + * Sets the Container that serves as the data source of the viewer. + * + * @param newDataSource + * The new data source Item + */ + public void setContainerDataSource(Container newDataSource); + + /** + * Gets the Container serving as the data source of the viewer. + * + * @return data source Container + */ + public Container getContainerDataSource(); + + } + + /** + *

+ * Interface implemented by the editor classes supporting editing the + * Container. Implementing this interface means that the Container serving + * as the data source of the editor can be modified through it. + *

+ *

+ * Note that not implementing the Container.Editor interface + * does not restrict the class from editing the Container contents + * internally. + *

+ */ + public interface Editor extends Container.Viewer { + + } + + /* Contents change event ******************************************* */ + + /** + * An Event object specifying the Container whose Item set + * has changed. Note that these events are triggered only through succesful + * calls to the newItem and removeAllItems + * methods in the Container.Managed interface. + */ + public interface ItemSetChangeEvent { + + /** + * Gets the Property where the event occurred. + * + * @return source of the event + */ + public Container getContainer(); + } + + /** Container Item set change listener interface. */ + public interface ItemSetChangeListener { + + /** + * Lets the listener know a Containers Item set has changed. + * + * @param event + * change event text + */ + public void containerItemSetChange(Container.ItemSetChangeEvent event); + } + + /** + * The interface for adding and removing ItemSetChangeEvent + * listeners. By implementing this interface a class explicitly announces + * that it will generate a ItemSetChangeEvent when its + * contents are modified. + *

+ * Note: The general Java convention is not to explicitly declare that a + * class generates events, but to directly define the + * addListener and removeListener methods. + * That way the caller of these methods has no real way of finding out if + * the class really will send the events, or if it just defines the methods + * to be able to implement an interface. + *

+ */ + public interface ItemSetChangeNotifier { + + /** + * Adds an Item set change listener for the object. + * + * @param listener + * listener to be added + */ + public void addListener(Container.ItemSetChangeListener listener); + + /** + * Removes the Item set change listener from the object. + * + * @param listener + * listener to be removed + */ + public void removeListener(Container.ItemSetChangeListener listener); + } + + /* Property set change event ******************************************** */ + + /** + * An Event object specifying the Container whose Property + * set has changed. + *

+ * Note: These events are triggered only through succesful calls to the + * addProperty and removeProperty methods in + * the Container.Managed interface. + *

+ */ + public interface PropertySetChangeEvent { + + /** + * Retrieves the Container whose contents have been modified. + * + * @return Source Container of the event. + */ + public Container getContainer(); + } + + /** + * The listener interface for receiving PropertySetChangeEvent + * objects. + */ + public interface PropertySetChangeListener { + + /** + * Notifies this listener that the Containers contents has changed. + * + * @param event + * Change event. + */ + public void containerPropertySetChange( + Container.PropertySetChangeEvent event); + } + + /** + *

+ * The interface for adding and removing PropertySetChangeEvent + * listeners. By implementing this interface a class explicitly announces + * that it will generate a PropertySetChangeEvent when its + * contents are modified. + *

+ *

+ * Note that the general Java convention is not to explicitly declare that a + * class generates events, but to directly define the + * addListener and removeListener methods. + * That way the caller of these methods has no real way of finding out if + * the class really will send the events, or if it just defines the methods + * to be able to implement an interface. + *

+ */ + public interface PropertySetChangeNotifier { + + /** + * Registers a new Property set change listener for this Container. + * + * @param listener + * The new Listener to be registered + */ + public void addListener(Container.PropertySetChangeListener listener); + + /** + * Removes a previously registered Property set change listener. + * + * @param listener + * Listener to be removed + */ + public void removeListener(Container.PropertySetChangeListener listener); + } } \ No newline at end of file diff --git a/src/com/itmill/toolkit/data/Item.java b/src/com/itmill/toolkit/data/Item.java index 8e3437993e..a06a9dd72d 100644 --- a/src/com/itmill/toolkit/data/Item.java +++ b/src/com/itmill/toolkit/data/Item.java @@ -44,161 +44,161 @@ import java.util.Collection; */ public interface Item { - /** - * Gets the Property corresponding to the given Property ID stored in the - * Item. If the Item does not contain the Property, null is - * returned. - * - * @param id - * identifier of the Property to get - * @return the Property with the given ID or null - */ - public Property getItemProperty(Object id); - - /** - * Gets the collection of IDs of all Properties stored in the Item. - * - * @return unmodifiable collection containing IDs of the Properties stored - * the Item - */ - public Collection getItemPropertyIds(); - - /** - * Tries to add a new Property into the Item. - * - *

- * This functionality is optional. - *

- * - * @param id - * ID of the new Property - * @param property - * the Property to be added and associated with the id - * @return true if the operation succeeded, - * false if not - * @throws UnsupportedOperationException - * if the operation is not supported. - */ - public boolean addItemProperty(Object id, Property property) - throws UnsupportedOperationException; - - /** - * Removes the Property identified by ID from the Item. - * - *

- * This functionality is optional. - *

- * - * @param id - * ID of the Property to be removed - * @return true if the operation succeeded - * @throws UnsupportedOperationException - * if the operation is not supported. false if - * not - */ - public boolean removeItemProperty(Object id) - throws UnsupportedOperationException; - - /** - * Interface implemented by viewer classes capable of using an Item as a - * data source. - */ - public interface Viewer { - - /** - * Sets the Item that serves as the data source of the viewer. - * - * @param newDataSource - * The new data source Item - */ - public void setItemDataSource(Item newDataSource); - - /** - * Gets the Item serving as the data source of the viewer. - * - * @return data source Item - */ - public Item getItemDataSource(); - } - - /** - * Interface implemented by the Editor classes capable of - * editing the Item. Implementing this interface means that the Item serving - * as the data source of the editor can be modified through it. - *

- * Note : Not implementing the Item.Editor interface does not - * restrict the class from editing the contents of an internally. - *

- */ - public interface Editor extends Item.Viewer { - - } - - /* Property set change event ******************************************** */ - - /** - * An Event object specifying the Item whose contents has - * been changed through the Property interface. - *

- * Note: The values stored in the Properties may change without triggering - * this event. - *

- */ - public interface PropertySetChangeEvent { - - /** - * Retrieves the Item whose contents has been modified. - * - * @return source Item of the event - */ - public Item getItem(); - } - - /** - * The listener interface for receiving PropertySetChangeEvent - * objects. - */ - public interface PropertySetChangeListener { - - /** - * Notifies this listener that the Item's property set has changed. - * - * @param event - * Property set change event object - */ - public void itemPropertySetChange(Item.PropertySetChangeEvent event); - } - - /** - * The interface for adding and removing PropertySetChangeEvent - * listeners. By implementing this interface a class explicitly announces - * that it will generate a PropertySetChangeEvent when its - * Property set is modified. - *

- * Note : The general Java convention is not to explicitly declare that a - * class generates events, but to directly define the - * addListener and removeListener methods. - * That way the caller of these methods has no real way of finding out if - * the class really will send the events, or if it just defines the methods - * to be able to implement an interface. - *

- */ - public interface PropertySetChangeNotifier { - - /** - * Registers a new property set change listener for this Item. - * - * @param listener - * The new Listener to be registered. - */ - public void addListener(Item.PropertySetChangeListener listener); - - /** - * Removes a previously registered property set change listener. - * - * @param listener - * Listener to be removed. - */ - public void removeListener(Item.PropertySetChangeListener listener); - } + /** + * Gets the Property corresponding to the given Property ID stored in the + * Item. If the Item does not contain the Property, null is + * returned. + * + * @param id + * identifier of the Property to get + * @return the Property with the given ID or null + */ + public Property getItemProperty(Object id); + + /** + * Gets the collection of IDs of all Properties stored in the Item. + * + * @return unmodifiable collection containing IDs of the Properties stored + * the Item + */ + public Collection getItemPropertyIds(); + + /** + * Tries to add a new Property into the Item. + * + *

+ * This functionality is optional. + *

+ * + * @param id + * ID of the new Property + * @param property + * the Property to be added and associated with the id + * @return true if the operation succeeded, + * false if not + * @throws UnsupportedOperationException + * if the operation is not supported. + */ + public boolean addItemProperty(Object id, Property property) + throws UnsupportedOperationException; + + /** + * Removes the Property identified by ID from the Item. + * + *

+ * This functionality is optional. + *

+ * + * @param id + * ID of the Property to be removed + * @return true if the operation succeeded + * @throws UnsupportedOperationException + * if the operation is not supported. false + * if not + */ + public boolean removeItemProperty(Object id) + throws UnsupportedOperationException; + + /** + * Interface implemented by viewer classes capable of using an Item as a + * data source. + */ + public interface Viewer { + + /** + * Sets the Item that serves as the data source of the viewer. + * + * @param newDataSource + * The new data source Item + */ + public void setItemDataSource(Item newDataSource); + + /** + * Gets the Item serving as the data source of the viewer. + * + * @return data source Item + */ + public Item getItemDataSource(); + } + + /** + * Interface implemented by the Editor classes capable of + * editing the Item. Implementing this interface means that the Item serving + * as the data source of the editor can be modified through it. + *

+ * Note : Not implementing the Item.Editor interface does not + * restrict the class from editing the contents of an internally. + *

+ */ + public interface Editor extends Item.Viewer { + + } + + /* Property set change event ******************************************** */ + + /** + * An Event object specifying the Item whose contents has + * been changed through the Property interface. + *

+ * Note: The values stored in the Properties may change without triggering + * this event. + *

+ */ + public interface PropertySetChangeEvent { + + /** + * Retrieves the Item whose contents has been modified. + * + * @return source Item of the event + */ + public Item getItem(); + } + + /** + * The listener interface for receiving PropertySetChangeEvent + * objects. + */ + public interface PropertySetChangeListener { + + /** + * Notifies this listener that the Item's property set has changed. + * + * @param event + * Property set change event object + */ + public void itemPropertySetChange(Item.PropertySetChangeEvent event); + } + + /** + * The interface for adding and removing PropertySetChangeEvent + * listeners. By implementing this interface a class explicitly announces + * that it will generate a PropertySetChangeEvent when its + * Property set is modified. + *

+ * Note : The general Java convention is not to explicitly declare that a + * class generates events, but to directly define the + * addListener and removeListener methods. + * That way the caller of these methods has no real way of finding out if + * the class really will send the events, or if it just defines the methods + * to be able to implement an interface. + *

+ */ + public interface PropertySetChangeNotifier { + + /** + * Registers a new property set change listener for this Item. + * + * @param listener + * The new Listener to be registered. + */ + public void addListener(Item.PropertySetChangeListener listener); + + /** + * Removes a previously registered property set change listener. + * + * @param listener + * Listener to be removed. + */ + public void removeListener(Item.PropertySetChangeListener listener); + } } diff --git a/src/com/itmill/toolkit/data/Property.java b/src/com/itmill/toolkit/data/Property.java index 5999e5cd9e..aa9a79b6d0 100644 --- a/src/com/itmill/toolkit/data/Property.java +++ b/src/com/itmill/toolkit/data/Property.java @@ -60,372 +60,372 @@ package com.itmill.toolkit.data; */ public interface Property { - /** - * Gets the value stored in the Property. - * - * @return the value stored in the Property - */ - public Object getValue(); - - /** - * Sets the value of the Property. - *

- * Implementing this functionality is optional. If the functionality is - * missing, one should declare the Property to be in read-only mode and - * throw Property.ReadOnlyException in this function. - *

- * Note : It is not required, but highly recommended to support setting the - * value also as a String in addition to the native type of - * the Property (as given by the getType method). If the - * String conversion fails or is unsupported, the method - * should throw Property.ConversionException. The string - * conversion should at least understand the format returned by the - * toString method of the Property. - * - * @param newValue - * New value of the Property. This should be assignable to the - * type returned by getType, but also String type should be - * supported - * - * @throws Property.ReadOnlyException - * if the object is in read-only mode - * @throws Property.ConversionException - * if newValue can't be converted into the Property's native - * type directly or through String - */ - public void setValue(Object newValue) throws Property.ReadOnlyException, - Property.ConversionException; - - /** - * Returns the value of the Property in human readable textual format. The - * return value should be assignable to the setValue method - * if the Property is not in read-only mode. - * - * @return String representation of the value stored in the - * Property - */ - public String toString(); - - /** - * Returns the type of the Property. The methods getValue and - * setValue must be compatible with this type: one must be - * able to safely cast the value returned from getValue to - * the given type and pass any variable assignable to this type as an - * argument to setValue. - * - * @return type of the Property - */ - public Class getType(); - - /** - * Tests if the Property is in read-only mode. In read-only mode calls to - * the method setValue will throw - * ReadOnlyException and will not modify the value of the - * Property. - * - * @return true if the Property is in read-only mode, - * false if it's not - */ - public boolean isReadOnly(); - - /** - * Sets the Property's read-only mode to the specified status. - * - * This functionality is optional, but all properties must implement the - * isReadOnly mode query correctly. - * - * @param newStatus - * new read-only status of the Property - */ - public void setReadOnly(boolean newStatus); - - /** - * Exception object that signals that a requested Property - * modification failed because it's in read-only mode. - * - * @author IT Mill Ltd. - * @version - * @VERSION@ - * @since 3.0 - */ - public class ReadOnlyException extends RuntimeException { - - /** - * Serial generated by eclipse. - */ - private static final long serialVersionUID = 3257571702287119410L; - - /** - * Constructs a new ReadOnlyException without a detail - * message. - */ - public ReadOnlyException() { - } - - /** - * Constructs a new ReadOnlyException with the specified - * detail message. - * - * @param msg - * the detail message - */ - public ReadOnlyException(String msg) { - super(msg); - } - } - - /** - * An exception that signals that the value passed to the - * setValue method couldn't be converted to the native type - * of the Property. - * - * @author IT Mill Ltd - * @version - * @VERSION@ - * @since 3.0 - */ - public class ConversionException extends RuntimeException { - - /** - * Serial generated by eclipse. - */ - private static final long serialVersionUID = 3257571706666366008L; - - /** - * Constructs a new ConversionException without a detail - * message. - */ - public ConversionException() { - } - - /** - * Constructs a new ConversionException with the - * specified detail message. - * - * @param msg - * the detail message - */ - public ConversionException(String msg) { - super(msg); - } - - /** - * Constructs a new ConversionException from another - * exception. - * - * @param cause - * The cause of the the conversion failure - */ - public ConversionException(Throwable cause) { - super(cause.toString()); - } - } - - /** - * Interface implemented by the viewer classes capable of using a Property - * as a data source. - * - * @author IT Mill Ltd. - * @version - * @VERSION@ - * @since 3.0 - */ - public interface Viewer { - - /** - * Sets the Property that serves as the data source of the viewer. - * - * @param newDataSource - * the new data source Property - */ - public void setPropertyDataSource(Property newDataSource); - - /** - * Gets the Property serving as the data source of the viewer. - * - * @return the Property serving as the viewers data source - */ - public Property getPropertyDataSource(); - } - - /** - * Interface implemented by the editor classes capable of editing the - * Property. - *

- * Implementing this interface means that the Property serving as the data - * source of the editor can be modified through the editor. It does not - * restrict the editor from editing the Property internally, though if the - * Property is in a read-only mode, attempts to modify it will result in the - * ReadOnlyException being thrown. - *

- * - * @author IT Mill Ltd. - * @version - * @VERSION@ - * @since 3.0 - */ - public interface Editor extends Property.Viewer { - - } - - /* Value change event ******************************************* */ - - /** - * An Event object specifying the Property whose value has - * been changed. - * - * @author IT Mill Ltd. - * @version - * @VERSION@ - * @since 3.0 - */ - public interface ValueChangeEvent { - - /** - * Retrieves the Property that has been modified. - * - * @return source Property of the event - */ - public Property getProperty(); - } - - /** - * The listener interface for receiving - * ValueChangeEvent objects. - * - * @author IT Mill Ltd. - * @version - * @VERSION@ - * @since 3.0 - */ - public interface ValueChangeListener { - - /** - * Notifies this listener that the Property's value has changed. - * - * @param event - * value change event object - */ - public void valueChange(Property.ValueChangeEvent event); - } - - /** - * The interface for adding and removing ValueChangeEvent - * listeners. If a Property wishes to allow other objects to receive - * ValueChangeEvent generated by it, it must implement this - * interface. - *

- * Note : The general Java convention is not to explicitly declare that a - * class generates events, but to directly define the - * addListener and removeListener methods. - * That way the caller of these methods has no real way of finding out if - * the class really will send the events, or if it just defines the methods - * to be able to implement an interface. - *

- * - * @author IT Mill Ltd. - * @version - * @VERSION@ - * @since 3.0 - */ - public interface ValueChangeNotifier { - - /** - * Registers a new value change listener for this Property. - * - * @param listener - * the new Listener to be registered - */ - public void addListener(Property.ValueChangeListener listener); - - /** - * Removes a previously registered value change listener. - * - * @param listener - * listener to be removed - */ - public void removeListener(Property.ValueChangeListener listener); - } - - /* ReadOnly Status change event ***************************************** */ - - /** - * An Event object specifying the Property whose read-only - * status has been changed. - * - * @author IT Mill Ltd. - * @version - * @VERSION@ - * @since 3.0 - */ - public interface ReadOnlyStatusChangeEvent { - - /** - * Property whose read-only state has changed. - * - * @return source Property of the event. - */ - public Property getProperty(); - } - - /** - * The listener interface for receiving - * ReadOnlyStatusChangeEvent objects. - * - * @author IT Mill Ltd. - * @version - * @VERSION@ - * @since 3.0 - */ - public interface ReadOnlyStatusChangeListener { - - /** - * Notifies this listener that a Property's read-only status has - * changed. - * - * @param event - * Read-only status change event object - */ - public void readOnlyStatusChange( - Property.ReadOnlyStatusChangeEvent event); - } - - /** - * The interface for adding and removing - * ReadOnlyStatusChangeEvent listeners. If a Property wishes - * to allow other objects to receive ReadOnlyStatusChangeEvent - * generated by it, it must implement this interface. - *

- * Note : The general Java convention is not to explicitly declare that a - * class generates events, but to directly define the - * addListener and removeListener methods. - * That way the caller of these methods has no real way of finding out if - * the class really will send the events, or if it just defines the methods - * to be able to implement an interface. - *

- * - * @author IT Mill Ltd. - * @version - * @VERSION@ - * @since 3.0 - */ - public interface ReadOnlyStatusChangeNotifier { - - /** - * Registers a new read-only status change listener for this Property. - * - * @param listener - * the new Listener to be registered - */ - public void addListener(Property.ReadOnlyStatusChangeListener listener); - - /** - * Removes a previously registered read-only status change listener. - * - * @param listener - * listener to be removed - */ - public void removeListener( - Property.ReadOnlyStatusChangeListener listener); - } + /** + * Gets the value stored in the Property. + * + * @return the value stored in the Property + */ + public Object getValue(); + + /** + * Sets the value of the Property. + *

+ * Implementing this functionality is optional. If the functionality is + * missing, one should declare the Property to be in read-only mode and + * throw Property.ReadOnlyException in this function. + *

+ * Note : It is not required, but highly recommended to support setting the + * value also as a String in addition to the native type of + * the Property (as given by the getType method). If the + * String conversion fails or is unsupported, the method + * should throw Property.ConversionException. The string + * conversion should at least understand the format returned by the + * toString method of the Property. + * + * @param newValue + * New value of the Property. This should be assignable to + * the type returned by getType, but also String type should + * be supported + * + * @throws Property.ReadOnlyException + * if the object is in read-only mode + * @throws Property.ConversionException + * if newValue can't be converted into the Property's native + * type directly or through String + */ + public void setValue(Object newValue) throws Property.ReadOnlyException, + Property.ConversionException; + + /** + * Returns the value of the Property in human readable textual format. The + * return value should be assignable to the setValue method + * if the Property is not in read-only mode. + * + * @return String representation of the value stored in the + * Property + */ + public String toString(); + + /** + * Returns the type of the Property. The methods getValue and + * setValue must be compatible with this type: one must be + * able to safely cast the value returned from getValue to + * the given type and pass any variable assignable to this type as an + * argument to setValue. + * + * @return type of the Property + */ + public Class getType(); + + /** + * Tests if the Property is in read-only mode. In read-only mode calls to + * the method setValue will throw + * ReadOnlyException and will not modify the value of the + * Property. + * + * @return true if the Property is in read-only mode, + * false if it's not + */ + public boolean isReadOnly(); + + /** + * Sets the Property's read-only mode to the specified status. + * + * This functionality is optional, but all properties must implement the + * isReadOnly mode query correctly. + * + * @param newStatus + * new read-only status of the Property + */ + public void setReadOnly(boolean newStatus); + + /** + * Exception object that signals that a requested Property + * modification failed because it's in read-only mode. + * + * @author IT Mill Ltd. + * @version + * @VERSION@ + * @since 3.0 + */ + public class ReadOnlyException extends RuntimeException { + + /** + * Serial generated by eclipse. + */ + private static final long serialVersionUID = 3257571702287119410L; + + /** + * Constructs a new ReadOnlyException without a detail + * message. + */ + public ReadOnlyException() { + } + + /** + * Constructs a new ReadOnlyException with the specified + * detail message. + * + * @param msg + * the detail message + */ + public ReadOnlyException(String msg) { + super(msg); + } + } + + /** + * An exception that signals that the value passed to the + * setValue method couldn't be converted to the native type + * of the Property. + * + * @author IT Mill Ltd + * @version + * @VERSION@ + * @since 3.0 + */ + public class ConversionException extends RuntimeException { + + /** + * Serial generated by eclipse. + */ + private static final long serialVersionUID = 3257571706666366008L; + + /** + * Constructs a new ConversionException without a detail + * message. + */ + public ConversionException() { + } + + /** + * Constructs a new ConversionException with the + * specified detail message. + * + * @param msg + * the detail message + */ + public ConversionException(String msg) { + super(msg); + } + + /** + * Constructs a new ConversionException from another + * exception. + * + * @param cause + * The cause of the the conversion failure + */ + public ConversionException(Throwable cause) { + super(cause.toString()); + } + } + + /** + * Interface implemented by the viewer classes capable of using a Property + * as a data source. + * + * @author IT Mill Ltd. + * @version + * @VERSION@ + * @since 3.0 + */ + public interface Viewer { + + /** + * Sets the Property that serves as the data source of the viewer. + * + * @param newDataSource + * the new data source Property + */ + public void setPropertyDataSource(Property newDataSource); + + /** + * Gets the Property serving as the data source of the viewer. + * + * @return the Property serving as the viewers data source + */ + public Property getPropertyDataSource(); + } + + /** + * Interface implemented by the editor classes capable of editing the + * Property. + *

+ * Implementing this interface means that the Property serving as the data + * source of the editor can be modified through the editor. It does not + * restrict the editor from editing the Property internally, though if the + * Property is in a read-only mode, attempts to modify it will result in the + * ReadOnlyException being thrown. + *

+ * + * @author IT Mill Ltd. + * @version + * @VERSION@ + * @since 3.0 + */ + public interface Editor extends Property.Viewer { + + } + + /* Value change event ******************************************* */ + + /** + * An Event object specifying the Property whose value has + * been changed. + * + * @author IT Mill Ltd. + * @version + * @VERSION@ + * @since 3.0 + */ + public interface ValueChangeEvent { + + /** + * Retrieves the Property that has been modified. + * + * @return source Property of the event + */ + public Property getProperty(); + } + + /** + * The listener interface for receiving + * ValueChangeEvent objects. + * + * @author IT Mill Ltd. + * @version + * @VERSION@ + * @since 3.0 + */ + public interface ValueChangeListener { + + /** + * Notifies this listener that the Property's value has changed. + * + * @param event + * value change event object + */ + public void valueChange(Property.ValueChangeEvent event); + } + + /** + * The interface for adding and removing ValueChangeEvent + * listeners. If a Property wishes to allow other objects to receive + * ValueChangeEvent generated by it, it must implement this + * interface. + *

+ * Note : The general Java convention is not to explicitly declare that a + * class generates events, but to directly define the + * addListener and removeListener methods. + * That way the caller of these methods has no real way of finding out if + * the class really will send the events, or if it just defines the methods + * to be able to implement an interface. + *

+ * + * @author IT Mill Ltd. + * @version + * @VERSION@ + * @since 3.0 + */ + public interface ValueChangeNotifier { + + /** + * Registers a new value change listener for this Property. + * + * @param listener + * the new Listener to be registered + */ + public void addListener(Property.ValueChangeListener listener); + + /** + * Removes a previously registered value change listener. + * + * @param listener + * listener to be removed + */ + public void removeListener(Property.ValueChangeListener listener); + } + + /* ReadOnly Status change event ***************************************** */ + + /** + * An Event object specifying the Property whose read-only + * status has been changed. + * + * @author IT Mill Ltd. + * @version + * @VERSION@ + * @since 3.0 + */ + public interface ReadOnlyStatusChangeEvent { + + /** + * Property whose read-only state has changed. + * + * @return source Property of the event. + */ + public Property getProperty(); + } + + /** + * The listener interface for receiving + * ReadOnlyStatusChangeEvent objects. + * + * @author IT Mill Ltd. + * @version + * @VERSION@ + * @since 3.0 + */ + public interface ReadOnlyStatusChangeListener { + + /** + * Notifies this listener that a Property's read-only status has + * changed. + * + * @param event + * Read-only status change event object + */ + public void readOnlyStatusChange( + Property.ReadOnlyStatusChangeEvent event); + } + + /** + * The interface for adding and removing + * ReadOnlyStatusChangeEvent listeners. If a Property wishes + * to allow other objects to receive ReadOnlyStatusChangeEvent + * generated by it, it must implement this interface. + *

+ * Note : The general Java convention is not to explicitly declare that a + * class generates events, but to directly define the + * addListener and removeListener methods. + * That way the caller of these methods has no real way of finding out if + * the class really will send the events, or if it just defines the methods + * to be able to implement an interface. + *

+ * + * @author IT Mill Ltd. + * @version + * @VERSION@ + * @since 3.0 + */ + public interface ReadOnlyStatusChangeNotifier { + + /** + * Registers a new read-only status change listener for this Property. + * + * @param listener + * the new Listener to be registered + */ + public void addListener(Property.ReadOnlyStatusChangeListener listener); + + /** + * Removes a previously registered read-only status change listener. + * + * @param listener + * listener to be removed + */ + public void removeListener( + Property.ReadOnlyStatusChangeListener listener); + } } diff --git a/src/com/itmill/toolkit/data/Validatable.java b/src/com/itmill/toolkit/data/Validatable.java index 4cce9bc983..9219dc8b85 100644 --- a/src/com/itmill/toolkit/data/Validatable.java +++ b/src/com/itmill/toolkit/data/Validatable.java @@ -45,89 +45,89 @@ import java.util.Collection; */ public interface Validatable { - /** - *

- * Adds a new validator for this object. The validator's - * {@link Validator#validate(Object)} method is activated every time the - * object's value needs to be verified, that is, when the {@link #isValid()} - * method is called. This usually happens when the object's value changes. - *

- * - * @param validator - * the new validator - */ - void addValidator(Validator validator); - - /** - *

- * Removes a previously registered validator from the object. The specified - * validator is removed from the object and its validate - * method is no longer called in {@link #isValid()}. - *

- * - * @param validator - * the validator to remove - */ - void removeValidator(Validator validator); - - /** - *

- * Lists all validators currently registered for the object. If no - * validators are registered, returns null. - *

- * - * @return collection of validators or null - */ - public Collection getValidators(); - - /** - *

- * Tests the current value of the object against all registered validators. - * The registered validators are iterated and for each the - * {@link Validator#validate(Object)} method is called. If any validator - * throws the {@link Validator.InvalidValueException} this method returns - * false. - *

- * - * @return true if the registered validators concur that the - * value is valid, false otherwise - */ - public boolean isValid(); - - /** - *

- * Checks the validity of the validatable. If the validatable is valid this - * method should do nothing, and if it's not valid, it should throw - * Validator.InvalidValueException - *

- * - * @throws Validator.InvalidValueException - * if the value is not valid - */ - public void validate() throws Validator.InvalidValueException; - - /** - *

- * Checks the validabtable object accept invalid values.The default value is - * true. - *

- * - */ - public boolean isInvalidAllowed(); - - /** - *

- * Should the validabtable object accept invalid values. Supporting this - * configuration possibility is optional. By default invalid values are - * allowed. - *

- * - * @param invalidValueAllowed - * - * @throws UnsupportedOperationException - * if the setInvalidAllowed is not supported. - */ - public void setInvalidAllowed(boolean invalidValueAllowed) - throws UnsupportedOperationException; + /** + *

+ * Adds a new validator for this object. The validator's + * {@link Validator#validate(Object)} method is activated every time the + * object's value needs to be verified, that is, when the {@link #isValid()} + * method is called. This usually happens when the object's value changes. + *

+ * + * @param validator + * the new validator + */ + void addValidator(Validator validator); + + /** + *

+ * Removes a previously registered validator from the object. The specified + * validator is removed from the object and its validate + * method is no longer called in {@link #isValid()}. + *

+ * + * @param validator + * the validator to remove + */ + void removeValidator(Validator validator); + + /** + *

+ * Lists all validators currently registered for the object. If no + * validators are registered, returns null. + *

+ * + * @return collection of validators or null + */ + public Collection getValidators(); + + /** + *

+ * Tests the current value of the object against all registered validators. + * The registered validators are iterated and for each the + * {@link Validator#validate(Object)} method is called. If any validator + * throws the {@link Validator.InvalidValueException} this method returns + * false. + *

+ * + * @return true if the registered validators concur that the + * value is valid, false otherwise + */ + public boolean isValid(); + + /** + *

+ * Checks the validity of the validatable. If the validatable is valid this + * method should do nothing, and if it's not valid, it should throw + * Validator.InvalidValueException + *

+ * + * @throws Validator.InvalidValueException + * if the value is not valid + */ + public void validate() throws Validator.InvalidValueException; + + /** + *

+ * Checks the validabtable object accept invalid values.The default value is + * true. + *

+ * + */ + public boolean isInvalidAllowed(); + + /** + *

+ * Should the validabtable object accept invalid values. Supporting this + * configuration possibility is optional. By default invalid values are + * allowed. + *

+ * + * @param invalidValueAllowed + * + * @throws UnsupportedOperationException + * if the setInvalidAllowed is not supported. + */ + public void setInvalidAllowed(boolean invalidValueAllowed) + throws UnsupportedOperationException; } diff --git a/src/com/itmill/toolkit/data/Validator.java b/src/com/itmill/toolkit/data/Validator.java index c4397eb95a..2dcbb5bb43 100644 --- a/src/com/itmill/toolkit/data/Validator.java +++ b/src/com/itmill/toolkit/data/Validator.java @@ -48,141 +48,143 @@ import com.itmill.toolkit.terminal.PaintTarget; */ public interface Validator { - /** - * Checks the given value against this validator. If the value is valid this - * method should do nothing, and if it's not valid, it should throw - * Validator.InvalidValueException - * - * @param value - * the value to check - * @throws Validator.InvalidValueException - * if the value is not valid - */ - public void validate(Object value) throws Validator.InvalidValueException; - - /** - * Tests if the given value is valid. - * - * @param value - * the value to check - * @return true for valid value, otherwise false. - */ - public boolean isValid(Object value); - - /** - * Adds the proposing functionality to a {@link Validator}. A - * Suggestive validator can propose a valid value for the - * object it is attached to validate. This way the {@link Validatable} - * object may avoid situations where it contains a value that could lead to - * a error. - * - * @author IT Mill Ltd. - * @version - * @VERSION@ - * @since 3.0 - */ - public interface Suggestive extends Validator { - - /** - * Suggests another value that can be used instead of the proposedValue - * if it is invalid. If it is valid in the opinion of this validator, - * however, it is returned as is. - * - * @param proposedValue - * Originally proposed value that could be invalid. - * @return Suggested value that's not invalid against this validator - */ - public Object suggestValidValue(Object proposedValue); - } - - /** - * Invalid value exception can be thrown by {@link Validator} when a given - * value is not valid. - * - * @author IT Mill Ltd. - * @version - * @VERSION@ - * @since 3.0 - */ - public class InvalidValueException extends RuntimeException implements - ErrorMessage { - - /** - * Serial generated by eclipse. - */ - private static final long serialVersionUID = 3689073941163422257L; - - /** Array of validation errors that are causing the problem. */ - private InvalidValueException[] causes = null; - - /** - * Constructs a new InvalidValueException with the - * specified detail message. - * - * @param message - * The detail message of the problem. - */ - public InvalidValueException(String message) { - this(message, new InvalidValueException[] {}); - } - - /** - * Constructs a new InvalidValueException with a set of - * causing validation exceptions. The error message contains first the - * given message and then a list of validation errors in the given - * validatables. - * - * @param message - * The detail message of the problem. - * @param causes - * Array of validatables whos invalidities are possiblity - * causing the invalidity. - */ - public InvalidValueException(String message, - InvalidValueException[] causes) { - super(message); - if (causes == null) - throw new NullPointerException( - "Possible causes array must not be null"); - this.causes = causes; - } - - public final int getErrorLevel() { - return ErrorMessage.ERROR; - } - - public void paint(PaintTarget target) throws PaintException { - target.startTag("error"); - target.addAttribute("level", "error"); - - // Error message - String message = getLocalizedMessage(); - if (message != null) - target.addText(message); - - // Paint all the causes - for (int i = 0; i < causes.length; i++) { - causes[i].paint(target); - } - - target.endTag("error"); - } - - /* Documented in super interface */ - public void addListener(RepaintRequestListener listener) { - } - - /* Documented in super interface */ - public void removeListener(RepaintRequestListener listener) { - } - - /* Documented in super interface */ - public void requestRepaint() { - } - - /* Documented in super interface */ - public void requestRepaintRequests() { - } - - } + /** + * Checks the given value against this validator. If the value is valid this + * method should do nothing, and if it's not valid, it should throw + * Validator.InvalidValueException + * + * @param value + * the value to check + * @throws Validator.InvalidValueException + * if the value is not valid + */ + public void validate(Object value) throws Validator.InvalidValueException; + + /** + * Tests if the given value is valid. + * + * @param value + * the value to check + * @return true for valid value, otherwise false. + */ + public boolean isValid(Object value); + + /** + * Adds the proposing functionality to a {@link Validator}. A + * Suggestive validator can propose a valid value for the + * object it is attached to validate. This way the {@link Validatable} + * object may avoid situations where it contains a value that could lead to + * a error. + * + * @author IT Mill Ltd. + * @version + * @VERSION@ + * @since 3.0 + */ + public interface Suggestive extends Validator { + + /** + * Suggests another value that can be used instead of the proposedValue + * if it is invalid. If it is valid in the opinion of this validator, + * however, it is returned as is. + * + * @param proposedValue + * Originally proposed value that could be invalid. + * @return Suggested value that's not invalid against this validator + */ + public Object suggestValidValue(Object proposedValue); + } + + /** + * Invalid value exception can be thrown by {@link Validator} when a given + * value is not valid. + * + * @author IT Mill Ltd. + * @version + * @VERSION@ + * @since 3.0 + */ + public class InvalidValueException extends RuntimeException implements + ErrorMessage { + + /** + * Serial generated by eclipse. + */ + private static final long serialVersionUID = 3689073941163422257L; + + /** Array of validation errors that are causing the problem. */ + private InvalidValueException[] causes = null; + + /** + * Constructs a new InvalidValueException with the + * specified detail message. + * + * @param message + * The detail message of the problem. + */ + public InvalidValueException(String message) { + this(message, new InvalidValueException[] {}); + } + + /** + * Constructs a new InvalidValueException with a set of + * causing validation exceptions. The error message contains first the + * given message and then a list of validation errors in the given + * validatables. + * + * @param message + * The detail message of the problem. + * @param causes + * Array of validatables whos invalidities are possiblity + * causing the invalidity. + */ + public InvalidValueException(String message, + InvalidValueException[] causes) { + super(message); + if (causes == null) { + throw new NullPointerException( + "Possible causes array must not be null"); + } + this.causes = causes; + } + + public final int getErrorLevel() { + return ErrorMessage.ERROR; + } + + public void paint(PaintTarget target) throws PaintException { + target.startTag("error"); + target.addAttribute("level", "error"); + + // Error message + String message = getLocalizedMessage(); + if (message != null) { + target.addText(message); + } + + // Paint all the causes + for (int i = 0; i < causes.length; i++) { + causes[i].paint(target); + } + + target.endTag("error"); + } + + /* Documented in super interface */ + public void addListener(RepaintRequestListener listener) { + } + + /* Documented in super interface */ + public void removeListener(RepaintRequestListener listener) { + } + + /* Documented in super interface */ + public void requestRepaint() { + } + + /* Documented in super interface */ + public void requestRepaintRequests() { + } + + } } diff --git a/src/com/itmill/toolkit/data/util/BeanItem.java b/src/com/itmill/toolkit/data/util/BeanItem.java index a6c50c4339..d5cb263274 100644 --- a/src/com/itmill/toolkit/data/util/BeanItem.java +++ b/src/com/itmill/toolkit/data/util/BeanItem.java @@ -28,8 +28,8 @@ package com.itmill.toolkit.data.util; -import java.beans.Introspector; import java.beans.BeanInfo; +import java.beans.Introspector; import java.beans.PropertyDescriptor; import java.lang.reflect.Method; import java.util.Collection; @@ -47,112 +47,112 @@ import com.itmill.toolkit.data.Property; */ public class BeanItem extends PropertysetItem { - /** - * The bean which this Item is based on. - */ - private Object bean; - - /** - *

- * Creates a new instance of BeanItem and adds all properties - * of a Java Bean to it. The properties are identified by their respective - * bean names. - *

- * - *

- * Note : This version only supports introspectable bean properties and - * their getter and setter methods. Stand-alone is and - * are methods are not supported. - *

- * - * @param bean - * the Java Bean to copy properties from. - * - */ - public BeanItem(Object bean) { - - this.bean = bean; - - // Try to introspect, if it fails, we just have an empty Item - try { - // Create bean information - BeanInfo info = Introspector.getBeanInfo(bean.getClass()); - PropertyDescriptor[] pd = info.getPropertyDescriptors(); - - // Add all the bean properties as MethodProperties to this Item - for (int i = 0; i < pd.length; i++) { - Method getMethod = pd[i].getReadMethod(); - Method setMethod = pd[i].getWriteMethod(); - Class type = pd[i].getPropertyType(); - String name = pd[i].getName(); - - if ((getMethod != null) && (setMethod != null)) { - Property p = new MethodProperty(type, bean, getMethod, - setMethod); - addItemProperty(name, p); - } - } - } catch (java.beans.IntrospectionException ignored) { - } - } - - /** - *

- * Creates a new instance of BeanItem and adds all listed - * properties of a Java Bean to it - in specified order. The properties are - * identified by their respective bean names. - *

- * - *

- * Note : This version only supports introspectable bean properties and - * their getter and setter methods. Stand-alone is and - * are methods are not supported. - *

- * - * @param bean - * the Java Bean to copy properties from. - * @param propertyIds - * id of the property. - */ - public BeanItem(Object bean, Collection propertyIds) { - - this.bean = bean; - - // Try to introspect, if it fails, we just have an empty Item - try { - // Create bean information - BeanInfo info = Introspector.getBeanInfo(bean.getClass()); - PropertyDescriptor[] pd = info.getPropertyDescriptors(); - - // Add all the bean properties as MethodProperties to this Item - for (Iterator iter = propertyIds.iterator(); iter.hasNext();) { - Object id = iter.next(); - for (int i = 0; i < pd.length; i++) { - String name = pd[i].getName(); - if (name.equals(id)) { - Method getMethod = pd[i].getReadMethod(); - Method setMethod = pd[i].getWriteMethod(); - Class type = pd[i].getPropertyType(); - - Property p = new MethodProperty(type, bean, getMethod, - setMethod); - addItemProperty(name, p); - } - } - } - - } catch (java.beans.IntrospectionException ignored) { - } - - } - - /** - * Gets the underlying JavaBean object. - * - * @return the bean object. - */ - public Object getBean() { - return bean; - } + /** + * The bean which this Item is based on. + */ + private Object bean; + + /** + *

+ * Creates a new instance of BeanItem and adds all properties + * of a Java Bean to it. The properties are identified by their respective + * bean names. + *

+ * + *

+ * Note : This version only supports introspectable bean properties and + * their getter and setter methods. Stand-alone is and + * are methods are not supported. + *

+ * + * @param bean + * the Java Bean to copy properties from. + * + */ + public BeanItem(Object bean) { + + this.bean = bean; + + // Try to introspect, if it fails, we just have an empty Item + try { + // Create bean information + BeanInfo info = Introspector.getBeanInfo(bean.getClass()); + PropertyDescriptor[] pd = info.getPropertyDescriptors(); + + // Add all the bean properties as MethodProperties to this Item + for (int i = 0; i < pd.length; i++) { + Method getMethod = pd[i].getReadMethod(); + Method setMethod = pd[i].getWriteMethod(); + Class type = pd[i].getPropertyType(); + String name = pd[i].getName(); + + if ((getMethod != null) && (setMethod != null)) { + Property p = new MethodProperty(type, bean, getMethod, + setMethod); + addItemProperty(name, p); + } + } + } catch (java.beans.IntrospectionException ignored) { + } + } + + /** + *

+ * Creates a new instance of BeanItem and adds all listed + * properties of a Java Bean to it - in specified order. The properties are + * identified by their respective bean names. + *

+ * + *

+ * Note : This version only supports introspectable bean properties and + * their getter and setter methods. Stand-alone is and + * are methods are not supported. + *

+ * + * @param bean + * the Java Bean to copy properties from. + * @param propertyIds + * id of the property. + */ + public BeanItem(Object bean, Collection propertyIds) { + + this.bean = bean; + + // Try to introspect, if it fails, we just have an empty Item + try { + // Create bean information + BeanInfo info = Introspector.getBeanInfo(bean.getClass()); + PropertyDescriptor[] pd = info.getPropertyDescriptors(); + + // Add all the bean properties as MethodProperties to this Item + for (Iterator iter = propertyIds.iterator(); iter.hasNext();) { + Object id = iter.next(); + for (int i = 0; i < pd.length; i++) { + String name = pd[i].getName(); + if (name.equals(id)) { + Method getMethod = pd[i].getReadMethod(); + Method setMethod = pd[i].getWriteMethod(); + Class type = pd[i].getPropertyType(); + + Property p = new MethodProperty(type, bean, getMethod, + setMethod); + addItemProperty(name, p); + } + } + } + + } catch (java.beans.IntrospectionException ignored) { + } + + } + + /** + * Gets the underlying JavaBean object. + * + * @return the bean object. + */ + public Object getBean() { + return bean; + } } diff --git a/src/com/itmill/toolkit/data/util/ContainerHierarchicalWrapper.java b/src/com/itmill/toolkit/data/util/ContainerHierarchicalWrapper.java index 7948e665c4..6246775f1f 100644 --- a/src/com/itmill/toolkit/data/util/ContainerHierarchicalWrapper.java +++ b/src/com/itmill/toolkit/data/util/ContainerHierarchicalWrapper.java @@ -29,11 +29,11 @@ package com.itmill.toolkit.data.util; import java.util.Collection; -import java.util.Iterator; -import java.util.LinkedList; import java.util.Collections; -import java.util.Hashtable; import java.util.HashSet; +import java.util.Hashtable; +import java.util.Iterator; +import java.util.LinkedList; import com.itmill.toolkit.data.Container; import com.itmill.toolkit.data.Item; @@ -57,575 +57,604 @@ import com.itmill.toolkit.data.Property; * @since 3.0 */ public class ContainerHierarchicalWrapper implements Container.Hierarchical, - Container.ItemSetChangeNotifier, Container.PropertySetChangeNotifier { - - /** The wrapped container */ - private Container container; - - /** Set of IDs of those contained Items that can't have children. */ - private HashSet noChildrenAllowed = null; - - /** Mapping from Item ID to parent Item */ - private Hashtable parent = null; - - /** Mapping from Item ID to a list of child IDs */ - private Hashtable children = null; - - /** List that contains all root elements of the container. */ - private LinkedList roots = null; - - /** Is the wrapped container hierarchical by itself ? */ - private boolean hierarchical; - - /** - * Constructs a new hierarchical wrapper for an existing Container. Works - * even if the to-be-wrapped container already implements the - * Container.Hierarchical interface. - * - * @param toBeWrapped - * the container that needs to be accessed hierarchically - * @see #updateHierarchicalWrapper() - */ - public ContainerHierarchicalWrapper(Container toBeWrapped) { - - container = toBeWrapped; - hierarchical = container instanceof Container.Hierarchical; - - // Check arguments - if (container == null) - throw new NullPointerException("Null can not be wrapped"); - - // Create initial order if needed - if (!hierarchical) { - noChildrenAllowed = new HashSet(); - parent = new Hashtable(); - children = new Hashtable(); - roots = new LinkedList(container.getItemIds()); - } - - updateHierarchicalWrapper(); - } - - /** - * Updates the wrapper's internal hierarchy data to include all Items in the - * underlying container. If the contents of the wrapped container change - * without the wrapper's knowledge, this method needs to be called to update - * the hierarchy information of the Items. - */ - public void updateHierarchicalWrapper() { - - if (!hierarchical) { - - // Recreate hierarchy and datasrtuctures if missing - if (noChildrenAllowed == null || parent == null || children == null - || roots == null) { - noChildrenAllowed = new HashSet(); - parent = new Hashtable(); - children = new Hashtable(); - roots = new LinkedList(container.getItemIds()); - } - - // Check that the hierarchy is up-to-date - else { - - // Calculate the set of all items in the hierarchy - HashSet s = new HashSet(); - s.add(parent.keySet()); - s.add(children.keySet()); - s.addAll(roots); - - // Remove unnecessary items - for (Iterator i = s.iterator(); i.hasNext();) { - Object id = i.next(); - if (!container.containsId(id)) - removeFromHierarchyWrapper(id); - } - - // Add all the missing items - Collection ids = container.getItemIds(); - for (Iterator i = ids.iterator(); i.hasNext();) { - Object id = i.next(); - if (!s.contains(id)) { - addToHierarchyWrapper(id); - s.add(id); - } - } - } - } - } - - /** - * Removes the specified Item from the wrapper's internal hierarchy - * structure. - *

- * Note : The Item is not removed from the underlying Container. - *

- * - * @param itemId - * the ID of the item to remove from the hierarchy. - */ - private void removeFromHierarchyWrapper(Object itemId) { - - if (isRoot(itemId)) - roots.remove(itemId); - Object p = parent.get(itemId); - if (p != null) { - LinkedList c = (LinkedList) children.get(p); - if (c != null) - c.remove(itemId); - } - parent.remove(itemId); - children.remove(itemId); - noChildrenAllowed.remove(itemId); - } - - /** - * Adds the specified Item specified to the internal hierarchy structure. - * The new item is added as a root Item. The underlying container is not - * modified. - * - * @param itemId - * the ID of the item to add to the hierarchy. - */ - private void addToHierarchyWrapper(Object itemId) { - roots.add(itemId); - } - - /* - * Can the specified Item have any children? Don't add a JavaDoc comment - * here, we use the default documentation from implemented interface. - */ - public boolean areChildrenAllowed(Object itemId) { - - // If the wrapped container implements the method directly, use it - if (hierarchical) - return ((Container.Hierarchical) container) - .areChildrenAllowed(itemId); - return !noChildrenAllowed.contains(itemId); - } - - /* - * Gets the IDs of the children of the specified Item. Don't add a JavaDoc - * comment here, we use the default documentation from implemented - * interface. - */ - public Collection getChildren(Object itemId) { - - // If the wrapped container implements the method directly, use it - if (hierarchical) - return ((Container.Hierarchical) container).getChildren(itemId); - - Collection c = (Collection) children.get(itemId); - if (c == null) - return null; - return Collections.unmodifiableCollection(c); - } - - /* - * Gets the ID of the parent of the specified Item. Don't add a JavaDoc - * comment here, we use the default documentation from implemented - * interface. - */ - public Object getParent(Object itemId) { - - // If the wrapped container implements the method directly, use it - if (hierarchical) - return ((Container.Hierarchical) container).getParent(itemId); - - return parent.get(itemId); - } - - /* - * Is the Item corresponding to the given ID a leaf node? Don't add a - * JavaDoc comment here, we use the default documentation from implemented - * interface. - */ - public boolean hasChildren(Object itemId) { - - // If the wrapped container implements the method directly, use it - if (hierarchical) - return ((Container.Hierarchical) container).hasChildren(itemId); - - return children.get(itemId) != null; - } - - /* - * Is the Item corresponding to the given ID a root node? Don't add a - * JavaDoc comment here, we use the default documentation from implemented - * interface. - */ - public boolean isRoot(Object itemId) { - - // If the wrapped container implements the method directly, use it - if (hierarchical) - return ((Container.Hierarchical) container).isRoot(itemId); - - return parent.get(itemId) == null; - } - - /* - * Gets the IDs of the root elements in the container. Don't add a JavaDoc - * comment here, we use the default documentation from implemented - * interface. - */ - public Collection rootItemIds() { - - // If the wrapped container implements the method directly, use it - if (hierarchical) - return ((Container.Hierarchical) container).rootItemIds(); - - return Collections.unmodifiableCollection(roots); - } - - /** - *

- * Sets the given Item's capability to have children. If the Item identified - * with the itemId already has children and the areChildrenAllowed is false - * this method fails and false is returned; the children must - * be first explicitly removed with - * {@link #setParent(Object itemId, Object newParentId)} or - * {@link com.itmill.toolkit.data.Container#removeItem(Object itemId)}. - *

- * - * @param itemId - * the ID of the Item in the container whose child capability is - * to be set. - * @param childrenAllowed - * the boolean value specifying if the Item can have children or - * not. - * @return true if the operation succeeded, - * false if not - */ - public boolean setChildrenAllowed(Object itemId, boolean childrenAllowed) { - - // If the wrapped container implements the method directly, use it - if (hierarchical) - return ((Container.Hierarchical) container).setChildrenAllowed( - itemId, childrenAllowed); - - // Check that the item is in the container - if (!containsId(itemId)) - return false; - - // Update status - if (childrenAllowed) - noChildrenAllowed.remove(itemId); - else - noChildrenAllowed.add(itemId); - - return true; - } - - /** - *

- * Sets the parent of an Item. The new parent item must exist and be able to - * have children. (canHaveChildren(newParentId) == true). - * It is also possible to detach a node from the hierarchy (and thus make it - * root) by setting the parent null. - *

- * - * @param itemId - * the ID of the item to be set as the child of the Item - * identified with newParentId. - * @param newParentId - * the ID of the Item that's to be the new parent of the Item - * identified with itemId. - * @return true if the operation succeeded, - * false if not - */ - public boolean setParent(Object itemId, Object newParentId) { - - // If the wrapped container implements the method directly, use it - if (hierarchical) - return ((Container.Hierarchical) container).setParent(itemId, - newParentId); - - // Check that the item is in the container - if (!containsId(itemId)) - return false; - - // Get the old parent - Object oldParentId = parent.get(itemId); - - // Check if no change is necessary - if ((newParentId == null && oldParentId == null) - || (newParentId != null && newParentId.equals(oldParentId))) - return true; - - // Making root - if (newParentId == null) { - - // Remove from old parents children list - LinkedList l = (LinkedList) children.get(itemId); - if (l != null) { - l.remove(itemId); - if (l.isEmpty()) - children.remove(itemId); - } - - // Add to be a root - roots.add(itemId); - - // Update parent - parent.remove(itemId); - - return true; - } - - // Check that the new parent exists in container and can have - // children - if (!containsId(newParentId) || noChildrenAllowed.contains(newParentId)) - return false; - - // Check that setting parent doesn't result to a loop - Object o = newParentId; - while (o != null && !o.equals(itemId)) - o = parent.get(o); - if (o != null) - return false; - - // Update parent - parent.put(itemId, newParentId); - LinkedList pcl = (LinkedList) children.get(newParentId); - if (pcl == null) { - pcl = new LinkedList(); - children.put(newParentId, pcl); - } - pcl.add(itemId); - - // Remove from old parent or root - if (oldParentId == null) - roots.remove(itemId); - else { - LinkedList l = (LinkedList) children.get(oldParentId); - if (l != null) { - l.remove(itemId); - if (l.isEmpty()) - children.remove(oldParentId); - } - } - - return true; - } - - /** - * Creates a new Item into the Container, assigns it an automatic ID, and - * adds it to the hierarchy. - * - * @return the autogenerated ID of the new Item or null if - * the operation failed - * @throws UnsupportedOperationException - * if the addItem is not supported. - */ - public Object addItem() throws UnsupportedOperationException { - - Object id = container.addItem(); - if (id != null) - addToHierarchyWrapper(id); - return id; - } - - /** - * Adds a new Item by its ID to the underlying container and to the - * hierarchy. - * - * @param itemId - * the ID of the Item to be created. - * @return the added Item or null if the operation failed. - * @throws UnsupportedOperationException - * if the addItem is not supported. - */ - public Item addItem(Object itemId) throws UnsupportedOperationException { - - Item item = container.addItem(itemId); - if (item != null) - addToHierarchyWrapper(itemId); - return item; - } - - /** - * Removes all items from the underlying container and from the hierarcy. - * - * @return true if the operation succeeded, - * false if not - * @throws UnsupportedOperationException - * if the removeAllItems is not supported. - */ - public boolean removeAllItems() throws UnsupportedOperationException { - - boolean success = container.removeAllItems(); - - if (success) { - roots.clear(); - parent.clear(); - children.clear(); - noChildrenAllowed.clear(); - } - return success; - } - - /** - * Removes an Item specified by the itemId from the underlying container and - * from the hierarcy. - * - * @param itemId - * the ID of the Item to be removed. - * @return true if the operation succeeded, - * false if not - * @throws UnsupportedOperationException - * if the removeItem is not supported. - */ - public boolean removeItem(Object itemId) - throws UnsupportedOperationException { - - boolean success = container.removeItem(itemId); - - if (success) - removeFromHierarchyWrapper(itemId); - - return success; - } - - /** - * Adds a new Property to all Items in the Container. - * - * @param propertyId - * the ID of the new Property. - * @param type - * the Data type of the new Property. - * @param defaultValue - * the value all created Properties are initialized to. - * @return true if the operation succeeded, - * false if not - * @throws UnsupportedOperationException - * if the addContainerProperty is not supported. - */ - public boolean addContainerProperty(Object propertyId, Class type, - Object defaultValue) throws UnsupportedOperationException { - - return container.addContainerProperty(propertyId, type, defaultValue); - } - - /** - * Removes the specified Property from the underlying container and from the - * hierarchy. - *

- * Note : The Property will be removed from all Items in the Container. - *

- * - * @param propertyId - * the ID of the Property to remove. - * @return true if the operation succeeded, - * false if not - * @throws UnsupportedOperationException - * if the removeContainerProperty is not supported. - */ - public boolean removeContainerProperty(Object propertyId) - throws UnsupportedOperationException { - return container.removeContainerProperty(propertyId); - } - - /* - * Does the container contain the specified Item? Don't add a JavaDoc - * comment here, we use the default documentation from implemented - * interface. - */ - public boolean containsId(Object itemId) { - return container.containsId(itemId); - } - - /* - * Gets the specified Item from the container. Don't add a JavaDoc comment - * here, we use the default documentation from implemented interface. - */ - public Item getItem(Object itemId) { - return container.getItem(itemId); - } - - /* - * Gets the ID's of all Items stored in the Container Don't add a JavaDoc - * comment here, we use the default documentation from implemented - * interface. - */ - public Collection getItemIds() { - return container.getItemIds(); - } - - /* - * Gets the Property identified by the given itemId and propertyId from the - * Container Don't add a JavaDoc comment here, we use the default - * documentation from implemented interface. - */ - public Property getContainerProperty(Object itemId, Object propertyId) { - return container.getContainerProperty(itemId, propertyId); - } - - /* - * Gets the ID's of all Properties stored in the Container Don't add a - * JavaDoc comment here, we use the default documentation from implemented - * interface. - */ - public Collection getContainerPropertyIds() { - return container.getContainerPropertyIds(); - } - - /* - * Gets the data type of all Properties identified by the given Property ID. - * Don't add a JavaDoc comment here, we use the default documentation from - * implemented interface. - */ - public Class getType(Object propertyId) { - return container.getType(propertyId); - } - - /* - * Gets the number of Items in the Container. Don't add a JavaDoc comment - * here, we use the default documentation from implemented interface. - */ - public int size() { - return container.size(); - } - - /* - * Registers a new Item set change listener for this Container. Don't add a - * JavaDoc comment here, we use the default documentation from implemented - * interface. - */ - public void addListener(Container.ItemSetChangeListener listener) { - if (container instanceof Container.ItemSetChangeNotifier) - ((Container.ItemSetChangeNotifier) container).addListener(listener); - } - - /* - * Removes a Item set change listener from the object. Don't add a JavaDoc - * comment here, we use the default documentation from implemented - * interface. - */ - public void removeListener(Container.ItemSetChangeListener listener) { - if (container instanceof Container.ItemSetChangeNotifier) - ((Container.ItemSetChangeNotifier) container) - .removeListener(listener); - } - - /* - * Registers a new Property set change listener for this Container. Don't - * add a JavaDoc comment here, we use the default documentation from - * implemented interface. - */ - public void addListener(Container.PropertySetChangeListener listener) { - if (container instanceof Container.PropertySetChangeNotifier) - ((Container.PropertySetChangeNotifier) container) - .addListener(listener); - } - - /* - * Removes a Property set change listener from the object. Don't add a - * JavaDoc comment here, we use the default documentation from implemented - * interface. - */ - public void removeListener(Container.PropertySetChangeListener listener) { - if (container instanceof Container.PropertySetChangeNotifier) - ((Container.PropertySetChangeNotifier) container) - .removeListener(listener); - } + Container.ItemSetChangeNotifier, Container.PropertySetChangeNotifier { + + /** The wrapped container */ + private Container container; + + /** Set of IDs of those contained Items that can't have children. */ + private HashSet noChildrenAllowed = null; + + /** Mapping from Item ID to parent Item */ + private Hashtable parent = null; + + /** Mapping from Item ID to a list of child IDs */ + private Hashtable children = null; + + /** List that contains all root elements of the container. */ + private LinkedList roots = null; + + /** Is the wrapped container hierarchical by itself ? */ + private boolean hierarchical; + + /** + * Constructs a new hierarchical wrapper for an existing Container. Works + * even if the to-be-wrapped container already implements the + * Container.Hierarchical interface. + * + * @param toBeWrapped + * the container that needs to be accessed hierarchically + * @see #updateHierarchicalWrapper() + */ + public ContainerHierarchicalWrapper(Container toBeWrapped) { + + container = toBeWrapped; + hierarchical = container instanceof Container.Hierarchical; + + // Check arguments + if (container == null) { + throw new NullPointerException("Null can not be wrapped"); + } + + // Create initial order if needed + if (!hierarchical) { + noChildrenAllowed = new HashSet(); + parent = new Hashtable(); + children = new Hashtable(); + roots = new LinkedList(container.getItemIds()); + } + + updateHierarchicalWrapper(); + } + + /** + * Updates the wrapper's internal hierarchy data to include all Items in the + * underlying container. If the contents of the wrapped container change + * without the wrapper's knowledge, this method needs to be called to update + * the hierarchy information of the Items. + */ + public void updateHierarchicalWrapper() { + + if (!hierarchical) { + + // Recreate hierarchy and datasrtuctures if missing + if (noChildrenAllowed == null || parent == null || children == null + || roots == null) { + noChildrenAllowed = new HashSet(); + parent = new Hashtable(); + children = new Hashtable(); + roots = new LinkedList(container.getItemIds()); + } + + // Check that the hierarchy is up-to-date + else { + + // Calculate the set of all items in the hierarchy + HashSet s = new HashSet(); + s.add(parent.keySet()); + s.add(children.keySet()); + s.addAll(roots); + + // Remove unnecessary items + for (Iterator i = s.iterator(); i.hasNext();) { + Object id = i.next(); + if (!container.containsId(id)) { + removeFromHierarchyWrapper(id); + } + } + + // Add all the missing items + Collection ids = container.getItemIds(); + for (Iterator i = ids.iterator(); i.hasNext();) { + Object id = i.next(); + if (!s.contains(id)) { + addToHierarchyWrapper(id); + s.add(id); + } + } + } + } + } + + /** + * Removes the specified Item from the wrapper's internal hierarchy + * structure. + *

+ * Note : The Item is not removed from the underlying Container. + *

+ * + * @param itemId + * the ID of the item to remove from the hierarchy. + */ + private void removeFromHierarchyWrapper(Object itemId) { + + if (isRoot(itemId)) { + roots.remove(itemId); + } + Object p = parent.get(itemId); + if (p != null) { + LinkedList c = (LinkedList) children.get(p); + if (c != null) { + c.remove(itemId); + } + } + parent.remove(itemId); + children.remove(itemId); + noChildrenAllowed.remove(itemId); + } + + /** + * Adds the specified Item specified to the internal hierarchy structure. + * The new item is added as a root Item. The underlying container is not + * modified. + * + * @param itemId + * the ID of the item to add to the hierarchy. + */ + private void addToHierarchyWrapper(Object itemId) { + roots.add(itemId); + } + + /* + * Can the specified Item have any children? Don't add a JavaDoc comment + * here, we use the default documentation from implemented interface. + */ + public boolean areChildrenAllowed(Object itemId) { + + // If the wrapped container implements the method directly, use it + if (hierarchical) { + return ((Container.Hierarchical) container) + .areChildrenAllowed(itemId); + } + return !noChildrenAllowed.contains(itemId); + } + + /* + * Gets the IDs of the children of the specified Item. Don't add a JavaDoc + * comment here, we use the default documentation from implemented + * interface. + */ + public Collection getChildren(Object itemId) { + + // If the wrapped container implements the method directly, use it + if (hierarchical) { + return ((Container.Hierarchical) container).getChildren(itemId); + } + + Collection c = (Collection) children.get(itemId); + if (c == null) { + return null; + } + return Collections.unmodifiableCollection(c); + } + + /* + * Gets the ID of the parent of the specified Item. Don't add a JavaDoc + * comment here, we use the default documentation from implemented + * interface. + */ + public Object getParent(Object itemId) { + + // If the wrapped container implements the method directly, use it + if (hierarchical) { + return ((Container.Hierarchical) container).getParent(itemId); + } + + return parent.get(itemId); + } + + /* + * Is the Item corresponding to the given ID a leaf node? Don't add a + * JavaDoc comment here, we use the default documentation from implemented + * interface. + */ + public boolean hasChildren(Object itemId) { + + // If the wrapped container implements the method directly, use it + if (hierarchical) { + return ((Container.Hierarchical) container).hasChildren(itemId); + } + + return children.get(itemId) != null; + } + + /* + * Is the Item corresponding to the given ID a root node? Don't add a + * JavaDoc comment here, we use the default documentation from implemented + * interface. + */ + public boolean isRoot(Object itemId) { + + // If the wrapped container implements the method directly, use it + if (hierarchical) { + return ((Container.Hierarchical) container).isRoot(itemId); + } + + return parent.get(itemId) == null; + } + + /* + * Gets the IDs of the root elements in the container. Don't add a JavaDoc + * comment here, we use the default documentation from implemented + * interface. + */ + public Collection rootItemIds() { + + // If the wrapped container implements the method directly, use it + if (hierarchical) { + return ((Container.Hierarchical) container).rootItemIds(); + } + + return Collections.unmodifiableCollection(roots); + } + + /** + *

+ * Sets the given Item's capability to have children. If the Item identified + * with the itemId already has children and the areChildrenAllowed is false + * this method fails and false is returned; the children must + * be first explicitly removed with + * {@link #setParent(Object itemId, Object newParentId)} or + * {@link com.itmill.toolkit.data.Container#removeItem(Object itemId)}. + *

+ * + * @param itemId + * the ID of the Item in the container whose child capability + * is to be set. + * @param childrenAllowed + * the boolean value specifying if the Item can have children + * or not. + * @return true if the operation succeeded, + * false if not + */ + public boolean setChildrenAllowed(Object itemId, boolean childrenAllowed) { + + // If the wrapped container implements the method directly, use it + if (hierarchical) { + return ((Container.Hierarchical) container).setChildrenAllowed( + itemId, childrenAllowed); + } + + // Check that the item is in the container + if (!containsId(itemId)) { + return false; + } + + // Update status + if (childrenAllowed) { + noChildrenAllowed.remove(itemId); + } else { + noChildrenAllowed.add(itemId); + } + + return true; + } + + /** + *

+ * Sets the parent of an Item. The new parent item must exist and be able to + * have children. (canHaveChildren(newParentId) == true). + * It is also possible to detach a node from the hierarchy (and thus make it + * root) by setting the parent null. + *

+ * + * @param itemId + * the ID of the item to be set as the child of the Item + * identified with newParentId. + * @param newParentId + * the ID of the Item that's to be the new parent of the Item + * identified with itemId. + * @return true if the operation succeeded, + * false if not + */ + public boolean setParent(Object itemId, Object newParentId) { + + // If the wrapped container implements the method directly, use it + if (hierarchical) { + return ((Container.Hierarchical) container).setParent(itemId, + newParentId); + } + + // Check that the item is in the container + if (!containsId(itemId)) { + return false; + } + + // Get the old parent + Object oldParentId = parent.get(itemId); + + // Check if no change is necessary + if ((newParentId == null && oldParentId == null) + || (newParentId != null && newParentId.equals(oldParentId))) { + return true; + } + + // Making root + if (newParentId == null) { + + // Remove from old parents children list + LinkedList l = (LinkedList) children.get(itemId); + if (l != null) { + l.remove(itemId); + if (l.isEmpty()) { + children.remove(itemId); + } + } + + // Add to be a root + roots.add(itemId); + + // Update parent + parent.remove(itemId); + + return true; + } + + // Check that the new parent exists in container and can have + // children + if (!containsId(newParentId) || noChildrenAllowed.contains(newParentId)) { + return false; + } + + // Check that setting parent doesn't result to a loop + Object o = newParentId; + while (o != null && !o.equals(itemId)) { + o = parent.get(o); + } + if (o != null) { + return false; + } + + // Update parent + parent.put(itemId, newParentId); + LinkedList pcl = (LinkedList) children.get(newParentId); + if (pcl == null) { + pcl = new LinkedList(); + children.put(newParentId, pcl); + } + pcl.add(itemId); + + // Remove from old parent or root + if (oldParentId == null) { + roots.remove(itemId); + } else { + LinkedList l = (LinkedList) children.get(oldParentId); + if (l != null) { + l.remove(itemId); + if (l.isEmpty()) { + children.remove(oldParentId); + } + } + } + + return true; + } + + /** + * Creates a new Item into the Container, assigns it an automatic ID, and + * adds it to the hierarchy. + * + * @return the autogenerated ID of the new Item or null if + * the operation failed + * @throws UnsupportedOperationException + * if the addItem is not supported. + */ + public Object addItem() throws UnsupportedOperationException { + + Object id = container.addItem(); + if (id != null) { + addToHierarchyWrapper(id); + } + return id; + } + + /** + * Adds a new Item by its ID to the underlying container and to the + * hierarchy. + * + * @param itemId + * the ID of the Item to be created. + * @return the added Item or null if the operation failed. + * @throws UnsupportedOperationException + * if the addItem is not supported. + */ + public Item addItem(Object itemId) throws UnsupportedOperationException { + + Item item = container.addItem(itemId); + if (item != null) { + addToHierarchyWrapper(itemId); + } + return item; + } + + /** + * Removes all items from the underlying container and from the hierarcy. + * + * @return true if the operation succeeded, + * false if not + * @throws UnsupportedOperationException + * if the removeAllItems is not supported. + */ + public boolean removeAllItems() throws UnsupportedOperationException { + + boolean success = container.removeAllItems(); + + if (success) { + roots.clear(); + parent.clear(); + children.clear(); + noChildrenAllowed.clear(); + } + return success; + } + + /** + * Removes an Item specified by the itemId from the underlying container and + * from the hierarcy. + * + * @param itemId + * the ID of the Item to be removed. + * @return true if the operation succeeded, + * false if not + * @throws UnsupportedOperationException + * if the removeItem is not supported. + */ + public boolean removeItem(Object itemId) + throws UnsupportedOperationException { + + boolean success = container.removeItem(itemId); + + if (success) { + removeFromHierarchyWrapper(itemId); + } + + return success; + } + + /** + * Adds a new Property to all Items in the Container. + * + * @param propertyId + * the ID of the new Property. + * @param type + * the Data type of the new Property. + * @param defaultValue + * the value all created Properties are initialized to. + * @return true if the operation succeeded, + * false if not + * @throws UnsupportedOperationException + * if the addContainerProperty is not supported. + */ + public boolean addContainerProperty(Object propertyId, Class type, + Object defaultValue) throws UnsupportedOperationException { + + return container.addContainerProperty(propertyId, type, defaultValue); + } + + /** + * Removes the specified Property from the underlying container and from the + * hierarchy. + *

+ * Note : The Property will be removed from all Items in the Container. + *

+ * + * @param propertyId + * the ID of the Property to remove. + * @return true if the operation succeeded, + * false if not + * @throws UnsupportedOperationException + * if the removeContainerProperty is not supported. + */ + public boolean removeContainerProperty(Object propertyId) + throws UnsupportedOperationException { + return container.removeContainerProperty(propertyId); + } + + /* + * Does the container contain the specified Item? Don't add a JavaDoc + * comment here, we use the default documentation from implemented + * interface. + */ + public boolean containsId(Object itemId) { + return container.containsId(itemId); + } + + /* + * Gets the specified Item from the container. Don't add a JavaDoc comment + * here, we use the default documentation from implemented interface. + */ + public Item getItem(Object itemId) { + return container.getItem(itemId); + } + + /* + * Gets the ID's of all Items stored in the Container Don't add a JavaDoc + * comment here, we use the default documentation from implemented + * interface. + */ + public Collection getItemIds() { + return container.getItemIds(); + } + + /* + * Gets the Property identified by the given itemId and propertyId from the + * Container Don't add a JavaDoc comment here, we use the default + * documentation from implemented interface. + */ + public Property getContainerProperty(Object itemId, Object propertyId) { + return container.getContainerProperty(itemId, propertyId); + } + + /* + * Gets the ID's of all Properties stored in the Container Don't add a + * JavaDoc comment here, we use the default documentation from implemented + * interface. + */ + public Collection getContainerPropertyIds() { + return container.getContainerPropertyIds(); + } + + /* + * Gets the data type of all Properties identified by the given Property ID. + * Don't add a JavaDoc comment here, we use the default documentation from + * implemented interface. + */ + public Class getType(Object propertyId) { + return container.getType(propertyId); + } + + /* + * Gets the number of Items in the Container. Don't add a JavaDoc comment + * here, we use the default documentation from implemented interface. + */ + public int size() { + return container.size(); + } + + /* + * Registers a new Item set change listener for this Container. Don't add a + * JavaDoc comment here, we use the default documentation from implemented + * interface. + */ + public void addListener(Container.ItemSetChangeListener listener) { + if (container instanceof Container.ItemSetChangeNotifier) { + ((Container.ItemSetChangeNotifier) container).addListener(listener); + } + } + + /* + * Removes a Item set change listener from the object. Don't add a JavaDoc + * comment here, we use the default documentation from implemented + * interface. + */ + public void removeListener(Container.ItemSetChangeListener listener) { + if (container instanceof Container.ItemSetChangeNotifier) { + ((Container.ItemSetChangeNotifier) container) + .removeListener(listener); + } + } + + /* + * Registers a new Property set change listener for this Container. Don't + * add a JavaDoc comment here, we use the default documentation from + * implemented interface. + */ + public void addListener(Container.PropertySetChangeListener listener) { + if (container instanceof Container.PropertySetChangeNotifier) { + ((Container.PropertySetChangeNotifier) container) + .addListener(listener); + } + } + + /* + * Removes a Property set change listener from the object. Don't add a + * JavaDoc comment here, we use the default documentation from implemented + * interface. + */ + public void removeListener(Container.PropertySetChangeListener listener) { + if (container instanceof Container.PropertySetChangeNotifier) { + ((Container.PropertySetChangeNotifier) container) + .removeListener(listener); + } + } } diff --git a/src/com/itmill/toolkit/data/util/ContainerOrderedWrapper.java b/src/com/itmill/toolkit/data/util/ContainerOrderedWrapper.java index 02f0813db4..b2fc22e8f8 100644 --- a/src/com/itmill/toolkit/data/util/ContainerOrderedWrapper.java +++ b/src/com/itmill/toolkit/data/util/ContainerOrderedWrapper.java @@ -29,9 +29,9 @@ package com.itmill.toolkit.data.util; import java.util.Collection; +import java.util.Hashtable; import java.util.Iterator; import java.util.LinkedList; -import java.util.Hashtable; import com.itmill.toolkit.data.Container; import com.itmill.toolkit.data.Item; @@ -55,493 +55,517 @@ import com.itmill.toolkit.data.Property; * @since 3.0 */ public class ContainerOrderedWrapper implements Container.Ordered, - Container.ItemSetChangeNotifier, Container.PropertySetChangeNotifier { - - /** - * The wrapped container - */ - private Container container; - - /** - * Ordering information, ie. the mapping from Item ID to the next item ID - */ - private Hashtable next; - - /** - * Reverse ordering information for convenience and performance reasons. - */ - private Hashtable prev; - - /** - * ID of the first Item in the container. - */ - private Object first; - - /** - * ID of the last Item in the container. - */ - private Object last; - - /** - * Is the wrapped container ordered by itself, ie. does it implement the - * Container.Ordered interface by itself? If it does, this class will use - * the methods of the underlying container directly. - */ - private boolean ordered = false; - - /** - * Constructs a new ordered wrapper for an existing Container. Works even if - * the to-be-wrapped container already implements the Container.Ordered - * interface. - * - * @param toBeWrapped - * the container whose contents need to be ordered. - */ - public ContainerOrderedWrapper(Container toBeWrapped) { - - container = toBeWrapped; - ordered = container instanceof Container.Ordered; - - // Checks arguments - if (container == null) - throw new NullPointerException("Null can not be wrapped"); - - // Creates initial order if needed - updateOrderWrapper(); - } - - /** - * Removes the specified Item from the wrapper's internal hierarchy - * structure. - *

- * Note : The Item is not removed from the underlying Container. - *

- * - * @param id - * the ID of the Item to be removed from the ordering. - */ - private void removeFromOrderWrapper(Object id) { - if (id != null) { - Object pid = prev.get(id); - Object nid = next.get(id); - if (first.equals(id)) - first = nid; - if (last.equals(id)) - first = pid; - if (nid != null) - prev.put(nid, pid); - if (pid != null) - next.put(pid, nid); - next.remove(id); - prev.remove(id); - } - } - - /** - * Registers the specified Item to the last position in the wrapper's - * internal ordering. The underlying container is not modified. - * - * @param id - * the ID of the Item to be added to the ordering. - */ - private void addToOrderWrapper(Object id) { - - // Adds the if to tail - if (last != null) { - next.put(last, id); - prev.put(id, last); - last = id; - } else { - first = last = id; - } - } - - /** - * Registers the specified Item after the specified itemId in the wrapper's - * internal ordering. The underlying container is not modified. Given item - * id must be in the container, or must be null. - * - * @param id - * the ID of the Item to be added to the ordering. - * @param previousItemId - * the Id of the previous item. - */ - private void addToOrderWrapper(Object id, Object previousItemId) { - - if (last == previousItemId || last == null) - addToOrderWrapper(id); - else { - if (previousItemId == null) { - next.put(id, first); - prev.put(first, id); - first = id; - } else { - prev.put(id, previousItemId); - next.put(id, next.get(previousItemId)); - prev.put(next.get(previousItemId), id); - next.put(previousItemId, id); - } - } - } - - /** - * Updates the wrapper's internal ordering information to include all Items - * in the underlying container. - *

- * Note : If the contents of the wrapped container change without the - * wrapper's knowledge, this method needs to be called to update the - * ordering information of the Items. - *

- */ - public void updateOrderWrapper() { - - if (!ordered) { - - Collection ids = container.getItemIds(); - - // Recreates ordering if some parts of it are missing - if (next == null || first == null || last == null || prev != null) { - first = null; - last = null; - next = new Hashtable(); - prev = new Hashtable(); - } - - // Filter out all the missing items - LinkedList l = new LinkedList(next.keySet()); - for (Iterator i = l.iterator(); i.hasNext();) { - Object id = i.next(); - if (!container.containsId(id)) - removeFromOrderWrapper(id); - } - - // Adds missing items - for (Iterator i = ids.iterator(); i.hasNext();) { - Object id = i.next(); - if (!next.containsKey(id)) - addToOrderWrapper(id); - } - } - } - - /* - * Gets the first item stored in the ordered container Don't add a JavaDoc - * comment here, we use the default documentation from implemented - * interface. - */ - public Object firstItemId() { - if (ordered) - return ((Container.Ordered) container).firstItemId(); - return first; - } - - /* - * Tests if the given item is the first item in the container Don't add a - * JavaDoc comment here, we use the default documentation from implemented - * interface. - */ - public boolean isFirstId(Object itemId) { - if (ordered) - return ((Container.Ordered) container).isFirstId(itemId); - return first != null && first.equals(itemId); - } - - /* - * Tests if the given item is the last item in the container Don't add a - * JavaDoc comment here, we use the default documentation from implemented - * interface. - */ - public boolean isLastId(Object itemId) { - if (ordered) - return ((Container.Ordered) container).isLastId(itemId); - return last != null && last.equals(itemId); - } - - /* - * Gets the last item stored in the ordered container Don't add a JavaDoc - * comment here, we use the default documentation from implemented - * interface. - */ - public Object lastItemId() { - if (ordered) - return ((Container.Ordered) container).lastItemId(); - return last; - } - - /* - * Gets the item that is next from the specified item. Don't add a JavaDoc - * comment here, we use the default documentation from implemented - * interface. - */ - public Object nextItemId(Object itemId) { - if (ordered) - return ((Container.Ordered) container).nextItemId(itemId); - return next.get(itemId); - } - - /* - * Gets the item that is previous from the specified item. Don't add a - * JavaDoc comment here, we use the default documentation from implemented - * interface. - */ - public Object prevItemId(Object itemId) { - if (ordered) - return ((Container.Ordered) container).prevItemId(itemId); - return prev.get(itemId); - } - - /** - * Registers a new Property to all Items in the Container. - * - * @param propertyId - * the ID of the new Property. - * @param type - * the Data type of the new Property. - * @param defaultValue - * the value all created Properties are initialized to. - * @return true if the operation succeeded, - * false if not - */ - public boolean addContainerProperty(Object propertyId, Class type, - Object defaultValue) throws UnsupportedOperationException { - - return container.addContainerProperty(propertyId, type, defaultValue); - } - - /** - * Creates a new Item into the Container, assigns it an automatic ID, and - * adds it to the ordering. - * - * @return the autogenerated ID of the new Item or null if - * the operation failed - * @throws UnsupportedOperationException - * if the addItem is not supported. - */ - public Object addItem() throws UnsupportedOperationException { - - Object id = container.addItem(); - if (id != null) - addToOrderWrapper(id); - return id; - } - - /** - * Registers a new Item by its ID to the underlying container and to the - * ordering. - * - * @param itemId - * the ID of the Item to be created. - * @return the added Item or null if the operation failed - * @throws UnsupportedOperationException - * if the addItem is not supported. - */ - public Item addItem(Object itemId) throws UnsupportedOperationException { - Item item = container.addItem(itemId); - if (item != null) - addToOrderWrapper(itemId); - return item; - } - - /** - * Removes all items from the underlying container and from the ordering. - * - * @return true if the operation succeeded, otherwise - * false - * @throws UnsupportedOperationException - * if the removeAllItems is not supported. - */ - public boolean removeAllItems() throws UnsupportedOperationException { - boolean success = container.removeAllItems(); - if (success) { - first = last = null; - next.clear(); - prev.clear(); - } - return success; - } - - /** - * Removes an Item specified by the itemId from the underlying container and - * from the ordering. - * - * @param itemId - * the ID of the Item to be removed. - * @return true if the operation succeeded, - * false if not - * @throws UnsupportedOperationException - * if the removeItem is not supported. - */ - public boolean removeItem(Object itemId) - throws UnsupportedOperationException { - - boolean success = container.removeItem(itemId); - if (success) - removeFromOrderWrapper(itemId); - return success; - } - - /** - * Removes the specified Property from the underlying container and from the - * ordering. - *

- * Note : The Property will be removed from all the Items in the Container. - *

- * - * @param propertyId - * the ID of the Property to remove. - * @return true if the operation succeeded, - * false if not - * @throws UnsupportedOperationException - * if the removeContainerProperty is not supported. - */ - public boolean removeContainerProperty(Object propertyId) - throws UnsupportedOperationException { - return container.removeContainerProperty(propertyId); - } - - /* - * Does the container contain the specified Item? Don't add a JavaDoc - * comment here, we use the default documentation from implemented - * interface. - */ - public boolean containsId(Object itemId) { - return container.containsId(itemId); - } - - /* - * Gets the specified Item from the container. Don't add a JavaDoc comment - * here, we use the default documentation from implemented interface. - */ - public Item getItem(Object itemId) { - return container.getItem(itemId); - } - - /* - * Gets the ID's of all Items stored in the Container Don't add a JavaDoc - * comment here, we use the default documentation from implemented - * interface. - */ - public Collection getItemIds() { - return container.getItemIds(); - } - - /* - * Gets the Property identified by the given itemId and propertyId from the - * Container Don't add a JavaDoc comment here, we use the default - * documentation from implemented interface. - */ - public Property getContainerProperty(Object itemId, Object propertyId) { - return container.getContainerProperty(itemId, propertyId); - } - - /* - * Gets the ID's of all Properties stored in the Container Don't add a - * JavaDoc comment here, we use the default documentation from implemented - * interface. - */ - public Collection getContainerPropertyIds() { - return container.getContainerPropertyIds(); - } - - /* - * Gets the data type of all Properties identified by the given Property ID. - * Don't add a JavaDoc comment here, we use the default documentation from - * implemented interface. - */ - public Class getType(Object propertyId) { - return container.getType(propertyId); - } - - /* - * Gets the number of Items in the Container. Don't add a JavaDoc comment - * here, we use the default documentation from implemented interface. - */ - public int size() { - return container.size(); - } - - /* - * Registers a new Item set change listener for this Container. Don't add a - * JavaDoc comment here, we use the default documentation from implemented - * interface. - */ - public void addListener(Container.ItemSetChangeListener listener) { - if (container instanceof Container.ItemSetChangeNotifier) - ((Container.ItemSetChangeNotifier) container).addListener(listener); - } - - /* - * Removes a Item set change listener from the object. Don't add a JavaDoc - * comment here, we use the default documentation from implemented - * interface. - */ - public void removeListener(Container.ItemSetChangeListener listener) { - if (container instanceof Container.ItemSetChangeNotifier) - ((Container.ItemSetChangeNotifier) container) - .removeListener(listener); - } - - /* - * Registers a new Property set change listener for this Container. Don't - * add a JavaDoc comment here, we use the default documentation from - * implemented interface. - */ - public void addListener(Container.PropertySetChangeListener listener) { - if (container instanceof Container.PropertySetChangeNotifier) - ((Container.PropertySetChangeNotifier) container) - .addListener(listener); - } - - /* - * Removes a Property set change listener from the object. Don't add a - * JavaDoc comment here, we use the default documentation from implemented - * interface. - */ - public void removeListener(Container.PropertySetChangeListener listener) { - if (container instanceof Container.PropertySetChangeNotifier) - ((Container.PropertySetChangeNotifier) container) - .removeListener(listener); - } - - /** - * @see com.itmill.toolkit.data.Container.Ordered#addItemAfter(Object, - * Object) - */ - public Item addItemAfter(Object previousItemId, Object newItemId) - throws UnsupportedOperationException { - - // If the previous item is not in the container, fail - if (previousItemId != null && !containsId(previousItemId)) - return null; - - // Adds the item to container - Item item = container.addItem(newItemId); - - // Puts the new item to its correct place - if (item != null) - addToOrderWrapper(newItemId, previousItemId); - - return item; - } - - /** - * @see com.itmill.toolkit.data.Container.Ordered#addItemAfter(Object) - */ - public Object addItemAfter(Object previousItemId) - throws UnsupportedOperationException { - - // If the previous item is not in the container, fail - if (previousItemId != null && !containsId(previousItemId)) - return null; - - // Adds the item to container - Object id = container.addItem(); - - // Puts the new item to its correct place - if (id != null) - addToOrderWrapper(id, previousItemId); - - return id; - } + Container.ItemSetChangeNotifier, Container.PropertySetChangeNotifier { + + /** + * The wrapped container + */ + private Container container; + + /** + * Ordering information, ie. the mapping from Item ID to the next item ID + */ + private Hashtable next; + + /** + * Reverse ordering information for convenience and performance reasons. + */ + private Hashtable prev; + + /** + * ID of the first Item in the container. + */ + private Object first; + + /** + * ID of the last Item in the container. + */ + private Object last; + + /** + * Is the wrapped container ordered by itself, ie. does it implement the + * Container.Ordered interface by itself? If it does, this class will use + * the methods of the underlying container directly. + */ + private boolean ordered = false; + + /** + * Constructs a new ordered wrapper for an existing Container. Works even if + * the to-be-wrapped container already implements the Container.Ordered + * interface. + * + * @param toBeWrapped + * the container whose contents need to be ordered. + */ + public ContainerOrderedWrapper(Container toBeWrapped) { + + container = toBeWrapped; + ordered = container instanceof Container.Ordered; + + // Checks arguments + if (container == null) { + throw new NullPointerException("Null can not be wrapped"); + } + + // Creates initial order if needed + updateOrderWrapper(); + } + + /** + * Removes the specified Item from the wrapper's internal hierarchy + * structure. + *

+ * Note : The Item is not removed from the underlying Container. + *

+ * + * @param id + * the ID of the Item to be removed from the ordering. + */ + private void removeFromOrderWrapper(Object id) { + if (id != null) { + Object pid = prev.get(id); + Object nid = next.get(id); + if (first.equals(id)) { + first = nid; + } + if (last.equals(id)) { + first = pid; + } + if (nid != null) { + prev.put(nid, pid); + } + if (pid != null) { + next.put(pid, nid); + } + next.remove(id); + prev.remove(id); + } + } + + /** + * Registers the specified Item to the last position in the wrapper's + * internal ordering. The underlying container is not modified. + * + * @param id + * the ID of the Item to be added to the ordering. + */ + private void addToOrderWrapper(Object id) { + + // Adds the if to tail + if (last != null) { + next.put(last, id); + prev.put(id, last); + last = id; + } else { + first = last = id; + } + } + + /** + * Registers the specified Item after the specified itemId in the wrapper's + * internal ordering. The underlying container is not modified. Given item + * id must be in the container, or must be null. + * + * @param id + * the ID of the Item to be added to the ordering. + * @param previousItemId + * the Id of the previous item. + */ + private void addToOrderWrapper(Object id, Object previousItemId) { + + if (last == previousItemId || last == null) { + addToOrderWrapper(id); + } else { + if (previousItemId == null) { + next.put(id, first); + prev.put(first, id); + first = id; + } else { + prev.put(id, previousItemId); + next.put(id, next.get(previousItemId)); + prev.put(next.get(previousItemId), id); + next.put(previousItemId, id); + } + } + } + + /** + * Updates the wrapper's internal ordering information to include all Items + * in the underlying container. + *

+ * Note : If the contents of the wrapped container change without the + * wrapper's knowledge, this method needs to be called to update the + * ordering information of the Items. + *

+ */ + public void updateOrderWrapper() { + + if (!ordered) { + + Collection ids = container.getItemIds(); + + // Recreates ordering if some parts of it are missing + if (next == null || first == null || last == null || prev != null) { + first = null; + last = null; + next = new Hashtable(); + prev = new Hashtable(); + } + + // Filter out all the missing items + LinkedList l = new LinkedList(next.keySet()); + for (Iterator i = l.iterator(); i.hasNext();) { + Object id = i.next(); + if (!container.containsId(id)) { + removeFromOrderWrapper(id); + } + } + + // Adds missing items + for (Iterator i = ids.iterator(); i.hasNext();) { + Object id = i.next(); + if (!next.containsKey(id)) { + addToOrderWrapper(id); + } + } + } + } + + /* + * Gets the first item stored in the ordered container Don't add a JavaDoc + * comment here, we use the default documentation from implemented + * interface. + */ + public Object firstItemId() { + if (ordered) { + return ((Container.Ordered) container).firstItemId(); + } + return first; + } + + /* + * Tests if the given item is the first item in the container Don't add a + * JavaDoc comment here, we use the default documentation from implemented + * interface. + */ + public boolean isFirstId(Object itemId) { + if (ordered) { + return ((Container.Ordered) container).isFirstId(itemId); + } + return first != null && first.equals(itemId); + } + + /* + * Tests if the given item is the last item in the container Don't add a + * JavaDoc comment here, we use the default documentation from implemented + * interface. + */ + public boolean isLastId(Object itemId) { + if (ordered) { + return ((Container.Ordered) container).isLastId(itemId); + } + return last != null && last.equals(itemId); + } + + /* + * Gets the last item stored in the ordered container Don't add a JavaDoc + * comment here, we use the default documentation from implemented + * interface. + */ + public Object lastItemId() { + if (ordered) { + return ((Container.Ordered) container).lastItemId(); + } + return last; + } + + /* + * Gets the item that is next from the specified item. Don't add a JavaDoc + * comment here, we use the default documentation from implemented + * interface. + */ + public Object nextItemId(Object itemId) { + if (ordered) { + return ((Container.Ordered) container).nextItemId(itemId); + } + return next.get(itemId); + } + + /* + * Gets the item that is previous from the specified item. Don't add a + * JavaDoc comment here, we use the default documentation from implemented + * interface. + */ + public Object prevItemId(Object itemId) { + if (ordered) { + return ((Container.Ordered) container).prevItemId(itemId); + } + return prev.get(itemId); + } + + /** + * Registers a new Property to all Items in the Container. + * + * @param propertyId + * the ID of the new Property. + * @param type + * the Data type of the new Property. + * @param defaultValue + * the value all created Properties are initialized to. + * @return true if the operation succeeded, + * false if not + */ + public boolean addContainerProperty(Object propertyId, Class type, + Object defaultValue) throws UnsupportedOperationException { + + return container.addContainerProperty(propertyId, type, defaultValue); + } + + /** + * Creates a new Item into the Container, assigns it an automatic ID, and + * adds it to the ordering. + * + * @return the autogenerated ID of the new Item or null if + * the operation failed + * @throws UnsupportedOperationException + * if the addItem is not supported. + */ + public Object addItem() throws UnsupportedOperationException { + + Object id = container.addItem(); + if (id != null) { + addToOrderWrapper(id); + } + return id; + } + + /** + * Registers a new Item by its ID to the underlying container and to the + * ordering. + * + * @param itemId + * the ID of the Item to be created. + * @return the added Item or null if the operation failed + * @throws UnsupportedOperationException + * if the addItem is not supported. + */ + public Item addItem(Object itemId) throws UnsupportedOperationException { + Item item = container.addItem(itemId); + if (item != null) { + addToOrderWrapper(itemId); + } + return item; + } + + /** + * Removes all items from the underlying container and from the ordering. + * + * @return true if the operation succeeded, otherwise + * false + * @throws UnsupportedOperationException + * if the removeAllItems is not supported. + */ + public boolean removeAllItems() throws UnsupportedOperationException { + boolean success = container.removeAllItems(); + if (success) { + first = last = null; + next.clear(); + prev.clear(); + } + return success; + } + + /** + * Removes an Item specified by the itemId from the underlying container and + * from the ordering. + * + * @param itemId + * the ID of the Item to be removed. + * @return true if the operation succeeded, + * false if not + * @throws UnsupportedOperationException + * if the removeItem is not supported. + */ + public boolean removeItem(Object itemId) + throws UnsupportedOperationException { + + boolean success = container.removeItem(itemId); + if (success) { + removeFromOrderWrapper(itemId); + } + return success; + } + + /** + * Removes the specified Property from the underlying container and from the + * ordering. + *

+ * Note : The Property will be removed from all the Items in the Container. + *

+ * + * @param propertyId + * the ID of the Property to remove. + * @return true if the operation succeeded, + * false if not + * @throws UnsupportedOperationException + * if the removeContainerProperty is not supported. + */ + public boolean removeContainerProperty(Object propertyId) + throws UnsupportedOperationException { + return container.removeContainerProperty(propertyId); + } + + /* + * Does the container contain the specified Item? Don't add a JavaDoc + * comment here, we use the default documentation from implemented + * interface. + */ + public boolean containsId(Object itemId) { + return container.containsId(itemId); + } + + /* + * Gets the specified Item from the container. Don't add a JavaDoc comment + * here, we use the default documentation from implemented interface. + */ + public Item getItem(Object itemId) { + return container.getItem(itemId); + } + + /* + * Gets the ID's of all Items stored in the Container Don't add a JavaDoc + * comment here, we use the default documentation from implemented + * interface. + */ + public Collection getItemIds() { + return container.getItemIds(); + } + + /* + * Gets the Property identified by the given itemId and propertyId from the + * Container Don't add a JavaDoc comment here, we use the default + * documentation from implemented interface. + */ + public Property getContainerProperty(Object itemId, Object propertyId) { + return container.getContainerProperty(itemId, propertyId); + } + + /* + * Gets the ID's of all Properties stored in the Container Don't add a + * JavaDoc comment here, we use the default documentation from implemented + * interface. + */ + public Collection getContainerPropertyIds() { + return container.getContainerPropertyIds(); + } + + /* + * Gets the data type of all Properties identified by the given Property ID. + * Don't add a JavaDoc comment here, we use the default documentation from + * implemented interface. + */ + public Class getType(Object propertyId) { + return container.getType(propertyId); + } + + /* + * Gets the number of Items in the Container. Don't add a JavaDoc comment + * here, we use the default documentation from implemented interface. + */ + public int size() { + return container.size(); + } + + /* + * Registers a new Item set change listener for this Container. Don't add a + * JavaDoc comment here, we use the default documentation from implemented + * interface. + */ + public void addListener(Container.ItemSetChangeListener listener) { + if (container instanceof Container.ItemSetChangeNotifier) { + ((Container.ItemSetChangeNotifier) container).addListener(listener); + } + } + + /* + * Removes a Item set change listener from the object. Don't add a JavaDoc + * comment here, we use the default documentation from implemented + * interface. + */ + public void removeListener(Container.ItemSetChangeListener listener) { + if (container instanceof Container.ItemSetChangeNotifier) { + ((Container.ItemSetChangeNotifier) container) + .removeListener(listener); + } + } + + /* + * Registers a new Property set change listener for this Container. Don't + * add a JavaDoc comment here, we use the default documentation from + * implemented interface. + */ + public void addListener(Container.PropertySetChangeListener listener) { + if (container instanceof Container.PropertySetChangeNotifier) { + ((Container.PropertySetChangeNotifier) container) + .addListener(listener); + } + } + + /* + * Removes a Property set change listener from the object. Don't add a + * JavaDoc comment here, we use the default documentation from implemented + * interface. + */ + public void removeListener(Container.PropertySetChangeListener listener) { + if (container instanceof Container.PropertySetChangeNotifier) { + ((Container.PropertySetChangeNotifier) container) + .removeListener(listener); + } + } + + /** + * @see com.itmill.toolkit.data.Container.Ordered#addItemAfter(Object, + * Object) + */ + public Item addItemAfter(Object previousItemId, Object newItemId) + throws UnsupportedOperationException { + + // If the previous item is not in the container, fail + if (previousItemId != null && !containsId(previousItemId)) { + return null; + } + + // Adds the item to container + Item item = container.addItem(newItemId); + + // Puts the new item to its correct place + if (item != null) { + addToOrderWrapper(newItemId, previousItemId); + } + + return item; + } + + /** + * @see com.itmill.toolkit.data.Container.Ordered#addItemAfter(Object) + */ + public Object addItemAfter(Object previousItemId) + throws UnsupportedOperationException { + + // If the previous item is not in the container, fail + if (previousItemId != null && !containsId(previousItemId)) { + return null; + } + + // Adds the item to container + Object id = container.addItem(); + + // Puts the new item to its correct place + if (id != null) { + addToOrderWrapper(id, previousItemId); + } + + return id; + } } diff --git a/src/com/itmill/toolkit/data/util/FilesystemContainer.java b/src/com/itmill/toolkit/data/util/FilesystemContainer.java index f502b0fee8..789dd110aa 100644 --- a/src/com/itmill/toolkit/data/util/FilesystemContainer.java +++ b/src/com/itmill/toolkit/data/util/FilesystemContainer.java @@ -28,6 +28,10 @@ package com.itmill.toolkit.data.util; +import java.io.File; +import java.io.FilenameFilter; +import java.io.IOException; +import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; @@ -36,10 +40,6 @@ import java.util.Date; import java.util.Iterator; import java.util.LinkedList; import java.util.List; -import java.io.File; -import java.io.FilenameFilter; -import java.io.IOException; -import java.lang.reflect.Method; import com.itmill.toolkit.data.Container; import com.itmill.toolkit.data.Item; @@ -57,802 +57,837 @@ import com.itmill.toolkit.terminal.Resource; */ public class FilesystemContainer implements Container.Hierarchical { - /** - * String identifier of a file's "name" property. - */ - public static String PROPERTY_NAME = "Name"; - - /** - * String identifier of a file's "size" property. - */ - public static String PROPERTY_SIZE = "Size"; - - /** - * String identifier of a file's "icon" property. - */ - public static String PROPERTY_ICON = "Icon"; - - /** - * String identifier of a file's "last modified" property. - */ - public static String PROPERTY_LASTMODIFIED = "Last Modified"; - - /** - * List of the string identifiers for the available properties. - */ - public static Collection FILE_PROPERTIES; - - private static Method FILEITEM_LASTMODIFIED; - - private static Method FILEITEM_NAME; - - private static Method FILEITEM_ICON; - - private static Method FILEITEM_SIZE; - - static { - - FILE_PROPERTIES = new ArrayList(); - FILE_PROPERTIES.add(PROPERTY_NAME); - FILE_PROPERTIES.add(PROPERTY_ICON); - FILE_PROPERTIES.add(PROPERTY_SIZE); - FILE_PROPERTIES.add(PROPERTY_LASTMODIFIED); - FILE_PROPERTIES = Collections.unmodifiableCollection(FILE_PROPERTIES); - try { - FILEITEM_LASTMODIFIED = FileItem.class.getMethod("lastModified", - new Class[] {}); - FILEITEM_NAME = FileItem.class.getMethod("getName", new Class[] {}); - FILEITEM_ICON = FileItem.class.getMethod("getIcon", new Class[] {}); - FILEITEM_SIZE = FileItem.class.getMethod("getSize", new Class[] {}); - } catch (NoSuchMethodException e) { - - } - } - - private File[] roots = new File[] {}; - - private FilenameFilter filter = null; - - private boolean recursive = true; - - /** - * Constructs a new FileSystemContainer with the specified - * file as the root of the filesystem. The files are included recursively. - * - * @param root - * the root file for the new file-system container. Null values - * are ignored. - */ - public FilesystemContainer(File root) { - if (root != null) { - this.roots = new File[] { root }; - } - } - - /** - * Constructs a new FileSystemContainer with the specified - * file as the root of the filesystem. The files are included recursively. - * - * @param root - * the root file for the new file-system container. - * @param recursive - * should the container recursively contain subdirectories. - */ - public FilesystemContainer(File root, boolean recursive) { - this(root); - this.setRecursive(recursive); - } - - /** - * Constructs a new FileSystemContainer with the specified - * file as the root of the filesystem. - * - * @param root - * the root file for the new file-system container. - * @param extension - * the Filename extension (w/o separator) to limit the files in - * container. - * @param recursive - * should the container recursively contain subdirectories. - */ - public FilesystemContainer(File root, String extension, boolean recursive) { - this(root); - this.setFilter(extension); - this.setRecursive(recursive); - } - - /** - * Constructs a new FileSystemContainer with the specified - * root and recursivity status. - * - * @param root - * the root file for the new file-system container. - * @param filter - * the Filename filter to limit the files in container. - * @param recursive - * should the container recursively contain subdirectories. - */ - public FilesystemContainer(File root, FilenameFilter filter, - boolean recursive) { - this(root); - this.setFilter(filter); - this.setRecursive(recursive); - } - - /** - * Adds new root file directory. Adds a file to be included as root file - * directory in the FilesystemContainer. - * - * @param root - * the File to be added as root directory. Null values are - * ignored. - */ - public void addRoot(File root) { - if (root != null) { - File[] newRoots = new File[this.roots.length + 1]; - for (int i = 0; i < this.roots.length; i++) { - newRoots[i] = this.roots[i]; - } - newRoots[this.roots.length] = root; - this.roots = newRoots; - } - } - - /** - * Tests if the specified Item in the container may have children. Since a - * FileSystemContainer contains files and directories, this - * method returns true for directory Items only. - * - * @param itemId - * the id of the item. - * @return true if the specified Item is a directory, - * false otherwise. - */ - public boolean areChildrenAllowed(Object itemId) { - return itemId instanceof File && ((File) itemId).canRead() - && ((File) itemId).isDirectory(); - } - - /* - * Gets the ID's of all Items who are children of the specified Item. Don't - * add a JavaDoc comment here, we use the default documentation from - * implemented interface. - */ - public Collection getChildren(Object itemId) { - - if (!(itemId instanceof File)) - return Collections.unmodifiableCollection(new LinkedList()); - File[] f; - if (this.filter != null) - f = ((File) itemId).listFiles(this.filter); - else - f = ((File) itemId).listFiles(); - - if (f == null) - return Collections.unmodifiableCollection(new LinkedList()); - - List l = Arrays.asList(f); - Collections.sort(l); - - return Collections.unmodifiableCollection(l); - } - - /* - * Gets the parent item of the specified Item. Don't add a JavaDoc comment - * here, we use the default documentation from implemented interface. - */ - public Object getParent(Object itemId) { - - if (!(itemId instanceof File)) - return null; - return ((File) itemId).getParentFile(); - } - - /* - * Tests if the specified Item has any children. Don't add a JavaDoc comment - * here, we use the default documentation from implemented interface. - */ - public boolean hasChildren(Object itemId) { - - if (!(itemId instanceof File)) - return false; - String[] l; - if (this.filter != null) - l = ((File) itemId).list(this.filter); - else - l = ((File) itemId).list(); - return (l != null) && (l.length > 0); - } - - /* - * Tests if the specified Item is the root of the filesystem. Don't add a - * JavaDoc comment here, we use the default documentation from implemented - * interface. - */ - public boolean isRoot(Object itemId) { - - if (!(itemId instanceof File)) - return false; - for (int i = 0; i < roots.length; i++) { - if (roots[i].equals((File) itemId)) - return true; - } - return false; - } - - /* - * Gets the ID's of all root Items in the container. Don't add a JavaDoc - * comment here, we use the default documentation from implemented - * interface. - */ - public Collection rootItemIds() { - - File[] f; - - // in single root case we use children - if (roots.length == 1) { - if (this.filter != null) - f = roots[0].listFiles(this.filter); - else - f = roots[0].listFiles(); - } else { - f = this.roots; - } - - if (f == null) - return Collections.unmodifiableCollection(new LinkedList()); - - List l = Arrays.asList(f); - Collections.sort(l); - - return Collections.unmodifiableCollection(l); - } - - /** - * Returns false when conversion from files to directories is - * not supported. - * - * @param itemId - * the ID of the item. - * @param areChildrenAllowed - * the boolean value specifying if the Item can have children or - * not. - * @return true if the operaton is successful otherwise - * false. - * @throws UnsupportedOperationException - * if the setChildrenAllowed is not supported. - */ - public boolean setChildrenAllowed(Object itemId, boolean areChildrenAllowed) - throws UnsupportedOperationException { - - throw new UnsupportedOperationException( - "Conversion file to/from directory is not supported"); - } - - /** - * Returns false when moving files around in the filesystem - * is not supported. - * - * @param itemId - * the ID of the item. - * @param newParentId - * the ID of the Item that's to be the new parent of the Item - * identified with itemId. - * @return true if the operation is successful otherwise - * false. - * @throws UnsupportedOperationException - * if the setParent is not supported. - */ - public boolean setParent(Object itemId, Object newParentId) - throws UnsupportedOperationException { - - throw new UnsupportedOperationException("File moving is not supported"); - } - - /* - * Tests if the filesystem contains the specified Item. Don't add a JavaDoc - * comment here, we use the default documentation from implemented - * interface. - */ - public boolean containsId(Object itemId) { - - if (!(itemId instanceof File)) - return false; - boolean val = false; - - // Try to match all roots - for (int i = 0; i < roots.length; i++) { - try { - val |= ((File) itemId).getCanonicalPath().startsWith( - roots[i].getCanonicalPath()); - } catch (IOException e) { - // Exception ignored - } - - } - if (val && this.filter != null) - val &= this.filter.accept(((File) itemId).getParentFile(), - ((File) itemId).getName()); - return val; - } - - /* - * Gets the specified Item from the filesystem. Don't add a JavaDoc comment - * here, we use the default documentation from implemented interface. - */ - public Item getItem(Object itemId) { - - if (!(itemId instanceof File)) - return null; - return new FileItem((File) itemId); - } - - /** - * Internal recursive method to add the files under the specified directory - * to the collection. - * - * @param col - * the collection where the found items are added - * @param f - * the root file where to start adding files - */ - private void addItemIds(Collection col, File f) { - File[] l; - if (this.filter != null) - l = f.listFiles(this.filter); - else - l = f.listFiles(); - List ll = Arrays.asList(l); - Collections.sort(ll); - - for (Iterator i = ll.iterator(); i.hasNext();) { - File lf = (File) i.next(); - if (lf.isDirectory()) - addItemIds(col, lf); - else - col.add(lf); - } - } - - /* - * Gets the IDs of Items in the filesystem. Don't add a JavaDoc comment - * here, we use the default documentation from implemented interface. - */ - public Collection getItemIds() { - - if (recursive) { - Collection col = new ArrayList(); - for (int i = 0; i < roots.length; i++) { - addItemIds(col, roots[i]); - } - return Collections.unmodifiableCollection(col); - } else { - File[] f; - if (roots.length == 1) { - if (this.filter != null) - f = roots[0].listFiles(this.filter); - else - f = roots[0].listFiles(); - } else { - f = roots; - } - - if (f == null) - return Collections.unmodifiableCollection(new LinkedList()); - - List l = Arrays.asList(f); - Collections.sort(l); - return Collections.unmodifiableCollection(l); - } - - } - - /** - * Gets the specified property of the specified file Item. The available - * file properties are "Name", "Size" and "Last Modified". If propertyId is - * not one of those, null is returned. - * - * @param itemId - * the ID of the file whose property is requested. - * @param propertyId - * the property's ID. - * @return the requested property's value, or null - */ - public Property getContainerProperty(Object itemId, Object propertyId) { - - if (!(itemId instanceof File)) - return null; - - if (propertyId.equals(PROPERTY_NAME)) - return new MethodProperty(getType(propertyId), new FileItem( - (File) itemId), FILEITEM_NAME, null); - - if (propertyId.equals(PROPERTY_ICON)) - return new MethodProperty(getType(propertyId), new FileItem( - (File) itemId), FILEITEM_ICON, null); - - if (propertyId.equals(PROPERTY_SIZE)) - return new MethodProperty(getType(propertyId), new FileItem( - (File) itemId), FILEITEM_SIZE, null); - - if (propertyId.equals(PROPERTY_LASTMODIFIED)) - return new MethodProperty(getType(propertyId), new FileItem( - (File) itemId), FILEITEM_LASTMODIFIED, null); - - return null; - } - - /** - * Gets the collection of available file properties. - * - * @return Unmodifiable collection containing all available file properties. - */ - public Collection getContainerPropertyIds() { - return FILE_PROPERTIES; - } - - /** - * Gets the specified property's data type. "Name" is a String, - * "Size" is a Long, "Last Modified" is a Date. - * If propertyId is not one of those, null is returned. - * - * @param propertyId - * the ID of the property whose type is requested. - * @return data type of the requested property, or null - */ - public Class getType(Object propertyId) { - - if (propertyId.equals(PROPERTY_NAME)) - return String.class; - if (propertyId.equals(PROPERTY_ICON)) - return Resource.class; - if (propertyId.equals(PROPERTY_SIZE)) - return Long.class; - if (propertyId.equals(PROPERTY_LASTMODIFIED)) - return Date.class; - return null; - } - - /** - * Internal method to recursively calculate the number of files under a root - * directory. - * - * @param f - * the root to start counting from. - */ - private int getFileCounts(File f) { - File[] l; - if (this.filter != null) - l = f.listFiles(this.filter); - else - l = f.listFiles(); - - if (l == null) - return 0; - int ret = l.length; - for (int i = 0; i < l.length; i++) { - if (l[i].isDirectory()) - ret += getFileCounts(l[i]); - } - return ret; - } - - /** - * Gets the number of Items in the container. In effect, this is the - * combined amount of files and directories. - * - * @return Number of Items in the container. - */ - public int size() { - - if (recursive) { - int counts = 0; - for (int i = 0; i < roots.length; i++) { - counts += getFileCounts(this.roots[i]); - } - return counts; - } else { - File[] f; - if (roots.length == 1) { - if (this.filter != null) - f = roots[0].listFiles(this.filter); - else - f = roots[0].listFiles(); - } else { - f = roots; - } - - if (f == null) - return 0; - return f.length; - } - } - - /** - * A Item wrapper for files in a filesystem. - * - * @author IT Mill Ltd. - * @version - * @VERSION@ - * @since 3.0 - */ - public class FileItem implements Item { - - /** - * The wrapped file. - */ - private File file; - - /** - * Constructs a FileItem from a existing file. - */ - private FileItem(File file) { - this.file = file; - } - - /* - * Gets the specified property of this file. Don't add a JavaDoc comment - * here, we use the default documentation from implemented interface. - */ - public Property getItemProperty(Object id) { - return FilesystemContainer.this.getContainerProperty(file, id); - } - - /* - * Gets the IDs of all properties available for this item Don't add a - * JavaDoc comment here, we use the default documentation from - * implemented interface. - */ - public Collection getItemPropertyIds() { - return FilesystemContainer.this.getContainerPropertyIds(); - } - - /** - * Calculates a integer hash-code for the Property that's unique inside - * the Item containing the Property. Two different Properties inside the - * same Item contained in the same list always have different - * hash-codes, though Properties in different Items may have identical - * hash-codes. - * - * @return A locally unique hash-code as integer - */ - public int hashCode() { - return file.hashCode() ^ FilesystemContainer.this.hashCode(); - } - - /** - * Tests if the given object is the same as the this object. Two - * Properties got from an Item with the same ID are equal. - * - * @param obj - * an object to compare with this object. - * @return true if the given object is the same as this - * object, false if not - */ - public boolean equals(Object obj) { - if (obj == null || !(obj instanceof FileItem)) - return false; - FileItem fi = (FileItem) obj; - return fi.getHost() == getHost() && fi.file.equals(file); - } - - /** - * Gets the host of this file. - */ - private FilesystemContainer getHost() { - return FilesystemContainer.this; - } - - /** - * Gets the last modified date of this file. - * - * @return Date - */ - public Date lastModified() { - return new Date(this.file.lastModified()); - } - - /** - * Gets the name of this file. - * - * @return file name of this file. - */ - public String getName() { - return this.file.getName(); - } - - /** - * Gets the icon of this file. - * - * @return the icon of this file. - */ - public Resource getIcon() { - return FileTypeResolver.getIcon(this.file); - } - - /** - * Gets the size of this file. - * - * @return size - */ - public long getSize() { - if (this.file.isDirectory()) - return 0; - return this.file.length(); - } - - /** - * @see java.lang.Object#toString() - */ - public String toString() { - if ("".equals(file.getName())) - return file.getAbsolutePath(); - return file.getName(); - } - - /** - * Filesystem container does not support adding new properties. - * - * @see com.itmill.toolkit.data.Item#addItemProperty(Object, Property) - */ - public boolean addItemProperty(Object id, Property property) - throws UnsupportedOperationException { - throw new UnsupportedOperationException("Filesystem container " - + "does not support adding new properties"); - } - - /** - * Filesystem container does not support removing properties. - * - * @see com.itmill.toolkit.data.Item#removeItemProperty(Object) - */ - public boolean removeItemProperty(Object id) - throws UnsupportedOperationException { - throw new UnsupportedOperationException( - "Filesystem container does not support property removal"); - } - - } - - /** - * Generic file extension filter for displaying only files having certain - * extension. - * - * @author IT Mill Ltd. - * @version - * @VERSION@ - * @since 3.0 - */ - public class FileExtensionFilter implements FilenameFilter { - - private String filter; - - /** - * Constructs a new FileExtensionFilter using given extension. - * - * @param fileExtension - * the File extension without the separator (dot). - */ - public FileExtensionFilter(String fileExtension) { - this.filter = "." + fileExtension; - } - - /** - * Allows only files with the extension and directories. - * - * @see java.io.FilenameFilter#accept(File, String) - */ - public boolean accept(File dir, String name) { - if (name.endsWith(filter)) - return true; - return new File(dir, name).isDirectory(); - } - - } - - /** - * Returns the file filter used to limit the files in this container. - * - * @return Used filter instance or null if no filter is assigned. - */ - public FilenameFilter getFilter() { - return filter; - } - - /** - * Sets the file filter used to limit the files in this container. - * - * @param filter - * The filter to set. null disables filtering. - */ - public void setFilter(FilenameFilter filter) { - this.filter = filter; - } - - /** - * Sets the file filter used to limit the files in this container. - * - * @param extension - * the Filename extension (w/o separator) to limit the files in - * container. - */ - public void setFilter(String extension) { - this.filter = new FileExtensionFilter(extension); - } - - /** - * Is this container recursive filesystem. - * - * @return true if container is recursive, false - * otherwise. - */ - public boolean isRecursive() { - return recursive; - } - - /** - * Sets the container recursive property. Set this to false to limit the - * files directly under the root file. - *

- * Note : This is meaningful only if the root really is a directory. - *

- * - * @param recursive - * the New value for recursive property. - */ - public void setRecursive(boolean recursive) { - this.recursive = recursive; - } - - /** - * @see com.itmill.toolkit.data.Container#addContainerProperty(Object, - * Class, Object) - */ - public boolean addContainerProperty(Object propertyId, Class type, - Object defaultValue) throws UnsupportedOperationException { - throw new UnsupportedOperationException( - "File system container does not support this operation"); - } - - /** - * @see com.itmill.toolkit.data.Container#addItem() - */ - public Object addItem() throws UnsupportedOperationException { - throw new UnsupportedOperationException( - "File system container does not support this operation"); - } - - /** - * @see com.itmill.toolkit.data.Container#addItem(Object) - */ - public Item addItem(Object itemId) throws UnsupportedOperationException { - throw new UnsupportedOperationException( - "File system container does not support this operation"); - } - - /** - * @see com.itmill.toolkit.data.Container#removeAllItems() - */ - public boolean removeAllItems() throws UnsupportedOperationException { - throw new UnsupportedOperationException( - "File system container does not support this operation"); - } - - /** - * @see com.itmill.toolkit.data.Container#removeItem(Object) - */ - public boolean removeItem(Object itemId) - throws UnsupportedOperationException { - throw new UnsupportedOperationException( - "File system container does not support this operation"); - } - - /** - * @see com.itmill.toolkit.data.Container#removeContainerProperty(Object) - */ - public boolean removeContainerProperty(Object propertyId) - throws UnsupportedOperationException { - throw new UnsupportedOperationException( - "File system container does not support this operation"); - } + /** + * String identifier of a file's "name" property. + */ + public static String PROPERTY_NAME = "Name"; + + /** + * String identifier of a file's "size" property. + */ + public static String PROPERTY_SIZE = "Size"; + + /** + * String identifier of a file's "icon" property. + */ + public static String PROPERTY_ICON = "Icon"; + + /** + * String identifier of a file's "last modified" property. + */ + public static String PROPERTY_LASTMODIFIED = "Last Modified"; + + /** + * List of the string identifiers for the available properties. + */ + public static Collection FILE_PROPERTIES; + + private static Method FILEITEM_LASTMODIFIED; + + private static Method FILEITEM_NAME; + + private static Method FILEITEM_ICON; + + private static Method FILEITEM_SIZE; + + static { + + FILE_PROPERTIES = new ArrayList(); + FILE_PROPERTIES.add(PROPERTY_NAME); + FILE_PROPERTIES.add(PROPERTY_ICON); + FILE_PROPERTIES.add(PROPERTY_SIZE); + FILE_PROPERTIES.add(PROPERTY_LASTMODIFIED); + FILE_PROPERTIES = Collections.unmodifiableCollection(FILE_PROPERTIES); + try { + FILEITEM_LASTMODIFIED = FileItem.class.getMethod("lastModified", + new Class[] {}); + FILEITEM_NAME = FileItem.class.getMethod("getName", new Class[] {}); + FILEITEM_ICON = FileItem.class.getMethod("getIcon", new Class[] {}); + FILEITEM_SIZE = FileItem.class.getMethod("getSize", new Class[] {}); + } catch (NoSuchMethodException e) { + + } + } + + private File[] roots = new File[] {}; + + private FilenameFilter filter = null; + + private boolean recursive = true; + + /** + * Constructs a new FileSystemContainer with the specified + * file as the root of the filesystem. The files are included recursively. + * + * @param root + * the root file for the new file-system container. Null + * values are ignored. + */ + public FilesystemContainer(File root) { + if (root != null) { + roots = new File[] { root }; + } + } + + /** + * Constructs a new FileSystemContainer with the specified + * file as the root of the filesystem. The files are included recursively. + * + * @param root + * the root file for the new file-system container. + * @param recursive + * should the container recursively contain subdirectories. + */ + public FilesystemContainer(File root, boolean recursive) { + this(root); + setRecursive(recursive); + } + + /** + * Constructs a new FileSystemContainer with the specified + * file as the root of the filesystem. + * + * @param root + * the root file for the new file-system container. + * @param extension + * the Filename extension (w/o separator) to limit the files + * in container. + * @param recursive + * should the container recursively contain subdirectories. + */ + public FilesystemContainer(File root, String extension, boolean recursive) { + this(root); + this.setFilter(extension); + setRecursive(recursive); + } + + /** + * Constructs a new FileSystemContainer with the specified + * root and recursivity status. + * + * @param root + * the root file for the new file-system container. + * @param filter + * the Filename filter to limit the files in container. + * @param recursive + * should the container recursively contain subdirectories. + */ + public FilesystemContainer(File root, FilenameFilter filter, + boolean recursive) { + this(root); + this.setFilter(filter); + setRecursive(recursive); + } + + /** + * Adds new root file directory. Adds a file to be included as root file + * directory in the FilesystemContainer. + * + * @param root + * the File to be added as root directory. Null values are + * ignored. + */ + public void addRoot(File root) { + if (root != null) { + File[] newRoots = new File[roots.length + 1]; + for (int i = 0; i < roots.length; i++) { + newRoots[i] = roots[i]; + } + newRoots[roots.length] = root; + roots = newRoots; + } + } + + /** + * Tests if the specified Item in the container may have children. Since a + * FileSystemContainer contains files and directories, this + * method returns true for directory Items only. + * + * @param itemId + * the id of the item. + * @return true if the specified Item is a directory, + * false otherwise. + */ + public boolean areChildrenAllowed(Object itemId) { + return itemId instanceof File && ((File) itemId).canRead() + && ((File) itemId).isDirectory(); + } + + /* + * Gets the ID's of all Items who are children of the specified Item. Don't + * add a JavaDoc comment here, we use the default documentation from + * implemented interface. + */ + public Collection getChildren(Object itemId) { + + if (!(itemId instanceof File)) { + return Collections.unmodifiableCollection(new LinkedList()); + } + File[] f; + if (filter != null) { + f = ((File) itemId).listFiles(filter); + } else { + f = ((File) itemId).listFiles(); + } + + if (f == null) { + return Collections.unmodifiableCollection(new LinkedList()); + } + + List l = Arrays.asList(f); + Collections.sort(l); + + return Collections.unmodifiableCollection(l); + } + + /* + * Gets the parent item of the specified Item. Don't add a JavaDoc comment + * here, we use the default documentation from implemented interface. + */ + public Object getParent(Object itemId) { + + if (!(itemId instanceof File)) { + return null; + } + return ((File) itemId).getParentFile(); + } + + /* + * Tests if the specified Item has any children. Don't add a JavaDoc comment + * here, we use the default documentation from implemented interface. + */ + public boolean hasChildren(Object itemId) { + + if (!(itemId instanceof File)) { + return false; + } + String[] l; + if (filter != null) { + l = ((File) itemId).list(filter); + } else { + l = ((File) itemId).list(); + } + return (l != null) && (l.length > 0); + } + + /* + * Tests if the specified Item is the root of the filesystem. Don't add a + * JavaDoc comment here, we use the default documentation from implemented + * interface. + */ + public boolean isRoot(Object itemId) { + + if (!(itemId instanceof File)) { + return false; + } + for (int i = 0; i < roots.length; i++) { + if (roots[i].equals(itemId)) { + return true; + } + } + return false; + } + + /* + * Gets the ID's of all root Items in the container. Don't add a JavaDoc + * comment here, we use the default documentation from implemented + * interface. + */ + public Collection rootItemIds() { + + File[] f; + + // in single root case we use children + if (roots.length == 1) { + if (filter != null) { + f = roots[0].listFiles(filter); + } else { + f = roots[0].listFiles(); + } + } else { + f = roots; + } + + if (f == null) { + return Collections.unmodifiableCollection(new LinkedList()); + } + + List l = Arrays.asList(f); + Collections.sort(l); + + return Collections.unmodifiableCollection(l); + } + + /** + * Returns false when conversion from files to directories is + * not supported. + * + * @param itemId + * the ID of the item. + * @param areChildrenAllowed + * the boolean value specifying if the Item can have children + * or not. + * @return true if the operaton is successful otherwise + * false. + * @throws UnsupportedOperationException + * if the setChildrenAllowed is not supported. + */ + public boolean setChildrenAllowed(Object itemId, boolean areChildrenAllowed) + throws UnsupportedOperationException { + + throw new UnsupportedOperationException( + "Conversion file to/from directory is not supported"); + } + + /** + * Returns false when moving files around in the filesystem + * is not supported. + * + * @param itemId + * the ID of the item. + * @param newParentId + * the ID of the Item that's to be the new parent of the Item + * identified with itemId. + * @return true if the operation is successful otherwise + * false. + * @throws UnsupportedOperationException + * if the setParent is not supported. + */ + public boolean setParent(Object itemId, Object newParentId) + throws UnsupportedOperationException { + + throw new UnsupportedOperationException("File moving is not supported"); + } + + /* + * Tests if the filesystem contains the specified Item. Don't add a JavaDoc + * comment here, we use the default documentation from implemented + * interface. + */ + public boolean containsId(Object itemId) { + + if (!(itemId instanceof File)) { + return false; + } + boolean val = false; + + // Try to match all roots + for (int i = 0; i < roots.length; i++) { + try { + val |= ((File) itemId).getCanonicalPath().startsWith( + roots[i].getCanonicalPath()); + } catch (IOException e) { + // Exception ignored + } + + } + if (val && filter != null) { + val &= filter.accept(((File) itemId).getParentFile(), + ((File) itemId).getName()); + } + return val; + } + + /* + * Gets the specified Item from the filesystem. Don't add a JavaDoc comment + * here, we use the default documentation from implemented interface. + */ + public Item getItem(Object itemId) { + + if (!(itemId instanceof File)) { + return null; + } + return new FileItem((File) itemId); + } + + /** + * Internal recursive method to add the files under the specified directory + * to the collection. + * + * @param col + * the collection where the found items are added + * @param f + * the root file where to start adding files + */ + private void addItemIds(Collection col, File f) { + File[] l; + if (filter != null) { + l = f.listFiles(filter); + } else { + l = f.listFiles(); + } + List ll = Arrays.asList(l); + Collections.sort(ll); + + for (Iterator i = ll.iterator(); i.hasNext();) { + File lf = (File) i.next(); + if (lf.isDirectory()) { + addItemIds(col, lf); + } else { + col.add(lf); + } + } + } + + /* + * Gets the IDs of Items in the filesystem. Don't add a JavaDoc comment + * here, we use the default documentation from implemented interface. + */ + public Collection getItemIds() { + + if (recursive) { + Collection col = new ArrayList(); + for (int i = 0; i < roots.length; i++) { + addItemIds(col, roots[i]); + } + return Collections.unmodifiableCollection(col); + } else { + File[] f; + if (roots.length == 1) { + if (filter != null) { + f = roots[0].listFiles(filter); + } else { + f = roots[0].listFiles(); + } + } else { + f = roots; + } + + if (f == null) { + return Collections.unmodifiableCollection(new LinkedList()); + } + + List l = Arrays.asList(f); + Collections.sort(l); + return Collections.unmodifiableCollection(l); + } + + } + + /** + * Gets the specified property of the specified file Item. The available + * file properties are "Name", "Size" and "Last Modified". If propertyId is + * not one of those, null is returned. + * + * @param itemId + * the ID of the file whose property is requested. + * @param propertyId + * the property's ID. + * @return the requested property's value, or null + */ + public Property getContainerProperty(Object itemId, Object propertyId) { + + if (!(itemId instanceof File)) { + return null; + } + + if (propertyId.equals(PROPERTY_NAME)) { + return new MethodProperty(getType(propertyId), new FileItem( + (File) itemId), FILEITEM_NAME, null); + } + + if (propertyId.equals(PROPERTY_ICON)) { + return new MethodProperty(getType(propertyId), new FileItem( + (File) itemId), FILEITEM_ICON, null); + } + + if (propertyId.equals(PROPERTY_SIZE)) { + return new MethodProperty(getType(propertyId), new FileItem( + (File) itemId), FILEITEM_SIZE, null); + } + + if (propertyId.equals(PROPERTY_LASTMODIFIED)) { + return new MethodProperty(getType(propertyId), new FileItem( + (File) itemId), FILEITEM_LASTMODIFIED, null); + } + + return null; + } + + /** + * Gets the collection of available file properties. + * + * @return Unmodifiable collection containing all available file properties. + */ + public Collection getContainerPropertyIds() { + return FILE_PROPERTIES; + } + + /** + * Gets the specified property's data type. "Name" is a String, + * "Size" is a Long, "Last Modified" is a Date. + * If propertyId is not one of those, null is returned. + * + * @param propertyId + * the ID of the property whose type is requested. + * @return data type of the requested property, or null + */ + public Class getType(Object propertyId) { + + if (propertyId.equals(PROPERTY_NAME)) { + return String.class; + } + if (propertyId.equals(PROPERTY_ICON)) { + return Resource.class; + } + if (propertyId.equals(PROPERTY_SIZE)) { + return Long.class; + } + if (propertyId.equals(PROPERTY_LASTMODIFIED)) { + return Date.class; + } + return null; + } + + /** + * Internal method to recursively calculate the number of files under a root + * directory. + * + * @param f + * the root to start counting from. + */ + private int getFileCounts(File f) { + File[] l; + if (filter != null) { + l = f.listFiles(filter); + } else { + l = f.listFiles(); + } + + if (l == null) { + return 0; + } + int ret = l.length; + for (int i = 0; i < l.length; i++) { + if (l[i].isDirectory()) { + ret += getFileCounts(l[i]); + } + } + return ret; + } + + /** + * Gets the number of Items in the container. In effect, this is the + * combined amount of files and directories. + * + * @return Number of Items in the container. + */ + public int size() { + + if (recursive) { + int counts = 0; + for (int i = 0; i < roots.length; i++) { + counts += getFileCounts(roots[i]); + } + return counts; + } else { + File[] f; + if (roots.length == 1) { + if (filter != null) { + f = roots[0].listFiles(filter); + } else { + f = roots[0].listFiles(); + } + } else { + f = roots; + } + + if (f == null) { + return 0; + } + return f.length; + } + } + + /** + * A Item wrapper for files in a filesystem. + * + * @author IT Mill Ltd. + * @version + * @VERSION@ + * @since 3.0 + */ + public class FileItem implements Item { + + /** + * The wrapped file. + */ + private File file; + + /** + * Constructs a FileItem from a existing file. + */ + private FileItem(File file) { + this.file = file; + } + + /* + * Gets the specified property of this file. Don't add a JavaDoc comment + * here, we use the default documentation from implemented interface. + */ + public Property getItemProperty(Object id) { + return getContainerProperty(file, id); + } + + /* + * Gets the IDs of all properties available for this item Don't add a + * JavaDoc comment here, we use the default documentation from + * implemented interface. + */ + public Collection getItemPropertyIds() { + return getContainerPropertyIds(); + } + + /** + * Calculates a integer hash-code for the Property that's unique inside + * the Item containing the Property. Two different Properties inside the + * same Item contained in the same list always have different + * hash-codes, though Properties in different Items may have identical + * hash-codes. + * + * @return A locally unique hash-code as integer + */ + public int hashCode() { + return file.hashCode() ^ FilesystemContainer.this.hashCode(); + } + + /** + * Tests if the given object is the same as the this object. Two + * Properties got from an Item with the same ID are equal. + * + * @param obj + * an object to compare with this object. + * @return true if the given object is the same as this + * object, false if not + */ + public boolean equals(Object obj) { + if (obj == null || !(obj instanceof FileItem)) { + return false; + } + FileItem fi = (FileItem) obj; + return fi.getHost() == getHost() && fi.file.equals(file); + } + + /** + * Gets the host of this file. + */ + private FilesystemContainer getHost() { + return FilesystemContainer.this; + } + + /** + * Gets the last modified date of this file. + * + * @return Date + */ + public Date lastModified() { + return new Date(file.lastModified()); + } + + /** + * Gets the name of this file. + * + * @return file name of this file. + */ + public String getName() { + return file.getName(); + } + + /** + * Gets the icon of this file. + * + * @return the icon of this file. + */ + public Resource getIcon() { + return FileTypeResolver.getIcon(file); + } + + /** + * Gets the size of this file. + * + * @return size + */ + public long getSize() { + if (file.isDirectory()) { + return 0; + } + return file.length(); + } + + /** + * @see java.lang.Object#toString() + */ + public String toString() { + if ("".equals(file.getName())) { + return file.getAbsolutePath(); + } + return file.getName(); + } + + /** + * Filesystem container does not support adding new properties. + * + * @see com.itmill.toolkit.data.Item#addItemProperty(Object, Property) + */ + public boolean addItemProperty(Object id, Property property) + throws UnsupportedOperationException { + throw new UnsupportedOperationException("Filesystem container " + + "does not support adding new properties"); + } + + /** + * Filesystem container does not support removing properties. + * + * @see com.itmill.toolkit.data.Item#removeItemProperty(Object) + */ + public boolean removeItemProperty(Object id) + throws UnsupportedOperationException { + throw new UnsupportedOperationException( + "Filesystem container does not support property removal"); + } + + } + + /** + * Generic file extension filter for displaying only files having certain + * extension. + * + * @author IT Mill Ltd. + * @version + * @VERSION@ + * @since 3.0 + */ + public class FileExtensionFilter implements FilenameFilter { + + private String filter; + + /** + * Constructs a new FileExtensionFilter using given extension. + * + * @param fileExtension + * the File extension without the separator (dot). + */ + public FileExtensionFilter(String fileExtension) { + filter = "." + fileExtension; + } + + /** + * Allows only files with the extension and directories. + * + * @see java.io.FilenameFilter#accept(File, String) + */ + public boolean accept(File dir, String name) { + if (name.endsWith(filter)) { + return true; + } + return new File(dir, name).isDirectory(); + } + + } + + /** + * Returns the file filter used to limit the files in this container. + * + * @return Used filter instance or null if no filter is assigned. + */ + public FilenameFilter getFilter() { + return filter; + } + + /** + * Sets the file filter used to limit the files in this container. + * + * @param filter + * The filter to set. null disables filtering. + */ + public void setFilter(FilenameFilter filter) { + this.filter = filter; + } + + /** + * Sets the file filter used to limit the files in this container. + * + * @param extension + * the Filename extension (w/o separator) to limit the files + * in container. + */ + public void setFilter(String extension) { + filter = new FileExtensionFilter(extension); + } + + /** + * Is this container recursive filesystem. + * + * @return true if container is recursive, false + * otherwise. + */ + public boolean isRecursive() { + return recursive; + } + + /** + * Sets the container recursive property. Set this to false to limit the + * files directly under the root file. + *

+ * Note : This is meaningful only if the root really is a directory. + *

+ * + * @param recursive + * the New value for recursive property. + */ + public void setRecursive(boolean recursive) { + this.recursive = recursive; + } + + /** + * @see com.itmill.toolkit.data.Container#addContainerProperty(Object, + * Class, Object) + */ + public boolean addContainerProperty(Object propertyId, Class type, + Object defaultValue) throws UnsupportedOperationException { + throw new UnsupportedOperationException( + "File system container does not support this operation"); + } + + /** + * @see com.itmill.toolkit.data.Container#addItem() + */ + public Object addItem() throws UnsupportedOperationException { + throw new UnsupportedOperationException( + "File system container does not support this operation"); + } + + /** + * @see com.itmill.toolkit.data.Container#addItem(Object) + */ + public Item addItem(Object itemId) throws UnsupportedOperationException { + throw new UnsupportedOperationException( + "File system container does not support this operation"); + } + + /** + * @see com.itmill.toolkit.data.Container#removeAllItems() + */ + public boolean removeAllItems() throws UnsupportedOperationException { + throw new UnsupportedOperationException( + "File system container does not support this operation"); + } + + /** + * @see com.itmill.toolkit.data.Container#removeItem(Object) + */ + public boolean removeItem(Object itemId) + throws UnsupportedOperationException { + throw new UnsupportedOperationException( + "File system container does not support this operation"); + } + + /** + * @see com.itmill.toolkit.data.Container#removeContainerProperty(Object) + */ + public boolean removeContainerProperty(Object propertyId) + throws UnsupportedOperationException { + throw new UnsupportedOperationException( + "File system container does not support this operation"); + } } diff --git a/src/com/itmill/toolkit/data/util/HierarchicalContainer.java b/src/com/itmill/toolkit/data/util/HierarchicalContainer.java index b9de5d26de..81ff28546e 100644 --- a/src/com/itmill/toolkit/data/util/HierarchicalContainer.java +++ b/src/com/itmill/toolkit/data/util/HierarchicalContainer.java @@ -29,10 +29,10 @@ package com.itmill.toolkit.data.util; import java.util.Collection; -import java.util.LinkedList; import java.util.Collections; -import java.util.Hashtable; import java.util.HashSet; +import java.util.Hashtable; +import java.util.LinkedList; import com.itmill.toolkit.data.Container; import com.itmill.toolkit.data.Item; @@ -47,262 +47,276 @@ import com.itmill.toolkit.data.Item; * @since 3.0 */ public class HierarchicalContainer extends IndexedContainer implements - Container.Hierarchical { - - /** - * Set of IDs of those contained Items that can't have children. - */ - private HashSet noChildrenAllowed = new HashSet(); - - /** - * Mapping from Item ID to parent Item. - */ - private Hashtable parent = new Hashtable(); - - /** - * Mapping from Item ID to a list of child IDs. - */ - private Hashtable children = new Hashtable(); - - /** - * List that contains all root elements of the container. - */ - private LinkedList roots = new LinkedList(); - - /* - * Can the specified Item have any children? Don't add a JavaDoc comment - * here, we use the default documentation from implemented interface. - */ - public boolean areChildrenAllowed(Object itemId) { - return !noChildrenAllowed.contains(itemId); - } - - /* - * Gets the IDs of the children of the specified Item. Don't add a JavaDoc - * comment here, we use the default documentation from implemented - * interface. - */ - public Collection getChildren(Object itemId) { - Collection c = (Collection) children.get(itemId); - if (c == null) - return null; - return Collections.unmodifiableCollection(c); - } - - /* - * Gets the ID of the parent of the specified Item. Don't add a JavaDoc - * comment here, we use the default documentation from implemented - * interface. - */ - public Object getParent(Object itemId) { - return parent.get(itemId); - } - - /* - * Is the Item corresponding to the given ID a leaf node? Don't add a - * JavaDoc comment here, we use the default documentation from implemented - * interface. - */ - public boolean hasChildren(Object itemId) { - return children.get(itemId) != null; - } - - /* - * Is the Item corresponding to the given ID a root node? Don't add a - * JavaDoc comment here, we use the default documentation from implemented - * interface. - */ - public boolean isRoot(Object itemId) { - return parent.get(itemId) == null; - } - - /* - * Gets the IDs of the root elements in the container. Don't add a JavaDoc - * comment here, we use the default documentation from implemented - * interface. - */ - public Collection rootItemIds() { - return Collections.unmodifiableCollection(roots); - } - - /** - *

- * Sets the given Item's capability to have children. If the Item identified - * with the itemId already has children and the areChildrenAllowed is false - * this method fails and false is returned; the children must - * be first explicitly removed with - * {@link #setParent(Object itemId, Object newParentId)} or - * {@link com.itmill.toolkit.data.Container#removeItem(Object itemId)}. - *

- * - * @param itemId - * the ID of the Item in the container whose child capability is - * to be set. - * @param childrenAllowed - * the boolean value specifying if the Item can have children or - * not. - * @return true if the operation succeeded, - * false if not - */ - public boolean setChildrenAllowed(Object itemId, boolean childrenAllowed) { - - // Checks that the item is in the container - if (!containsId(itemId)) - return false; - - // Updates status - if (childrenAllowed) - noChildrenAllowed.remove(itemId); - else - noChildrenAllowed.add(itemId); - - return true; - } - - /** - *

- * Sets the parent of an Item. The new parent item must exist and be able to - * have children. (canHaveChildren(newParentId) == true). - * It is also possible to detach a node from the hierarchy (and thus make it - * root) by setting the parent null. - *

- * - * @param itemId - * the ID of the item to be set as the child of the Item - * identified with newParentId. - * @param newParentId - * the ID of the Item that's to be the new parent of the Item - * identified with itemId. - * @return true if the operation succeeded, - * false if not - */ - public boolean setParent(Object itemId, Object newParentId) { - - // Checks that the item is in the container - if (!containsId(itemId)) - return false; - - // Gets the old parent - Object oldParentId = parent.get(itemId); - - // Checks if no change is necessary - if ((newParentId == null && oldParentId == null) - || newParentId.equals(oldParentId)) - return true; - - // Making root - if (newParentId == null) { - - // Removes from old parents children list - LinkedList l = (LinkedList) children.get(itemId); - if (l != null) { - l.remove(itemId); - if (l.isEmpty()) - children.remove(itemId); - } - - // Add to be a root - roots.add(itemId); - - // Updates parent - parent.remove(itemId); - - return true; - } - - // Checks that the new parent exists in container and can have - // children - if (!containsId(newParentId) || noChildrenAllowed.contains(newParentId)) - return false; - - // Checks that setting parent doesn't result to a loop - Object o = newParentId; - while (o != null && !o.equals(itemId)) - o = parent.get(o); - if (o != null) - return false; - - // Updates parent - parent.put(itemId, newParentId); - LinkedList pcl = (LinkedList) children.get(newParentId); - if (pcl == null) { - pcl = new LinkedList(); - children.put(newParentId, pcl); - } - pcl.add(itemId); - - // Removes from old parent or root - if (oldParentId == null) - roots.remove(itemId); - else { - LinkedList l = (LinkedList) children.get(oldParentId); - if (l != null) { - l.remove(itemId); - if (l.isEmpty()) - children.remove(oldParentId); - } - } - - return true; - } - - /** - * @see com.itmill.toolkit.data.Container#addItem() - */ - public Object addItem() { - Object id = super.addItem(); - if (id != null && !roots.contains(id)) - roots.add(id); - return id; - - } - - /** - * @see com.itmill.toolkit.data.Container#addItem(Object) - */ - public Item addItem(Object itemId) { - Item item = super.addItem(itemId); - if (item != null) - roots.add(itemId); - return item; - } - - /** - * @see com.itmill.toolkit.data.Container#removeAllItems() - */ - public boolean removeAllItems() { - boolean success = super.removeAllItems(); - - if (success) { - roots.clear(); - parent.clear(); - children.clear(); - noChildrenAllowed.clear(); - } - return success; - } - - /** - * @see com.itmill.toolkit.data.Container#removeItem(Object) - */ - public boolean removeItem(Object itemId) { - boolean success = super.removeItem(itemId); - - if (success) { - if (isRoot(itemId)) - roots.remove(itemId); - children.remove(itemId); - Object p = parent.get(itemId); - if (p != null) { - LinkedList c = (LinkedList) children.get(p); - if (c != null) - c.remove(itemId); - } - parent.remove(itemId); - noChildrenAllowed.remove(itemId); - } - - return success; - } + Container.Hierarchical { + + /** + * Set of IDs of those contained Items that can't have children. + */ + private HashSet noChildrenAllowed = new HashSet(); + + /** + * Mapping from Item ID to parent Item. + */ + private Hashtable parent = new Hashtable(); + + /** + * Mapping from Item ID to a list of child IDs. + */ + private Hashtable children = new Hashtable(); + + /** + * List that contains all root elements of the container. + */ + private LinkedList roots = new LinkedList(); + + /* + * Can the specified Item have any children? Don't add a JavaDoc comment + * here, we use the default documentation from implemented interface. + */ + public boolean areChildrenAllowed(Object itemId) { + return !noChildrenAllowed.contains(itemId); + } + + /* + * Gets the IDs of the children of the specified Item. Don't add a JavaDoc + * comment here, we use the default documentation from implemented + * interface. + */ + public Collection getChildren(Object itemId) { + Collection c = (Collection) children.get(itemId); + if (c == null) { + return null; + } + return Collections.unmodifiableCollection(c); + } + + /* + * Gets the ID of the parent of the specified Item. Don't add a JavaDoc + * comment here, we use the default documentation from implemented + * interface. + */ + public Object getParent(Object itemId) { + return parent.get(itemId); + } + + /* + * Is the Item corresponding to the given ID a leaf node? Don't add a + * JavaDoc comment here, we use the default documentation from implemented + * interface. + */ + public boolean hasChildren(Object itemId) { + return children.get(itemId) != null; + } + + /* + * Is the Item corresponding to the given ID a root node? Don't add a + * JavaDoc comment here, we use the default documentation from implemented + * interface. + */ + public boolean isRoot(Object itemId) { + return parent.get(itemId) == null; + } + + /* + * Gets the IDs of the root elements in the container. Don't add a JavaDoc + * comment here, we use the default documentation from implemented + * interface. + */ + public Collection rootItemIds() { + return Collections.unmodifiableCollection(roots); + } + + /** + *

+ * Sets the given Item's capability to have children. If the Item identified + * with the itemId already has children and the areChildrenAllowed is false + * this method fails and false is returned; the children must + * be first explicitly removed with + * {@link #setParent(Object itemId, Object newParentId)} or + * {@link com.itmill.toolkit.data.Container#removeItem(Object itemId)}. + *

+ * + * @param itemId + * the ID of the Item in the container whose child capability + * is to be set. + * @param childrenAllowed + * the boolean value specifying if the Item can have children + * or not. + * @return true if the operation succeeded, + * false if not + */ + public boolean setChildrenAllowed(Object itemId, boolean childrenAllowed) { + + // Checks that the item is in the container + if (!containsId(itemId)) { + return false; + } + + // Updates status + if (childrenAllowed) { + noChildrenAllowed.remove(itemId); + } else { + noChildrenAllowed.add(itemId); + } + + return true; + } + + /** + *

+ * Sets the parent of an Item. The new parent item must exist and be able to + * have children. (canHaveChildren(newParentId) == true). + * It is also possible to detach a node from the hierarchy (and thus make it + * root) by setting the parent null. + *

+ * + * @param itemId + * the ID of the item to be set as the child of the Item + * identified with newParentId. + * @param newParentId + * the ID of the Item that's to be the new parent of the Item + * identified with itemId. + * @return true if the operation succeeded, + * false if not + */ + public boolean setParent(Object itemId, Object newParentId) { + + // Checks that the item is in the container + if (!containsId(itemId)) { + return false; + } + + // Gets the old parent + Object oldParentId = parent.get(itemId); + + // Checks if no change is necessary + if ((newParentId == null && oldParentId == null) + || newParentId.equals(oldParentId)) { + return true; + } + + // Making root + if (newParentId == null) { + + // Removes from old parents children list + LinkedList l = (LinkedList) children.get(itemId); + if (l != null) { + l.remove(itemId); + if (l.isEmpty()) { + children.remove(itemId); + } + } + + // Add to be a root + roots.add(itemId); + + // Updates parent + parent.remove(itemId); + + return true; + } + + // Checks that the new parent exists in container and can have + // children + if (!containsId(newParentId) || noChildrenAllowed.contains(newParentId)) { + return false; + } + + // Checks that setting parent doesn't result to a loop + Object o = newParentId; + while (o != null && !o.equals(itemId)) { + o = parent.get(o); + } + if (o != null) { + return false; + } + + // Updates parent + parent.put(itemId, newParentId); + LinkedList pcl = (LinkedList) children.get(newParentId); + if (pcl == null) { + pcl = new LinkedList(); + children.put(newParentId, pcl); + } + pcl.add(itemId); + + // Removes from old parent or root + if (oldParentId == null) { + roots.remove(itemId); + } else { + LinkedList l = (LinkedList) children.get(oldParentId); + if (l != null) { + l.remove(itemId); + if (l.isEmpty()) { + children.remove(oldParentId); + } + } + } + + return true; + } + + /** + * @see com.itmill.toolkit.data.Container#addItem() + */ + public Object addItem() { + Object id = super.addItem(); + if (id != null && !roots.contains(id)) { + roots.add(id); + } + return id; + + } + + /** + * @see com.itmill.toolkit.data.Container#addItem(Object) + */ + public Item addItem(Object itemId) { + Item item = super.addItem(itemId); + if (item != null) { + roots.add(itemId); + } + return item; + } + + /** + * @see com.itmill.toolkit.data.Container#removeAllItems() + */ + public boolean removeAllItems() { + boolean success = super.removeAllItems(); + + if (success) { + roots.clear(); + parent.clear(); + children.clear(); + noChildrenAllowed.clear(); + } + return success; + } + + /** + * @see com.itmill.toolkit.data.Container#removeItem(Object) + */ + public boolean removeItem(Object itemId) { + boolean success = super.removeItem(itemId); + + if (success) { + if (isRoot(itemId)) { + roots.remove(itemId); + } + children.remove(itemId); + Object p = parent.get(itemId); + if (p != null) { + LinkedList c = (LinkedList) children.get(p); + if (c != null) { + c.remove(itemId); + } + } + parent.remove(itemId); + noChildrenAllowed.remove(itemId); + } + + return success; + } } diff --git a/src/com/itmill/toolkit/data/util/IndexedContainer.java b/src/com/itmill/toolkit/data/util/IndexedContainer.java index 5271dc8015..081385fc0c 100644 --- a/src/com/itmill/toolkit/data/util/IndexedContainer.java +++ b/src/com/itmill/toolkit/data/util/IndexedContainer.java @@ -28,8 +28,18 @@ package com.itmill.toolkit.data.util; -import java.util.*; import java.lang.reflect.Constructor; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.Comparator; +import java.util.EventObject; +import java.util.HashSet; +import java.util.Hashtable; +import java.util.Iterator; +import java.util.LinkedHashSet; +import java.util.LinkedList; +import java.util.NoSuchElementException; import com.itmill.toolkit.data.Container; import com.itmill.toolkit.data.Item; @@ -53,1593 +63,1724 @@ import com.itmill.toolkit.data.Property; */ public class IndexedContainer implements Container, Container.Indexed, - Container.ItemSetChangeNotifier, Container.PropertySetChangeNotifier, - Property.ValueChangeNotifier, Container.Sortable, Comparator, Cloneable, Container.Filterable { - - /* Internal structure *************************************************** */ - - /** - * Linked list of ordered Item IDs. - */ - private ArrayList itemIds = new ArrayList(); - - /** List of item ids that passes the filtering */ - private LinkedHashSet filteredItemIds = null; - - /** - * Linked list of ordered Property IDs. - */ - private ArrayList propertyIds = new ArrayList(); - - /** - * Property ID to type mapping. - */ - private Hashtable types = new Hashtable(); - - /** - * Hash of Items, where each Item is implemented as a mapping from Property - * ID to Property value. - */ - private Hashtable items = new Hashtable(); - - /** - * Set of properties that are read-only. - */ - private HashSet readOnlyProperties = new HashSet(); - - /** - * List of all Property value change event listeners listening all the - * properties. - */ - private LinkedList propertyValueChangeListeners = null; - - /** - * Data structure containing all listeners interested in changes to single - * Properties. The data structure is a hashtable mapping Property IDs to a - * hashtable that maps Item IDs to a linked list of listeners listening - * Property identified by given Property ID and Item ID. - */ - private Hashtable singlePropertyValueChangeListeners = null; - - /** - * List of all Property set change event listeners. - */ - private LinkedList propertySetChangeListeners = null; - - /** - * List of all container Item set change event listeners. - */ - private LinkedList itemSetChangeListeners = null; - - /** - * Temporary store for sorting property ids. - */ - private Object[] sortPropertyId; - - /** - * Temporary store for sorting direction. - */ - private boolean[] sortDirection; - - /** Filters that are applied to the container to limit the items visible in it */ - private HashSet filters; - - /* Container constructors *********************************************** */ - - public IndexedContainer() { - } - - public IndexedContainer(Collection itemIds) { - if (items != null) { - for (Iterator i = itemIds.iterator(); i.hasNext();) { - this.addItem(i.next()); - } - } - } - - /* Container methods **************************************************** */ - - /** - * Gets the Item with the given Item ID from the list. If the list does not - * contain the requested Item (or it is filtered to be invisible), - * null is returned. - * - * @param itemId - * the ID of the Item to retrieve. - * @return the Item with the given ID or null if the Item is - * not found in the list - */ - public Item getItem(Object itemId) { - if (items.containsKey(itemId) && (filteredItemIds == null || filteredItemIds.contains(itemId))) - return new IndexedContainerItem(itemId); - return null; - } - - /** - * Gets the ID's of all Items stored in the list. The ID's are returned as a - * unmodifiable collection. - * - * @return unmodifiable collection of Item IDs - */ - public Collection getItemIds() { - if (filteredItemIds != null) return Collections.unmodifiableCollection(filteredItemIds); - return Collections.unmodifiableCollection(itemIds); - } - - /** - * Gets the ID's of all Properties stored in the list. The ID's are returned - * as a unmodifiable collection. - * - * @return unmodifiable collection of Property IDs - */ - public Collection getContainerPropertyIds() { - return Collections.unmodifiableCollection(propertyIds); - } - - /** - * Gets the type of a Property stored in the list. - * - * @param id - * the ID of the Property. - * @return Type of the requested Property - */ - public Class getType(Object propertyId) { - return (Class) types.get(propertyId); - } - - /** - * Gets the Property identified by the given Item ID and Property ID from - * the lsit. If the list does not contain the Property, null - * is returned. - * - * @param itemId - * the ID of the Item which contains the requested Property. - * @param propertyId - * the ID of the Property to retrieve. - * @return Property with the given ID or null - * - * @see com.itmill.toolkit.data.Container#getContainerProperty(Object, - * Object) - */ - public Property getContainerProperty(Object itemId, Object propertyId) { - if (filteredItemIds == null) { - if (!items.containsKey(itemId)) return null; - } else if (!filteredItemIds.contains(itemId)) return null; - - return new IndexedContainerProperty(itemId, propertyId); - } - - /** - * Gets the number of Items in the list. - * - * @return number of Items in the list - */ - public int size() { - if (filteredItemIds == null) return itemIds.size(); - return filteredItemIds.size(); - } - - /** - * Tests if the list contains the specified Item - * - * @param itemId - * the ID the of Item to be tested for. - * @return true if the operation succeeded, - * false if not - */ - public boolean containsId(Object itemId) { - if (filteredItemIds != null) return filteredItemIds.contains(itemId); - return items.containsKey(itemId); - } - - /** - * Adds a new Property to all Items in the list. The Property ID, data type - * and default value of the new Property are given as parameters. - * - * @param propertyId - * the ID of the new Property. - * @param type - * the Data type of the new Property. - * @param defaultValue - * the value all created Properties are initialized to. - * @return true if the operation succeeded, - * false if not - */ - public boolean addContainerProperty(Object propertyId, Class type, - Object defaultValue) { - - // Fails, if nulls are given - if (propertyId == null || type == null) - return false; - - // Fails if the Property is already present - if (propertyIds.contains(propertyId)) - return false; - - // Adds the Property to Property list and types - propertyIds.add(propertyId); - types.put(propertyId, type); - - // If default value is given, set it - if (defaultValue != null) - for (Iterator i = itemIds.iterator(); i.hasNext();) - getItem(i.next()).getItemProperty(propertyId).setValue( - defaultValue); - - // Sends a change event - fireContainerPropertySetChange(); - - return true; - } - - /** - * Removes all Items from the list. - *

- * Note : The Property ID and type information is preserved. - *

- * - * @return true if the operation succeeded, - * false if not - */ - public boolean removeAllItems() { - - // Removes all Items - itemIds.clear(); - items.clear(); - if (filteredItemIds != null) filteredItemIds.clear(); - - // Sends a change event - fireContentsChange(); - - return true; - } - - /** - * Creates a new Item into the list, and assign it an automatic ID. The new - * ID is returned, or null if the operation fails. After a - * successful call you can use the - * {@link #getItem(Object ItemId) getItem}method to fetch the - * Item. - * - * @return ID of the newly created Item, or null in case of a - * failure - */ - public Object addItem() { - - // Creates a new id - Object id = new Object(); - - // Adds the Item into container - addItem(id); - - return id; - } - - /** - * Creates a new Item with the given ID into the list. The new Item is - * returned, and it is ready to have its Properties modified. Returns - * null if the operation fails or the Container already - * contains a Item with the given ID. - * - * @param itemId - * the ID of the Item to be created. - * @return Created new Item, or null in case of a failure - */ - public Item addItem(Object itemId) { - - // Makes sure that the Item has not been created yet - if (items.containsKey(itemId)) - return null; - - // Adds the Item to container - itemIds.add(itemId); - items.put(itemId, new Hashtable()); - Item item = getItem(itemId); - if (filteredItemIds != null) - if (passesFilters(item)) - filteredItemIds.add(itemId); - - // Sends the event - fireContentsChange(); - - return item; - } - - /** - * Removes the Item corresponding to the given Item ID from the list. - * - * @param itemId - * the ID of the Item to remove. - * @return true if the operation succeeded, - * false if not - */ - public boolean removeItem(Object itemId) { - - if (items.remove(itemId) == null) - return false; - itemIds.remove(itemId); - if (filteredItemIds != null) filteredItemIds.remove(itemId); - - fireContentsChange(); - - return true; - } - - /** - * Removes a Property specified by the given Property ID from the list. Note - * that the Property will be removed from all Items in the list. - * - * @param propertyId - * the ID of the Property to remove. - * @return true if the operation succeeded, - * false if not - */ - public boolean removeContainerProperty(Object propertyId) { - - // Fails if the Property is not present - if (!propertyIds.contains(propertyId)) - return false; - - // Removes the Property to Property list and types - propertyIds.remove(propertyId); - types.remove(propertyId); - - // If remove the Property from all Items - for (Iterator i = itemIds.iterator(); i.hasNext();) - ((Hashtable) items.get(i.next())).remove(propertyId); - - // Sends a change event - fireContainerPropertySetChange(); - - return true; - } - - /* Container.Ordered methods ******************************************** */ - - /** - * Gets the ID of the first Item in the list. - * - * @return ID of the first Item in the list - */ - public Object firstItemId() { - try { - if (filteredItemIds != null) return filteredItemIds.iterator().next(); - return itemIds.get(0); - } catch (IndexOutOfBoundsException e) { - } catch (NoSuchElementException e) { - } - return null; - } - - /** - * Gets the ID of the last Item in the list. - * - * @return ID of the last Item in the list - */ - public Object lastItemId() { - try { - if (filteredItemIds != null) { - Iterator i=filteredItemIds.iterator(); - Object last = null; - while (i.hasNext()) last = i.next(); - return last; - } - return itemIds.get(itemIds.size() - 1); - } catch (IndexOutOfBoundsException e) { - } - return null; - } - - /** - * Gets the ID of the Item following the Item that corresponds to the - * itemId. If the given Item is the last or not found in the list, - * null is returned. - * - * @param itemId - * the ID of an Item in the list. - * @return ID of the next Item or null - */ - public Object nextItemId(Object itemId) { - if (filteredItemIds != null) { - if (!filteredItemIds.contains(itemId)) return null; - Iterator i=filteredItemIds.iterator(); - if (itemId == null) return null; - while (i.hasNext() && !itemId.equals(i.next())); - if (i.hasNext()) return i.next(); - return null; - } - try { - return itemIds.get(itemIds.indexOf(itemId) + 1); - } catch (IndexOutOfBoundsException e) { - return null; - } - } - - /** - * Gets the ID of the Item preceding the Item that corresponds to the - * itemId. If the given Item is the first or not found in the list, - * null is returned. - * - * @param itemId - * the ID of an Item in the list. - * @return ID of the previous Item or null - */ - public Object prevItemId(Object itemId) { - if (filteredItemIds != null) { - if (!filteredItemIds.contains(itemId)) return null; - Iterator i=filteredItemIds.iterator(); - if (itemId == null) return null; - Object prev = null; - Object current; - while (i.hasNext() && !itemId.equals(current = i.next())) prev = current; - return prev; - } - try { - return itemIds.get(itemIds.indexOf(itemId) - 1); - } catch (IndexOutOfBoundsException e) { - return null; - } - } - - /** - * Tests if the Item corresponding to the given Item ID is the first Item in - * the list. - * - * @param itemId - * the ID of an Item in the list. - * @return true if the Item is first in the list, - * false if not - */ - public boolean isFirstId(Object itemId) { - if (filteredItemIds != null) { - try { - Object first = filteredItemIds.iterator().next(); - return (itemId != null && itemId.equals(first)); - } catch (NoSuchElementException e) { - return false; - } - } - return (size() >= 1 && itemIds.get(0).equals(itemId)); - } - - /** - * Tests if the Item corresponding to the given Item ID is the last Item in - * the list. - * - * @param itemId - * the ID of an Item in the list. - * @return true if the Item is last in the list, - * false if not - */ - public boolean isLastId(Object itemId) { - if (filteredItemIds != null) { - try { - Object last = null; - for (Iterator i=filteredItemIds.iterator(); i.hasNext();) last = i.next(); - return (itemId != null && itemId.equals(last)); - } catch (NoSuchElementException e) { - return false; - } - } - int s = size(); - return (s >= 1 && itemIds.get(s - 1).equals(itemId)); - } - - /** - * @see com.itmill.toolkit.data.Container.Ordered#addItemAfter(Object, - * Object) - */ - public Item addItemAfter(Object previousItemId, Object newItemId) { - - // Get the index of the addition - int index = 0; - if (previousItemId != null) { - index = 1 + indexOfId(previousItemId); - if (index <= 0 || index > size()) - return null; - } - - return addItemAt(index, newItemId); - } - - /** - * @see com.itmill.toolkit.data.Container.Ordered#addItemAfter(Object) - */ - public Object addItemAfter(Object previousItemId) { - - // Get the index of the addition - int index = 0; - if (previousItemId != null) { - index = 1 + indexOfId(previousItemId); - if (index <= 0 || index > size()) - return null; - } - - return addItemAt(index); - } - - /** - * Gets ID with the index. The following is true for the index: 0 <= index < - * size(). - * - * @return ID in the given index. - * @param index - * Index of the requested ID in the container. - */ - public Object getIdByIndex(int index) { - - if (filteredItemIds != null) { - if (index<0) throw new IndexOutOfBoundsException(); - try { - Iterator i = filteredItemIds.iterator(); - while (index-- > 0) i.next(); - return i.next(); - } catch (NoSuchElementException e) { - throw new IndexOutOfBoundsException(); - } - } - - return itemIds.get(index); - } - - /** - * Gets the index of an id. The following is true for the index: 0 <= index < - * size(). - * - * @return Index of the Item or -1 if the Item is not in the container. - * @param itemId - * ID of an Item in the collection - */ - public int indexOfId(Object itemId) { - if (filteredItemIds != null) { - int index=0; - if (itemId == null) return -1; - try { - for (Iterator i=filteredItemIds.iterator(); itemId.equals(i.next());) index++; - return index; - } catch (NoSuchElementException e) { - return -1; - } - } - return itemIds.indexOf(itemId); - } - - /** - * @see com.itmill.toolkit.data.Container.Indexed#addItemAt(int, Object) - */ - public Item addItemAt(int index, Object newItemId) { - - // Make sure that the Item has not been created yet - if (items.containsKey(newItemId)) - return null; - - // Adds the Item to container - itemIds.add(index, newItemId); - items.put(newItemId, new Hashtable()); - - if (filteredItemIds != null) - updateContainerFiltering(); - else - fireContentsChange(); - - return getItem(newItemId); - } - - /** - * @see com.itmill.toolkit.data.Container.Indexed#addItemAt(int) - */ - public Object addItemAt(int index) { - - // Creates a new id - Object id = new Object(); - - // Adds the Item into container - addItemAt(index, id); - - return id; - } - - /* Event notifiers ****************************************************** */ - - /** - * An event object specifying the list whose Property set has - * changed. - * - * @author IT Mill Ltd. - * @version - * @VERSION@ - * @since 3.0 - */ - private class PropertySetChangeEvent extends EventObject implements - Container.PropertySetChangeEvent { - - /** - * Serial generated by eclipse. - */ - private static final long serialVersionUID = 3257002172528079926L; - - private PropertySetChangeEvent(IndexedContainer source) { - super(source); - } - - /** - * Gets the list whose Property set has changed. - * - * @return source object of the event as a Container - */ - public Container getContainer() { - return (Container) getSource(); - } - } - - /** - * An event object specifying the list whose Item set has - * changed. - * - * @author IT Mill Ltd. - * @version - * @VERSION@ - * @since 3.0 - */ - private class ItemSetChangeEvent extends EventObject implements - Container.ItemSetChangeEvent { - - /** - * Serial generated by eclipse. - */ - private static final long serialVersionUID = 3832616279386372147L; - - private ItemSetChangeEvent(IndexedContainer source) { - super(source); - } - - /** - * Gets the list whose Item set has changed. - * - * @return source object of the event as a Container - */ - public Container getContainer() { - return (Container) getSource(); - } - - } - - /** - * An event object specifying the Propery in a list whose - * value has changed. - * - * @author IT Mill Ltd. - * @version - * @VERSION@ - * @since 3.0 - */ - private class PropertyValueChangeEvent extends EventObject implements - Property.ValueChangeEvent { - - /** - * Serial generated by eclipse. - */ - private static final long serialVersionUID = 3833749884498359857L; - - private PropertyValueChangeEvent(Property source) { - super(source); - } - - /** - * Gets the Property whose value has changed. - * - * @return source object of the event as a Property - */ - public Property getProperty() { - return (Property) getSource(); - } - - } - - /** - * Registers a new Property set change listener for this list. - * - * @param listener - * the new Listener to be registered. - */ - public void addListener(Container.PropertySetChangeListener listener) { - if (propertySetChangeListeners == null) - propertySetChangeListeners = new LinkedList(); - propertySetChangeListeners.add(listener); - } - - /** - * Removes a previously registered Property set change listener. - * - * @param listener - * the listener to be removed. - */ - public void removeListener(Container.PropertySetChangeListener listener) { - if (propertySetChangeListeners != null) - propertySetChangeListeners.remove(listener); - } - - /** - * Adds a Item set change listener for the list. - * - * @param listener - * the listener to be added. - */ - public void addListener(Container.ItemSetChangeListener listener) { - if (itemSetChangeListeners == null) - itemSetChangeListeners = new LinkedList(); - itemSetChangeListeners.add(listener); - } - - /** - * Removes a Item set change listener from the object. - * - * @param listener - * the listener to be removed. - */ - public void removeListener(Container.ItemSetChangeListener listener) { - if (itemSetChangeListeners != null) - itemSetChangeListeners.remove(listener); - } - - /** - * Registers a new value change listener for this object. - * - * @param listener - * the new Listener to be registered - */ - public void addListener(Property.ValueChangeListener listener) { - if (propertyValueChangeListeners == null) - propertyValueChangeListeners = new LinkedList(); - propertyValueChangeListeners.add(listener); - } - - /** - * Removes a previously registered value change listener. - * - * @param listener - * the listener to be removed. - */ - public void removeListener(Property.ValueChangeListener listener) { - if (propertyValueChangeListeners != null) - propertyValueChangeListeners.remove(listener); - } - - /** - * Sends a Property value change event to all interested listeners. - * - * @param source - * the IndexedContainerProperty object. - */ - private void firePropertyValueChange(IndexedContainerProperty source) { - - // Sends event to listeners listening all value changes - if (propertyValueChangeListeners != null) { - Object[] l = propertyValueChangeListeners.toArray(); - Property.ValueChangeEvent event = new IndexedContainer.PropertyValueChangeEvent( - source); - for (int i = 0; i < l.length; i++) - ((Property.ValueChangeListener) l[i]).valueChange(event); - } - - // Sends event to single property value change listeners - if (singlePropertyValueChangeListeners != null) { - Hashtable propertySetToListenerListMap = (Hashtable) singlePropertyValueChangeListeners - .get(source.propertyId); - if (propertySetToListenerListMap != null) { - LinkedList listenerList = (LinkedList) propertySetToListenerListMap - .get(source.itemId); - if (listenerList != null) { - Property.ValueChangeEvent event = new IndexedContainer.PropertyValueChangeEvent( - source); - for (Iterator i = listenerList.iterator(); i.hasNext();) - ((Property.ValueChangeListener) i.next()) - .valueChange(event); - } - } - } - - } - - /** - * Sends a Property set change event to all interested listeners. - */ - private void fireContainerPropertySetChange() { - if (propertySetChangeListeners != null) { - Object[] l = propertySetChangeListeners.toArray(); - Container.PropertySetChangeEvent event = new IndexedContainer.PropertySetChangeEvent( - this); - for (int i = 0; i < l.length; i++) - ((Container.PropertySetChangeListener) l[i]) - .containerPropertySetChange(event); - } - } - - /** - * Sends Item set change event to all registered interested listeners. - */ - private void fireContentsChange() { - if (itemSetChangeListeners != null) { - Object[] l = itemSetChangeListeners.toArray(); - Container.ItemSetChangeEvent event = new IndexedContainer.ItemSetChangeEvent( - this); - for (int i = 0; i < l.length; i++) - ((Container.ItemSetChangeListener) l[i]) - .containerItemSetChange(event); - } - } - - /** - * Adds new single Property change listener. - * - * @param propertyId - * the ID of the Property to add. - * @param itemId - * the ID of the Item . - * @param listener - * the listener to be added. - */ - private void addSinglePropertyChangeListener(Object propertyId, - Object itemId, Property.ValueChangeListener listener) { - if (listener != null) { - if (singlePropertyValueChangeListeners == null) - singlePropertyValueChangeListeners = new Hashtable(); - Hashtable propertySetToListenerListMap = (Hashtable) singlePropertyValueChangeListeners - .get(propertyId); - if (propertySetToListenerListMap == null) { - propertySetToListenerListMap = new Hashtable(); - singlePropertyValueChangeListeners.put(propertyId, - propertySetToListenerListMap); - } - LinkedList listenerList = (LinkedList) propertySetToListenerListMap - .get(itemId); - if (listenerList == null) { - listenerList = new LinkedList(); - propertySetToListenerListMap.put(itemId, listenerList); - } - listenerList.addLast(listener); - } - } - - /** - * Removes a previously registered single Property change listener. - * - * @param propertyId - * the ID of the Property to remove. - * @param itemId - * the ID of the Item. - * @param listener - * the listener to be removed. - */ - private void removeSinglePropertyChangeListener(Object propertyId, - Object itemId, Property.ValueChangeListener listener) { - if (listener != null && singlePropertyValueChangeListeners != null) { - Hashtable propertySetToListenerListMap = (Hashtable) singlePropertyValueChangeListeners - .get(propertyId); - if (propertySetToListenerListMap != null) { - LinkedList listenerList = (LinkedList) propertySetToListenerListMap - .get(itemId); - if (listenerList != null) { - listenerList.remove(listener); - if (listenerList.isEmpty()) - propertySetToListenerListMap.remove(itemId); - } - if (propertySetToListenerListMap.isEmpty()) - singlePropertyValueChangeListeners.remove(propertyId); - } - if (singlePropertyValueChangeListeners.isEmpty()) - singlePropertyValueChangeListeners = null; - } - } - - /* Internal Item and Property implementations *************************** */ - - /* - * A class implementing the com.itmill.toolkit.data.Item interface to be - * contained in the list. @author IT Mill Ltd. - * - * @version @VERSION@ - * @since 3.0 - */ - class IndexedContainerItem implements Item { - - /** - * Item ID in the host container for this Item. - */ - private Object itemId; - - /** - * Constructs a new ListItem instance and connects it to a host - * container. - * - * @param itemId - * the Item ID of the new Item. - */ - private IndexedContainerItem(Object itemId) { - - // Gets the item contents from the host - if (itemId == null) - throw new NullPointerException(); - this.itemId = itemId; - } - - /** - * Gets the Property corresponding to the given Property ID stored in - * the Item. If the Item does not contain the Property, - * null is returned. - * - * @param id - * the identifier of the Property to get. - * @return the Property with the given ID or null - */ - public Property getItemProperty(Object id) { - return new IndexedContainerProperty(itemId, id); - } - - /** - * Gets the collection containing the IDs of all Properties stored in - * the Item. - * - * @return unmodifiable collection contaning IDs of the Properties - * stored the Item - */ - public Collection getItemPropertyIds() { - return Collections.unmodifiableCollection(propertyIds); - } - - /** - * Gets the String representation of the contents of the - * Item. The format of the string is a space separated catenation of the - * String representations of the Properties contained by - * the Item. - * - * @return String representation of the Item contents - */ - public String toString() { - String retValue = ""; - - for (Iterator i = propertyIds.iterator(); i.hasNext();) { - Object propertyId = i.next(); - retValue += getItemProperty(propertyId).toString(); - if (i.hasNext()) - retValue += " "; - } - - return retValue; - } - - /** - * Calculates a integer hash-code for the Item that's unique inside the - * list. Two Items inside the same list have always different - * hash-codes, though Items in different lists may have identical - * hash-codes. - * - * @return A locally unique hash-code as integer - */ - public int hashCode() { - return getHost().hashCode() ^ itemId.hashCode(); - } - - /** - * Tests if the given object is the same as the this object. Two Items - * got from a list container with the same ID are equal. - * - * @param obj - * an object to compare with this object - * @return true if the given object is the same as this - * object, false if not - */ - public boolean equals(Object obj) { - if (obj == null - || !obj.getClass().equals(IndexedContainerItem.class)) - return false; - IndexedContainerItem li = (IndexedContainerItem) obj; - return getHost() == li.getHost() && itemId.equals(li.itemId); - } - - /** - * - * @return - */ - private IndexedContainer getHost() { - return IndexedContainer.this; - } - - /** - * Indexed container does not support adding new properties. - * - * @see com.itmill.toolkit.data.Item#addProperty(Object, Property) - */ - public boolean addItemProperty(Object id, Property property) - throws UnsupportedOperationException { - throw new UnsupportedOperationException("Indexed container item " - + "does not support adding new properties"); - } - - /** - * Indexed container does not support removing properties. - * - * @see com.itmill.toolkit.data.Item#removeProperty(Object) - */ - public boolean removeItemProperty(Object id) - throws UnsupportedOperationException { - throw new UnsupportedOperationException( - "Indexed container item does not support property removal"); - } - - } - - /** - * A class implementing the com.itmill.toolkit.data.Property interface to be - * contained in the Items contained in the list. - * - * @author IT Mill Ltd. - * - * @version - * @VERSION@ - * @since 3.0 - */ - private class IndexedContainerProperty implements Property, - Property.ValueChangeNotifier { - - /** - * ID of the Item, where the Property resides. - */ - private Object itemId; - - /** - * Id of the Property. - */ - private Object propertyId; - - /** - * Constructs a new ListProperty object and connect it to a ListItem and - * a ListContainer. - * - * @param itemId - * the ID of the Item to connect the new Property to. - * @param propertyId - * the Property ID of the new Property. - * @param host - * the list that contains the Item to contain the new - * Property. - */ - private IndexedContainerProperty(Object itemId, Object propertyId) { - if (itemId == null || propertyId == null) - throw new NullPointerException(); - this.propertyId = propertyId; - this.itemId = itemId; - } - - /** - * Returns the type of the Property. The methods getValue - * and setValue must be compatible with this type: one - * must be able to safely cast the value returned from - * getValue to the given type and pass any variable - * assignable to this type as a parameter to setValue - * Tests if the Property is in read-only mode. In read-only mode calls - * to the method setValue will throw - * ReadOnlyException s and will not modify the value of - * the Property. - *

- * - * @return true if the Property is in read-only mode, - * false if it's not. - */ - public boolean isReadOnly() { - return readOnlyProperties.contains(this); - } - - /** - * Sets the Property's read-only mode to the specified status. - * - * @param newStatus - * the new read-only status of the Property. - */ - public void setReadOnly(boolean newStatus) { - if (newStatus) - readOnlyProperties.add(this); - else - readOnlyProperties.remove(this); - } - - /** - * Sets the value of the Property. By default this method will try to - * assign the value directly, but if it is unassignable, it will try to - * use the String constructor of the internal data type - * to assign the value, - * - * @param newValue - * the New value of the Property. This should be assignable - * to the Property's internal type or support - * toString. - * - * @throws Property.ReadOnlyException - * if the object is in read-only mode - * @throws Property.ConversionException - * if newValue can't be converted into the - * Property's native type directly or through - * String - */ - public void setValue(Object newValue) - throws Property.ReadOnlyException, Property.ConversionException { - - // Gets the Property set - Hashtable propertySet = (Hashtable) items.get(itemId); - - // Support null values on all types - if (newValue == null) - propertySet.remove(propertyId); - - // Try to assign the compatible value directly - else if (getType().isAssignableFrom(newValue.getClass())) - propertySet.put(propertyId, newValue); - - // Otherwise try to convert the value trough string constructor - else - try { - - // Gets the string constructor - Constructor constr = getType().getConstructor( - new Class[] { String.class }); - - // Creates new object from the string - propertySet.put(propertyId, constr - .newInstance(new Object[] { newValue.toString() })); - - } catch (java.lang.Exception e) { - throw new Property.ConversionException( - "Conversion for value '" + newValue + "' of class " - + newValue.getClass().getName() + " to " - + getType().getName() + " failed"); - } - - firePropertyValueChange(this); - } - - /** - * Returns the value of the Property in human readable textual format. - * The return value should be assignable to the setValue - * method if the Property is not in read-only mode. - * - * @return String representation of the value stored in - * the Property - */ - public String toString() { - Object value = getValue(); - if (value == null) - return null; - return value.toString(); - } - - /** - * Calculates a integer hash-code for the Property that's unique inside - * the Item containing the Property. Two different Properties inside the - * same Item contained in the same list always have different - * hash-codes, though Properties in different Items may have identical - * hash-codes. - * - * @return A locally unique hash-code as integer - */ - public int hashCode() { - return itemId.hashCode() ^ propertyId.hashCode() - ^ IndexedContainer.this.hashCode(); - } - - /** - * Tests if the given object is the same as the this object. Two - * Properties got from an Item with the same ID are equal. - * - * @param obj - * an object to compare with this object - * @return true if the given object is the same as this - * object, false if not - */ - public boolean equals(Object obj) { - if (obj == null - || !obj.getClass().equals(IndexedContainerProperty.class)) - return false; - IndexedContainerProperty lp = (IndexedContainerProperty) obj; - return lp.getHost() == getHost() - && lp.propertyId.equals(propertyId) - && lp.itemId.equals(itemId); - } - - /** - * Registers a new value change listener for this Property. - * - * @param listener - * the new Listener to be registered. - * @see com.itmill.toolkit.data.Property.ValueChangeNotifier#addListener(ValueChangeListener) - */ - public void addListener(Property.ValueChangeListener listener) { - addSinglePropertyChangeListener(propertyId, itemId, listener); - } - - /** - * Removes a previously registered value change listener. - * - * @param listener - * listener to be removed - * @see com.itmill.toolkit.data.Property.ValueChangeNotifier#removeListener(ValueChangeListener) - */ - public void removeListener(Property.ValueChangeListener listener) { - removeSinglePropertyChangeListener(propertyId, itemId, listener); - } - - private IndexedContainer getHost() { - return IndexedContainer.this; - } - - } - - /** - * @see com.itmill.toolkit.data.Container.Sortable#sort(java.lang.Object[], - * boolean[]) - */ - public synchronized void sort(Object[] propertyId, boolean[] ascending) { - - // Removes any non-sortable property ids - ArrayList ids = new ArrayList(); - ArrayList orders = new ArrayList(); - Collection sortable = getSortableContainerPropertyIds(); - for (int i = 0; i < propertyId.length; i++) - if (sortable.contains(propertyId[i])) { - ids.add(propertyId[i]); - orders.add(new Boolean(i < ascending.length ? ascending[i] - : true)); - } - - if (ids.size() == 0) - return; - sortPropertyId = ids.toArray(); - sortDirection = new boolean[orders.size()]; - for (int i = 0; i < sortDirection.length; i++) - sortDirection[i] = ((Boolean) orders.get(i)).booleanValue(); - - // Sort - Collections.sort(this.itemIds, this); - if (filteredItemIds != null) updateContainerFiltering(); - else fireContentsChange(); - - // Remove temporary references - sortPropertyId = null; - sortDirection = null; - - } - - /** - * @see com.itmill.toolkit.data.Container.Sortable#getSortableContainerPropertyIds() - */ - public Collection getSortableContainerPropertyIds() { - - LinkedList list = new LinkedList(); - for (Iterator i = this.propertyIds.iterator(); i.hasNext();) { - Object id = i.next(); - Class type = this.getType(id); - if (type != null && Comparable.class.isAssignableFrom(type)) { - list.add(id); - } - } - - return list; - } - - /** - * Compares two items for sorting. - * - * @see java.util.Comparator#compare(java.lang.Object, java.lang.Object) - * @see #sort((java.lang.Object[], boolean[]) - */ - public int compare(Object o1, Object o2) { - - for (int i = 0; i < sortPropertyId.length; i++) { - - // Get the compared properties - Property pp1 = getContainerProperty(o1, this.sortPropertyId[i]); - Property pp2 = getContainerProperty(o2, this.sortPropertyId[i]); - - // Get the compared values - Object p1 = pp1 == null ? null : pp1.getValue(); - Object p2 = pp2 == null ? null : pp2.getValue(); - - // Result of the comparison - int r = 0; - - // Normal non-null comparison - if (p1 != null && p2 != null) { - if ((p1 instanceof Boolean) && (p2 instanceof Boolean)) - r = p1.equals(p2) ? 0 - : ((this.sortDirection[i] ? 1 : -1) * (((Boolean) p1) - .booleanValue() ? 1 : -1)); - else - r = this.sortDirection[i] ? ((Comparable) p1).compareTo(p2) - : -((Comparable) p1).compareTo(p2); - } - - // If both are nulls - else if (p1 == p2) - r = 0; - - // If one of the properties are null - else - r = (this.sortDirection[i] ? 1 : -1) * (p1 == null ? -1 : 1); - - // If order can be decided - if (r != 0) - return r; - } - - return 0; - } - - /** - * Supports cloning of the IndexedContainer cleanly. - * - * @throws CloneNotSupportedException - * if an object cannot be cloned. . - */ - public Object clone() throws CloneNotSupportedException { - - // Creates the clone - IndexedContainer nc = new IndexedContainer(); - - // Clone the shallow properties - nc.itemIds = this.itemIds != null ? (ArrayList) this.itemIds.clone() - : null; - nc.itemSetChangeListeners = this.itemSetChangeListeners != null ? (LinkedList) this.itemSetChangeListeners - .clone() - : null; - nc.propertyIds = this.propertyIds != null ? (ArrayList) this.propertyIds - .clone() - : null; - nc.propertySetChangeListeners = this.propertySetChangeListeners != null ? (LinkedList) this.propertySetChangeListeners - .clone() - : null; - nc.propertyValueChangeListeners = this.propertyValueChangeListeners != null ? (LinkedList) this.propertyValueChangeListeners - .clone() - : null; - nc.readOnlyProperties = this.readOnlyProperties != null ? (HashSet) this.readOnlyProperties - .clone() - : null; - nc.singlePropertyValueChangeListeners = this.singlePropertyValueChangeListeners != null ? (Hashtable) this.singlePropertyValueChangeListeners - .clone() - : null; - nc.sortDirection = this.sortDirection != null ? (boolean[]) this.sortDirection - .clone() - : null; - nc.sortPropertyId = this.sortPropertyId != null ? (Object[]) this.sortPropertyId - .clone() - : null; - nc.types = this.types != null ? (Hashtable) this.types.clone() : null; - - nc.filters = this.filters == null ? null : (HashSet) this.filters.clone(); - - nc.filteredItemIds = this.filteredItemIds == null ? null : (LinkedHashSet) this.filteredItemIds.clone(); - - // Clone property-values - if (this.items == null) - nc.items = null; - else { - nc.items = new Hashtable(); - for (Iterator i = this.items.keySet().iterator(); i.hasNext();) { - Object id = i.next(); - Hashtable it = (Hashtable) this.items.get(id); - nc.items.put(id, it.clone()); - } - } - - return nc; - } - - /** - * @see java.lang.Object#equals(java.lang.Object) - */ - public boolean equals(Object obj) { - - // Only ones of the objects of the same class can be equal - if (!(obj instanceof IndexedContainer)) - return false; - IndexedContainer o = (IndexedContainer) obj; - - // Checks the properties one by one - if (itemIds != o.itemIds && o.itemIds != null - && !o.itemIds.equals(this.itemIds)) - return false; - if (filters != o.filters && o.filters != null - && !o.filters.equals(this.filters)) - return false; - if (items != o.items && o.items != null && !o.items.equals(this.items)) - return false; - if (itemSetChangeListeners != o.itemSetChangeListeners - && o.itemSetChangeListeners != null - && !o.itemSetChangeListeners - .equals(this.itemSetChangeListeners)) - return false; - if (propertyIds != o.propertyIds && o.propertyIds != null - && !o.propertyIds.equals(this.propertyIds)) - return false; - if (propertySetChangeListeners != o.propertySetChangeListeners - && o.propertySetChangeListeners != null - && !o.propertySetChangeListeners - .equals(this.propertySetChangeListeners)) - return false; - if (propertyValueChangeListeners != o.propertyValueChangeListeners - && o.propertyValueChangeListeners != null - && !o.propertyValueChangeListeners - .equals(this.propertyValueChangeListeners)) - return false; - if (readOnlyProperties != o.readOnlyProperties - && o.readOnlyProperties != null - && !o.readOnlyProperties.equals(this.readOnlyProperties)) - return false; - if (singlePropertyValueChangeListeners != o.singlePropertyValueChangeListeners - && o.singlePropertyValueChangeListeners != null - && !o.singlePropertyValueChangeListeners - .equals(this.singlePropertyValueChangeListeners)) - return false; - if (sortDirection != o.sortDirection && o.sortDirection != null - && !o.sortDirection.equals(this.sortDirection)) - return false; - if (sortPropertyId != o.sortPropertyId && o.sortPropertyId != null - && !o.sortPropertyId.equals(this.sortPropertyId)) - return false; - if (types != o.types && o.types != null && !o.types.equals(this.types)) - return false; - - return true; - } - - /** - * @see java.lang.Object#hashCode() - */ - public int hashCode() { - - // The hash-code is calculated as combination hash of the members - return (this.itemIds != null ? this.itemIds.hashCode() : 0) - ^ (this.items != null ? this.items.hashCode() : 0) - ^ (this.filters != null ? this.filters.hashCode() : 0) - ^ (this.itemSetChangeListeners != null ? this.itemSetChangeListeners - .hashCode() - : 0) - ^ (this.propertyIds != null ? this.propertyIds.hashCode() : 0) - ^ (this.propertySetChangeListeners != null ? this.propertySetChangeListeners - .hashCode() - : 0) - ^ (this.propertyValueChangeListeners != null ? this.propertyValueChangeListeners - .hashCode() - : 0) - ^ (this.readOnlyProperties != null ? this.readOnlyProperties - .hashCode() : 0) - ^ (this.singlePropertyValueChangeListeners != null ? this.singlePropertyValueChangeListeners - .hashCode() - : 0) - ^ (this.sortPropertyId != null ? this.sortPropertyId.hashCode() - : 0) - ^ (this.types != null ? this.types.hashCode() : 0) - ^ (this.sortDirection != null ? this.sortDirection.hashCode() - : 0); - } - - private class Filter { - Object propertyId; - String filterString; - boolean ignoreCase; - boolean onlyMatchPrefix; - Filter(Object propertyId, String filterString, boolean ignoreCase, boolean onlyMatchPrefix) { - this.propertyId = propertyId;; - this.filterString = filterString; - this.ignoreCase = ignoreCase; - this.onlyMatchPrefix = onlyMatchPrefix; - } - public boolean equals(Object obj) { - - // Only ones of the objects of the same class can be equal - if (!(obj instanceof Filter)) - return false; - Filter o = (Filter) obj; - - // Checks the properties one by one - if (propertyId != o.propertyId && o.propertyId != null - && !o.propertyId.equals(this.propertyId)) - return false; - if (filterString != o.filterString && o.filterString != null - && !o.filterString.equals(this.filterString)) - return false; - if (ignoreCase!=o.ignoreCase) - return false; - if (onlyMatchPrefix!=o.onlyMatchPrefix) - return false; - - return true; - } - public int hashCode() { - return (this.propertyId != null ? this.propertyId.hashCode() : 0) - ^ (this.filterString != null ? this.filterString.hashCode() : 0); - } - - } - - public void addContainerFilter(Object propertyId, String filterString, boolean ignoreCase, boolean onlyMatchPrefix) { - if (filters == null) filters = new HashSet(); - filters.add(new Filter(propertyId, filterString, ignoreCase, onlyMatchPrefix)); - updateContainerFiltering(); - } - - public void removeAllContainerFilters() { - if (filters == null) return; - filters.clear(); - updateContainerFiltering(); - } - - public void removeContainerFilters(Object propertyId) { - if (filters == null || propertyId == null) return; - for (Iterator i=filters.iterator(); i.hasNext();) { - Filter f = (Filter) i.next(); - if (propertyId.equals(f.propertyId)) i.remove(); - } - updateContainerFiltering(); - } - - private void updateContainerFiltering() { - - // Clearing filters? - if (filters == null || filters.isEmpty()) { - filteredItemIds = null; - if(filters != null) { - filters = null; - fireContentsChange(); - } - return; - } - - // Reset filteres list - if (filteredItemIds == null) filteredItemIds = new LinkedHashSet(); - else filteredItemIds.clear(); - - // Filter - for (Iterator i=itemIds.iterator(); i.hasNext();) { - Object id = i.next(); - if (passesFilters(new IndexedContainerItem(id))) filteredItemIds.add(id); - } - - fireContentsChange(); - } - - private boolean passesFilters(Item item) { - if (filters == null) return true; - if (item == null) return false; - for (Iterator i=filters.iterator(); i.hasNext();) { - Filter f = (Filter) i.next(); - String s1 = f.ignoreCase ? f.filterString.toLowerCase() : f.filterString; - Property p = item.getItemProperty(f.propertyId); - if (p==null) return false; - String s2 = f.ignoreCase ? p.toString().toLowerCase() : p.toString(); - if (f.onlyMatchPrefix) { - if (s2.indexOf(s1) != 0) return false; - } else { - if (s2.indexOf(s1) < 0) return false; - } - } - return true; - } + Container.ItemSetChangeNotifier, Container.PropertySetChangeNotifier, + Property.ValueChangeNotifier, Container.Sortable, Comparator, + Cloneable, Container.Filterable { + + /* Internal structure *************************************************** */ + + /** + * Linked list of ordered Item IDs. + */ + private ArrayList itemIds = new ArrayList(); + + /** List of item ids that passes the filtering */ + private LinkedHashSet filteredItemIds = null; + + /** + * Linked list of ordered Property IDs. + */ + private ArrayList propertyIds = new ArrayList(); + + /** + * Property ID to type mapping. + */ + private Hashtable types = new Hashtable(); + + /** + * Hash of Items, where each Item is implemented as a mapping from Property + * ID to Property value. + */ + private Hashtable items = new Hashtable(); + + /** + * Set of properties that are read-only. + */ + private HashSet readOnlyProperties = new HashSet(); + + /** + * List of all Property value change event listeners listening all the + * properties. + */ + private LinkedList propertyValueChangeListeners = null; + + /** + * Data structure containing all listeners interested in changes to single + * Properties. The data structure is a hashtable mapping Property IDs to a + * hashtable that maps Item IDs to a linked list of listeners listening + * Property identified by given Property ID and Item ID. + */ + private Hashtable singlePropertyValueChangeListeners = null; + + /** + * List of all Property set change event listeners. + */ + private LinkedList propertySetChangeListeners = null; + + /** + * List of all container Item set change event listeners. + */ + private LinkedList itemSetChangeListeners = null; + + /** + * Temporary store for sorting property ids. + */ + private Object[] sortPropertyId; + + /** + * Temporary store for sorting direction. + */ + private boolean[] sortDirection; + + /** + * Filters that are applied to the container to limit the items visible in + * it + */ + private HashSet filters; + + /* Container constructors *********************************************** */ + + public IndexedContainer() { + } + + public IndexedContainer(Collection itemIds) { + if (items != null) { + for (Iterator i = itemIds.iterator(); i.hasNext();) { + this.addItem(i.next()); + } + } + } + + /* Container methods **************************************************** */ + + /** + * Gets the Item with the given Item ID from the list. If the list does not + * contain the requested Item (or it is filtered to be invisible), + * null is returned. + * + * @param itemId + * the ID of the Item to retrieve. + * @return the Item with the given ID or null if the Item is + * not found in the list + */ + public Item getItem(Object itemId) { + if (items.containsKey(itemId) + && (filteredItemIds == null || filteredItemIds.contains(itemId))) { + return new IndexedContainerItem(itemId); + } + return null; + } + + /** + * Gets the ID's of all Items stored in the list. The ID's are returned as a + * unmodifiable collection. + * + * @return unmodifiable collection of Item IDs + */ + public Collection getItemIds() { + if (filteredItemIds != null) { + return Collections.unmodifiableCollection(filteredItemIds); + } + return Collections.unmodifiableCollection(itemIds); + } + + /** + * Gets the ID's of all Properties stored in the list. The ID's are returned + * as a unmodifiable collection. + * + * @return unmodifiable collection of Property IDs + */ + public Collection getContainerPropertyIds() { + return Collections.unmodifiableCollection(propertyIds); + } + + /** + * Gets the type of a Property stored in the list. + * + * @param id + * the ID of the Property. + * @return Type of the requested Property + */ + public Class getType(Object propertyId) { + return (Class) types.get(propertyId); + } + + /** + * Gets the Property identified by the given Item ID and Property ID from + * the lsit. If the list does not contain the Property, null + * is returned. + * + * @param itemId + * the ID of the Item which contains the requested Property. + * @param propertyId + * the ID of the Property to retrieve. + * @return Property with the given ID or null + * + * @see com.itmill.toolkit.data.Container#getContainerProperty(Object, + * Object) + */ + public Property getContainerProperty(Object itemId, Object propertyId) { + if (filteredItemIds == null) { + if (!items.containsKey(itemId)) { + return null; + } + } else if (!filteredItemIds.contains(itemId)) { + return null; + } + + return new IndexedContainerProperty(itemId, propertyId); + } + + /** + * Gets the number of Items in the list. + * + * @return number of Items in the list + */ + public int size() { + if (filteredItemIds == null) { + return itemIds.size(); + } + return filteredItemIds.size(); + } + + /** + * Tests if the list contains the specified Item + * + * @param itemId + * the ID the of Item to be tested for. + * @return true if the operation succeeded, + * false if not + */ + public boolean containsId(Object itemId) { + if (filteredItemIds != null) { + return filteredItemIds.contains(itemId); + } + return items.containsKey(itemId); + } + + /** + * Adds a new Property to all Items in the list. The Property ID, data type + * and default value of the new Property are given as parameters. + * + * @param propertyId + * the ID of the new Property. + * @param type + * the Data type of the new Property. + * @param defaultValue + * the value all created Properties are initialized to. + * @return true if the operation succeeded, + * false if not + */ + public boolean addContainerProperty(Object propertyId, Class type, + Object defaultValue) { + + // Fails, if nulls are given + if (propertyId == null || type == null) { + return false; + } + + // Fails if the Property is already present + if (propertyIds.contains(propertyId)) { + return false; + } + + // Adds the Property to Property list and types + propertyIds.add(propertyId); + types.put(propertyId, type); + + // If default value is given, set it + if (defaultValue != null) { + for (Iterator i = itemIds.iterator(); i.hasNext();) { + getItem(i.next()).getItemProperty(propertyId).setValue( + defaultValue); + } + } + + // Sends a change event + fireContainerPropertySetChange(); + + return true; + } + + /** + * Removes all Items from the list. + *

+ * Note : The Property ID and type information is preserved. + *

+ * + * @return true if the operation succeeded, + * false if not + */ + public boolean removeAllItems() { + + // Removes all Items + itemIds.clear(); + items.clear(); + if (filteredItemIds != null) { + filteredItemIds.clear(); + } + + // Sends a change event + fireContentsChange(); + + return true; + } + + /** + * Creates a new Item into the list, and assign it an automatic ID. The new + * ID is returned, or null if the operation fails. After a + * successful call you can use the + * {@link #getItem(Object ItemId) getItem}method to fetch the + * Item. + * + * @return ID of the newly created Item, or null in case of a + * failure + */ + public Object addItem() { + + // Creates a new id + Object id = new Object(); + + // Adds the Item into container + addItem(id); + + return id; + } + + /** + * Creates a new Item with the given ID into the list. The new Item is + * returned, and it is ready to have its Properties modified. Returns + * null if the operation fails or the Container already + * contains a Item with the given ID. + * + * @param itemId + * the ID of the Item to be created. + * @return Created new Item, or null in case of a failure + */ + public Item addItem(Object itemId) { + + // Makes sure that the Item has not been created yet + if (items.containsKey(itemId)) { + return null; + } + + // Adds the Item to container + itemIds.add(itemId); + items.put(itemId, new Hashtable()); + Item item = getItem(itemId); + if (filteredItemIds != null) { + if (passesFilters(item)) { + filteredItemIds.add(itemId); + } + } + + // Sends the event + fireContentsChange(); + + return item; + } + + /** + * Removes the Item corresponding to the given Item ID from the list. + * + * @param itemId + * the ID of the Item to remove. + * @return true if the operation succeeded, + * false if not + */ + public boolean removeItem(Object itemId) { + + if (items.remove(itemId) == null) { + return false; + } + itemIds.remove(itemId); + if (filteredItemIds != null) { + filteredItemIds.remove(itemId); + } + + fireContentsChange(); + + return true; + } + + /** + * Removes a Property specified by the given Property ID from the list. Note + * that the Property will be removed from all Items in the list. + * + * @param propertyId + * the ID of the Property to remove. + * @return true if the operation succeeded, + * false if not + */ + public boolean removeContainerProperty(Object propertyId) { + + // Fails if the Property is not present + if (!propertyIds.contains(propertyId)) { + return false; + } + + // Removes the Property to Property list and types + propertyIds.remove(propertyId); + types.remove(propertyId); + + // If remove the Property from all Items + for (Iterator i = itemIds.iterator(); i.hasNext();) { + ((Hashtable) items.get(i.next())).remove(propertyId); + } + + // Sends a change event + fireContainerPropertySetChange(); + + return true; + } + + /* Container.Ordered methods ******************************************** */ + + /** + * Gets the ID of the first Item in the list. + * + * @return ID of the first Item in the list + */ + public Object firstItemId() { + try { + if (filteredItemIds != null) { + return filteredItemIds.iterator().next(); + } + return itemIds.get(0); + } catch (IndexOutOfBoundsException e) { + } catch (NoSuchElementException e) { + } + return null; + } + + /** + * Gets the ID of the last Item in the list. + * + * @return ID of the last Item in the list + */ + public Object lastItemId() { + try { + if (filteredItemIds != null) { + Iterator i = filteredItemIds.iterator(); + Object last = null; + while (i.hasNext()) { + last = i.next(); + } + return last; + } + return itemIds.get(itemIds.size() - 1); + } catch (IndexOutOfBoundsException e) { + } + return null; + } + + /** + * Gets the ID of the Item following the Item that corresponds to the + * itemId. If the given Item is the last or not found in the list, + * null is returned. + * + * @param itemId + * the ID of an Item in the list. + * @return ID of the next Item or null + */ + public Object nextItemId(Object itemId) { + if (filteredItemIds != null) { + if (!filteredItemIds.contains(itemId)) { + return null; + } + Iterator i = filteredItemIds.iterator(); + if (itemId == null) { + return null; + } + while (i.hasNext() && !itemId.equals(i.next())) { + ; + } + if (i.hasNext()) { + return i.next(); + } + return null; + } + try { + return itemIds.get(itemIds.indexOf(itemId) + 1); + } catch (IndexOutOfBoundsException e) { + return null; + } + } + + /** + * Gets the ID of the Item preceding the Item that corresponds to the + * itemId. If the given Item is the first or not found in the list, + * null is returned. + * + * @param itemId + * the ID of an Item in the list. + * @return ID of the previous Item or null + */ + public Object prevItemId(Object itemId) { + if (filteredItemIds != null) { + if (!filteredItemIds.contains(itemId)) { + return null; + } + Iterator i = filteredItemIds.iterator(); + if (itemId == null) { + return null; + } + Object prev = null; + Object current; + while (i.hasNext() && !itemId.equals(current = i.next())) { + prev = current; + } + return prev; + } + try { + return itemIds.get(itemIds.indexOf(itemId) - 1); + } catch (IndexOutOfBoundsException e) { + return null; + } + } + + /** + * Tests if the Item corresponding to the given Item ID is the first Item in + * the list. + * + * @param itemId + * the ID of an Item in the list. + * @return true if the Item is first in the list, + * false if not + */ + public boolean isFirstId(Object itemId) { + if (filteredItemIds != null) { + try { + Object first = filteredItemIds.iterator().next(); + return (itemId != null && itemId.equals(first)); + } catch (NoSuchElementException e) { + return false; + } + } + return (size() >= 1 && itemIds.get(0).equals(itemId)); + } + + /** + * Tests if the Item corresponding to the given Item ID is the last Item in + * the list. + * + * @param itemId + * the ID of an Item in the list. + * @return true if the Item is last in the list, + * false if not + */ + public boolean isLastId(Object itemId) { + if (filteredItemIds != null) { + try { + Object last = null; + for (Iterator i = filteredItemIds.iterator(); i.hasNext();) { + last = i.next(); + } + return (itemId != null && itemId.equals(last)); + } catch (NoSuchElementException e) { + return false; + } + } + int s = size(); + return (s >= 1 && itemIds.get(s - 1).equals(itemId)); + } + + /** + * @see com.itmill.toolkit.data.Container.Ordered#addItemAfter(Object, + * Object) + */ + public Item addItemAfter(Object previousItemId, Object newItemId) { + + // Get the index of the addition + int index = 0; + if (previousItemId != null) { + index = 1 + indexOfId(previousItemId); + if (index <= 0 || index > size()) { + return null; + } + } + + return addItemAt(index, newItemId); + } + + /** + * @see com.itmill.toolkit.data.Container.Ordered#addItemAfter(Object) + */ + public Object addItemAfter(Object previousItemId) { + + // Get the index of the addition + int index = 0; + if (previousItemId != null) { + index = 1 + indexOfId(previousItemId); + if (index <= 0 || index > size()) { + return null; + } + } + + return addItemAt(index); + } + + /** + * Gets ID with the index. The following is true for the index: 0 <= index < + * size(). + * + * @return ID in the given index. + * @param index + * Index of the requested ID in the container. + */ + public Object getIdByIndex(int index) { + + if (filteredItemIds != null) { + if (index < 0) { + throw new IndexOutOfBoundsException(); + } + try { + Iterator i = filteredItemIds.iterator(); + while (index-- > 0) { + i.next(); + } + return i.next(); + } catch (NoSuchElementException e) { + throw new IndexOutOfBoundsException(); + } + } + + return itemIds.get(index); + } + + /** + * Gets the index of an id. The following is true for the index: 0 <= index < + * size(). + * + * @return Index of the Item or -1 if the Item is not in the container. + * @param itemId + * ID of an Item in the collection + */ + public int indexOfId(Object itemId) { + if (filteredItemIds != null) { + int index = 0; + if (itemId == null) { + return -1; + } + try { + for (Iterator i = filteredItemIds.iterator(); itemId.equals(i + .next());) { + index++; + } + return index; + } catch (NoSuchElementException e) { + return -1; + } + } + return itemIds.indexOf(itemId); + } + + /** + * @see com.itmill.toolkit.data.Container.Indexed#addItemAt(int, Object) + */ + public Item addItemAt(int index, Object newItemId) { + + // Make sure that the Item has not been created yet + if (items.containsKey(newItemId)) { + return null; + } + + // Adds the Item to container + itemIds.add(index, newItemId); + items.put(newItemId, new Hashtable()); + + if (filteredItemIds != null) { + updateContainerFiltering(); + } else { + fireContentsChange(); + } + + return getItem(newItemId); + } + + /** + * @see com.itmill.toolkit.data.Container.Indexed#addItemAt(int) + */ + public Object addItemAt(int index) { + + // Creates a new id + Object id = new Object(); + + // Adds the Item into container + addItemAt(index, id); + + return id; + } + + /* Event notifiers ****************************************************** */ + + /** + * An event object specifying the list whose Property set has + * changed. + * + * @author IT Mill Ltd. + * @version + * @VERSION@ + * @since 3.0 + */ + private class PropertySetChangeEvent extends EventObject implements + Container.PropertySetChangeEvent { + + /** + * Serial generated by eclipse. + */ + private static final long serialVersionUID = 3257002172528079926L; + + private PropertySetChangeEvent(IndexedContainer source) { + super(source); + } + + /** + * Gets the list whose Property set has changed. + * + * @return source object of the event as a Container + */ + public Container getContainer() { + return (Container) getSource(); + } + } + + /** + * An event object specifying the list whose Item set has + * changed. + * + * @author IT Mill Ltd. + * @version + * @VERSION@ + * @since 3.0 + */ + private class ItemSetChangeEvent extends EventObject implements + Container.ItemSetChangeEvent { + + /** + * Serial generated by eclipse. + */ + private static final long serialVersionUID = 3832616279386372147L; + + private ItemSetChangeEvent(IndexedContainer source) { + super(source); + } + + /** + * Gets the list whose Item set has changed. + * + * @return source object of the event as a Container + */ + public Container getContainer() { + return (Container) getSource(); + } + + } + + /** + * An event object specifying the Propery in a list whose + * value has changed. + * + * @author IT Mill Ltd. + * @version + * @VERSION@ + * @since 3.0 + */ + private class PropertyValueChangeEvent extends EventObject implements + Property.ValueChangeEvent { + + /** + * Serial generated by eclipse. + */ + private static final long serialVersionUID = 3833749884498359857L; + + private PropertyValueChangeEvent(Property source) { + super(source); + } + + /** + * Gets the Property whose value has changed. + * + * @return source object of the event as a Property + */ + public Property getProperty() { + return (Property) getSource(); + } + + } + + /** + * Registers a new Property set change listener for this list. + * + * @param listener + * the new Listener to be registered. + */ + public void addListener(Container.PropertySetChangeListener listener) { + if (propertySetChangeListeners == null) { + propertySetChangeListeners = new LinkedList(); + } + propertySetChangeListeners.add(listener); + } + + /** + * Removes a previously registered Property set change listener. + * + * @param listener + * the listener to be removed. + */ + public void removeListener(Container.PropertySetChangeListener listener) { + if (propertySetChangeListeners != null) { + propertySetChangeListeners.remove(listener); + } + } + + /** + * Adds a Item set change listener for the list. + * + * @param listener + * the listener to be added. + */ + public void addListener(Container.ItemSetChangeListener listener) { + if (itemSetChangeListeners == null) { + itemSetChangeListeners = new LinkedList(); + } + itemSetChangeListeners.add(listener); + } + + /** + * Removes a Item set change listener from the object. + * + * @param listener + * the listener to be removed. + */ + public void removeListener(Container.ItemSetChangeListener listener) { + if (itemSetChangeListeners != null) { + itemSetChangeListeners.remove(listener); + } + } + + /** + * Registers a new value change listener for this object. + * + * @param listener + * the new Listener to be registered + */ + public void addListener(Property.ValueChangeListener listener) { + if (propertyValueChangeListeners == null) { + propertyValueChangeListeners = new LinkedList(); + } + propertyValueChangeListeners.add(listener); + } + + /** + * Removes a previously registered value change listener. + * + * @param listener + * the listener to be removed. + */ + public void removeListener(Property.ValueChangeListener listener) { + if (propertyValueChangeListeners != null) { + propertyValueChangeListeners.remove(listener); + } + } + + /** + * Sends a Property value change event to all interested listeners. + * + * @param source + * the IndexedContainerProperty object. + */ + private void firePropertyValueChange(IndexedContainerProperty source) { + + // Sends event to listeners listening all value changes + if (propertyValueChangeListeners != null) { + Object[] l = propertyValueChangeListeners.toArray(); + Property.ValueChangeEvent event = new IndexedContainer.PropertyValueChangeEvent( + source); + for (int i = 0; i < l.length; i++) { + ((Property.ValueChangeListener) l[i]).valueChange(event); + } + } + + // Sends event to single property value change listeners + if (singlePropertyValueChangeListeners != null) { + Hashtable propertySetToListenerListMap = (Hashtable) singlePropertyValueChangeListeners + .get(source.propertyId); + if (propertySetToListenerListMap != null) { + LinkedList listenerList = (LinkedList) propertySetToListenerListMap + .get(source.itemId); + if (listenerList != null) { + Property.ValueChangeEvent event = new IndexedContainer.PropertyValueChangeEvent( + source); + for (Iterator i = listenerList.iterator(); i.hasNext();) { + ((Property.ValueChangeListener) i.next()) + .valueChange(event); + } + } + } + } + + } + + /** + * Sends a Property set change event to all interested listeners. + */ + private void fireContainerPropertySetChange() { + if (propertySetChangeListeners != null) { + Object[] l = propertySetChangeListeners.toArray(); + Container.PropertySetChangeEvent event = new IndexedContainer.PropertySetChangeEvent( + this); + for (int i = 0; i < l.length; i++) { + ((Container.PropertySetChangeListener) l[i]) + .containerPropertySetChange(event); + } + } + } + + /** + * Sends Item set change event to all registered interested listeners. + */ + private void fireContentsChange() { + if (itemSetChangeListeners != null) { + Object[] l = itemSetChangeListeners.toArray(); + Container.ItemSetChangeEvent event = new IndexedContainer.ItemSetChangeEvent( + this); + for (int i = 0; i < l.length; i++) { + ((Container.ItemSetChangeListener) l[i]) + .containerItemSetChange(event); + } + } + } + + /** + * Adds new single Property change listener. + * + * @param propertyId + * the ID of the Property to add. + * @param itemId + * the ID of the Item . + * @param listener + * the listener to be added. + */ + private void addSinglePropertyChangeListener(Object propertyId, + Object itemId, Property.ValueChangeListener listener) { + if (listener != null) { + if (singlePropertyValueChangeListeners == null) { + singlePropertyValueChangeListeners = new Hashtable(); + } + Hashtable propertySetToListenerListMap = (Hashtable) singlePropertyValueChangeListeners + .get(propertyId); + if (propertySetToListenerListMap == null) { + propertySetToListenerListMap = new Hashtable(); + singlePropertyValueChangeListeners.put(propertyId, + propertySetToListenerListMap); + } + LinkedList listenerList = (LinkedList) propertySetToListenerListMap + .get(itemId); + if (listenerList == null) { + listenerList = new LinkedList(); + propertySetToListenerListMap.put(itemId, listenerList); + } + listenerList.addLast(listener); + } + } + + /** + * Removes a previously registered single Property change listener. + * + * @param propertyId + * the ID of the Property to remove. + * @param itemId + * the ID of the Item. + * @param listener + * the listener to be removed. + */ + private void removeSinglePropertyChangeListener(Object propertyId, + Object itemId, Property.ValueChangeListener listener) { + if (listener != null && singlePropertyValueChangeListeners != null) { + Hashtable propertySetToListenerListMap = (Hashtable) singlePropertyValueChangeListeners + .get(propertyId); + if (propertySetToListenerListMap != null) { + LinkedList listenerList = (LinkedList) propertySetToListenerListMap + .get(itemId); + if (listenerList != null) { + listenerList.remove(listener); + if (listenerList.isEmpty()) { + propertySetToListenerListMap.remove(itemId); + } + } + if (propertySetToListenerListMap.isEmpty()) { + singlePropertyValueChangeListeners.remove(propertyId); + } + } + if (singlePropertyValueChangeListeners.isEmpty()) { + singlePropertyValueChangeListeners = null; + } + } + } + + /* Internal Item and Property implementations *************************** */ + + /* + * A class implementing the com.itmill.toolkit.data.Item interface to be + * contained in the list. @author IT Mill Ltd. + * + * @version @VERSION@ + * @since 3.0 + */ + class IndexedContainerItem implements Item { + + /** + * Item ID in the host container for this Item. + */ + private Object itemId; + + /** + * Constructs a new ListItem instance and connects it to a host + * container. + * + * @param itemId + * the Item ID of the new Item. + */ + private IndexedContainerItem(Object itemId) { + + // Gets the item contents from the host + if (itemId == null) { + throw new NullPointerException(); + } + this.itemId = itemId; + } + + /** + * Gets the Property corresponding to the given Property ID stored in + * the Item. If the Item does not contain the Property, + * null is returned. + * + * @param id + * the identifier of the Property to get. + * @return the Property with the given ID or null + */ + public Property getItemProperty(Object id) { + return new IndexedContainerProperty(itemId, id); + } + + /** + * Gets the collection containing the IDs of all Properties stored in + * the Item. + * + * @return unmodifiable collection contaning IDs of the Properties + * stored the Item + */ + public Collection getItemPropertyIds() { + return Collections.unmodifiableCollection(propertyIds); + } + + /** + * Gets the String representation of the contents of the + * Item. The format of the string is a space separated catenation of the + * String representations of the Properties contained by + * the Item. + * + * @return String representation of the Item contents + */ + public String toString() { + String retValue = ""; + + for (Iterator i = propertyIds.iterator(); i.hasNext();) { + Object propertyId = i.next(); + retValue += getItemProperty(propertyId).toString(); + if (i.hasNext()) { + retValue += " "; + } + } + + return retValue; + } + + /** + * Calculates a integer hash-code for the Item that's unique inside the + * list. Two Items inside the same list have always different + * hash-codes, though Items in different lists may have identical + * hash-codes. + * + * @return A locally unique hash-code as integer + */ + public int hashCode() { + return getHost().hashCode() ^ itemId.hashCode(); + } + + /** + * Tests if the given object is the same as the this object. Two Items + * got from a list container with the same ID are equal. + * + * @param obj + * an object to compare with this object + * @return true if the given object is the same as this + * object, false if not + */ + public boolean equals(Object obj) { + if (obj == null + || !obj.getClass().equals(IndexedContainerItem.class)) { + return false; + } + IndexedContainerItem li = (IndexedContainerItem) obj; + return getHost() == li.getHost() && itemId.equals(li.itemId); + } + + /** + * + * @return + */ + private IndexedContainer getHost() { + return IndexedContainer.this; + } + + /** + * Indexed container does not support adding new properties. + * + * @see com.itmill.toolkit.data.Item#addProperty(Object, Property) + */ + public boolean addItemProperty(Object id, Property property) + throws UnsupportedOperationException { + throw new UnsupportedOperationException("Indexed container item " + + "does not support adding new properties"); + } + + /** + * Indexed container does not support removing properties. + * + * @see com.itmill.toolkit.data.Item#removeProperty(Object) + */ + public boolean removeItemProperty(Object id) + throws UnsupportedOperationException { + throw new UnsupportedOperationException( + "Indexed container item does not support property removal"); + } + + } + + /** + * A class implementing the com.itmill.toolkit.data.Property interface to be + * contained in the Items contained in the list. + * + * @author IT Mill Ltd. + * + * @version + * @VERSION@ + * @since 3.0 + */ + private class IndexedContainerProperty implements Property, + Property.ValueChangeNotifier { + + /** + * ID of the Item, where the Property resides. + */ + private Object itemId; + + /** + * Id of the Property. + */ + private Object propertyId; + + /** + * Constructs a new ListProperty object and connect it to a ListItem and + * a ListContainer. + * + * @param itemId + * the ID of the Item to connect the new Property to. + * @param propertyId + * the Property ID of the new Property. + * @param host + * the list that contains the Item to contain the new + * Property. + */ + private IndexedContainerProperty(Object itemId, Object propertyId) { + if (itemId == null || propertyId == null) { + throw new NullPointerException(); + } + this.propertyId = propertyId; + this.itemId = itemId; + } + + /** + * Returns the type of the Property. The methods getValue + * and setValue must be compatible with this type: one + * must be able to safely cast the value returned from + * getValue to the given type and pass any variable + * assignable to this type as a parameter to setValue + * Tests if the Property is in read-only mode. In read-only mode calls + * to the method setValue will throw + * ReadOnlyException s and will not modify the value of + * the Property. + *

+ * + * @return true if the Property is in read-only mode, + * false if it's not. + */ + public boolean isReadOnly() { + return readOnlyProperties.contains(this); + } + + /** + * Sets the Property's read-only mode to the specified status. + * + * @param newStatus + * the new read-only status of the Property. + */ + public void setReadOnly(boolean newStatus) { + if (newStatus) { + readOnlyProperties.add(this); + } else { + readOnlyProperties.remove(this); + } + } + + /** + * Sets the value of the Property. By default this method will try to + * assign the value directly, but if it is unassignable, it will try to + * use the String constructor of the internal data type + * to assign the value, + * + * @param newValue + * the New value of the Property. This should be + * assignable to the Property's internal type or support + * toString. + * + * @throws Property.ReadOnlyException + * if the object is in read-only mode + * @throws Property.ConversionException + * if newValue can't be converted into + * the Property's native type directly or through + * String + */ + public void setValue(Object newValue) + throws Property.ReadOnlyException, Property.ConversionException { + + // Gets the Property set + Hashtable propertySet = (Hashtable) items.get(itemId); + + // Support null values on all types + if (newValue == null) { + propertySet.remove(propertyId); + } else if (getType().isAssignableFrom(newValue.getClass())) { + propertySet.put(propertyId, newValue); + } else { + try { + + // Gets the string constructor + Constructor constr = getType().getConstructor( + new Class[] { String.class }); + + // Creates new object from the string + propertySet.put(propertyId, constr + .newInstance(new Object[] { newValue.toString() })); + + } catch (java.lang.Exception e) { + throw new Property.ConversionException( + "Conversion for value '" + newValue + "' of class " + + newValue.getClass().getName() + " to " + + getType().getName() + " failed"); + } + } + + firePropertyValueChange(this); + } + + /** + * Returns the value of the Property in human readable textual format. + * The return value should be assignable to the setValue + * method if the Property is not in read-only mode. + * + * @return String representation of the value stored in + * the Property + */ + public String toString() { + Object value = getValue(); + if (value == null) { + return null; + } + return value.toString(); + } + + /** + * Calculates a integer hash-code for the Property that's unique inside + * the Item containing the Property. Two different Properties inside the + * same Item contained in the same list always have different + * hash-codes, though Properties in different Items may have identical + * hash-codes. + * + * @return A locally unique hash-code as integer + */ + public int hashCode() { + return itemId.hashCode() ^ propertyId.hashCode() + ^ IndexedContainer.this.hashCode(); + } + + /** + * Tests if the given object is the same as the this object. Two + * Properties got from an Item with the same ID are equal. + * + * @param obj + * an object to compare with this object + * @return true if the given object is the same as this + * object, false if not + */ + public boolean equals(Object obj) { + if (obj == null + || !obj.getClass().equals(IndexedContainerProperty.class)) { + return false; + } + IndexedContainerProperty lp = (IndexedContainerProperty) obj; + return lp.getHost() == getHost() + && lp.propertyId.equals(propertyId) + && lp.itemId.equals(itemId); + } + + /** + * Registers a new value change listener for this Property. + * + * @param listener + * the new Listener to be registered. + * @see com.itmill.toolkit.data.Property.ValueChangeNotifier#addListener(ValueChangeListener) + */ + public void addListener(Property.ValueChangeListener listener) { + addSinglePropertyChangeListener(propertyId, itemId, listener); + } + + /** + * Removes a previously registered value change listener. + * + * @param listener + * listener to be removed + * @see com.itmill.toolkit.data.Property.ValueChangeNotifier#removeListener(ValueChangeListener) + */ + public void removeListener(Property.ValueChangeListener listener) { + removeSinglePropertyChangeListener(propertyId, itemId, listener); + } + + private IndexedContainer getHost() { + return IndexedContainer.this; + } + + } + + /** + * @see com.itmill.toolkit.data.Container.Sortable#sort(java.lang.Object[], + * boolean[]) + */ + public synchronized void sort(Object[] propertyId, boolean[] ascending) { + + // Removes any non-sortable property ids + ArrayList ids = new ArrayList(); + ArrayList orders = new ArrayList(); + Collection sortable = getSortableContainerPropertyIds(); + for (int i = 0; i < propertyId.length; i++) { + if (sortable.contains(propertyId[i])) { + ids.add(propertyId[i]); + orders.add(new Boolean(i < ascending.length ? ascending[i] + : true)); + } + } + + if (ids.size() == 0) { + return; + } + sortPropertyId = ids.toArray(); + sortDirection = new boolean[orders.size()]; + for (int i = 0; i < sortDirection.length; i++) { + sortDirection[i] = ((Boolean) orders.get(i)).booleanValue(); + } + + // Sort + Collections.sort(itemIds, this); + if (filteredItemIds != null) { + updateContainerFiltering(); + } else { + fireContentsChange(); + } + + // Remove temporary references + sortPropertyId = null; + sortDirection = null; + + } + + /** + * @see com.itmill.toolkit.data.Container.Sortable#getSortableContainerPropertyIds() + */ + public Collection getSortableContainerPropertyIds() { + + LinkedList list = new LinkedList(); + for (Iterator i = propertyIds.iterator(); i.hasNext();) { + Object id = i.next(); + Class type = getType(id); + if (type != null && Comparable.class.isAssignableFrom(type)) { + list.add(id); + } + } + + return list; + } + + /** + * Compares two items for sorting. + * + * @see java.util.Comparator#compare(java.lang.Object, java.lang.Object) + * @see #sort((java.lang.Object[], boolean[]) + */ + public int compare(Object o1, Object o2) { + + for (int i = 0; i < sortPropertyId.length; i++) { + + // Get the compared properties + Property pp1 = getContainerProperty(o1, sortPropertyId[i]); + Property pp2 = getContainerProperty(o2, sortPropertyId[i]); + + // Get the compared values + Object p1 = pp1 == null ? null : pp1.getValue(); + Object p2 = pp2 == null ? null : pp2.getValue(); + + // Result of the comparison + int r = 0; + + // Normal non-null comparison + if (p1 != null && p2 != null) { + if ((p1 instanceof Boolean) && (p2 instanceof Boolean)) { + r = p1.equals(p2) ? 0 + : ((sortDirection[i] ? 1 : -1) * (((Boolean) p1) + .booleanValue() ? 1 : -1)); + } else { + r = sortDirection[i] ? ((Comparable) p1).compareTo(p2) + : -((Comparable) p1).compareTo(p2); + } + } + + // If both are nulls + else if (p1 == p2) { + r = 0; + } else { + r = (sortDirection[i] ? 1 : -1) * (p1 == null ? -1 : 1); + } + + // If order can be decided + if (r != 0) { + return r; + } + } + + return 0; + } + + /** + * Supports cloning of the IndexedContainer cleanly. + * + * @throws CloneNotSupportedException + * if an object cannot be cloned. . + */ + public Object clone() throws CloneNotSupportedException { + + // Creates the clone + IndexedContainer nc = new IndexedContainer(); + + // Clone the shallow properties + nc.itemIds = itemIds != null ? (ArrayList) itemIds.clone() : null; + nc.itemSetChangeListeners = itemSetChangeListeners != null ? (LinkedList) itemSetChangeListeners + .clone() + : null; + nc.propertyIds = propertyIds != null ? (ArrayList) propertyIds.clone() + : null; + nc.propertySetChangeListeners = propertySetChangeListeners != null ? (LinkedList) propertySetChangeListeners + .clone() + : null; + nc.propertyValueChangeListeners = propertyValueChangeListeners != null ? (LinkedList) propertyValueChangeListeners + .clone() + : null; + nc.readOnlyProperties = readOnlyProperties != null ? (HashSet) readOnlyProperties + .clone() + : null; + nc.singlePropertyValueChangeListeners = singlePropertyValueChangeListeners != null ? (Hashtable) singlePropertyValueChangeListeners + .clone() + : null; + nc.sortDirection = sortDirection != null ? (boolean[]) sortDirection + .clone() : null; + nc.sortPropertyId = sortPropertyId != null ? (Object[]) sortPropertyId + .clone() : null; + nc.types = types != null ? (Hashtable) types.clone() : null; + + nc.filters = filters == null ? null : (HashSet) filters.clone(); + + nc.filteredItemIds = filteredItemIds == null ? null + : (LinkedHashSet) filteredItemIds.clone(); + + // Clone property-values + if (items == null) { + nc.items = null; + } else { + nc.items = new Hashtable(); + for (Iterator i = items.keySet().iterator(); i.hasNext();) { + Object id = i.next(); + Hashtable it = (Hashtable) items.get(id); + nc.items.put(id, it.clone()); + } + } + + return nc; + } + + /** + * @see java.lang.Object#equals(java.lang.Object) + */ + public boolean equals(Object obj) { + + // Only ones of the objects of the same class can be equal + if (!(obj instanceof IndexedContainer)) { + return false; + } + IndexedContainer o = (IndexedContainer) obj; + + // Checks the properties one by one + if (itemIds != o.itemIds && o.itemIds != null + && !o.itemIds.equals(itemIds)) { + return false; + } + if (filters != o.filters && o.filters != null + && !o.filters.equals(filters)) { + return false; + } + if (items != o.items && o.items != null && !o.items.equals(items)) { + return false; + } + if (itemSetChangeListeners != o.itemSetChangeListeners + && o.itemSetChangeListeners != null + && !o.itemSetChangeListeners.equals(itemSetChangeListeners)) { + return false; + } + if (propertyIds != o.propertyIds && o.propertyIds != null + && !o.propertyIds.equals(propertyIds)) { + return false; + } + if (propertySetChangeListeners != o.propertySetChangeListeners + && o.propertySetChangeListeners != null + && !o.propertySetChangeListeners + .equals(propertySetChangeListeners)) { + return false; + } + if (propertyValueChangeListeners != o.propertyValueChangeListeners + && o.propertyValueChangeListeners != null + && !o.propertyValueChangeListeners + .equals(propertyValueChangeListeners)) { + return false; + } + if (readOnlyProperties != o.readOnlyProperties + && o.readOnlyProperties != null + && !o.readOnlyProperties.equals(readOnlyProperties)) { + return false; + } + if (singlePropertyValueChangeListeners != o.singlePropertyValueChangeListeners + && o.singlePropertyValueChangeListeners != null + && !o.singlePropertyValueChangeListeners + .equals(singlePropertyValueChangeListeners)) { + return false; + } + if (sortDirection != o.sortDirection && o.sortDirection != null + && !o.sortDirection.equals(sortDirection)) { + return false; + } + if (sortPropertyId != o.sortPropertyId && o.sortPropertyId != null + && !o.sortPropertyId.equals(sortPropertyId)) { + return false; + } + if (types != o.types && o.types != null && !o.types.equals(types)) { + return false; + } + + return true; + } + + /** + * @see java.lang.Object#hashCode() + */ + public int hashCode() { + + // The hash-code is calculated as combination hash of the members + return (itemIds != null ? itemIds.hashCode() : 0) + ^ (items != null ? items.hashCode() : 0) + ^ (filters != null ? filters.hashCode() : 0) + ^ (itemSetChangeListeners != null ? itemSetChangeListeners + .hashCode() : 0) + ^ (propertyIds != null ? propertyIds.hashCode() : 0) + ^ (propertySetChangeListeners != null ? propertySetChangeListeners + .hashCode() + : 0) + ^ (propertyValueChangeListeners != null ? propertyValueChangeListeners + .hashCode() + : 0) + ^ (readOnlyProperties != null ? readOnlyProperties.hashCode() + : 0) + ^ (singlePropertyValueChangeListeners != null ? singlePropertyValueChangeListeners + .hashCode() + : 0) + ^ (sortPropertyId != null ? sortPropertyId.hashCode() : 0) + ^ (types != null ? types.hashCode() : 0) + ^ (sortDirection != null ? sortDirection.hashCode() : 0); + } + + private class Filter { + Object propertyId; + String filterString; + boolean ignoreCase; + boolean onlyMatchPrefix; + + Filter(Object propertyId, String filterString, boolean ignoreCase, + boolean onlyMatchPrefix) { + this.propertyId = propertyId; + ; + this.filterString = filterString; + this.ignoreCase = ignoreCase; + this.onlyMatchPrefix = onlyMatchPrefix; + } + + public boolean equals(Object obj) { + + // Only ones of the objects of the same class can be equal + if (!(obj instanceof Filter)) { + return false; + } + Filter o = (Filter) obj; + + // Checks the properties one by one + if (propertyId != o.propertyId && o.propertyId != null + && !o.propertyId.equals(propertyId)) { + return false; + } + if (filterString != o.filterString && o.filterString != null + && !o.filterString.equals(filterString)) { + return false; + } + if (ignoreCase != o.ignoreCase) { + return false; + } + if (onlyMatchPrefix != o.onlyMatchPrefix) { + return false; + } + + return true; + } + + public int hashCode() { + return (propertyId != null ? propertyId.hashCode() : 0) + ^ (filterString != null ? filterString.hashCode() : 0); + } + + } + + public void addContainerFilter(Object propertyId, String filterString, + boolean ignoreCase, boolean onlyMatchPrefix) { + if (filters == null) { + filters = new HashSet(); + } + filters.add(new Filter(propertyId, filterString, ignoreCase, + onlyMatchPrefix)); + updateContainerFiltering(); + } + + public void removeAllContainerFilters() { + if (filters == null) { + return; + } + filters.clear(); + updateContainerFiltering(); + } + + public void removeContainerFilters(Object propertyId) { + if (filters == null || propertyId == null) { + return; + } + for (Iterator i = filters.iterator(); i.hasNext();) { + Filter f = (Filter) i.next(); + if (propertyId.equals(f.propertyId)) { + i.remove(); + } + } + updateContainerFiltering(); + } + + private void updateContainerFiltering() { + + // Clearing filters? + if (filters == null || filters.isEmpty()) { + filteredItemIds = null; + if (filters != null) { + filters = null; + fireContentsChange(); + } + return; + } + + // Reset filteres list + if (filteredItemIds == null) { + filteredItemIds = new LinkedHashSet(); + } else { + filteredItemIds.clear(); + } + + // Filter + for (Iterator i = itemIds.iterator(); i.hasNext();) { + Object id = i.next(); + if (passesFilters(new IndexedContainerItem(id))) { + filteredItemIds.add(id); + } + } + + fireContentsChange(); + } + + private boolean passesFilters(Item item) { + if (filters == null) { + return true; + } + if (item == null) { + return false; + } + for (Iterator i = filters.iterator(); i.hasNext();) { + Filter f = (Filter) i.next(); + String s1 = f.ignoreCase ? f.filterString.toLowerCase() + : f.filterString; + Property p = item.getItemProperty(f.propertyId); + if (p == null) { + return false; + } + String s2 = f.ignoreCase ? p.toString().toLowerCase() : p + .toString(); + if (f.onlyMatchPrefix) { + if (s2.indexOf(s1) != 0) { + return false; + } + } else { + if (s2.indexOf(s1) < 0) { + return false; + } + } + } + return true; + } } \ No newline at end of file diff --git a/src/com/itmill/toolkit/data/util/MethodProperty.java b/src/com/itmill/toolkit/data/util/MethodProperty.java index 7c56f7e3bb..e28ce8f385 100644 --- a/src/com/itmill/toolkit/data/util/MethodProperty.java +++ b/src/com/itmill/toolkit/data/util/MethodProperty.java @@ -62,761 +62,777 @@ import com.itmill.toolkit.data.Property; */ public class MethodProperty implements Property { - /** - * The object that includes the property the MethodProperty is bound to. - */ - private Object instance; - - /** - * Argument arrays for the getter and setter methods. - */ - private Object[] setArgs, getArgs; - - /** - * Is the MethodProperty read-only? - */ - private boolean readOnly; - - /** - * The getter and setter methods. - */ - private Method setMethod, getMethod; - - /** - * Index of the new value in the argument list for the setter method. If the - * setter method requires several parameters, this index tells which one is - * the actual value to change. - */ - private int setArgumentIndex; - - /** - * Type of the property. - */ - private Class type; - - /** - * List of listeners who are interested in the read-only status changes of - * the MethodProperty - */ - private LinkedList readOnlyStatusChangeListeners = null; - - /** - *

- * Creates a new instance of MethodProperty from a named bean - * property. This constructor takes an object and the name of a bean - * property and initializes itself with the accessor methods for the - * property. - *

- *

- * The getter method of a MethodProperty instantiated with - * this constructor will be called with no arguments, and the setter method - * with only the new value as the sole argument. - *

- * - *

- * If the setter method is unavailable, the resulting - * MethodProperty will be read-only, otherwise it will be - * read-write. - *

- * - *

- * Method names are constucted from the bean property by adding - * get/is/are/set prefix and capitalising the first character in the name of - * the given bean property. - *

- * - * @param instance - * the object that includes the property. - * @param beanPropertyName - * the name of the property to bind to. - */ - public MethodProperty(Object instance, String beanPropertyName) { - - Class beanClass = instance.getClass(); - - // Assure that the first letter is upper cased (it is a common - // mistake to write firstName, not FirstName). - if (Character.isLowerCase(beanPropertyName.charAt(0))) { - char[] buf = beanPropertyName.toCharArray(); - buf[0] = Character.toUpperCase(buf[0]); - beanPropertyName = new String(buf); - } - - // Find the get method - getMethod = null; - try { - getMethod = beanClass.getMethod("get" + beanPropertyName, - new Class[] {}); - } catch (java.lang.NoSuchMethodException ignored) { - try { - getMethod = beanClass.getMethod("is" + beanPropertyName, - new Class[] {}); - } catch (java.lang.NoSuchMethodException ignoredAsWell) { - try { - getMethod = beanClass.getMethod("are" + beanPropertyName, - new Class[] {}); - } catch (java.lang.NoSuchMethodException e) { - throw new MethodProperty.MethodException("Bean property " - + beanPropertyName + " can not be found"); - } - } - } - - // In case the get method is found, resolve the type - type = getMethod.getReturnType(); - - // Finds the set method - setMethod = null; - try { - setMethod = beanClass.getMethod("set" + beanPropertyName, - new Class[] { type }); - } catch (java.lang.NoSuchMethodException skipped) { - } - - // Gets the return type from get method - if (type.isPrimitive()) { - if (type.equals(Boolean.TYPE)) - type = Boolean.class; - else if (type.equals(Integer.TYPE)) - type = Integer.class; - else if (type.equals(Float.TYPE)) - type = Float.class; - else if (type.equals(Double.TYPE)) - type = Double.class; - else if (type.equals(Byte.TYPE)) - type = Byte.class; - else if (type.equals(Character.TYPE)) - type = Character.class; - else if (type.equals(Short.TYPE)) - type = Short.class; - else if (type.equals(Long.TYPE)) - type = Long.class; - } - - setArguments(new Object[] {}, new Object[] { null }, 0); - this.readOnly = (setMethod == null); - this.instance = instance; - } - - /** - *

- * Creates a new instance of MethodProperty from named getter - * and setter methods. The getter method of a MethodProperty - * instantiated with this constructor will be called with no arguments, and - * the setter method with only the new value as the sole argument. - *

- * - *

- * If the setter method is null, the resulting - * MethodProperty will be read-only, otherwise it will be - * read-write. - *

- * - * @param type - * the type of the property. - * @param instance - * the object that includes the property. - * @param getMethodName - * the name of the getter method. - * @param setMethodName - * the name of the setter method. - * - */ - public MethodProperty(Class type, Object instance, String getMethodName, - String setMethodName) { - this(type, instance, getMethodName, setMethodName, new Object[] {}, - new Object[] { null }, 0); - } - - /** - *

- * Creates a new instance of MethodProperty with the getter - * and setter methods. The getter method of a MethodProperty - * instantiated with this constructor will be called with no arguments, and - * the setter method with only the new value as the sole argument. - *

- * - *

- * If the setter method is null, the resulting - * MethodProperty will be read-only, otherwise it will be - * read-write. - *

- * - * @param type - * the type of the property. - * @param instance - * the object that includes the property. - * @param getMethod - * the getter method. - * @param setMethod - * the setter method. - */ - public MethodProperty(Class type, Object instance, Method getMethod, - Method setMethod) { - this(type, instance, getMethod, setMethod, new Object[] {}, - new Object[] { null }, 0); - } - - /** - *

- * Creates a new instance of MethodProperty from named getter - * and setter methods and argument lists. The getter method of a - * MethodProperty instantiated with this constructor will be - * called with the getArgs as arguments. The setArgs will be used as the - * arguments for the setter method, though the argument indexed by the - * setArgumentIndex will be replaced with the argument passed to the - * {@link #setValue(Object newValue)} method. - *

- * - *

- * For example, if the setArgs contains A, - * B and C, and setArgumentIndex = - * 1, - * the call methodProperty.setValue(X) would result in the - * setter method to be called with the parameter set of - * {A, X, C} - *

- * - * @param type - * the type of the property. - * @param instance - * the object that includes the property. - * @param getMethodName - * the name of the getter method. - * @param setMethodName - * the name of the setter method. - * @param getArgs - * the fixed argument list to be passed to the getter method. - * @param setArgs - * the fixed argument list to be passed to the setter method. - * @param setArgumentIndex - * the index of the argument in setArgs to be - * replaced with newValue when - * {@link #setValue(Object newValue)} is called. - */ - public MethodProperty(Class type, Object instance, String getMethodName, - String setMethodName, Object[] getArgs, Object[] setArgs, - int setArgumentIndex) { - - // Check the setargs and setargs index - if (setMethodName != null && setArgs == null) - throw new IndexOutOfBoundsException("The setArgs can not be null"); - if (setMethodName != null - && (setArgumentIndex < 0 || setArgumentIndex >= setArgs.length)) - throw new IndexOutOfBoundsException( - "The setArgumentIndex must be >= 0 and < setArgs.length"); - - // Set type - this.type = type; - - // Find set and get -methods - Method[] m = instance.getClass().getMethods(); - - // Finds get method - boolean found = false; - for (int i = 0; i < m.length; i++) { - - // Tests the name of the get Method - if (!m[i].getName().equals(getMethodName)) { - - // name does not match, try next method - continue; - } - - // Tests return type - if (!type.equals(m[i].getReturnType())) - continue; - - // Tests the parameter types - Class[] c = m[i].getParameterTypes(); - if (c.length != getArgs.length) { - - // not the right amount of parameters, try next method - continue; - } - int j = 0; - while (j < c.length) { - if (getArgs[j] != null - && !c[j].isAssignableFrom(getArgs[j].getClass())) { - - // parameter type does not match, try next method - break; - } - j++; - } - if (j == c.length) { - - // all paramteters matched - if (found == true) { - throw new MethodProperty.MethodException( - "Could not uniquely identify " + getMethodName - + "-method"); - } else { - found = true; - getMethod = m[i]; - } - } - } - if (found != true) { - throw new MethodProperty.MethodException("Could not find " - + getMethodName + "-method"); - } - - // Finds set method - if (setMethodName != null) { - - // Finds setMethod - found = false; - for (int i = 0; i < m.length; i++) { - - // Checks name - if (!m[i].getName().equals(setMethodName)) { - - // name does not match, try next method - continue; - } - - // Checks parameter compatibility - Class[] c = m[i].getParameterTypes(); - if (c.length != setArgs.length) { - - // not the right amount of parameters, try next method - continue; - } - int j = 0; - while (j < c.length) { - if (setArgs[j] != null - && !c[j].isAssignableFrom(setArgs[j].getClass())) { - - // parameter type does not match, try next method - break; - } else if (j == setArgumentIndex && !c[j].equals(type)) { - - // Property type is not the same as setArg type - break; - } - j++; - } - if (j == c.length) { - - // all parameters match - if (found == true) { - throw new MethodProperty.MethodException( - "Could not identify unique " + setMethodName - + "-method"); - } else { - found = true; - setMethod = m[i]; - } - } - } - if (found != true) { - throw new MethodProperty.MethodException("Could not identify " - + setMethodName + "-method"); - } - } - - // Gets the return type from get method - if (type.isPrimitive()) { - if (type.equals(Boolean.TYPE)) - type = Boolean.class; - else if (type.equals(Integer.TYPE)) - type = Integer.class; - else if (type.equals(Float.TYPE)) - type = Float.class; - else if (type.equals(Double.TYPE)) - type = Double.class; - else if (type.equals(Byte.TYPE)) - type = Byte.class; - else if (type.equals(Character.TYPE)) - type = Character.class; - else if (type.equals(Short.TYPE)) - type = Short.class; - else if (type.equals(Long.TYPE)) - type = Long.class; - } - - setArguments(getArgs, setArgs, setArgumentIndex); - this.readOnly = (setMethod == null); - this.instance = instance; - } - - /** - *

- * Creates a new instance of MethodProperty from the getter - * and setter methods, and argument lists. - *

- *

- * This constructor behaves exactly like - * {@link #MethodProperty(Class type, Object instance, String getMethodName, - * String setMethodName, Object [] getArgs, Object [] setArgs, int - * setArgumentIndex)} except that instead of names of the getter and setter - * methods this constructor is given the actual methods themselves. - *

- * - * @param type - * the type of the property. - * @param instance - * the object that includes the property. - * @param getMethod - * the getter method. - * @param setMethod - * the setter method. - * @param getArgs - * the fixed argument list to be passed to the getter method. - * @param setArgs - * the fixed argument list to be passed to the setter method. - * @param setArgumentIndex - * the index of the argument in setArgs to be - * replaced with newValue when - * {@link #setValue(Object newValue)} is called. - */ - public MethodProperty(Class type, Object instance, Method getMethod, - Method setMethod, Object[] getArgs, Object[] setArgs, - int setArgumentIndex) { - - if (getMethod == null) { - throw new MethodProperty.MethodException( - "Property GET-method cannot not be null: " + type); - } - - if (setMethod != null - && (setArgumentIndex < 0 || setArgumentIndex >= setArgs.length)) - throw new IndexOutOfBoundsException( - "The setArgumentIndex must be >= 0 and < setArgs.length"); - - // Gets the return type from get method - if (type.isPrimitive()) { - if (type.equals(Boolean.TYPE)) - type = Boolean.class; - else if (type.equals(Integer.TYPE)) - type = Integer.class; - else if (type.equals(Float.TYPE)) - type = Float.class; - else if (type.equals(Double.TYPE)) - type = Double.class; - else if (type.equals(Byte.TYPE)) - type = Byte.class; - else if (type.equals(Character.TYPE)) - type = Character.class; - else if (type.equals(Short.TYPE)) - type = Short.class; - else if (type.equals(Long.TYPE)) - type = Long.class; - } - - this.getMethod = getMethod; - this.setMethod = setMethod; - setArguments(getArgs, setArgs, setArgumentIndex); - this.readOnly = (setMethod == null); - this.instance = instance; - this.type = type; - } - - /** - * Returns the type of the Property. The methods getValue and - * setValue must be compatible with this type: one must be - * able to safely cast the value returned from getValue to - * the given type and pass any variable assignable to this type as an - * argument to setValue. - * - * @return type of the Property - */ - public final Class getType() { - return type; - } - - /** - * Tests if the object is in read-only mode. In read-only mode calls to - * setValue will throw ReadOnlyException and - * will not modify the value of the Property. - * - * @return true if the object is in read-only mode, - * false if it's not - */ - public boolean isReadOnly() { - return readOnly; - } - - /** - * Gets the value stored in the Property. The value is resolved by calling - * the specified getter method with the argument specified at instantiation. - * - * @return the value of the Property - */ - public Object getValue() { - try { - return getMethod.invoke(instance, getArgs); - } catch (Throwable e) { - throw new MethodProperty.MethodException(e); - } - } - - /** - * Returns the value of the MethodProperty in human readable - * textual format. The return value should be assignable to the - * setValue method if the Property is not in read-only mode. - * - * @return String representation of the value stored in the Property - */ - public String toString() { - Object value = getValue(); - if (value == null) - return null; - return value.toString(); - } - - /** - *

- * Sets the setter method and getter method argument lists. - *

- * - * @param getArgs - * the fixed argument list to be passed to the getter method. - * @param setArgs - * the fixed argument list to be passed to the setter method. - * @param setArgumentIndex - * the index of the argument in setArgs to be - * replaced with newValue when - * {@link #setValue(Object newValue)} is called. - */ - public void setArguments(Object[] getArgs, Object[] setArgs, - int setArgumentIndex) { - this.getArgs = new Object[getArgs.length]; - for (int i = 0; i < getArgs.length; i++) - this.getArgs[i] = getArgs[i]; - this.setArgs = new Object[setArgs.length]; - for (int i = 0; i < setArgs.length; i++) - this.setArgs[i] = setArgs[i]; - this.setArgumentIndex = setArgumentIndex; - } - - /** - * Sets the value of the property. This method supports setting from - * Strings if either String is directly - * assignable to property type, or the type class contains a string - * constructor. - * - * @param newValue - * the New value of the property. - * @throws Property.ReadOnlyException if the object is in - * read-only mode. - * @throws Property.ConversionException if newValue - * can't be converted into the Property's native type directly - * or through String. - * @see #invokeSetMethod(Object) - */ - public void setValue(Object newValue) throws Property.ReadOnlyException, - Property.ConversionException { - - // Checks the mode - if (isReadOnly()) - throw new Property.ReadOnlyException(); - - // Try to assign the compatible value directly - if (newValue == null || type.isAssignableFrom(newValue.getClass())) - invokeSetMethod(newValue); - - // Otherwise try to convert the value trough string constructor - else { - - Object value; - try { - - // Gets the string constructor - Constructor constr = getType().getConstructor( - new Class[] { String.class }); - - value = constr - .newInstance(new Object[] { newValue.toString() }); - - } catch (java.lang.Exception e) { - throw new Property.ConversionException(e); - } - - // Creates new object from the string - invokeSetMethod(value); - } - } - - /** - * Internal method to actually call the setter method of the wrapped - * property. - * - * @param value - */ - private void invokeSetMethod(Object value) { - - try { - // Construct a temporary argument array only if needed - if (setArgs.length == 1) - setMethod.invoke(instance, new Object[] { value }); - else { - - // Sets the value to argument array - Object[] args = new Object[setArgs.length]; - for (int i = 0; i < setArgs.length; i++) - args[i] = (i == setArgumentIndex) ? value : setArgs[i]; - setMethod.invoke(instance, args); - } - } catch (InvocationTargetException e) { - Throwable targetException = e.getTargetException(); - throw new MethodProperty.MethodException(targetException); - } catch (Exception e) { - throw new MethodProperty.MethodException(e); - } - } - - /** - * Sets the Property's read-only mode to the specified status. - * - * @param newStatus - * the new read-only status of the Property. - */ - public void setReadOnly(boolean newStatus) { - boolean prevStatus = readOnly; - if (newStatus) - readOnly = true; - else - readOnly = (setMethod == null); - if (prevStatus != readOnly) - fireReadOnlyStatusChange(); - } - - /** - * Exception object that signals that there were problems - * calling or finding the specified getter or setter methods of the - * property. - * - * @author IT Mill Ltd. - * @version - * @VERSION@ - * @since 3.0 - */ - public class MethodException extends RuntimeException { - - /** - * Serial generated by eclipse. - */ - private static final long serialVersionUID = 3690473623827855153L; - - /** - * Cause of the method exception - */ - private Throwable cause; - - /** - * Constructs a new MethodException with the specified - * detail message. - * - * @param msg - * the detail message. - */ - public MethodException(String msg) { - super(msg); - } - - /** - * Constructs a new MethodException from another - * exception. - * - * @param cause - * the cause of the exception. - */ - public MethodException(Throwable cause) { - this.cause = cause; - } - - /** - * @see java.lang.Throwable#getCause() - */ - public Throwable getCause() { - return cause; - } - - /** - * Gets the method property this exception originates from. - */ - public MethodProperty getMethodProperty() { - return MethodProperty.this; - } - } - - /* Events *************************************************************** */ - - /** - * An Event object specifying the Property whose read-only - * status has been changed. - * - * @author IT Mill Ltd. - * @version - * @VERSION@ - * @since 3.0 - */ - private class ReadOnlyStatusChangeEvent extends java.util.EventObject - implements Property.ReadOnlyStatusChangeEvent { - - /** - * Serial generated by eclipse. - */ - private static final long serialVersionUID = 3258129163305955896L; - - /** - * Constructs a new read-only status change event for this object. - * - * @param source - * source object of the event. - */ - protected ReadOnlyStatusChangeEvent(MethodProperty source) { - super(source); - } - - /** - * Gets the Property whose read-only state has changed. - * - * @return source Property of the event. - */ - public Property getProperty() { - return (Property) getSource(); - } - - } - - /** - * Registers a new read-only status change listener for this Property. - * - * @param listener - * the new Listener to be registered. - */ - public void addListener(Property.ReadOnlyStatusChangeListener listener) { - if (readOnlyStatusChangeListeners == null) - readOnlyStatusChangeListeners = new LinkedList(); - readOnlyStatusChangeListeners.add(listener); - } - - /** - * Removes a previously registered read-only status change listener. - * - * @param listener - * the listener to be removed. - */ - public void removeListener(Property.ReadOnlyStatusChangeListener listener) { - if (readOnlyStatusChangeListeners != null) - readOnlyStatusChangeListeners.remove(listener); - } - - /** - * Sends a read only status change event to all registered listeners. - */ - private void fireReadOnlyStatusChange() { - if (readOnlyStatusChangeListeners != null) { - Object[] l = readOnlyStatusChangeListeners.toArray(); - Property.ReadOnlyStatusChangeEvent event = new MethodProperty.ReadOnlyStatusChangeEvent( - this); - for (int i = 0; i < l.length; i++) - ((Property.ReadOnlyStatusChangeListener) l[i]) - .readOnlyStatusChange(event); - } - } + /** + * The object that includes the property the MethodProperty is bound to. + */ + private Object instance; + + /** + * Argument arrays for the getter and setter methods. + */ + private Object[] setArgs, getArgs; + + /** + * Is the MethodProperty read-only? + */ + private boolean readOnly; + + /** + * The getter and setter methods. + */ + private Method setMethod, getMethod; + + /** + * Index of the new value in the argument list for the setter method. If the + * setter method requires several parameters, this index tells which one is + * the actual value to change. + */ + private int setArgumentIndex; + + /** + * Type of the property. + */ + private Class type; + + /** + * List of listeners who are interested in the read-only status changes of + * the MethodProperty + */ + private LinkedList readOnlyStatusChangeListeners = null; + + /** + *

+ * Creates a new instance of MethodProperty from a named bean + * property. This constructor takes an object and the name of a bean + * property and initializes itself with the accessor methods for the + * property. + *

+ *

+ * The getter method of a MethodProperty instantiated with + * this constructor will be called with no arguments, and the setter method + * with only the new value as the sole argument. + *

+ * + *

+ * If the setter method is unavailable, the resulting + * MethodProperty will be read-only, otherwise it will be + * read-write. + *

+ * + *

+ * Method names are constucted from the bean property by adding + * get/is/are/set prefix and capitalising the first character in the name of + * the given bean property. + *

+ * + * @param instance + * the object that includes the property. + * @param beanPropertyName + * the name of the property to bind to. + */ + public MethodProperty(Object instance, String beanPropertyName) { + + Class beanClass = instance.getClass(); + + // Assure that the first letter is upper cased (it is a common + // mistake to write firstName, not FirstName). + if (Character.isLowerCase(beanPropertyName.charAt(0))) { + char[] buf = beanPropertyName.toCharArray(); + buf[0] = Character.toUpperCase(buf[0]); + beanPropertyName = new String(buf); + } + + // Find the get method + getMethod = null; + try { + getMethod = beanClass.getMethod("get" + beanPropertyName, + new Class[] {}); + } catch (java.lang.NoSuchMethodException ignored) { + try { + getMethod = beanClass.getMethod("is" + beanPropertyName, + new Class[] {}); + } catch (java.lang.NoSuchMethodException ignoredAsWell) { + try { + getMethod = beanClass.getMethod("are" + beanPropertyName, + new Class[] {}); + } catch (java.lang.NoSuchMethodException e) { + throw new MethodProperty.MethodException("Bean property " + + beanPropertyName + " can not be found"); + } + } + } + + // In case the get method is found, resolve the type + type = getMethod.getReturnType(); + + // Finds the set method + setMethod = null; + try { + setMethod = beanClass.getMethod("set" + beanPropertyName, + new Class[] { type }); + } catch (java.lang.NoSuchMethodException skipped) { + } + + // Gets the return type from get method + if (type.isPrimitive()) { + if (type.equals(Boolean.TYPE)) { + type = Boolean.class; + } else if (type.equals(Integer.TYPE)) { + type = Integer.class; + } else if (type.equals(Float.TYPE)) { + type = Float.class; + } else if (type.equals(Double.TYPE)) { + type = Double.class; + } else if (type.equals(Byte.TYPE)) { + type = Byte.class; + } else if (type.equals(Character.TYPE)) { + type = Character.class; + } else if (type.equals(Short.TYPE)) { + type = Short.class; + } else if (type.equals(Long.TYPE)) { + type = Long.class; + } + } + + setArguments(new Object[] {}, new Object[] { null }, 0); + readOnly = (setMethod == null); + this.instance = instance; + } + + /** + *

+ * Creates a new instance of MethodProperty from named getter + * and setter methods. The getter method of a MethodProperty + * instantiated with this constructor will be called with no arguments, and + * the setter method with only the new value as the sole argument. + *

+ * + *

+ * If the setter method is null, the resulting + * MethodProperty will be read-only, otherwise it will be + * read-write. + *

+ * + * @param type + * the type of the property. + * @param instance + * the object that includes the property. + * @param getMethodName + * the name of the getter method. + * @param setMethodName + * the name of the setter method. + * + */ + public MethodProperty(Class type, Object instance, String getMethodName, + String setMethodName) { + this(type, instance, getMethodName, setMethodName, new Object[] {}, + new Object[] { null }, 0); + } + + /** + *

+ * Creates a new instance of MethodProperty with the getter + * and setter methods. The getter method of a MethodProperty + * instantiated with this constructor will be called with no arguments, and + * the setter method with only the new value as the sole argument. + *

+ * + *

+ * If the setter method is null, the resulting + * MethodProperty will be read-only, otherwise it will be + * read-write. + *

+ * + * @param type + * the type of the property. + * @param instance + * the object that includes the property. + * @param getMethod + * the getter method. + * @param setMethod + * the setter method. + */ + public MethodProperty(Class type, Object instance, Method getMethod, + Method setMethod) { + this(type, instance, getMethod, setMethod, new Object[] {}, + new Object[] { null }, 0); + } + + /** + *

+ * Creates a new instance of MethodProperty from named getter + * and setter methods and argument lists. The getter method of a + * MethodProperty instantiated with this constructor will be + * called with the getArgs as arguments. The setArgs will be used as the + * arguments for the setter method, though the argument indexed by the + * setArgumentIndex will be replaced with the argument passed to the + * {@link #setValue(Object newValue)} method. + *

+ * + *

+ * For example, if the setArgs contains A, + * B and C, and setArgumentIndex = + * 1, + * the call methodProperty.setValue(X) would result in the + * setter method to be called with the parameter set of + * {A, X, C} + *

+ * + * @param type + * the type of the property. + * @param instance + * the object that includes the property. + * @param getMethodName + * the name of the getter method. + * @param setMethodName + * the name of the setter method. + * @param getArgs + * the fixed argument list to be passed to the getter method. + * @param setArgs + * the fixed argument list to be passed to the setter method. + * @param setArgumentIndex + * the index of the argument in setArgs to be + * replaced with newValue when + * {@link #setValue(Object newValue)} is called. + */ + public MethodProperty(Class type, Object instance, String getMethodName, + String setMethodName, Object[] getArgs, Object[] setArgs, + int setArgumentIndex) { + + // Check the setargs and setargs index + if (setMethodName != null && setArgs == null) { + throw new IndexOutOfBoundsException("The setArgs can not be null"); + } + if (setMethodName != null + && (setArgumentIndex < 0 || setArgumentIndex >= setArgs.length)) { + throw new IndexOutOfBoundsException( + "The setArgumentIndex must be >= 0 and < setArgs.length"); + } + + // Set type + this.type = type; + + // Find set and get -methods + Method[] m = instance.getClass().getMethods(); + + // Finds get method + boolean found = false; + for (int i = 0; i < m.length; i++) { + + // Tests the name of the get Method + if (!m[i].getName().equals(getMethodName)) { + + // name does not match, try next method + continue; + } + + // Tests return type + if (!type.equals(m[i].getReturnType())) { + continue; + } + + // Tests the parameter types + Class[] c = m[i].getParameterTypes(); + if (c.length != getArgs.length) { + + // not the right amount of parameters, try next method + continue; + } + int j = 0; + while (j < c.length) { + if (getArgs[j] != null + && !c[j].isAssignableFrom(getArgs[j].getClass())) { + + // parameter type does not match, try next method + break; + } + j++; + } + if (j == c.length) { + + // all paramteters matched + if (found == true) { + throw new MethodProperty.MethodException( + "Could not uniquely identify " + getMethodName + + "-method"); + } else { + found = true; + getMethod = m[i]; + } + } + } + if (found != true) { + throw new MethodProperty.MethodException("Could not find " + + getMethodName + "-method"); + } + + // Finds set method + if (setMethodName != null) { + + // Finds setMethod + found = false; + for (int i = 0; i < m.length; i++) { + + // Checks name + if (!m[i].getName().equals(setMethodName)) { + + // name does not match, try next method + continue; + } + + // Checks parameter compatibility + Class[] c = m[i].getParameterTypes(); + if (c.length != setArgs.length) { + + // not the right amount of parameters, try next method + continue; + } + int j = 0; + while (j < c.length) { + if (setArgs[j] != null + && !c[j].isAssignableFrom(setArgs[j].getClass())) { + + // parameter type does not match, try next method + break; + } else if (j == setArgumentIndex && !c[j].equals(type)) { + + // Property type is not the same as setArg type + break; + } + j++; + } + if (j == c.length) { + + // all parameters match + if (found == true) { + throw new MethodProperty.MethodException( + "Could not identify unique " + setMethodName + + "-method"); + } else { + found = true; + setMethod = m[i]; + } + } + } + if (found != true) { + throw new MethodProperty.MethodException("Could not identify " + + setMethodName + "-method"); + } + } + + // Gets the return type from get method + if (type.isPrimitive()) { + if (type.equals(Boolean.TYPE)) { + type = Boolean.class; + } else if (type.equals(Integer.TYPE)) { + type = Integer.class; + } else if (type.equals(Float.TYPE)) { + type = Float.class; + } else if (type.equals(Double.TYPE)) { + type = Double.class; + } else if (type.equals(Byte.TYPE)) { + type = Byte.class; + } else if (type.equals(Character.TYPE)) { + type = Character.class; + } else if (type.equals(Short.TYPE)) { + type = Short.class; + } else if (type.equals(Long.TYPE)) { + type = Long.class; + } + } + + setArguments(getArgs, setArgs, setArgumentIndex); + readOnly = (setMethod == null); + this.instance = instance; + } + + /** + *

+ * Creates a new instance of MethodProperty from the getter + * and setter methods, and argument lists. + *

+ *

+ * This constructor behaves exactly like + * {@link #MethodProperty(Class type, Object instance, String getMethodName, + * String setMethodName, Object [] getArgs, Object [] setArgs, int + * setArgumentIndex)} except that instead of names of the getter and setter + * methods this constructor is given the actual methods themselves. + *

+ * + * @param type + * the type of the property. + * @param instance + * the object that includes the property. + * @param getMethod + * the getter method. + * @param setMethod + * the setter method. + * @param getArgs + * the fixed argument list to be passed to the getter method. + * @param setArgs + * the fixed argument list to be passed to the setter method. + * @param setArgumentIndex + * the index of the argument in setArgs to be + * replaced with newValue when + * {@link #setValue(Object newValue)} is called. + */ + public MethodProperty(Class type, Object instance, Method getMethod, + Method setMethod, Object[] getArgs, Object[] setArgs, + int setArgumentIndex) { + + if (getMethod == null) { + throw new MethodProperty.MethodException( + "Property GET-method cannot not be null: " + type); + } + + if (setMethod != null + && (setArgumentIndex < 0 || setArgumentIndex >= setArgs.length)) { + throw new IndexOutOfBoundsException( + "The setArgumentIndex must be >= 0 and < setArgs.length"); + } + + // Gets the return type from get method + if (type.isPrimitive()) { + if (type.equals(Boolean.TYPE)) { + type = Boolean.class; + } else if (type.equals(Integer.TYPE)) { + type = Integer.class; + } else if (type.equals(Float.TYPE)) { + type = Float.class; + } else if (type.equals(Double.TYPE)) { + type = Double.class; + } else if (type.equals(Byte.TYPE)) { + type = Byte.class; + } else if (type.equals(Character.TYPE)) { + type = Character.class; + } else if (type.equals(Short.TYPE)) { + type = Short.class; + } else if (type.equals(Long.TYPE)) { + type = Long.class; + } + } + + this.getMethod = getMethod; + this.setMethod = setMethod; + setArguments(getArgs, setArgs, setArgumentIndex); + readOnly = (setMethod == null); + this.instance = instance; + this.type = type; + } + + /** + * Returns the type of the Property. The methods getValue and + * setValue must be compatible with this type: one must be + * able to safely cast the value returned from getValue to + * the given type and pass any variable assignable to this type as an + * argument to setValue. + * + * @return type of the Property + */ + public final Class getType() { + return type; + } + + /** + * Tests if the object is in read-only mode. In read-only mode calls to + * setValue will throw ReadOnlyException and + * will not modify the value of the Property. + * + * @return true if the object is in read-only mode, + * false if it's not + */ + public boolean isReadOnly() { + return readOnly; + } + + /** + * Gets the value stored in the Property. The value is resolved by calling + * the specified getter method with the argument specified at instantiation. + * + * @return the value of the Property + */ + public Object getValue() { + try { + return getMethod.invoke(instance, getArgs); + } catch (Throwable e) { + throw new MethodProperty.MethodException(e); + } + } + + /** + * Returns the value of the MethodProperty in human readable + * textual format. The return value should be assignable to the + * setValue method if the Property is not in read-only mode. + * + * @return String representation of the value stored in the Property + */ + public String toString() { + Object value = getValue(); + if (value == null) { + return null; + } + return value.toString(); + } + + /** + *

+ * Sets the setter method and getter method argument lists. + *

+ * + * @param getArgs + * the fixed argument list to be passed to the getter method. + * @param setArgs + * the fixed argument list to be passed to the setter method. + * @param setArgumentIndex + * the index of the argument in setArgs to be + * replaced with newValue when + * {@link #setValue(Object newValue)} is called. + */ + public void setArguments(Object[] getArgs, Object[] setArgs, + int setArgumentIndex) { + this.getArgs = new Object[getArgs.length]; + for (int i = 0; i < getArgs.length; i++) { + this.getArgs[i] = getArgs[i]; + } + this.setArgs = new Object[setArgs.length]; + for (int i = 0; i < setArgs.length; i++) { + this.setArgs[i] = setArgs[i]; + } + this.setArgumentIndex = setArgumentIndex; + } + + /** + * Sets the value of the property. This method supports setting from + * Strings if either String is directly + * assignable to property type, or the type class contains a string + * constructor. + * + * @param newValue + * the New value of the property. + * @throws Property.ReadOnlyException if the object is in + * read-only mode. + * @throws Property.ConversionException if + * newValue can't be converted into the + * Property's native type directly or through + * String. + * @see #invokeSetMethod(Object) + */ + public void setValue(Object newValue) throws Property.ReadOnlyException, + Property.ConversionException { + + // Checks the mode + if (isReadOnly()) { + throw new Property.ReadOnlyException(); + } + + // Try to assign the compatible value directly + if (newValue == null || type.isAssignableFrom(newValue.getClass())) { + invokeSetMethod(newValue); + } else { + + Object value; + try { + + // Gets the string constructor + Constructor constr = getType().getConstructor( + new Class[] { String.class }); + + value = constr + .newInstance(new Object[] { newValue.toString() }); + + } catch (java.lang.Exception e) { + throw new Property.ConversionException(e); + } + + // Creates new object from the string + invokeSetMethod(value); + } + } + + /** + * Internal method to actually call the setter method of the wrapped + * property. + * + * @param value + */ + private void invokeSetMethod(Object value) { + + try { + // Construct a temporary argument array only if needed + if (setArgs.length == 1) { + setMethod.invoke(instance, new Object[] { value }); + } else { + + // Sets the value to argument array + Object[] args = new Object[setArgs.length]; + for (int i = 0; i < setArgs.length; i++) { + args[i] = (i == setArgumentIndex) ? value : setArgs[i]; + } + setMethod.invoke(instance, args); + } + } catch (InvocationTargetException e) { + Throwable targetException = e.getTargetException(); + throw new MethodProperty.MethodException(targetException); + } catch (Exception e) { + throw new MethodProperty.MethodException(e); + } + } + + /** + * Sets the Property's read-only mode to the specified status. + * + * @param newStatus + * the new read-only status of the Property. + */ + public void setReadOnly(boolean newStatus) { + boolean prevStatus = readOnly; + if (newStatus) { + readOnly = true; + } else { + readOnly = (setMethod == null); + } + if (prevStatus != readOnly) { + fireReadOnlyStatusChange(); + } + } + + /** + * Exception object that signals that there were problems + * calling or finding the specified getter or setter methods of the + * property. + * + * @author IT Mill Ltd. + * @version + * @VERSION@ + * @since 3.0 + */ + public class MethodException extends RuntimeException { + + /** + * Serial generated by eclipse. + */ + private static final long serialVersionUID = 3690473623827855153L; + + /** + * Cause of the method exception + */ + private Throwable cause; + + /** + * Constructs a new MethodException with the specified + * detail message. + * + * @param msg + * the detail message. + */ + public MethodException(String msg) { + super(msg); + } + + /** + * Constructs a new MethodException from another + * exception. + * + * @param cause + * the cause of the exception. + */ + public MethodException(Throwable cause) { + this.cause = cause; + } + + /** + * @see java.lang.Throwable#getCause() + */ + public Throwable getCause() { + return cause; + } + + /** + * Gets the method property this exception originates from. + */ + public MethodProperty getMethodProperty() { + return MethodProperty.this; + } + } + + /* Events *************************************************************** */ + + /** + * An Event object specifying the Property whose read-only + * status has been changed. + * + * @author IT Mill Ltd. + * @version + * @VERSION@ + * @since 3.0 + */ + private class ReadOnlyStatusChangeEvent extends java.util.EventObject + implements Property.ReadOnlyStatusChangeEvent { + + /** + * Serial generated by eclipse. + */ + private static final long serialVersionUID = 3258129163305955896L; + + /** + * Constructs a new read-only status change event for this object. + * + * @param source + * source object of the event. + */ + protected ReadOnlyStatusChangeEvent(MethodProperty source) { + super(source); + } + + /** + * Gets the Property whose read-only state has changed. + * + * @return source Property of the event. + */ + public Property getProperty() { + return (Property) getSource(); + } + + } + + /** + * Registers a new read-only status change listener for this Property. + * + * @param listener + * the new Listener to be registered. + */ + public void addListener(Property.ReadOnlyStatusChangeListener listener) { + if (readOnlyStatusChangeListeners == null) { + readOnlyStatusChangeListeners = new LinkedList(); + } + readOnlyStatusChangeListeners.add(listener); + } + + /** + * Removes a previously registered read-only status change listener. + * + * @param listener + * the listener to be removed. + */ + public void removeListener(Property.ReadOnlyStatusChangeListener listener) { + if (readOnlyStatusChangeListeners != null) { + readOnlyStatusChangeListeners.remove(listener); + } + } + + /** + * Sends a read only status change event to all registered listeners. + */ + private void fireReadOnlyStatusChange() { + if (readOnlyStatusChangeListeners != null) { + Object[] l = readOnlyStatusChangeListeners.toArray(); + Property.ReadOnlyStatusChangeEvent event = new MethodProperty.ReadOnlyStatusChangeEvent( + this); + for (int i = 0; i < l.length; i++) { + ((Property.ReadOnlyStatusChangeListener) l[i]) + .readOnlyStatusChange(event); + } + } + } } diff --git a/src/com/itmill/toolkit/data/util/ObjectProperty.java b/src/com/itmill/toolkit/data/util/ObjectProperty.java index 4f20dc230f..eddb870973 100644 --- a/src/com/itmill/toolkit/data/util/ObjectProperty.java +++ b/src/com/itmill/toolkit/data/util/ObjectProperty.java @@ -28,11 +28,11 @@ package com.itmill.toolkit.data.util; -import com.itmill.toolkit.data.Property; - import java.lang.reflect.Constructor; import java.util.LinkedList; +import com.itmill.toolkit.data.Property; + /** * A simple data object containing one typed value. This class is a * straightforward implementation of the the @@ -44,332 +44,339 @@ import java.util.LinkedList; * @since 3.0 */ public class ObjectProperty implements Property, Property.ValueChangeNotifier, - Property.ReadOnlyStatusChangeNotifier { - - /** - * A boolean value storing the Property's read-only status information. - */ - private boolean readOnly = false; - - /** - * The value contained by the Property. - */ - private Object value; - - /** - * Data type of the Property's value. - */ - private Class type; - - /** - * Internal list of registered value change listeners. - */ - private LinkedList valueChangeListeners = null; - - /** - * Internal list of registered read-only status change listeners. - */ - private LinkedList readOnlyStatusChangeListeners = null; - - /** - * Creates a new instance of ObjectProperty with the given value. The type - * of the property is automatically initialized to be the type of the given - * value. - * - * @param value - * the Initial value of the Property. - */ - public ObjectProperty(Object value) { - this(value, value.getClass()); - } - - /** - * Creates a new instance of ObjectProperty with the given value and type. - * - * @param value - * the Initial value of the Property. - * @param type - * the type of the value. The value must be assignable to given - * type. - */ - public ObjectProperty(Object value, Class type) { - - // Set the values - this.type = type; - setValue(value); - } - - /** - * Creates a new instance of ObjectProperty with the given value, type and - * read-only mode status. - * - * @param value - * the Initial value of the property. - * @param type - * the type of the value. value must be assignable - * to this type. - * @param readOnly - * Sets the read-only mode. - */ - public ObjectProperty(Object value, Class type, boolean readOnly) { - this(value, type); - setReadOnly(readOnly); - } - - /** - * Returns the type of the ObjectProperty. The methods getValue - * and setValue must be compatible with this type: one must - * be able to safely cast the value returned from getValue to - * the given type and pass any variable assignable to this type as an - * argument to setValue. - * - * @return type of the Property - */ - public final Class getType() { - return type; - } - - /** - * Gets the value stored in the Property. - * - * @return the value stored in the Property - */ - public Object getValue() { - return value; - } - - /** - * Returns the value of the ObjectProperty in human readable textual format. - * The return value should be assignable to the setValue - * method if the Property is not in read-only mode. - * - * @return String representation of the value stored in the - * ObjectProperty - */ - public String toString() { - Object value = getValue(); - if (value != null) - return value.toString(); - else - return null; - } - - /** - * Tests if the Property is in read-only mode. In read-only mode calls to - * the method setValue will throw - * ReadOnlyExceptions and will not modify the value of the - * Property. - * - * @return true if the Property is in read-only mode, - * false if it's not - */ - public boolean isReadOnly() { - return readOnly; - } - - /** - * Sets the Property's read-only mode to the specified status. - * - * @param newStatus - * the new read-only status of the Property. - */ - public void setReadOnly(boolean newStatus) { - if (newStatus != readOnly) { - readOnly = newStatus; - fireReadOnlyStatusChange(); - } - } - - /** - * Sets the value of the property. This method supports setting from - * String if either String is directly - * assignable to property type, or the type class contains a string - * constructor. - * - * @param newValue - * the New value of the property. - * @throws Property.ReadOnlyException if the object is in - * read-only mode - * @throws Property.ConversionException if the newValue can't be - * converted into the Property's native type directly or through - * String - */ - public void setValue(Object newValue) throws Property.ReadOnlyException, - Property.ConversionException { - - // Checks the mode - if (isReadOnly()) - throw new Property.ReadOnlyException(); - - // Tries to assign the compatible value directly - if (newValue == null || type.isAssignableFrom(newValue.getClass())) - value = newValue; - - // Otherwise try to convert the value trough string constructor - else - try { - - // Gets the string constructor - Constructor constr = getType().getConstructor( - new Class[] { String.class }); - - // Creates new object from the string - value = constr - .newInstance(new Object[] { newValue.toString() }); - - } catch (java.lang.Exception e) { - throw new Property.ConversionException(e); - } - - fireValueChange(); - } - - /* Events *************************************************************** */ - - /** - * An Event object specifying the ObjectProperty whose value - * has changed. - * - * @author IT Mill Ltd. - * @version - * @VERSION@ - * @since 3.0 - */ - private class ValueChangeEvent extends java.util.EventObject implements - Property.ValueChangeEvent { - - /** - * Serial generated by eclipse. - */ - private static final long serialVersionUID = 3256718468479725873L; - - /** - * Constructs a new value change event for this object. - * - * @param source - * the source object of the event. - */ - protected ValueChangeEvent(ObjectProperty source) { - super(source); - } - - /** - * Gets the Property whose read-only state has changed. - * - * @return source the Property of the event. - */ - public Property getProperty() { - return (Property) getSource(); - } - } - - /** - * An Event object specifying the Property whose read-only - * status has been changed. - * - * @author IT Mill Ltd. - * @version - * @VERSION@ - * @since 3.0 - */ - private class ReadOnlyStatusChangeEvent extends java.util.EventObject - implements Property.ReadOnlyStatusChangeEvent { - - /** - * Serial generated by eclipse. - */ - private static final long serialVersionUID = 3907208273529616696L; - - /** - * Constructs a new read-only status change event for this object. - * - * @param source - * source object of the event - */ - protected ReadOnlyStatusChangeEvent(ObjectProperty source) { - super(source); - } - - /** - * Gets the Property whose read-only state has changed. - * - * @return source Property of the event. - */ - public Property getProperty() { - return (Property) getSource(); - } - } - - /** - * Removes a previously registered value change listener. - * - * @param listener - * the listener to be removed. - */ - public void removeListener(Property.ValueChangeListener listener) { - if (valueChangeListeners != null) - valueChangeListeners.remove(listener); - } - - /** - * Registers a new value change listener for this ObjectProperty. - * - * @param listener - * the new Listener to be registered - */ - public void addListener(Property.ValueChangeListener listener) { - if (valueChangeListeners == null) - valueChangeListeners = new LinkedList(); - valueChangeListeners.add(listener); - } - - /** - * Registers a new read-only status change listener for this Property. - * - * @param listener - * the new Listener to be registered - */ - public void addListener(Property.ReadOnlyStatusChangeListener listener) { - if (readOnlyStatusChangeListeners == null) - readOnlyStatusChangeListeners = new LinkedList(); - readOnlyStatusChangeListeners.add(listener); - } - - /** - * Removes a previously registered read-only status change listener. - * - * @param listener - * the listener to be removed. - */ - public void removeListener(Property.ReadOnlyStatusChangeListener listener) { - if (readOnlyStatusChangeListeners != null) - readOnlyStatusChangeListeners.remove(listener); - } - - /** - * Sends a value change event to all registered listeners. - */ - private void fireValueChange() { - if (valueChangeListeners != null) { - Object[] l = valueChangeListeners.toArray(); - Property.ValueChangeEvent event = new ObjectProperty.ValueChangeEvent( - this); - for (int i = 0; i < l.length; i++) - ((Property.ValueChangeListener) l[i]).valueChange(event); - } - } - - /** - * Sends a read only status change event to all registered listeners. - */ - private void fireReadOnlyStatusChange() { - if (readOnlyStatusChangeListeners != null) { - Object[] l = readOnlyStatusChangeListeners.toArray(); - Property.ReadOnlyStatusChangeEvent event = new ObjectProperty.ReadOnlyStatusChangeEvent( - this); - for (int i = 0; i < l.length; i++) - ((Property.ReadOnlyStatusChangeListener) l[i]) - .readOnlyStatusChange(event); - } - } + Property.ReadOnlyStatusChangeNotifier { + + /** + * A boolean value storing the Property's read-only status information. + */ + private boolean readOnly = false; + + /** + * The value contained by the Property. + */ + private Object value; + + /** + * Data type of the Property's value. + */ + private Class type; + + /** + * Internal list of registered value change listeners. + */ + private LinkedList valueChangeListeners = null; + + /** + * Internal list of registered read-only status change listeners. + */ + private LinkedList readOnlyStatusChangeListeners = null; + + /** + * Creates a new instance of ObjectProperty with the given value. The type + * of the property is automatically initialized to be the type of the given + * value. + * + * @param value + * the Initial value of the Property. + */ + public ObjectProperty(Object value) { + this(value, value.getClass()); + } + + /** + * Creates a new instance of ObjectProperty with the given value and type. + * + * @param value + * the Initial value of the Property. + * @param type + * the type of the value. The value must be assignable to + * given type. + */ + public ObjectProperty(Object value, Class type) { + + // Set the values + this.type = type; + setValue(value); + } + + /** + * Creates a new instance of ObjectProperty with the given value, type and + * read-only mode status. + * + * @param value + * the Initial value of the property. + * @param type + * the type of the value. value must be + * assignable to this type. + * @param readOnly + * Sets the read-only mode. + */ + public ObjectProperty(Object value, Class type, boolean readOnly) { + this(value, type); + setReadOnly(readOnly); + } + + /** + * Returns the type of the ObjectProperty. The methods getValue + * and setValue must be compatible with this type: one must + * be able to safely cast the value returned from getValue to + * the given type and pass any variable assignable to this type as an + * argument to setValue. + * + * @return type of the Property + */ + public final Class getType() { + return type; + } + + /** + * Gets the value stored in the Property. + * + * @return the value stored in the Property + */ + public Object getValue() { + return value; + } + + /** + * Returns the value of the ObjectProperty in human readable textual format. + * The return value should be assignable to the setValue + * method if the Property is not in read-only mode. + * + * @return String representation of the value stored in the + * ObjectProperty + */ + public String toString() { + Object value = getValue(); + if (value != null) { + return value.toString(); + } else { + return null; + } + } + + /** + * Tests if the Property is in read-only mode. In read-only mode calls to + * the method setValue will throw + * ReadOnlyExceptions and will not modify the value of the + * Property. + * + * @return true if the Property is in read-only mode, + * false if it's not + */ + public boolean isReadOnly() { + return readOnly; + } + + /** + * Sets the Property's read-only mode to the specified status. + * + * @param newStatus + * the new read-only status of the Property. + */ + public void setReadOnly(boolean newStatus) { + if (newStatus != readOnly) { + readOnly = newStatus; + fireReadOnlyStatusChange(); + } + } + + /** + * Sets the value of the property. This method supports setting from + * String if either String is directly + * assignable to property type, or the type class contains a string + * constructor. + * + * @param newValue + * the New value of the property. + * @throws Property.ReadOnlyException if the object is in + * read-only mode + * @throws Property.ConversionException if the newValue + * can't be converted into the Property's native type + * directly or through String + */ + public void setValue(Object newValue) throws Property.ReadOnlyException, + Property.ConversionException { + + // Checks the mode + if (isReadOnly()) { + throw new Property.ReadOnlyException(); + } + + // Tries to assign the compatible value directly + if (newValue == null || type.isAssignableFrom(newValue.getClass())) { + value = newValue; + } else { + try { + + // Gets the string constructor + Constructor constr = getType().getConstructor( + new Class[] { String.class }); + + // Creates new object from the string + value = constr + .newInstance(new Object[] { newValue.toString() }); + + } catch (java.lang.Exception e) { + throw new Property.ConversionException(e); + } + } + + fireValueChange(); + } + + /* Events *************************************************************** */ + + /** + * An Event object specifying the ObjectProperty whose value + * has changed. + * + * @author IT Mill Ltd. + * @version + * @VERSION@ + * @since 3.0 + */ + private class ValueChangeEvent extends java.util.EventObject implements + Property.ValueChangeEvent { + + /** + * Serial generated by eclipse. + */ + private static final long serialVersionUID = 3256718468479725873L; + + /** + * Constructs a new value change event for this object. + * + * @param source + * the source object of the event. + */ + protected ValueChangeEvent(ObjectProperty source) { + super(source); + } + + /** + * Gets the Property whose read-only state has changed. + * + * @return source the Property of the event. + */ + public Property getProperty() { + return (Property) getSource(); + } + } + + /** + * An Event object specifying the Property whose read-only + * status has been changed. + * + * @author IT Mill Ltd. + * @version + * @VERSION@ + * @since 3.0 + */ + private class ReadOnlyStatusChangeEvent extends java.util.EventObject + implements Property.ReadOnlyStatusChangeEvent { + + /** + * Serial generated by eclipse. + */ + private static final long serialVersionUID = 3907208273529616696L; + + /** + * Constructs a new read-only status change event for this object. + * + * @param source + * source object of the event + */ + protected ReadOnlyStatusChangeEvent(ObjectProperty source) { + super(source); + } + + /** + * Gets the Property whose read-only state has changed. + * + * @return source Property of the event. + */ + public Property getProperty() { + return (Property) getSource(); + } + } + + /** + * Removes a previously registered value change listener. + * + * @param listener + * the listener to be removed. + */ + public void removeListener(Property.ValueChangeListener listener) { + if (valueChangeListeners != null) { + valueChangeListeners.remove(listener); + } + } + + /** + * Registers a new value change listener for this ObjectProperty. + * + * @param listener + * the new Listener to be registered + */ + public void addListener(Property.ValueChangeListener listener) { + if (valueChangeListeners == null) { + valueChangeListeners = new LinkedList(); + } + valueChangeListeners.add(listener); + } + + /** + * Registers a new read-only status change listener for this Property. + * + * @param listener + * the new Listener to be registered + */ + public void addListener(Property.ReadOnlyStatusChangeListener listener) { + if (readOnlyStatusChangeListeners == null) { + readOnlyStatusChangeListeners = new LinkedList(); + } + readOnlyStatusChangeListeners.add(listener); + } + + /** + * Removes a previously registered read-only status change listener. + * + * @param listener + * the listener to be removed. + */ + public void removeListener(Property.ReadOnlyStatusChangeListener listener) { + if (readOnlyStatusChangeListeners != null) { + readOnlyStatusChangeListeners.remove(listener); + } + } + + /** + * Sends a value change event to all registered listeners. + */ + private void fireValueChange() { + if (valueChangeListeners != null) { + Object[] l = valueChangeListeners.toArray(); + Property.ValueChangeEvent event = new ObjectProperty.ValueChangeEvent( + this); + for (int i = 0; i < l.length; i++) { + ((Property.ValueChangeListener) l[i]).valueChange(event); + } + } + } + + /** + * Sends a read only status change event to all registered listeners. + */ + private void fireReadOnlyStatusChange() { + if (readOnlyStatusChangeListeners != null) { + Object[] l = readOnlyStatusChangeListeners.toArray(); + Property.ReadOnlyStatusChangeEvent event = new ObjectProperty.ReadOnlyStatusChangeEvent( + this); + for (int i = 0; i < l.length; i++) { + ((Property.ReadOnlyStatusChangeListener) l[i]) + .readOnlyStatusChange(event); + } + } + } } diff --git a/src/com/itmill/toolkit/data/util/PropertysetItem.java b/src/com/itmill/toolkit/data/util/PropertysetItem.java index b8d299941e..355538326d 100644 --- a/src/com/itmill/toolkit/data/util/PropertysetItem.java +++ b/src/com/itmill/toolkit/data/util/PropertysetItem.java @@ -50,279 +50,291 @@ import com.itmill.toolkit.data.Property; * @since 3.0 */ public class PropertysetItem implements Item, Item.PropertySetChangeNotifier, - Cloneable { - - /* Private representation of the item *********************************** */ - - /** - * Mapping from property id to property. - */ - private HashMap map = new HashMap(); - - /** - * List of all property ids to maintain the order. - */ - private LinkedList list = new LinkedList(); - - /** - * List of property set modification listeners. - */ - private LinkedList propertySetChangeListeners = null; - - /* Item methods ******************************************************** */ - - /** - * Gets the Property corresponding to the given Property ID stored in the - * Item. If the Item does not contain the Property, null is - * returned. - * - * @param id - * the identifier of the Property to get. - * @return the Property with the given ID or null - */ - public Property getItemProperty(Object id) { - return (Property) map.get(id); - } - - /** - * Gets the collection of IDs of all Properties stored in the Item. - * - * @return unmodifiable collection containing IDs of the Properties stored - * the Item - */ - public Collection getItemPropertyIds() { - return Collections.unmodifiableCollection(list); - } - - /* Item.Managed methods ************************************************* */ - - /** - * Removes the Property identified by ID from the Item. This functionality - * is optional. If the method is not implemented, the method always returns - * false. - * - * @param id - * the ID of the Property to be removed. - * @return true if the operation succeeded false - * if not - */ - public boolean removeItemProperty(Object id) { - - // Cant remove missing properties - if (map.remove(id) == null) { - return false; - } - list.remove(id); - - // Send change events - fireItemPropertySetChange(); - - return true; - } - - /** - * Tries to add a new Property into the Item. - * - * @param id - * the ID of the new Property. - * @param property - * the Property to be added and associated with the id. - * @return true if the operation succeeded, - * false if not - */ - public boolean addItemProperty(Object id, Property property) { - - // Cant add a property twice - if (map.containsKey(id)) - return false; - - // Put the property to map - map.put(id, property); - list.add(id); - - // Send event - fireItemPropertySetChange(); - - return true; - } - - /** - * Gets the String representation of the contents of the - * Item. The format of the string is a space separated catenation of the - * String representations of the Properties contained by the - * Item. - * - * @return String representation of the Item contents - */ - public String toString() { - String retValue = ""; - - for (Iterator i = getItemPropertyIds().iterator(); i.hasNext();) { - Object propertyId = i.next(); - retValue += getItemProperty(propertyId).toString(); - if (i.hasNext()) - retValue += " "; - } - - return retValue; - } - - /* Notifiers ************************************************************ */ - - /** - * An event object specifying an Item whose Property set has - * changed. - * - * @author IT Mill Ltd. - * @version - * @VERSION@ - * @since 3.0 - */ - private class PropertySetChangeEvent extends EventObject implements - Item.PropertySetChangeEvent { - - /** - * Serial generated by eclipse. - */ - private static final long serialVersionUID = 3257562910590055991L; - - private PropertySetChangeEvent(Item source) { - super(source); - } - - /** - * Gets the Item whose Property set has changed. - * - * @return source object of the event as an Item - */ - public Item getItem() { - return (Item) getSource(); - } - } - - /** - * Registers a new property set change listener for this Item. - * - * @param listener - * the new Listener to be registered. - */ - public void addListener(Item.PropertySetChangeListener listener) { - if (propertySetChangeListeners == null) - propertySetChangeListeners = new LinkedList(); - propertySetChangeListeners.add(listener); - } - - /** - * Removes a previously registered property set change listener. - * - * @param listener - * the Listener to be removed. - */ - public void removeListener(Item.PropertySetChangeListener listener) { - if (propertySetChangeListeners != null) - propertySetChangeListeners.remove(listener); - } - - /** - * Sends a Property set change event to all interested listeners. - */ - private void fireItemPropertySetChange() { - if (propertySetChangeListeners != null) { - Object[] l = propertySetChangeListeners.toArray(); - Item.PropertySetChangeEvent event = new PropertysetItem.PropertySetChangeEvent( - this); - for (int i = 0; i < l.length; i++) - ((Item.PropertySetChangeListener) l[i]) - .itemPropertySetChange(event); - } - } - - /** - * Creates and returns a copy of this object. - *

- * The method clone performs a shallow copy of the - * PropertysetItem. - *

- *

- * Note : All arrays are considered to implement the interface Cloneable. - * Otherwise, this method creates a new instance of the class of this object - * and initializes all its fields with exactly the contents of the - * corresponding fields of this object, as if by assignment, the contents of - * the fields are not themselves cloned. Thus, this method performs a - * "shallow copy" of this object, not a "deep copy" operation. - *

- * - * @throws CloneNotSupportedException - * if the object's class does not support the Cloneable - * interface. - * - * @see java.lang.Object#clone() - */ - public Object clone() throws CloneNotSupportedException { - - PropertysetItem npsi = new PropertysetItem(); - - npsi.list = this.list != null ? (LinkedList) list.clone() : null; - npsi.propertySetChangeListeners = this.propertySetChangeListeners != null ? (LinkedList) propertySetChangeListeners - .clone() - : null; - npsi.map = (HashMap) this.map.clone(); - - return npsi; - } - - /** - * Returns true if and only if the argument is not - * null and is a Boolean object that represents the same - * boolean value as this object. - * - * @param obj - * the object to compare with. - * @return true if the Boolean objects represent the same - * value otherwise false. - * @see java.lang.Object#equals(java.lang.Object) - */ - public boolean equals(Object obj) { - - if (obj == null || !(obj instanceof PropertysetItem)) - return false; - - PropertysetItem other = (PropertysetItem) obj; - - if (other.list != this.list) { - if (other.list == null) - return false; - if (!other.list.equals(this.list)) - return false; - } - if (other.map != this.map) { - if (other.map == null) - return false; - if (!other.map.equals(this.map)) - return false; - } - if (other.propertySetChangeListeners != this.propertySetChangeListeners) { - if (other.propertySetChangeListeners == null) - return false; - if (!other.propertySetChangeListeners - .equals(this.propertySetChangeListeners)) - return false; - } - - return true; - } - - /** - * Returns the hash code value for this list. - * - * @return the hash code value. - * @see java.lang.Object#hashCode() - */ - public int hashCode() { - - return (list == null ? 0 : list.hashCode()) - ^ (map == null ? 0 : map.hashCode()) - ^ (propertySetChangeListeners == null ? 0 - : propertySetChangeListeners.hashCode()); - } + Cloneable { + + /* Private representation of the item *********************************** */ + + /** + * Mapping from property id to property. + */ + private HashMap map = new HashMap(); + + /** + * List of all property ids to maintain the order. + */ + private LinkedList list = new LinkedList(); + + /** + * List of property set modification listeners. + */ + private LinkedList propertySetChangeListeners = null; + + /* Item methods ******************************************************** */ + + /** + * Gets the Property corresponding to the given Property ID stored in the + * Item. If the Item does not contain the Property, null is + * returned. + * + * @param id + * the identifier of the Property to get. + * @return the Property with the given ID or null + */ + public Property getItemProperty(Object id) { + return (Property) map.get(id); + } + + /** + * Gets the collection of IDs of all Properties stored in the Item. + * + * @return unmodifiable collection containing IDs of the Properties stored + * the Item + */ + public Collection getItemPropertyIds() { + return Collections.unmodifiableCollection(list); + } + + /* Item.Managed methods ************************************************* */ + + /** + * Removes the Property identified by ID from the Item. This functionality + * is optional. If the method is not implemented, the method always returns + * false. + * + * @param id + * the ID of the Property to be removed. + * @return true if the operation succeeded false + * if not + */ + public boolean removeItemProperty(Object id) { + + // Cant remove missing properties + if (map.remove(id) == null) { + return false; + } + list.remove(id); + + // Send change events + fireItemPropertySetChange(); + + return true; + } + + /** + * Tries to add a new Property into the Item. + * + * @param id + * the ID of the new Property. + * @param property + * the Property to be added and associated with the id. + * @return true if the operation succeeded, + * false if not + */ + public boolean addItemProperty(Object id, Property property) { + + // Cant add a property twice + if (map.containsKey(id)) { + return false; + } + + // Put the property to map + map.put(id, property); + list.add(id); + + // Send event + fireItemPropertySetChange(); + + return true; + } + + /** + * Gets the String representation of the contents of the + * Item. The format of the string is a space separated catenation of the + * String representations of the Properties contained by the + * Item. + * + * @return String representation of the Item contents + */ + public String toString() { + String retValue = ""; + + for (Iterator i = getItemPropertyIds().iterator(); i.hasNext();) { + Object propertyId = i.next(); + retValue += getItemProperty(propertyId).toString(); + if (i.hasNext()) { + retValue += " "; + } + } + + return retValue; + } + + /* Notifiers ************************************************************ */ + + /** + * An event object specifying an Item whose Property set has + * changed. + * + * @author IT Mill Ltd. + * @version + * @VERSION@ + * @since 3.0 + */ + private class PropertySetChangeEvent extends EventObject implements + Item.PropertySetChangeEvent { + + /** + * Serial generated by eclipse. + */ + private static final long serialVersionUID = 3257562910590055991L; + + private PropertySetChangeEvent(Item source) { + super(source); + } + + /** + * Gets the Item whose Property set has changed. + * + * @return source object of the event as an Item + */ + public Item getItem() { + return (Item) getSource(); + } + } + + /** + * Registers a new property set change listener for this Item. + * + * @param listener + * the new Listener to be registered. + */ + public void addListener(Item.PropertySetChangeListener listener) { + if (propertySetChangeListeners == null) { + propertySetChangeListeners = new LinkedList(); + } + propertySetChangeListeners.add(listener); + } + + /** + * Removes a previously registered property set change listener. + * + * @param listener + * the Listener to be removed. + */ + public void removeListener(Item.PropertySetChangeListener listener) { + if (propertySetChangeListeners != null) { + propertySetChangeListeners.remove(listener); + } + } + + /** + * Sends a Property set change event to all interested listeners. + */ + private void fireItemPropertySetChange() { + if (propertySetChangeListeners != null) { + Object[] l = propertySetChangeListeners.toArray(); + Item.PropertySetChangeEvent event = new PropertysetItem.PropertySetChangeEvent( + this); + for (int i = 0; i < l.length; i++) { + ((Item.PropertySetChangeListener) l[i]) + .itemPropertySetChange(event); + } + } + } + + /** + * Creates and returns a copy of this object. + *

+ * The method clone performs a shallow copy of the + * PropertysetItem. + *

+ *

+ * Note : All arrays are considered to implement the interface Cloneable. + * Otherwise, this method creates a new instance of the class of this object + * and initializes all its fields with exactly the contents of the + * corresponding fields of this object, as if by assignment, the contents of + * the fields are not themselves cloned. Thus, this method performs a + * "shallow copy" of this object, not a "deep copy" operation. + *

+ * + * @throws CloneNotSupportedException + * if the object's class does not support the Cloneable + * interface. + * + * @see java.lang.Object#clone() + */ + public Object clone() throws CloneNotSupportedException { + + PropertysetItem npsi = new PropertysetItem(); + + npsi.list = list != null ? (LinkedList) list.clone() : null; + npsi.propertySetChangeListeners = propertySetChangeListeners != null ? (LinkedList) propertySetChangeListeners + .clone() + : null; + npsi.map = (HashMap) map.clone(); + + return npsi; + } + + /** + * Returns true if and only if the argument is not + * null and is a Boolean object that represents the same + * boolean value as this object. + * + * @param obj + * the object to compare with. + * @return true if the Boolean objects represent the same + * value otherwise false. + * @see java.lang.Object#equals(java.lang.Object) + */ + public boolean equals(Object obj) { + + if (obj == null || !(obj instanceof PropertysetItem)) { + return false; + } + + PropertysetItem other = (PropertysetItem) obj; + + if (other.list != list) { + if (other.list == null) { + return false; + } + if (!other.list.equals(list)) { + return false; + } + } + if (other.map != map) { + if (other.map == null) { + return false; + } + if (!other.map.equals(map)) { + return false; + } + } + if (other.propertySetChangeListeners != propertySetChangeListeners) { + if (other.propertySetChangeListeners == null) { + return false; + } + if (!other.propertySetChangeListeners + .equals(propertySetChangeListeners)) { + return false; + } + } + + return true; + } + + /** + * Returns the hash code value for this list. + * + * @return the hash code value. + * @see java.lang.Object#hashCode() + */ + public int hashCode() { + + return (list == null ? 0 : list.hashCode()) + ^ (map == null ? 0 : map.hashCode()) + ^ (propertySetChangeListeners == null ? 0 + : propertySetChangeListeners.hashCode()); + } } diff --git a/src/com/itmill/toolkit/data/util/QueryContainer.java b/src/com/itmill/toolkit/data/util/QueryContainer.java index 2593350bd9..a3ab78e5c0 100644 --- a/src/com/itmill/toolkit/data/util/QueryContainer.java +++ b/src/com/itmill/toolkit/data/util/QueryContainer.java @@ -37,10 +37,10 @@ import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.HashMap; + import com.itmill.toolkit.data.Container; import com.itmill.toolkit.data.Item; import com.itmill.toolkit.data.Property; -import com.itmill.toolkit.data.util.ObjectProperty; /** *

@@ -71,578 +71,593 @@ import com.itmill.toolkit.data.util.ObjectProperty; */ public class QueryContainer implements Container, Container.Ordered, - Container.Indexed { - - // default ResultSet type - public static final int DEFAULT_RESULTSET_TYPE = ResultSet.TYPE_SCROLL_INSENSITIVE; - - // default ResultSet concurrency - public static final int DEFAULT_RESULTSET_CONCURRENCY = ResultSet.CONCUR_READ_ONLY; - - private int resultSetType = DEFAULT_RESULTSET_TYPE; - - private int resultSetConcurrency = DEFAULT_RESULTSET_CONCURRENCY; - - private String queryStatement; - - private Connection connection; - - private ResultSet result; - - private Collection propertyIds; - - private HashMap propertyTypes = new HashMap(); - - private int size = -1; - - private Statement statement; - - /** - * Constructs new QueryContainer with the specified - * queryStatement. - * - * @param queryStatement - * Database query - * @param connection - * Connection object - * @param resultSetType - * @param resultSetConcurrency - * @throws SQLException - * when database operation fails - */ - public QueryContainer(String queryStatement, Connection connection, - int resultSetType, int resultSetConcurrency) throws SQLException { - this.queryStatement = queryStatement; - this.connection = connection; - this.resultSetType = resultSetType; - this.resultSetConcurrency = resultSetConcurrency; - init(); - } - - /** - * Constructs new QueryContainer with the specified - * queryStatement using the default resultset type and default resultset - * concurrency. - * - * @param queryStatement - * Database query - * @param connection - * Connection object - * @see QueryContainer#DEFAULT_RESULTSET_TYPE - * @see QueryContainer#DEFAULT_RESULTSET_CONCURRENCY - * @throws SQLException - * when database operation fails - */ - public QueryContainer(String queryStatement, Connection connection) - throws SQLException { - this(queryStatement, connection, DEFAULT_RESULTSET_TYPE, - DEFAULT_RESULTSET_CONCURRENCY); - } - - /** - * Fills the Container with the items and properties. Invoked by the - * constructor. - * - * @throws SQLException - * when parameter initialization fails. - * @see QueryContainer#QueryContainer(String, Connection, int, int). - */ - private void init() throws SQLException { - refresh(); - ResultSetMetaData metadata; - metadata = result.getMetaData(); - int count = metadata.getColumnCount(); - ArrayList list = new ArrayList(count); - for (int i = 1; i <= count; i++) { - String columnName = metadata.getColumnName(i); - list.add(columnName); - Property p = getContainerProperty(new Integer(1), columnName); - propertyTypes.put(columnName, p == null ? Object.class : p - .getType()); - } - propertyIds = Collections.unmodifiableCollection(list); - } - - /** - *

- * Restores items in the container. This method will update the latest data - * to the container. - *

- * Note: This method should be used to update the container with the latest - * items. - * - * @throws SQLException - * when database operation fails - * - */ - - public void refresh() throws SQLException { - close(); - statement = connection.createStatement(resultSetType, - resultSetConcurrency); - result = statement.executeQuery(queryStatement); - result.last(); - size = result.getRow(); - } - - /** - * Releases and nullifies the statement. - * - * @throws SQLException - * when database operation fails - */ - - public void close() throws SQLException { - if (statement != null) - statement.close(); - statement = null; - } - - /** - * Gets the Item with the given Item ID from the Container. - * - * @param id - * ID of the Item to retrieve - * @return Item Id. - */ - - public Item getItem(Object id) { - return new Row(id); - } - - /** - * Gets the collection of propertyId from the Container. - * - * @return Collection of Property ID. - */ - - public Collection getContainerPropertyIds() { - return propertyIds; - } - - /** - * Gets an collection of all the item IDs in the container. - * - * @return collection of Item IDs - */ - public Collection getItemIds() { - Collection c = new ArrayList(size); - for (int i = 1; i <= size; i++) - c.add(new Integer(i)); - return c; - } - - /** - * Gets the property identified by the given itemId and propertyId from the - * container. If the container does not contain the property - * null is returned. - * - * @param itemId - * ID of the Item which contains the Property - * @param propertyId - * ID of the Property to retrieve - * - * @return Property with the given ID if exists; null - * otherwise. - */ - - public synchronized Property getContainerProperty(Object itemId, - Object propertyId) { - if (!(itemId instanceof Integer && propertyId instanceof String)) - return null; - Object value; - try { - result.absolute(((Integer) itemId).intValue()); - value = result.getObject((String) propertyId); - } catch (Exception e) { - return null; - } - - // Handle also null values from the database - return new ObjectProperty(value != null ? value : new String("")); - } - - /** - * Gets the data type of all properties identified by the given type ID. - * - * @param id - * ID identifying the Properties - * - * @return data type of the Properties - */ - - public Class getType(Object id) { - return (Class) propertyTypes.get(id); - } - - /** - * Gets the number of items in the container. - * - * @return the number of items in the container. - */ - public int size() { - return size; - } - - /** - * Tests if the list contains the specified Item. - * - * @param id - * ID the of Item to be tested. - * @return true if given id is in the container; - * false otherwise. - */ - public boolean containsId(Object id) { - if (!(id instanceof Integer)) - return false; - int i = ((Integer) id).intValue(); - if (i < 1) - return false; - if (i > size) - return false; - return true; - } - - /** - * Creates new Item with the given ID into the Container. - * - * @param itemId - * ID of the Item to be created. - * - * @return Created new Item, or null if it fails. - * - * @throws UnsupportedOperationException - * if the addItem method is not supported. - */ - public Item addItem(Object itemId) throws UnsupportedOperationException { - throw new UnsupportedOperationException(); - } - - /** - * Creates a new Item into the Container, and assign it an ID. - * - * @return ID of the newly created Item, or null if it fails. - * @throws UnsupportedOperationException - * if the addItem method is not supported. - */ - public Object addItem() throws UnsupportedOperationException { - throw new UnsupportedOperationException(); - } - - /** - * Removes the Item identified by ItemId from the Container. - * - * @param itemId - * ID of the Item to remove. - * @return true if the operation succeeded; - * false otherwise. - * @throws UnsupportedOperationException - * if the removeItem method is not supported. - */ - public boolean removeItem(Object itemId) - throws UnsupportedOperationException { - throw new UnsupportedOperationException(); - } - - /** - * Adds new Property to all Items in the Container. - * - * @param propertyId - * ID of the Property - * @param type - * Data type of the new Property - * @param defaultValue - * The value all created Properties are initialized to. - * @return true if the operation succeeded; - * false otherwise. - * @throws UnsupportedOperationException - * if the addContainerProperty method is not supported. - */ - public boolean addContainerProperty(Object propertyId, Class type, - Object defaultValue) throws UnsupportedOperationException { - throw new UnsupportedOperationException(); - } - - /** - * Removes a Property specified by the given Property ID from the Container. - * - * @param propertyId - * ID of the Property to remove - * @return true if the operation succeeded; - * false otherwise. - * @throws UnsupportedOperationException - * if the removeContainerProperty method is not supported. - */ - public boolean removeContainerProperty(Object propertyId) - throws UnsupportedOperationException { - throw new UnsupportedOperationException(); - } - - /** - * Removes all Items from the Container. - * - * @return true if the operation succeeded; - * false otherwise. - * @throws UnsupportedOperationException - * if the removeAllItems method is not supported. - */ - public boolean removeAllItems() throws UnsupportedOperationException { - throw new UnsupportedOperationException(); - } - - /** - * Adds new item after the given item. - * - * @param previousItemId - * Id of the previous item in ordered container. - * @param newItemId - * Id of the new item to be added. - * @return Returns new item or null if the operation fails. - * @throws UnsupportedOperationException - * if the addItemAfter method is not supported. - */ - public Item addItemAfter(Object previousItemId, Object newItemId) - throws UnsupportedOperationException { - throw new UnsupportedOperationException(); - } - - /** - * Adds new item after the given item. - * - * @param previousItemId - * Id of the previous item in ordered container. - * @return Returns item id created new item or null if the - * operation fails. - * @throws UnsupportedOperationException - * if the addItemAfter method is not supported. - */ - public Object addItemAfter(Object previousItemId) - throws UnsupportedOperationException { - throw new UnsupportedOperationException(); - } - - /** - * Returns id of first item in the Container. - * - * @return ID of the first Item in the list. - */ - public Object firstItemId() { - if (size < 1) - return null; - return new Integer(1); - } - - /** - * Returns true if given id is first id at first index. - * - * @param id - * ID of an Item in the Container. - */ - public boolean isFirstId(Object id) { - return size > 0 && (id instanceof Integer) - && ((Integer) id).intValue() == 1; - } - - /** - * Returns true if given id is last id at last index. - * - * @param id - * ID of an Item in the Container - * - */ - public boolean isLastId(Object id) { - return size > 0 && (id instanceof Integer) - && ((Integer) id).intValue() == size; - } - - /** - * Returns id of last item in the Container. - * - * @return ID of the last Item. - */ - public Object lastItemId() { - if (size < 1) - return null; - return new Integer(size); - } - - /** - * Returns id of next item in container at next index. - * - * @param id - * ID of an Item in the Container. - * @return ID of the next Item or null. - */ - public Object nextItemId(Object id) { - if (size < 1 || !(id instanceof Integer)) - return null; - int i = ((Integer) id).intValue(); - if (i >= size) - return null; - return new Integer(i + 1); - } - - /** - * Returns id of previous item in container at previous index. - * - * @param id - * ID of an Item in the Container. - * @return ID of the previous Item or null. - */ - public Object prevItemId(Object id) { - if (size < 1 || !(id instanceof Integer)) - return null; - int i = ((Integer) id).intValue(); - if (i <= 1) - return null; - return new Integer(i - 1); - } - - /** - * The Row class implements methods of Item. - * - * @author IT Mill Ltd. - * @version - * @since 4.0 - */ - class Row implements Item { - - Object id; - - private Row(Object rowId) { - id = rowId; - } - - /** - * Adds the item property. - * - * @param id - * ID of the new Property. - * @param property - * Property to be added and associated with ID. - * @return true if the operation succeeded; - * false otherwise. - * @throws UnsupportedOperationException - * if the addItemProperty method is not supported. - */ - public boolean addItemProperty(Object id, Property property) - throws UnsupportedOperationException { - throw new UnsupportedOperationException(); - } - - /** - * Gets the property corresponding to the given property ID stored in - * the Item. - * - * @param propertyId - * identifier of the Property to get - * @return the Property with the given ID or null - */ - public Property getItemProperty(Object propertyId) { - return getContainerProperty(id, propertyId); - } - - /** - * Gets the collection of property IDs stored in the Item. - * - * @return unmodifiable collection containing IDs of the Properties - * stored the Item. - */ - public Collection getItemPropertyIds() { - return propertyIds; - } - - /** - * Removes given item property. - * - * @param id - * ID of the Property to be removed. - * @return true if the item property is removed; - * false otherwise. - * @throws UnsupportedOperationException - * if the removeItemProperty is not supported. - */ - public boolean removeItemProperty(Object id) - throws UnsupportedOperationException { - throw new UnsupportedOperationException(); - } - - } - - /** - * Closes the statement. - * - * @see #close() - */ - public void finalize() { - try { - close(); - } catch (SQLException ignored) { - - } - } - - /** - * Adds the given item at the position of given index. - * - * @param index - * Index to add the new item. - * @param newItemId - * Id of the new item to be added. - * @return new item or null if the operation fails. - * @throws UnsupportedOperationException - * if the addItemAt is not supported. - */ - public Item addItemAt(int index, Object newItemId) - throws UnsupportedOperationException { - throw new UnsupportedOperationException(); - } - - /** - * Adds item at the position of provided index in the container. - * - * @param index - * Index to add the new item. - * @return item id created new item or null if the operation - * fails. - * - * @throws UnsupportedOperationException - * if the addItemAt is not supported. - */ - - public Object addItemAt(int index) throws UnsupportedOperationException { - throw new UnsupportedOperationException(); - } - - /** - * Gets the Index id in the container. - * - * @param index - * Index Id. - * @return ID in the given index. - */ - public Object getIdByIndex(int index) { - if (size < 1 || index < 0 || index >= size) - return null; - return new Integer(index + 1); - } - - /** - * Gets the index of the Item corresponding to id in the container. - * - * @param id - * ID of an Item in the Container - * @return index of the Item, or -1 if the Container does not include the - * Item - */ - - public int indexOfId(Object id) { - if (size < 1 || !(id instanceof Integer)) - return -1; - int i = ((Integer) id).intValue(); - if (i >= size || i < 1) - return -1; - return i - 1; - } + Container.Indexed { + + // default ResultSet type + public static final int DEFAULT_RESULTSET_TYPE = ResultSet.TYPE_SCROLL_INSENSITIVE; + + // default ResultSet concurrency + public static final int DEFAULT_RESULTSET_CONCURRENCY = ResultSet.CONCUR_READ_ONLY; + + private int resultSetType = DEFAULT_RESULTSET_TYPE; + + private int resultSetConcurrency = DEFAULT_RESULTSET_CONCURRENCY; + + private String queryStatement; + + private Connection connection; + + private ResultSet result; + + private Collection propertyIds; + + private HashMap propertyTypes = new HashMap(); + + private int size = -1; + + private Statement statement; + + /** + * Constructs new QueryContainer with the specified + * queryStatement. + * + * @param queryStatement + * Database query + * @param connection + * Connection object + * @param resultSetType + * @param resultSetConcurrency + * @throws SQLException + * when database operation fails + */ + public QueryContainer(String queryStatement, Connection connection, + int resultSetType, int resultSetConcurrency) throws SQLException { + this.queryStatement = queryStatement; + this.connection = connection; + this.resultSetType = resultSetType; + this.resultSetConcurrency = resultSetConcurrency; + init(); + } + + /** + * Constructs new QueryContainer with the specified + * queryStatement using the default resultset type and default resultset + * concurrency. + * + * @param queryStatement + * Database query + * @param connection + * Connection object + * @see QueryContainer#DEFAULT_RESULTSET_TYPE + * @see QueryContainer#DEFAULT_RESULTSET_CONCURRENCY + * @throws SQLException + * when database operation fails + */ + public QueryContainer(String queryStatement, Connection connection) + throws SQLException { + this(queryStatement, connection, DEFAULT_RESULTSET_TYPE, + DEFAULT_RESULTSET_CONCURRENCY); + } + + /** + * Fills the Container with the items and properties. Invoked by the + * constructor. + * + * @throws SQLException + * when parameter initialization fails. + * @see QueryContainer#QueryContainer(String, Connection, int, int). + */ + private void init() throws SQLException { + refresh(); + ResultSetMetaData metadata; + metadata = result.getMetaData(); + int count = metadata.getColumnCount(); + ArrayList list = new ArrayList(count); + for (int i = 1; i <= count; i++) { + String columnName = metadata.getColumnName(i); + list.add(columnName); + Property p = getContainerProperty(new Integer(1), columnName); + propertyTypes.put(columnName, p == null ? Object.class : p + .getType()); + } + propertyIds = Collections.unmodifiableCollection(list); + } + + /** + *

+ * Restores items in the container. This method will update the latest data + * to the container. + *

+ * Note: This method should be used to update the container with the latest + * items. + * + * @throws SQLException + * when database operation fails + * + */ + + public void refresh() throws SQLException { + close(); + statement = connection.createStatement(resultSetType, + resultSetConcurrency); + result = statement.executeQuery(queryStatement); + result.last(); + size = result.getRow(); + } + + /** + * Releases and nullifies the statement. + * + * @throws SQLException + * when database operation fails + */ + + public void close() throws SQLException { + if (statement != null) { + statement.close(); + } + statement = null; + } + + /** + * Gets the Item with the given Item ID from the Container. + * + * @param id + * ID of the Item to retrieve + * @return Item Id. + */ + + public Item getItem(Object id) { + return new Row(id); + } + + /** + * Gets the collection of propertyId from the Container. + * + * @return Collection of Property ID. + */ + + public Collection getContainerPropertyIds() { + return propertyIds; + } + + /** + * Gets an collection of all the item IDs in the container. + * + * @return collection of Item IDs + */ + public Collection getItemIds() { + Collection c = new ArrayList(size); + for (int i = 1; i <= size; i++) { + c.add(new Integer(i)); + } + return c; + } + + /** + * Gets the property identified by the given itemId and propertyId from the + * container. If the container does not contain the property + * null is returned. + * + * @param itemId + * ID of the Item which contains the Property + * @param propertyId + * ID of the Property to retrieve + * + * @return Property with the given ID if exists; null + * otherwise. + */ + + public synchronized Property getContainerProperty(Object itemId, + Object propertyId) { + if (!(itemId instanceof Integer && propertyId instanceof String)) { + return null; + } + Object value; + try { + result.absolute(((Integer) itemId).intValue()); + value = result.getObject((String) propertyId); + } catch (Exception e) { + return null; + } + + // Handle also null values from the database + return new ObjectProperty(value != null ? value : new String("")); + } + + /** + * Gets the data type of all properties identified by the given type ID. + * + * @param id + * ID identifying the Properties + * + * @return data type of the Properties + */ + + public Class getType(Object id) { + return (Class) propertyTypes.get(id); + } + + /** + * Gets the number of items in the container. + * + * @return the number of items in the container. + */ + public int size() { + return size; + } + + /** + * Tests if the list contains the specified Item. + * + * @param id + * ID the of Item to be tested. + * @return true if given id is in the container; + * false otherwise. + */ + public boolean containsId(Object id) { + if (!(id instanceof Integer)) { + return false; + } + int i = ((Integer) id).intValue(); + if (i < 1) { + return false; + } + if (i > size) { + return false; + } + return true; + } + + /** + * Creates new Item with the given ID into the Container. + * + * @param itemId + * ID of the Item to be created. + * + * @return Created new Item, or null if it fails. + * + * @throws UnsupportedOperationException + * if the addItem method is not supported. + */ + public Item addItem(Object itemId) throws UnsupportedOperationException { + throw new UnsupportedOperationException(); + } + + /** + * Creates a new Item into the Container, and assign it an ID. + * + * @return ID of the newly created Item, or null if it fails. + * @throws UnsupportedOperationException + * if the addItem method is not supported. + */ + public Object addItem() throws UnsupportedOperationException { + throw new UnsupportedOperationException(); + } + + /** + * Removes the Item identified by ItemId from the Container. + * + * @param itemId + * ID of the Item to remove. + * @return true if the operation succeeded; + * false otherwise. + * @throws UnsupportedOperationException + * if the removeItem method is not supported. + */ + public boolean removeItem(Object itemId) + throws UnsupportedOperationException { + throw new UnsupportedOperationException(); + } + + /** + * Adds new Property to all Items in the Container. + * + * @param propertyId + * ID of the Property + * @param type + * Data type of the new Property + * @param defaultValue + * The value all created Properties are initialized to. + * @return true if the operation succeeded; + * false otherwise. + * @throws UnsupportedOperationException + * if the addContainerProperty method is not supported. + */ + public boolean addContainerProperty(Object propertyId, Class type, + Object defaultValue) throws UnsupportedOperationException { + throw new UnsupportedOperationException(); + } + + /** + * Removes a Property specified by the given Property ID from the Container. + * + * @param propertyId + * ID of the Property to remove + * @return true if the operation succeeded; + * false otherwise. + * @throws UnsupportedOperationException + * if the removeContainerProperty method is not supported. + */ + public boolean removeContainerProperty(Object propertyId) + throws UnsupportedOperationException { + throw new UnsupportedOperationException(); + } + + /** + * Removes all Items from the Container. + * + * @return true if the operation succeeded; + * false otherwise. + * @throws UnsupportedOperationException + * if the removeAllItems method is not supported. + */ + public boolean removeAllItems() throws UnsupportedOperationException { + throw new UnsupportedOperationException(); + } + + /** + * Adds new item after the given item. + * + * @param previousItemId + * Id of the previous item in ordered container. + * @param newItemId + * Id of the new item to be added. + * @return Returns new item or null if the operation fails. + * @throws UnsupportedOperationException + * if the addItemAfter method is not supported. + */ + public Item addItemAfter(Object previousItemId, Object newItemId) + throws UnsupportedOperationException { + throw new UnsupportedOperationException(); + } + + /** + * Adds new item after the given item. + * + * @param previousItemId + * Id of the previous item in ordered container. + * @return Returns item id created new item or null if the + * operation fails. + * @throws UnsupportedOperationException + * if the addItemAfter method is not supported. + */ + public Object addItemAfter(Object previousItemId) + throws UnsupportedOperationException { + throw new UnsupportedOperationException(); + } + + /** + * Returns id of first item in the Container. + * + * @return ID of the first Item in the list. + */ + public Object firstItemId() { + if (size < 1) { + return null; + } + return new Integer(1); + } + + /** + * Returns true if given id is first id at first index. + * + * @param id + * ID of an Item in the Container. + */ + public boolean isFirstId(Object id) { + return size > 0 && (id instanceof Integer) + && ((Integer) id).intValue() == 1; + } + + /** + * Returns true if given id is last id at last index. + * + * @param id + * ID of an Item in the Container + * + */ + public boolean isLastId(Object id) { + return size > 0 && (id instanceof Integer) + && ((Integer) id).intValue() == size; + } + + /** + * Returns id of last item in the Container. + * + * @return ID of the last Item. + */ + public Object lastItemId() { + if (size < 1) { + return null; + } + return new Integer(size); + } + + /** + * Returns id of next item in container at next index. + * + * @param id + * ID of an Item in the Container. + * @return ID of the next Item or null. + */ + public Object nextItemId(Object id) { + if (size < 1 || !(id instanceof Integer)) { + return null; + } + int i = ((Integer) id).intValue(); + if (i >= size) { + return null; + } + return new Integer(i + 1); + } + + /** + * Returns id of previous item in container at previous index. + * + * @param id + * ID of an Item in the Container. + * @return ID of the previous Item or null. + */ + public Object prevItemId(Object id) { + if (size < 1 || !(id instanceof Integer)) { + return null; + } + int i = ((Integer) id).intValue(); + if (i <= 1) { + return null; + } + return new Integer(i - 1); + } + + /** + * The Row class implements methods of Item. + * + * @author IT Mill Ltd. + * @version + * @since 4.0 + */ + class Row implements Item { + + Object id; + + private Row(Object rowId) { + id = rowId; + } + + /** + * Adds the item property. + * + * @param id + * ID of the new Property. + * @param property + * Property to be added and associated with ID. + * @return true if the operation succeeded; + * false otherwise. + * @throws UnsupportedOperationException + * if the addItemProperty method is not supported. + */ + public boolean addItemProperty(Object id, Property property) + throws UnsupportedOperationException { + throw new UnsupportedOperationException(); + } + + /** + * Gets the property corresponding to the given property ID stored in + * the Item. + * + * @param propertyId + * identifier of the Property to get + * @return the Property with the given ID or null + */ + public Property getItemProperty(Object propertyId) { + return getContainerProperty(id, propertyId); + } + + /** + * Gets the collection of property IDs stored in the Item. + * + * @return unmodifiable collection containing IDs of the Properties + * stored the Item. + */ + public Collection getItemPropertyIds() { + return propertyIds; + } + + /** + * Removes given item property. + * + * @param id + * ID of the Property to be removed. + * @return true if the item property is removed; + * false otherwise. + * @throws UnsupportedOperationException + * if the removeItemProperty is not supported. + */ + public boolean removeItemProperty(Object id) + throws UnsupportedOperationException { + throw new UnsupportedOperationException(); + } + + } + + /** + * Closes the statement. + * + * @see #close() + */ + public void finalize() { + try { + close(); + } catch (SQLException ignored) { + + } + } + + /** + * Adds the given item at the position of given index. + * + * @param index + * Index to add the new item. + * @param newItemId + * Id of the new item to be added. + * @return new item or null if the operation fails. + * @throws UnsupportedOperationException + * if the addItemAt is not supported. + */ + public Item addItemAt(int index, Object newItemId) + throws UnsupportedOperationException { + throw new UnsupportedOperationException(); + } + + /** + * Adds item at the position of provided index in the container. + * + * @param index + * Index to add the new item. + * @return item id created new item or null if the operation + * fails. + * + * @throws UnsupportedOperationException + * if the addItemAt is not supported. + */ + + public Object addItemAt(int index) throws UnsupportedOperationException { + throw new UnsupportedOperationException(); + } + + /** + * Gets the Index id in the container. + * + * @param index + * Index Id. + * @return ID in the given index. + */ + public Object getIdByIndex(int index) { + if (size < 1 || index < 0 || index >= size) { + return null; + } + return new Integer(index + 1); + } + + /** + * Gets the index of the Item corresponding to id in the container. + * + * @param id + * ID of an Item in the Container + * @return index of the Item, or -1 if the Container does not include the + * Item + */ + + public int indexOfId(Object id) { + if (size < 1 || !(id instanceof Integer)) { + return -1; + } + int i = ((Integer) id).intValue(); + if (i >= size || i < 1) { + return -1; + } + return i - 1; + } } diff --git a/src/com/itmill/toolkit/data/validator/CompositeValidator.java b/src/com/itmill/toolkit/data/validator/CompositeValidator.java index 1a5839455e..3abe1d40d9 100644 --- a/src/com/itmill/toolkit/data/validator/CompositeValidator.java +++ b/src/com/itmill/toolkit/data/validator/CompositeValidator.java @@ -33,7 +33,7 @@ import java.util.HashSet; import java.util.Iterator; import java.util.LinkedList; -import com.itmill.toolkit.data.*; +import com.itmill.toolkit.data.Validator; /** * The CompositeValidator allows you to chain (compose) many @@ -49,247 +49,260 @@ import com.itmill.toolkit.data.*; */ public class CompositeValidator implements Validator { - /** - * The validators are combined with AND clause: validity of - * the composite implies validity of the all validators it is composed of - * must be valid. - */ - public static final int MODE_AND = 0; - - /** - * The validators are combined with OR clause: validity of - * the composite implies that some of validators it is composed of must be - * valid. - */ - public static final int MODE_OR = 1; - - /** - * The validators are combined with and clause: validity of the composite - * implies validity of the all validators it is composed of - */ - public static final int MODE_DEFAULT = MODE_AND; - - /** - * Operation mode. - */ - private int mode = MODE_DEFAULT; - - /** - * List of contained validators. - */ - private LinkedList validators = new LinkedList(); - - /** - * Error message. - */ - private String errorMessage; - - /** - * Construct a composite validator in AND mode without error - * message. - */ - public CompositeValidator() { - } - - /** - * Constructs a composite validator in given mode. - */ - public CompositeValidator(int mode, String errorMessage) { - setMode(mode); - setErrorMessage(errorMessage); - } - - /** - * Validates the given value. - *

- * The value is valid, if: - *

    - *
  • MODE_AND: All of the sub-validators are valid - *
  • MODE_OR: Any of the sub-validators are valid - *
- * - * If the value is invalid, validation error is thrown. If the error message - * is set (non-null), it is used. If the error message has not been set, the - * first error occurred is thrown. - *

- * - * @param value - * the value to check. - * @throws Validator.InvalidValueException - * if the value is not valid. - */ - public void validate(Object value) throws Validator.InvalidValueException { - switch (mode) { - case MODE_AND: - for (Iterator i = validators.iterator(); i.hasNext();) - ((Validator) i.next()).validate(value); - return; - - case MODE_OR: - Validator.InvalidValueException first = null; - for (Iterator i = validators.iterator(); i.hasNext();) - try { - ((Validator) i.next()).validate(value); - return; - } catch (Validator.InvalidValueException e) { - if (first == null) - first = e; - } - if (first == null) - return; - String em = getErrorMessage(); - if (em != null) - throw new Validator.InvalidValueException(em); - else - throw first; - } - throw new IllegalStateException( - "The validator is in unsupported operation mode"); - } - - /** - * Checks the validity of the the given value. The value is valid, if: - *
    - *
  • MODE_AND: All of the sub-validators are valid - *
  • MODE_OR: Any of the sub-validators are valid - *
- * - * @param value - * the value to check. - */ - public boolean isValid(Object value) { - switch (mode) { - case MODE_AND: - for (Iterator i = validators.iterator(); i.hasNext();) { - Validator v = (Validator) i.next(); - if (!v.isValid(value)) - return false; - } - return true; - - case MODE_OR: - for (Iterator i = validators.iterator(); i.hasNext();) { - Validator v = (Validator) i.next(); - if (v.isValid(value)) - return true; - } - return false; - } - throw new IllegalStateException( - "The valitor is in unsupported operation mode"); - } - - /** - * Gets the mode of the validator. - * - * @return Operation mode of the validator: MODE_AND or - * MODE_OR. - */ - public final int getMode() { - return mode; - } - - /** - * Sets the mode of the validator. The valid modes are: - *
    - *
  • MODE_AND (default) - *
  • MODE_OR - *
- * - * @param mode - * the mode to set. - */ - public void setMode(int mode) { - if (mode != MODE_AND && mode != MODE_OR) - throw new IllegalArgumentException("Mode " + mode + " unsupported"); - this.mode = mode; - } - - /** - * Gets the error message for the composite validator. If the error message - * is null, original error messages of the sub-validators are used instead. - */ - public String getErrorMessage() { - if (this.errorMessage != null) - return this.errorMessage; - - // TODO Return composite error message - - return null; - } - - /** - * Sets the error message for the composite validator. If the error message - * is null, original error messages of the sub-validators are used instead. - * - * @param errorMessage - * the Error Message to set. - */ - public void setErrorMessage(String errorMessage) { - this.errorMessage = errorMessage; - } - - /** - * Adds validator to the interface. - * - * @param validator - * the Validator object which performs validation checks on this - * set of data field values. - */ - public void addValidator(Validator validator) { - if (validator == null) - return; - validators.add(validator); - } - - /** - * Removes a validator from the composite. - * - * @param validator - * the Validator object which performs validation checks on this - * set of data field values. - */ - public void removeValidator(Validator validator) { - validators.remove(validator); - } - - /** - * Gets sub-validators by class. - * - *

- * If the component contains directly or recursively (it contains another - * composite containing the validator) validators compatible with given type - * they are returned. This only applies to AND mode composite - * validators. - *

- * - *

- * If the validator is in OR mode or does not contain any - * validators of given type null is returned. - *

- * - * @return Collection of validators compatible with given type that must - * apply or null if none fould. - */ - public Collection getSubValidators(Class validatorType) { - if (mode != MODE_AND) - return null; - - HashSet found = new HashSet(); - for (Iterator i = validators.iterator(); i.hasNext();) { - Validator v = (Validator) i.next(); - if (validatorType.isAssignableFrom(v.getClass())) - found.add(v); - if (v instanceof CompositeValidator - && ((CompositeValidator) v).getMode() == MODE_AND) { - Collection c = ((CompositeValidator) v) - .getSubValidators(validatorType); - if (c != null) - found.addAll(c); - } - } - - return found.isEmpty() ? null : found; - } + /** + * The validators are combined with AND clause: validity of + * the composite implies validity of the all validators it is composed of + * must be valid. + */ + public static final int MODE_AND = 0; + + /** + * The validators are combined with OR clause: validity of + * the composite implies that some of validators it is composed of must be + * valid. + */ + public static final int MODE_OR = 1; + + /** + * The validators are combined with and clause: validity of the composite + * implies validity of the all validators it is composed of + */ + public static final int MODE_DEFAULT = MODE_AND; + + /** + * Operation mode. + */ + private int mode = MODE_DEFAULT; + + /** + * List of contained validators. + */ + private LinkedList validators = new LinkedList(); + + /** + * Error message. + */ + private String errorMessage; + + /** + * Construct a composite validator in AND mode without error + * message. + */ + public CompositeValidator() { + } + + /** + * Constructs a composite validator in given mode. + */ + public CompositeValidator(int mode, String errorMessage) { + setMode(mode); + setErrorMessage(errorMessage); + } + + /** + * Validates the given value. + *

+ * The value is valid, if: + *

    + *
  • MODE_AND: All of the sub-validators are valid + *
  • MODE_OR: Any of the sub-validators are valid + *
+ * + * If the value is invalid, validation error is thrown. If the error message + * is set (non-null), it is used. If the error message has not been set, the + * first error occurred is thrown. + *

+ * + * @param value + * the value to check. + * @throws Validator.InvalidValueException + * if the value is not valid. + */ + public void validate(Object value) throws Validator.InvalidValueException { + switch (mode) { + case MODE_AND: + for (Iterator i = validators.iterator(); i.hasNext();) { + ((Validator) i.next()).validate(value); + } + return; + + case MODE_OR: + Validator.InvalidValueException first = null; + for (Iterator i = validators.iterator(); i.hasNext();) { + try { + ((Validator) i.next()).validate(value); + return; + } catch (Validator.InvalidValueException e) { + if (first == null) { + first = e; + } + } + } + if (first == null) { + return; + } + String em = getErrorMessage(); + if (em != null) { + throw new Validator.InvalidValueException(em); + } else { + throw first; + } + } + throw new IllegalStateException( + "The validator is in unsupported operation mode"); + } + + /** + * Checks the validity of the the given value. The value is valid, if: + *
    + *
  • MODE_AND: All of the sub-validators are valid + *
  • MODE_OR: Any of the sub-validators are valid + *
+ * + * @param value + * the value to check. + */ + public boolean isValid(Object value) { + switch (mode) { + case MODE_AND: + for (Iterator i = validators.iterator(); i.hasNext();) { + Validator v = (Validator) i.next(); + if (!v.isValid(value)) { + return false; + } + } + return true; + + case MODE_OR: + for (Iterator i = validators.iterator(); i.hasNext();) { + Validator v = (Validator) i.next(); + if (v.isValid(value)) { + return true; + } + } + return false; + } + throw new IllegalStateException( + "The valitor is in unsupported operation mode"); + } + + /** + * Gets the mode of the validator. + * + * @return Operation mode of the validator: MODE_AND or + * MODE_OR. + */ + public final int getMode() { + return mode; + } + + /** + * Sets the mode of the validator. The valid modes are: + *
    + *
  • MODE_AND (default) + *
  • MODE_OR + *
+ * + * @param mode + * the mode to set. + */ + public void setMode(int mode) { + if (mode != MODE_AND && mode != MODE_OR) { + throw new IllegalArgumentException("Mode " + mode + " unsupported"); + } + this.mode = mode; + } + + /** + * Gets the error message for the composite validator. If the error message + * is null, original error messages of the sub-validators are used instead. + */ + public String getErrorMessage() { + if (errorMessage != null) { + return errorMessage; + } + + // TODO Return composite error message + + return null; + } + + /** + * Sets the error message for the composite validator. If the error message + * is null, original error messages of the sub-validators are used instead. + * + * @param errorMessage + * the Error Message to set. + */ + public void setErrorMessage(String errorMessage) { + this.errorMessage = errorMessage; + } + + /** + * Adds validator to the interface. + * + * @param validator + * the Validator object which performs validation checks on + * this set of data field values. + */ + public void addValidator(Validator validator) { + if (validator == null) { + return; + } + validators.add(validator); + } + + /** + * Removes a validator from the composite. + * + * @param validator + * the Validator object which performs validation checks on + * this set of data field values. + */ + public void removeValidator(Validator validator) { + validators.remove(validator); + } + + /** + * Gets sub-validators by class. + * + *

+ * If the component contains directly or recursively (it contains another + * composite containing the validator) validators compatible with given type + * they are returned. This only applies to AND mode composite + * validators. + *

+ * + *

+ * If the validator is in OR mode or does not contain any + * validators of given type null is returned. + *

+ * + * @return Collection of validators compatible with given type that must + * apply or null if none fould. + */ + public Collection getSubValidators(Class validatorType) { + if (mode != MODE_AND) { + return null; + } + + HashSet found = new HashSet(); + for (Iterator i = validators.iterator(); i.hasNext();) { + Validator v = (Validator) i.next(); + if (validatorType.isAssignableFrom(v.getClass())) { + found.add(v); + } + if (v instanceof CompositeValidator + && ((CompositeValidator) v).getMode() == MODE_AND) { + Collection c = ((CompositeValidator) v) + .getSubValidators(validatorType); + if (c != null) { + found.addAll(c); + } + } + } + + return found.isEmpty() ? null : found; + } } diff --git a/src/com/itmill/toolkit/data/validator/NullValidator.java b/src/com/itmill/toolkit/data/validator/NullValidator.java index 7c7ae464ff..24cb25b339 100644 --- a/src/com/itmill/toolkit/data/validator/NullValidator.java +++ b/src/com/itmill/toolkit/data/validator/NullValidator.java @@ -28,7 +28,7 @@ package com.itmill.toolkit.data.validator; -import com.itmill.toolkit.data.*; +import com.itmill.toolkit.data.Validator; /** * This validator is used for validating properties that do or do not allow null @@ -41,83 +41,85 @@ import com.itmill.toolkit.data.*; */ public class NullValidator implements Validator { - private boolean allowNull; - - private String errorMessage; - - /** - * Creates a new NullValidator. - * - * @param errorMessage - * the error message to display on invalidation. - * @param allowNull - * Are nulls allowed? - */ - public NullValidator(String errorMessage, boolean allowNull) { - setErrorMessage(errorMessage); - setNullAllowed(allowNull); - } - - /** - * Validates the data given in value. - * - * @param value - * the value to validate. - * @throws Validator.InvalidValueException - * if the value was invalid. - */ - public void validate(Object value) throws Validator.InvalidValueException { - if ((allowNull && value != null) || (!allowNull && value == null)) - throw new Validator.InvalidValueException(errorMessage); - } - - /** - * Tests if the given value is valid. - * - * @param value - * the value to validate. - * @returns true for valid value, otherwise - * false. - */ - public boolean isValid(Object value) { - return allowNull ? value == null : value != null; - } - - /** - * Returns true if nulls are allowed otherwise - * false. - */ - public final boolean isNullAllowed() { - return allowNull; - } - - /** - * Sets if nulls are to be allowed. - * - * @param allowNull If true, only nulls are allowed. If false only non-nulls are allowed. - * Do we allow nulls? - */ - public void setNullAllowed(boolean allowNull) { - this.allowNull = allowNull; - } - - /** - * Gets the error message that is displayed in case the value is invalid. - * - * @return the Error Message. - */ - public String getErrorMessage() { - return errorMessage; - } - - /** - * Sets the error message to be displayed on invalid value. - * - * @param errorMessage - * the Error Message to set. - */ - public void setErrorMessage(String errorMessage) { - this.errorMessage = errorMessage; - } + private boolean allowNull; + + private String errorMessage; + + /** + * Creates a new NullValidator. + * + * @param errorMessage + * the error message to display on invalidation. + * @param allowNull + * Are nulls allowed? + */ + public NullValidator(String errorMessage, boolean allowNull) { + setErrorMessage(errorMessage); + setNullAllowed(allowNull); + } + + /** + * Validates the data given in value. + * + * @param value + * the value to validate. + * @throws Validator.InvalidValueException + * if the value was invalid. + */ + public void validate(Object value) throws Validator.InvalidValueException { + if ((allowNull && value != null) || (!allowNull && value == null)) { + throw new Validator.InvalidValueException(errorMessage); + } + } + + /** + * Tests if the given value is valid. + * + * @param value + * the value to validate. + * @returns true for valid value, otherwise + * false. + */ + public boolean isValid(Object value) { + return allowNull ? value == null : value != null; + } + + /** + * Returns true if nulls are allowed otherwise + * false. + */ + public final boolean isNullAllowed() { + return allowNull; + } + + /** + * Sets if nulls are to be allowed. + * + * @param allowNull + * If true, only nulls are allowed. If false only non-nulls + * are allowed. Do we allow nulls? + */ + public void setNullAllowed(boolean allowNull) { + this.allowNull = allowNull; + } + + /** + * Gets the error message that is displayed in case the value is invalid. + * + * @return the Error Message. + */ + public String getErrorMessage() { + return errorMessage; + } + + /** + * Sets the error message to be displayed on invalid value. + * + * @param errorMessage + * the Error Message to set. + */ + public void setErrorMessage(String errorMessage) { + this.errorMessage = errorMessage; + } } diff --git a/src/com/itmill/toolkit/data/validator/StringLengthValidator.java b/src/com/itmill/toolkit/data/validator/StringLengthValidator.java index 4159041e1b..68ddfe46fb 100644 --- a/src/com/itmill/toolkit/data/validator/StringLengthValidator.java +++ b/src/com/itmill/toolkit/data/validator/StringLengthValidator.java @@ -28,7 +28,7 @@ package com.itmill.toolkit.data.validator; -import com.itmill.toolkit.data.*; +import com.itmill.toolkit.data.Validator; /** * This StringLengthValidator is used to validate the length of @@ -41,161 +41,171 @@ import com.itmill.toolkit.data.*; */ public class StringLengthValidator implements Validator { - private int minLength = -1; - - private int maxLength = -1; - - private boolean allowNull = true; - - private String errorMessage; - - /** - * Creates a new StringLengthValidator with a given error message. - * - * @param errorMessage - * the message to display in case the value does not validate. - */ - public StringLengthValidator(String errorMessage) { - setErrorMessage(errorMessage); - } - - /** - * Creates a new StringLengthValidator with a given error message, - * permissable lengths and null-string allowance. - * - * @param errorMessage - * the message to display in case the value does not validate. - * @param minLength - * the minimum permissable length of the string. - * @param maxLength - * the maximum permissable length of the string. - * @param allowNull - * Are null strings permissable? - */ - public StringLengthValidator(String errorMessage, int minLength, - int maxLength, boolean allowNull) { - this(errorMessage); - setMinLength(minLength); - setMaxLength(maxLength); - setNullAllowed(allowNull); - } - - /** - * Validates the value. - * - * @param value - * the value to validate. - * @throws Validator.InvalidValueException - * if the value was invalid. - */ - public void validate(Object value) throws Validator.InvalidValueException { - if (value == null && !allowNull) - throw new Validator.InvalidValueException(errorMessage); - String s = value.toString(); - if (s == null && !allowNull) - throw new Validator.InvalidValueException(errorMessage); - int len = s.length(); - if ((minLength >= 0 && len < minLength) - || (maxLength >= 0 && len > maxLength)) - throw new Validator.InvalidValueException(errorMessage); - } - - /** - * Checks if the given value is valid. - * - * @param value - * the value to validate. - * @return true for valid value, otherwise false. - */ - public boolean isValid(Object value) { - if (value == null && !allowNull) - return true; - String s = value.toString(); - if (s == null && !allowNull) - return true; - int len = s.length(); - if ((minLength >= 0 && len < minLength) - || (maxLength >= 0 && len > maxLength)) - return false; - return true; - } - - /** - * Returns true if null strings are allowed. - * - * @return true if allows null string, otherwise - * false. - */ - public final boolean isNullAllowed() { - return allowNull; - } - - /** - * Gets the maximum permissable length of the string. - * - * @return the maximum length of the string. - */ - public final int getMaxLength() { - return maxLength; - } - - /** - * Gets the minimum permissable length of the string. - * - * @return the minimum length of the string. - */ - public final int getMinLength() { - return minLength; - } - - /** - * Sets whether null-strings are to be allowed. - */ - public void setNullAllowed(boolean allowNull) { - this.allowNull = allowNull; - } - - /** - * Sets the maximum permissable length of the string. - * - * @param maxLength - * the length to set. - */ - public void setMaxLength(int maxLength) { - if (maxLength < -1) - maxLength = -1; - this.maxLength = maxLength; - } - - /** - * Sets the minimum permissable length. - * - * @param minLength - * the length to set. - */ - public void setMinLength(int minLength) { - if (minLength < -1) - minLength = -1; - this.minLength = minLength; - } - - /** - * Gets the message to be displayed in case the value does not validate. - * - * @return the Error Message. - */ - public String getErrorMessage() { - return errorMessage; - } - - /** - * Sets the message to be displayer in case the value does not validate. - * - * @param errorMessage - * the Error Message to set. - */ - public void setErrorMessage(String errorMessage) { - this.errorMessage = errorMessage; - } + private int minLength = -1; + + private int maxLength = -1; + + private boolean allowNull = true; + + private String errorMessage; + + /** + * Creates a new StringLengthValidator with a given error message. + * + * @param errorMessage + * the message to display in case the value does not + * validate. + */ + public StringLengthValidator(String errorMessage) { + setErrorMessage(errorMessage); + } + + /** + * Creates a new StringLengthValidator with a given error message, + * permissable lengths and null-string allowance. + * + * @param errorMessage + * the message to display in case the value does not + * validate. + * @param minLength + * the minimum permissable length of the string. + * @param maxLength + * the maximum permissable length of the string. + * @param allowNull + * Are null strings permissable? + */ + public StringLengthValidator(String errorMessage, int minLength, + int maxLength, boolean allowNull) { + this(errorMessage); + setMinLength(minLength); + setMaxLength(maxLength); + setNullAllowed(allowNull); + } + + /** + * Validates the value. + * + * @param value + * the value to validate. + * @throws Validator.InvalidValueException + * if the value was invalid. + */ + public void validate(Object value) throws Validator.InvalidValueException { + if (value == null && !allowNull) { + throw new Validator.InvalidValueException(errorMessage); + } + String s = value.toString(); + if (s == null && !allowNull) { + throw new Validator.InvalidValueException(errorMessage); + } + int len = s.length(); + if ((minLength >= 0 && len < minLength) + || (maxLength >= 0 && len > maxLength)) { + throw new Validator.InvalidValueException(errorMessage); + } + } + + /** + * Checks if the given value is valid. + * + * @param value + * the value to validate. + * @return true for valid value, otherwise false. + */ + public boolean isValid(Object value) { + if (value == null && !allowNull) { + return true; + } + String s = value.toString(); + if (s == null && !allowNull) { + return true; + } + int len = s.length(); + if ((minLength >= 0 && len < minLength) + || (maxLength >= 0 && len > maxLength)) { + return false; + } + return true; + } + + /** + * Returns true if null strings are allowed. + * + * @return true if allows null string, otherwise + * false. + */ + public final boolean isNullAllowed() { + return allowNull; + } + + /** + * Gets the maximum permissable length of the string. + * + * @return the maximum length of the string. + */ + public final int getMaxLength() { + return maxLength; + } + + /** + * Gets the minimum permissable length of the string. + * + * @return the minimum length of the string. + */ + public final int getMinLength() { + return minLength; + } + + /** + * Sets whether null-strings are to be allowed. + */ + public void setNullAllowed(boolean allowNull) { + this.allowNull = allowNull; + } + + /** + * Sets the maximum permissable length of the string. + * + * @param maxLength + * the length to set. + */ + public void setMaxLength(int maxLength) { + if (maxLength < -1) { + maxLength = -1; + } + this.maxLength = maxLength; + } + + /** + * Sets the minimum permissable length. + * + * @param minLength + * the length to set. + */ + public void setMinLength(int minLength) { + if (minLength < -1) { + minLength = -1; + } + this.minLength = minLength; + } + + /** + * Gets the message to be displayed in case the value does not validate. + * + * @return the Error Message. + */ + public String getErrorMessage() { + return errorMessage; + } + + /** + * Sets the message to be displayer in case the value does not validate. + * + * @param errorMessage + * the Error Message to set. + */ + public void setErrorMessage(String errorMessage) { + this.errorMessage = errorMessage; + } } diff --git a/src/com/itmill/toolkit/demo/BrowserDemo.java b/src/com/itmill/toolkit/demo/BrowserDemo.java index 62a5a5fde5..5a03dce9d9 100644 --- a/src/com/itmill/toolkit/demo/BrowserDemo.java +++ b/src/com/itmill/toolkit/demo/BrowserDemo.java @@ -15,58 +15,59 @@ import com.itmill.toolkit.ui.Window; * @see com.itmill.toolkit.ui.Window */ public class BrowserDemo extends com.itmill.toolkit.Application implements - Select.ValueChangeListener { + Select.ValueChangeListener { - // Default URL to open. - private static final String DEFAULT_URL = "http://www.itmill.com"; + // Default URL to open. + private static final String DEFAULT_URL = "http://www.itmill.com"; - // The embedded page - Embedded emb = new Embedded(); + // The embedded page + Embedded emb = new Embedded(); - public void init() { - // Create and set main window - Window browser = new Window("IT Mill Browser"); - setMainWindow(browser); + public void init() { + // Create and set main window + Window browser = new Window("IT Mill Browser"); + setMainWindow(browser); - // Use the expand layout to allow one component to use as much space as - // possible. - ExpandLayout exl = new ExpandLayout(); - browser.setLayout(exl); - exl.setSizeFull(); + // Use the expand layout to allow one component to use as much + // space as + // possible. + ExpandLayout exl = new ExpandLayout(); + browser.setLayout(exl); + exl.setSizeFull(); - // create the address combobox - Select select = new Select(); - // allow input - select.setNewItemsAllowed(true); - // no empty selection - select.setNullSelectionAllowed(false); - // no 'go' -button clicking necessary - select.setImmediate(true); - // add some pre-configured URLs - select.addItem(DEFAULT_URL); - select.addItem("http://www.google.com"); - select.addItem("http://toolkit.itmill.com/demo"); - // add to layout - exl.addComponent(select); - // add listener and select initial URL - select.addListener(this); - select.setValue(DEFAULT_URL); + // create the address combobox + Select select = new Select(); + // allow input + select.setNewItemsAllowed(true); + // no empty selection + select.setNullSelectionAllowed(false); + // no 'go' -button clicking necessary + select.setImmediate(true); + // add some pre-configured URLs + select.addItem(DEFAULT_URL); + select.addItem("http://www.google.com"); + select.addItem("http://toolkit.itmill.com/demo"); + // add to layout + exl.addComponent(select); + // add listener and select initial URL + select.addListener(this); + select.setValue(DEFAULT_URL); - // configure the embedded and add to layout - emb.setType(Embedded.TYPE_BROWSER); - exl.addComponent(emb); - // make the embedded as large as possible - exl.expand(emb); + // configure the embedded and add to layout + emb.setType(Embedded.TYPE_BROWSER); + exl.addComponent(emb); + // make the embedded as large as possible + exl.expand(emb); - } + } - public void valueChange(ValueChangeEvent event) { - String url = (String) event.getProperty().getValue(); - if (url != null) { - // the selected url has changed, let's go there - emb.setSource(new ExternalResource(url)); - } + public void valueChange(ValueChangeEvent event) { + String url = (String) event.getProperty().getValue(); + if (url != null) { + // the selected url has changed, let's go there + emb.setSource(new ExternalResource(url)); + } - } + } } diff --git a/src/com/itmill/toolkit/demo/BufferedComponents.java b/src/com/itmill/toolkit/demo/BufferedComponents.java index 6a560e39c6..b2a75e1a16 100644 --- a/src/com/itmill/toolkit/demo/BufferedComponents.java +++ b/src/com/itmill/toolkit/demo/BufferedComponents.java @@ -11,65 +11,66 @@ import com.itmill.toolkit.ui.Button.ClickEvent; public class BufferedComponents extends Application { - private ObjectProperty property; + private ObjectProperty property; - private TextField text; + private TextField text; - public void init() { + public void init() { - Window w = new Window("Buffered UI components demo"); - addWindow(w); + Window w = new Window("Buffered UI components demo"); + addWindow(w); - // Create property - Float floatValue = new Float(1.0f); - property = new ObjectProperty(floatValue); + // Create property + Float floatValue = new Float(1.0f); + property = new ObjectProperty(floatValue); - // Textfield - text = new TextField("TextField (Buffered, using ObjectProperty)", - property); - text.setImmediate(true); - text.setWriteThrough(false); - w.addComponent(text); + // Textfield + text = new TextField("TextField (Buffered, using ObjectProperty)", + property); + text.setImmediate(true); + text.setWriteThrough(false); + w.addComponent(text); - // Property state - Label propertyState = new Label(property); - propertyState.setCaption("Property (data source) state"); - w.addComponent(propertyState); + // Property state + Label propertyState = new Label(property); + propertyState.setCaption("Property (data source) state"); + w.addComponent(propertyState); - // Button state - Label textState = new Label(text); - textState.setCaption("TextField state"); - w.addComponent(textState); + // Button state + Label textState = new Label(text); + textState.setCaption("TextField state"); + w.addComponent(textState); - // Button to change the property - w.addComponent(new Button("increase property value", - new Button.ClickListener() { - public void buttonClick(ClickEvent event) { - Float currentValue = (Float) property.getValue(); - property.setValue(new Float( - currentValue.floatValue() + 1.0)); - } - })); + // Button to change the property + w.addComponent(new Button("increase property value", + new Button.ClickListener() { + public void buttonClick(ClickEvent event) { + Float currentValue = (Float) property.getValue(); + property.setValue(new Float( + currentValue.floatValue() + 1.0)); + } + })); - // Buffering - w.addComponent(new Button("Write through enabled", new MethodProperty( - text, "writeThrough"))); - w.addComponent(new Button("discard", new Button.ClickListener() { - public void buttonClick(ClickEvent event) { - text.discard(); - } - })); - w.addComponent(new Button("commit", new Button.ClickListener() { - public void buttonClick(ClickEvent event) { - text.commit(); - } - })); + // Buffering + w.addComponent(new Button("Write through enabled", new MethodProperty( + text, "writeThrough"))); + w.addComponent(new Button("discard", new Button.ClickListener() { + public void buttonClick(ClickEvent event) { + text.discard(); + } + })); + w.addComponent(new Button("commit", new Button.ClickListener() { + public void buttonClick(ClickEvent event) { + text.commit(); + } + })); - // Restart button for application - // (easier debugging when you dont have to restart the server to make - // code changes) - Button restart = new Button("restart", this, "close"); - restart.setStyle("link"); - w.addComponent(restart); - } + // Restart button for application + // (easier debugging when you dont have to restart the server to + // make + // code changes) + Button restart = new Button("restart", this, "close"); + restart.setStyle("link"); + w.addComponent(restart); + } } diff --git a/src/com/itmill/toolkit/demo/CachingDemo.java b/src/com/itmill/toolkit/demo/CachingDemo.java index 6b91a76174..4cc47719f5 100644 --- a/src/com/itmill/toolkit/demo/CachingDemo.java +++ b/src/com/itmill/toolkit/demo/CachingDemo.java @@ -19,45 +19,45 @@ import com.itmill.toolkit.ui.Window; */ public class CachingDemo extends com.itmill.toolkit.Application { - public void init() { - - Window main = new Window("Client-side caching example"); - setMainWindow(main); - - setTheme("example"); - - TabSheet ts = new TabSheet(); - main.addComponent(ts); - - Layout layout = new OrderedLayout(); - layout.setMargin(true); - Label l = new Label( - "This is a normal label, quick to render.
The second tab will be slow to render the first time, after that it will be as quick as this one."); - l.setCaption("A normal label"); - l.setContentMode(Label.CONTENT_XHTML); - layout.addComponent(l); - - ts.addTab(layout, "Normal", null); - - layout = new OrderedLayout(); - layout.setMargin(true); - l = new Label( - "The first time you change to this tab, this label is very slow to produce (server-side).
However, it will seem fast the second time you change to this tab, because it has not changed and is cached client-side.") { - public void paintContent(PaintTarget target) throws PaintException { - try { - Thread.sleep(3000); - } catch (Exception e) { - // IGNORED - } - super.paintContent(target); - } - - }; - l.setCaption("A slow label"); - l.setContentMode(Label.CONTENT_XHTML); - layout.addComponent(l); - ts.addTab(layout, "Slow", null); - - } + public void init() { + + Window main = new Window("Client-side caching example"); + setMainWindow(main); + + setTheme("example"); + + TabSheet ts = new TabSheet(); + main.addComponent(ts); + + Layout layout = new OrderedLayout(); + layout.setMargin(true); + Label l = new Label( + "This is a normal label, quick to render.
The second tab will be slow to render the first time, after that it will be as quick as this one."); + l.setCaption("A normal label"); + l.setContentMode(Label.CONTENT_XHTML); + layout.addComponent(l); + + ts.addTab(layout, "Normal", null); + + layout = new OrderedLayout(); + layout.setMargin(true); + l = new Label( + "The first time you change to this tab, this label is very slow to produce (server-side).
However, it will seem fast the second time you change to this tab, because it has not changed and is cached client-side.") { + public void paintContent(PaintTarget target) throws PaintException { + try { + Thread.sleep(3000); + } catch (Exception e) { + // IGNORED + } + super.paintContent(target); + } + + }; + l.setCaption("A slow label"); + l.setContentMode(Label.CONTENT_XHTML); + layout.addComponent(l); + ts.addTab(layout, "Slow", null); + + } } diff --git a/src/com/itmill/toolkit/demo/Calc.java b/src/com/itmill/toolkit/demo/Calc.java index 7d57debc99..5a3788ac52 100644 --- a/src/com/itmill/toolkit/demo/Calc.java +++ b/src/com/itmill/toolkit/demo/Calc.java @@ -1,6 +1,9 @@ package com.itmill.toolkit.demo; -import com.itmill.toolkit.ui.*; +import com.itmill.toolkit.ui.Button; +import com.itmill.toolkit.ui.GridLayout; +import com.itmill.toolkit.ui.Label; +import com.itmill.toolkit.ui.Window; /** *

@@ -20,103 +23,109 @@ import com.itmill.toolkit.ui.*; * @see com.itmill.toolkit.ui.Button.ClickListener */ public class Calc extends com.itmill.toolkit.Application implements - Button.ClickListener { - - /** The label used as the display */ - private Label display = null; - - /** Last completed result */ - private double stored = 0.0; - - /** The number being currently edited. */ - private double current = 0.0; - - /** Last activated operation. */ - private String operation = "C"; - - /** Button captions. */ - private static String[] captions = // Captions for the buttons - { "7", "8", "9", "/", "4", "5", "6", "*", "1", "2", "3", "-", "0", "=", - "C", "+" }; - - /** - *

- * Initializes the application. This is the only method an application is - * required to implement. It's called by the framework and it should perform - * whatever initialization tasks the application needs to perform. - *

- * - *

- * In this case we create the main window, the display, the grid to hold the - * buttons, and the buttons themselves. - *

- */ - public void init() { - - // Create a new layout for the components used by the calculator - GridLayout layout = new GridLayout(4, 5); - - // Create a new label component for displaying the result - display = new Label(Double.toString(current)); - display.setCaption("Result"); - - // Place the label to the top of the previously created grid. - layout.addComponent(display, 0, 0, 3, 0); - - // Create the buttons and place them in the grid - for (int i = 0; i < captions.length; i++) { - Button button = new Button(captions[i], this); - layout.addComponent(button); - } - - // Create the main window with a caption and add it to the application. - addWindow(new Window("Calculator", layout)); - - } - - /** - *

- * The button listener method called any time a button is pressed. This - * method catches all button presses, figures out what the user wanted the - * application to do, and updates the UI accordingly. - *

- * - *

- * The button click event passed to this method contains information about - * which button was pressed. If it was a number, the currently edited number - * is updated. If it was something else, the requested operation is - * performed. In either case the display label is updated to include the - * outcome of the button click. - *

- * - * @param event - * the button click event specifying which button was pressed - */ - public void buttonClick(Button.ClickEvent event) { - - try { - // Number button pressed - current = current * 10 - + Double.parseDouble(event.getButton().getCaption()); - display.setValue(Double.toString(current)); - } catch (java.lang.NumberFormatException e) { - - // Operation button pressed - if (operation.equals("+")) - stored += current; - if (operation.equals("-")) - stored -= current; - if (operation.equals("*")) - stored *= current; - if (operation.equals("/")) - stored /= current; - if (operation.equals("C")) - stored = current; - if (event.getButton().getCaption().equals("C")) - stored = 0.0; - operation = event.getButton().getCaption(); - current = 0.0; - display.setValue(Double.toString(stored)); - } - } + Button.ClickListener { + + /** The label used as the display */ + private Label display = null; + + /** Last completed result */ + private double stored = 0.0; + + /** The number being currently edited. */ + private double current = 0.0; + + /** Last activated operation. */ + private String operation = "C"; + + /** Button captions. */ + private static String[] captions = // Captions for the buttons + { "7", "8", "9", "/", "4", "5", "6", "*", "1", "2", "3", "-", "0", "=", + "C", "+" }; + + /** + *

+ * Initializes the application. This is the only method an application is + * required to implement. It's called by the framework and it should perform + * whatever initialization tasks the application needs to perform. + *

+ * + *

+ * In this case we create the main window, the display, the grid to hold the + * buttons, and the buttons themselves. + *

+ */ + public void init() { + + // Create a new layout for the components used by the calculator + GridLayout layout = new GridLayout(4, 5); + + // Create a new label component for displaying the result + display = new Label(Double.toString(current)); + display.setCaption("Result"); + + // Place the label to the top of the previously created grid. + layout.addComponent(display, 0, 0, 3, 0); + + // Create the buttons and place them in the grid + for (int i = 0; i < captions.length; i++) { + Button button = new Button(captions[i], this); + layout.addComponent(button); + } + + // Create the main window with a caption and add it to the application. + addWindow(new Window("Calculator", layout)); + + } + + /** + *

+ * The button listener method called any time a button is pressed. This + * method catches all button presses, figures out what the user wanted the + * application to do, and updates the UI accordingly. + *

+ * + *

+ * The button click event passed to this method contains information about + * which button was pressed. If it was a number, the currently edited number + * is updated. If it was something else, the requested operation is + * performed. In either case the display label is updated to include the + * outcome of the button click. + *

+ * + * @param event + * the button click event specifying which button was pressed + */ + public void buttonClick(Button.ClickEvent event) { + + try { + // Number button pressed + current = current * 10 + + Double.parseDouble(event.getButton().getCaption()); + display.setValue(Double.toString(current)); + } catch (java.lang.NumberFormatException e) { + + // Operation button pressed + if (operation.equals("+")) { + stored += current; + } + if (operation.equals("-")) { + stored -= current; + } + if (operation.equals("*")) { + stored *= current; + } + if (operation.equals("/")) { + stored /= current; + } + if (operation.equals("C")) { + stored = current; + } + if (event.getButton().getCaption().equals("C")) { + stored = 0.0; + } + operation = event.getButton().getCaption(); + current = 0.0; + display.setValue(Double.toString(stored)); + } + } } diff --git a/src/com/itmill/toolkit/demo/CustomLayoutDemo.java b/src/com/itmill/toolkit/demo/CustomLayoutDemo.java index 6035fdc0cc..0bf256b409 100644 --- a/src/com/itmill/toolkit/demo/CustomLayoutDemo.java +++ b/src/com/itmill/toolkit/demo/CustomLayoutDemo.java @@ -1,6 +1,13 @@ package com.itmill.toolkit.demo; -import com.itmill.toolkit.ui.*; +import com.itmill.toolkit.ui.Button; +import com.itmill.toolkit.ui.CustomLayout; +import com.itmill.toolkit.ui.Field; +import com.itmill.toolkit.ui.Label; +import com.itmill.toolkit.ui.Panel; +import com.itmill.toolkit.ui.TextField; +import com.itmill.toolkit.ui.Tree; +import com.itmill.toolkit.ui.Window; import com.itmill.toolkit.ui.Component.Event; import com.itmill.toolkit.ui.Component.Listener; @@ -18,110 +25,111 @@ import com.itmill.toolkit.ui.Component.Listener; * */ public class CustomLayoutDemo extends com.itmill.toolkit.Application implements - Listener { - - private CustomLayout mainLayout = null; - - private Panel bodyPanel = new Panel(); - - private TextField username = new TextField("Username"); - - private TextField loginPwd = new TextField("Password"); - - private Button loginButton = new Button("Login", this, "loginClicked"); - - private Tree menu = new Tree(); - - /** - * Initialize Application. Demo components are added to main window. - */ - public void init() { - Window mainWindow = new Window("CustomLayout demo"); - setMainWindow(mainWindow); - - // set the application to use example -theme - setTheme("example"); - - // Create custom layout, themes/example/layout/mainLayout.html - mainLayout = new CustomLayout("mainLayout"); - // wrap custom layout inside a panel - Panel customLayoutPanel = new Panel( - "Panel containing custom layout (mainLayout.html)"); - customLayoutPanel.addComponent(mainLayout); - - // Login components - loginPwd.setSecret(true); - mainLayout.addComponent(username, "loginUser"); - mainLayout.addComponent(loginPwd, "loginPassword"); - mainLayout.addComponent(loginButton, "loginButton"); - - // Menu component, when clicked bodyPanel is updated - menu.addItem("Welcome"); - menu.addItem("Products"); - menu.addItem("Support"); - menu.addItem("News"); - menu.addItem("Developers"); - menu.addItem("Contact"); - // "this" handles all menu events, e.g. node clicked event - menu.addListener((Listener) this); - // Value changes are immediate - menu.setImmediate(true); - menu.setNullSelectionAllowed(false); - mainLayout.addComponent(menu, "menu"); - - // Body component - mainLayout.addComponent(bodyPanel, "body"); - - // Initial body are comes from Welcome.html - setBody("Welcome"); - - // Add heading label and custom layout panel to main window - mainWindow.addComponent(new Label("

Custom layout demo

", - Label.CONTENT_XHTML)); - mainWindow.addComponent(customLayoutPanel); - } - - /** - * Login button clicked. Hide login components and replace username - * component with "Welcome user Username" message. - * - */ - public void loginClicked() { - username.setVisible(false); - loginPwd.setVisible(false); - if (username.getValue().toString().length() < 1) - username.setValue("Anonymous"); - mainLayout.replaceComponent(loginButton, new Label("Welcome user " - + username.getValue() + "", Label.CONTENT_XHTML)); - } - - /** - * Set body panel caption, remove all existing components and add given - * custom layout in it. - * - */ - public void setBody(String customLayout) { - bodyPanel.setCaption(customLayout + ".html"); - bodyPanel.removeAllComponents(); - bodyPanel.addComponent(new CustomLayout(customLayout)); - } - - /** - * Handle all menu events. Updates body panel contents if menu item is - * clicked. - */ - public void componentEvent(Event event) { - // Check if event occured at fsTree component - if (event.getSource() == menu) { - // Check if event is about changing value - if (event.getClass() == Field.ValueChangeEvent.class) { - // Update body area with selected item - setBody(menu.getValue().toString()); - } - // here we could check for other type of events for tree - // component - } - // here we could check for other component's events - } + Listener { + + private CustomLayout mainLayout = null; + + private Panel bodyPanel = new Panel(); + + private TextField username = new TextField("Username"); + + private TextField loginPwd = new TextField("Password"); + + private Button loginButton = new Button("Login", this, "loginClicked"); + + private Tree menu = new Tree(); + + /** + * Initialize Application. Demo components are added to main window. + */ + public void init() { + Window mainWindow = new Window("CustomLayout demo"); + setMainWindow(mainWindow); + + // set the application to use example -theme + setTheme("example"); + + // Create custom layout, themes/example/layout/mainLayout.html + mainLayout = new CustomLayout("mainLayout"); + // wrap custom layout inside a panel + Panel customLayoutPanel = new Panel( + "Panel containing custom layout (mainLayout.html)"); + customLayoutPanel.addComponent(mainLayout); + + // Login components + loginPwd.setSecret(true); + mainLayout.addComponent(username, "loginUser"); + mainLayout.addComponent(loginPwd, "loginPassword"); + mainLayout.addComponent(loginButton, "loginButton"); + + // Menu component, when clicked bodyPanel is updated + menu.addItem("Welcome"); + menu.addItem("Products"); + menu.addItem("Support"); + menu.addItem("News"); + menu.addItem("Developers"); + menu.addItem("Contact"); + // "this" handles all menu events, e.g. node clicked event + menu.addListener(this); + // Value changes are immediate + menu.setImmediate(true); + menu.setNullSelectionAllowed(false); + mainLayout.addComponent(menu, "menu"); + + // Body component + mainLayout.addComponent(bodyPanel, "body"); + + // Initial body are comes from Welcome.html + setBody("Welcome"); + + // Add heading label and custom layout panel to main window + mainWindow.addComponent(new Label("

Custom layout demo

", + Label.CONTENT_XHTML)); + mainWindow.addComponent(customLayoutPanel); + } + + /** + * Login button clicked. Hide login components and replace username + * component with "Welcome user Username" message. + * + */ + public void loginClicked() { + username.setVisible(false); + loginPwd.setVisible(false); + if (username.getValue().toString().length() < 1) { + username.setValue("Anonymous"); + } + mainLayout.replaceComponent(loginButton, new Label("Welcome user " + + username.getValue() + "", Label.CONTENT_XHTML)); + } + + /** + * Set body panel caption, remove all existing components and add given + * custom layout in it. + * + */ + public void setBody(String customLayout) { + bodyPanel.setCaption(customLayout + ".html"); + bodyPanel.removeAllComponents(); + bodyPanel.addComponent(new CustomLayout(customLayout)); + } + + /** + * Handle all menu events. Updates body panel contents if menu item is + * clicked. + */ + public void componentEvent(Event event) { + // Check if event occured at fsTree component + if (event.getSource() == menu) { + // Check if event is about changing value + if (event.getClass() == Field.ValueChangeEvent.class) { + // Update body area with selected item + setBody(menu.getValue().toString()); + } + // here we could check for other type of events for tree + // component + } + // here we could check for other component's events + } } diff --git a/src/com/itmill/toolkit/demo/FilterSelect.java b/src/com/itmill/toolkit/demo/FilterSelect.java index 8abda479a2..5d0136fc40 100644 --- a/src/com/itmill/toolkit/demo/FilterSelect.java +++ b/src/com/itmill/toolkit/demo/FilterSelect.java @@ -4,6 +4,7 @@ import com.itmill.toolkit.ui.OrderedLayout; import com.itmill.toolkit.ui.Panel; import com.itmill.toolkit.ui.Select; import com.itmill.toolkit.ui.Window; +import com.itmill.toolkit.ui.AbstractSelect.Filtering; /** * The classic "hello, world!" example for IT Mill Toolkit. The class simply @@ -17,77 +18,77 @@ import com.itmill.toolkit.ui.Window; */ public class FilterSelect extends com.itmill.toolkit.Application { - private static final String[] firstnames = new String[] { "John", "Mary", - "Joe", "Sarah", "Jeff", "Jane", "Peter", "Marc", "Robert", "Paula", - "Lenny", "Kenny", "Nathan", "Nicole", "Laura", "Jos", "Josie", - "Linus" }; + private static final String[] firstnames = new String[] { "John", "Mary", + "Joe", "Sarah", "Jeff", "Jane", "Peter", "Marc", "Robert", "Paula", + "Lenny", "Kenny", "Nathan", "Nicole", "Laura", "Jos", "Josie", + "Linus" }; - private static final String[] lastnames = new String[] { "Torvalds", - "Smith", "Adams", "Black", "Wilson", "Richards", "Thompson", - "McGoff", "Halas", "Jones", "Beck", "Sheridan", "Picard", "Hill", - "Fielding", "Einstein" }; + private static final String[] lastnames = new String[] { "Torvalds", + "Smith", "Adams", "Black", "Wilson", "Richards", "Thompson", + "McGoff", "Halas", "Jones", "Beck", "Sheridan", "Picard", "Hill", + "Fielding", "Einstein" }; - /** - * The initialization method that is the only requirement for inheriting the - * com.itmill.toolkit.service.Application class. It will be automatically - * called by the framework when a user accesses the application. - */ - public void init() { + /** + * The initialization method that is the only requirement for inheriting the + * com.itmill.toolkit.service.Application class. It will be automatically + * called by the framework when a user accesses the application. + */ + public void init() { - /* - * - Create new window for the application - Give the window a visible - * title - Set the window to be the main window of the application - */ - Window main = new Window("Filter select demo"); - setMainWindow(main); + /* + * - Create new window for the application - Give the window a visible + * title - Set the window to be the main window of the application + */ + Window main = new Window("Filter select demo"); + setMainWindow(main); - // default filter - Select s1 = new Select(); - for (int i = 0; i < 105; i++) { - s1 - .addItem(firstnames[(int) (Math.random() * (firstnames.length - 1))] - + " " - + lastnames[(int) (Math.random() * (lastnames.length - 1))]); - } - s1.setImmediate(true); + // default filter + Select s1 = new Select(); + for (int i = 0; i < 105; i++) { + s1 + .addItem(firstnames[(int) (Math.random() * (firstnames.length - 1))] + + " " + + lastnames[(int) (Math.random() * (lastnames.length - 1))]); + } + s1.setImmediate(true); - // contains filter - Select s2 = new Select(); - for (int i = 0; i < 500; i++) { - s2 - .addItem(firstnames[(int) (Math.random() * (firstnames.length - 1))] - + " " - + lastnames[(int) (Math.random() * (lastnames.length - 1))]); - } - s2.setFilteringMode(Select.FILTERINGMODE_CONTAINS); + // contains filter + Select s2 = new Select(); + for (int i = 0; i < 500; i++) { + s2 + .addItem(firstnames[(int) (Math.random() * (firstnames.length - 1))] + + " " + + lastnames[(int) (Math.random() * (lastnames.length - 1))]); + } + s2.setFilteringMode(Filtering.FILTERINGMODE_CONTAINS); - // startswith filter - Select s3 = new Select(); - for (int i = 0; i < 500; i++) { - s3 - .addItem(firstnames[(int) (Math.random() * (firstnames.length - 1))] - + " " - + lastnames[(int) (Math.random() * (lastnames.length - 1))]); - } - s3.setFilteringMode(Select.FILTERINGMODE_STARTSWITH); + // startswith filter + Select s3 = new Select(); + for (int i = 0; i < 500; i++) { + s3 + .addItem(firstnames[(int) (Math.random() * (firstnames.length - 1))] + + " " + + lastnames[(int) (Math.random() * (lastnames.length - 1))]); + } + s3.setFilteringMode(Filtering.FILTERINGMODE_STARTSWITH); - // Add selects to UI using ordered layout and panels - OrderedLayout orderedLayout = new OrderedLayout( - OrderedLayout.ORIENTATION_HORIZONTAL); + // Add selects to UI using ordered layout and panels + OrderedLayout orderedLayout = new OrderedLayout( + OrderedLayout.ORIENTATION_HORIZONTAL); - Panel panel1 = new Panel("Select with default filter"); - Panel panel2 = new Panel("Select with contains filter"); - Panel panel3 = new Panel("Select with custom 'EndsWith' filter"); + Panel panel1 = new Panel("Select with default filter"); + Panel panel2 = new Panel("Select with contains filter"); + Panel panel3 = new Panel("Select with custom 'EndsWith' filter"); - panel1.addComponent(s1); - panel2.addComponent(s2); - panel3.addComponent(s3); + panel1.addComponent(s1); + panel2.addComponent(s2); + panel3.addComponent(s3); - orderedLayout.addComponent(panel1); - orderedLayout.addComponent(panel2); - orderedLayout.addComponent(panel3); - main.addComponent(orderedLayout); + orderedLayout.addComponent(panel1); + orderedLayout.addComponent(panel2); + orderedLayout.addComponent(panel3); + main.addComponent(orderedLayout); - } + } } diff --git a/src/com/itmill/toolkit/demo/HelloWorld.java b/src/com/itmill/toolkit/demo/HelloWorld.java index d4ab04e486..ace0e95913 100644 --- a/src/com/itmill/toolkit/demo/HelloWorld.java +++ b/src/com/itmill/toolkit/demo/HelloWorld.java @@ -1,6 +1,7 @@ package com.itmill.toolkit.demo; -import com.itmill.toolkit.ui.*; +import com.itmill.toolkit.ui.Label; +import com.itmill.toolkit.ui.Window; /** * The classic "hello, world!" example for IT Mill Toolkit. The class simply @@ -14,29 +15,29 @@ import com.itmill.toolkit.ui.*; */ public class HelloWorld extends com.itmill.toolkit.Application { - /** - * The initialization method that is the only requirement for inheriting the - * com.itmill.toolkit.service.Application class. It will be automatically - * called by the framework when a user accesses the application. - */ - public void init() { + /** + * The initialization method that is the only requirement for inheriting the + * com.itmill.toolkit.service.Application class. It will be automatically + * called by the framework when a user accesses the application. + */ + public void init() { - /* - * - Create new window for the application - Give the window a visible - * title - Set the window to be the main window of the application - */ - Window main = new Window("Hello window"); - setMainWindow(main); + /* + * - Create new window for the application - Give the window a visible + * title - Set the window to be the main window of the application + */ + Window main = new Window("Hello window"); + setMainWindow(main); - /* - * - Create a label with the classic text - Add the label to the main - * window - */ - main.addComponent(new Label("Hello World!")); + /* + * - Create a label with the classic text - Add the label to the main + * window + */ + main.addComponent(new Label("Hello World!")); - /* - * And that's it! The framework will display the main window and its - * contents when the application is accessed with the terminal. - */ - } + /* + * And that's it! The framework will display the main window and its + * contents when the application is accessed with the terminal. + */ + } } diff --git a/src/com/itmill/toolkit/demo/KeyboardShortcut.java b/src/com/itmill/toolkit/demo/KeyboardShortcut.java index e5170b7758..34aeaf779b 100644 --- a/src/com/itmill/toolkit/demo/KeyboardShortcut.java +++ b/src/com/itmill/toolkit/demo/KeyboardShortcut.java @@ -3,7 +3,11 @@ package com.itmill.toolkit.demo; import com.itmill.toolkit.event.Action; import com.itmill.toolkit.event.ShortcutAction; import com.itmill.toolkit.event.Action.Handler; -import com.itmill.toolkit.ui.*; +import com.itmill.toolkit.ui.AbstractField; +import com.itmill.toolkit.ui.Button; +import com.itmill.toolkit.ui.Label; +import com.itmill.toolkit.ui.TextField; +import com.itmill.toolkit.ui.Window; /** * Note: This feature is under development and is considered as beta @@ -12,98 +16,102 @@ import com.itmill.toolkit.ui.*; * */ public class KeyboardShortcut extends com.itmill.toolkit.Application implements - Handler { - private Window main; - - private Button a; - - private Button z; - - private Button x; - - private Button close; - - private AbstractField f; - - Action[] actions = new Action[] { - new ShortcutAction("Button a action", ShortcutAction.KeyCode.A, - new int[] { ShortcutAction.ModifierKey.CTRL, - ShortcutAction.ModifierKey.SHIFT }), - new ShortcutAction("Button z action", ShortcutAction.KeyCode.Z, - new int[] { ShortcutAction.ModifierKey.CTRL, - ShortcutAction.ModifierKey.SHIFT }), - new ShortcutAction("Button x action", ShortcutAction.KeyCode.X, - new int[] { ShortcutAction.ModifierKey.CTRL, - ShortcutAction.ModifierKey.SHIFT }), - new ShortcutAction("Restart ", ShortcutAction.KeyCode.ESCAPE, null) }; - - public void init() { - - main = new Window("Keyboard shortcuts demo"); - setMainWindow(main); - - main - .addComponent(new Label( - "

Test application for shortcut actions

" - + "

Notes:
" - + "This feature is under development and it's API may still change.
" - + "If events do not work, set focus to Textfield first.
" - + "Browsers may have reserved the keyboard combinations used in " - + "this demo for other purposes.

", - Label.CONTENT_XHTML)); - main - .addComponent(new Label( - "ESC restarts program, ctrl-shift-a clicks A button, " - + "ctrl-shift-z clicks Z button, ctrl-shift-x clicks X button")); - - // Restart button - close = new Button("restart", this, "close"); - - main.addComponent(close); - - a = new Button("Button A", this, "buttonAHandler"); - - z = new Button("Button Z", this, "buttonZHandler"); - - x = new Button("Button X", this, "buttonXHandler"); - - f = new TextField("Textfield"); - - main.addComponent(a); - main.addComponent(z); - main.addComponent(x); - main.addComponent(f); - - main.addActionHandler(this); - - f.focus(); - } - - public Action[] getActions(Object target, Object sender) { - return actions; - } - - public void handleAction(Action action, Object sender, Object target) { - if (action == actions[0]) - this.buttonAHandler(); - if (action == actions[1]) - this.buttonZHandler(); - if (action == actions[2]) - this.buttonXHandler(); - if (action == actions[3]) - this.close(); - } - - public void buttonAHandler() { - main.addComponent(new Label("Button A handler fired")); - } - - public void buttonZHandler() { - main.addComponent(new Label("Button Z handler fired")); - } - - public void buttonXHandler() { - main.addComponent(new Label("Button X handler fired")); - } + Handler { + private Window main; + + private Button a; + + private Button z; + + private Button x; + + private Button close; + + private AbstractField f; + + Action[] actions = new Action[] { + new ShortcutAction("Button a action", ShortcutAction.KeyCode.A, + new int[] { ShortcutAction.ModifierKey.CTRL, + ShortcutAction.ModifierKey.SHIFT }), + new ShortcutAction("Button z action", ShortcutAction.KeyCode.Z, + new int[] { ShortcutAction.ModifierKey.CTRL, + ShortcutAction.ModifierKey.SHIFT }), + new ShortcutAction("Button x action", ShortcutAction.KeyCode.X, + new int[] { ShortcutAction.ModifierKey.CTRL, + ShortcutAction.ModifierKey.SHIFT }), + new ShortcutAction("Restart ", ShortcutAction.KeyCode.ESCAPE, null) }; + + public void init() { + + main = new Window("Keyboard shortcuts demo"); + setMainWindow(main); + + main + .addComponent(new Label( + "

Test application for shortcut actions

" + + "

Notes:
" + + "This feature is under development and it's API may still change.
" + + "If events do not work, set focus to Textfield first.
" + + "Browsers may have reserved the keyboard combinations used in " + + "this demo for other purposes.

", + Label.CONTENT_XHTML)); + main + .addComponent(new Label( + "ESC restarts program, ctrl-shift-a clicks A button, " + + "ctrl-shift-z clicks Z button, ctrl-shift-x clicks X button")); + + // Restart button + close = new Button("restart", this, "close"); + + main.addComponent(close); + + a = new Button("Button A", this, "buttonAHandler"); + + z = new Button("Button Z", this, "buttonZHandler"); + + x = new Button("Button X", this, "buttonXHandler"); + + f = new TextField("Textfield"); + + main.addComponent(a); + main.addComponent(z); + main.addComponent(x); + main.addComponent(f); + + main.addActionHandler(this); + + f.focus(); + } + + public Action[] getActions(Object target, Object sender) { + return actions; + } + + public void handleAction(Action action, Object sender, Object target) { + if (action == actions[0]) { + buttonAHandler(); + } + if (action == actions[1]) { + buttonZHandler(); + } + if (action == actions[2]) { + buttonXHandler(); + } + if (action == actions[3]) { + close(); + } + } + + public void buttonAHandler() { + main.addComponent(new Label("Button A handler fired")); + } + + public void buttonZHandler() { + main.addComponent(new Label("Button Z handler fired")); + } + + public void buttonXHandler() { + main.addComponent(new Label("Button X handler fired")); + } } diff --git a/src/com/itmill/toolkit/demo/LayoutDemo.java b/src/com/itmill/toolkit/demo/LayoutDemo.java index bb73a25250..60b6c02aef 100644 --- a/src/com/itmill/toolkit/demo/LayoutDemo.java +++ b/src/com/itmill/toolkit/demo/LayoutDemo.java @@ -1,7 +1,15 @@ package com.itmill.toolkit.demo; import com.itmill.toolkit.terminal.ClassResource; -import com.itmill.toolkit.ui.*; +import com.itmill.toolkit.ui.Component; +import com.itmill.toolkit.ui.Embedded; +import com.itmill.toolkit.ui.GridLayout; +import com.itmill.toolkit.ui.Label; +import com.itmill.toolkit.ui.Layout; +import com.itmill.toolkit.ui.OrderedLayout; +import com.itmill.toolkit.ui.Panel; +import com.itmill.toolkit.ui.TabSheet; +import com.itmill.toolkit.ui.Window; /** * This example demonstrates layouts. Layouts are populated with sample Toolkit @@ -13,123 +21,123 @@ import com.itmill.toolkit.ui.*; */ public class LayoutDemo extends com.itmill.toolkit.Application { - /** - * Initialize Application. Demo components are added to main window. - */ - public void init() { - Window mainWindow = new Window("Layout demo"); - setMainWindow(mainWindow); + /** + * Initialize Application. Demo components are added to main window. + */ + public void init() { + Window mainWindow = new Window("Layout demo"); + setMainWindow(mainWindow); - // - // Create horizontal ordered layout - // - OrderedLayout layoutA = new OrderedLayout( - OrderedLayout.ORIENTATION_HORIZONTAL); - // Add 4 panels - fillLayout(layoutA, 4); + // + // Create horizontal ordered layout + // + OrderedLayout layoutA = new OrderedLayout( + OrderedLayout.ORIENTATION_HORIZONTAL); + // Add 4 panels + fillLayout(layoutA, 4); - // - // Create vertical ordered layout - // - OrderedLayout layoutB = new OrderedLayout( - OrderedLayout.ORIENTATION_VERTICAL); - // Add 4 panels - fillLayout(layoutB, 4); + // + // Create vertical ordered layout + // + OrderedLayout layoutB = new OrderedLayout( + OrderedLayout.ORIENTATION_VERTICAL); + // Add 4 panels + fillLayout(layoutB, 4); - // - // Create grid layout - // - GridLayout layoutG = new GridLayout(4, 4); - // Add 16 panels components - fillLayout(layoutG, 16); + // + // Create grid layout + // + GridLayout layoutG = new GridLayout(4, 4); + // Add 16 panels components + fillLayout(layoutG, 16); - // - // Create grid layout - // - GridLayout layoutG2 = new GridLayout(4, 4); - // Add 4 panels with absolute coordinates (diagonally) - layoutG2.addComponent(getExampleComponent("x=0, y=0"), 0, 0); - layoutG2.addComponent(getExampleComponent("x=1, y=1"), 1, 1); - layoutG2.addComponent(getExampleComponent("x=2, y=2"), 2, 2); - layoutG2.addComponent(getExampleComponent("x=3, y=3"), 3, 3); - // Add 4 pictures with absolute coordinates (diagonally) - layoutG2.addComponent(getExamplePicture("x=3, y=0"), 3, 0); - layoutG2.addComponent(getExamplePicture("x=2, y=1"), 2, 1); - layoutG2.addComponent(getExamplePicture("x=1, y=2"), 1, 2); - layoutG2.addComponent(getExamplePicture("x=0, y=3"), 0, 3); + // + // Create grid layout + // + GridLayout layoutG2 = new GridLayout(4, 4); + // Add 4 panels with absolute coordinates (diagonally) + layoutG2.addComponent(getExampleComponent("x=0, y=0"), 0, 0); + layoutG2.addComponent(getExampleComponent("x=1, y=1"), 1, 1); + layoutG2.addComponent(getExampleComponent("x=2, y=2"), 2, 2); + layoutG2.addComponent(getExampleComponent("x=3, y=3"), 3, 3); + // Add 4 pictures with absolute coordinates (diagonally) + layoutG2.addComponent(getExamplePicture("x=3, y=0"), 3, 0); + layoutG2.addComponent(getExamplePicture("x=2, y=1"), 2, 1); + layoutG2.addComponent(getExamplePicture("x=1, y=2"), 1, 2); + layoutG2.addComponent(getExamplePicture("x=0, y=3"), 0, 3); - // - // Create TabSheet - // - TabSheet tabsheet = new TabSheet(); - tabsheet - .setCaption("Tabsheet, above layouts are added to this component"); - tabsheet.addTab(layoutA, "Horizontal ordered layout", null); - tabsheet.addTab(layoutB, "Vertical ordered layout", null); - tabsheet.addTab(layoutG, "First grid layout", null); - tabsheet.addTab(layoutG2, "Second grid layout", null); + // + // Create TabSheet + // + TabSheet tabsheet = new TabSheet(); + tabsheet + .setCaption("Tabsheet, above layouts are added to this component"); + tabsheet.addTab(layoutA, "Horizontal ordered layout", null); + tabsheet.addTab(layoutB, "Vertical ordered layout", null); + tabsheet.addTab(layoutG, "First grid layout", null); + tabsheet.addTab(layoutG2, "Second grid layout", null); - // - // Add demo layouts to main window - // - mainWindow.addComponent(new Label( - "

Horizontal ordered layout

Added four components.", - Label.CONTENT_XHTML)); - mainWindow.addComponent(layoutA); - mainWindow.addComponent(new Label( - "

Vertical ordered layout

Added four components.", - Label.CONTENT_XHTML)); - mainWindow.addComponent(layoutB); - mainWindow.addComponent(new Label( - "

Grid Layout (4 x 4)

Added 16 components.", - Label.CONTENT_XHTML)); - mainWindow.addComponent(layoutG); - mainWindow - .addComponent(new Label("

Grid Layout (4 x 4)

" - + "Added four panels and four embedded components " - + "diagonally with absolute coordinates.", - Label.CONTENT_XHTML)); - mainWindow.addComponent(layoutG2); - mainWindow.addComponent(new Label( - "

TabSheet

Added above layouts as tabs.", - Label.CONTENT_XHTML)); - mainWindow.addComponent(tabsheet); + // + // Add demo layouts to main window + // + mainWindow.addComponent(new Label( + "

Horizontal ordered layout

Added four components.", + Label.CONTENT_XHTML)); + mainWindow.addComponent(layoutA); + mainWindow.addComponent(new Label( + "

Vertical ordered layout

Added four components.", + Label.CONTENT_XHTML)); + mainWindow.addComponent(layoutB); + mainWindow.addComponent(new Label( + "

Grid Layout (4 x 4)

Added 16 components.", + Label.CONTENT_XHTML)); + mainWindow.addComponent(layoutG); + mainWindow + .addComponent(new Label("

Grid Layout (4 x 4)

" + + "Added four panels and four embedded components " + + "diagonally with absolute coordinates.", + Label.CONTENT_XHTML)); + mainWindow.addComponent(layoutG2); + mainWindow.addComponent(new Label( + "

TabSheet

Added above layouts as tabs.", + Label.CONTENT_XHTML)); + mainWindow.addComponent(tabsheet); - } + } - private Component getExamplePicture(String caption) { - ClassResource cr = new ClassResource("features/m-bullet-blue.gif", this); - Embedded em = new Embedded("Embedded " + caption, cr); - em.setWidth(170); - return em; - } + private Component getExamplePicture(String caption) { + ClassResource cr = new ClassResource("features/m-bullet-blue.gif", this); + Embedded em = new Embedded("Embedded " + caption, cr); + em.setWidth(170); + return em; + } - private Component getExampleComponent(String caption) { - Panel panel = new Panel(); - panel.setCaption("Panel component " + caption); - panel - .addComponent(new Label( - "Panel is a container for other components, by default it draws a frame around it's " - + "extremities and may have a caption to clarify the nature of the contained components' purpose." - + " Panel contains an layout where the actual contained components are added, " - + "this layout may be switched on the fly.", - Label.CONTENT_XHTML)); - panel.setWidth(222); - return panel; - } + private Component getExampleComponent(String caption) { + Panel panel = new Panel(); + panel.setCaption("Panel component " + caption); + panel + .addComponent(new Label( + "Panel is a container for other components, by default it draws a frame around it's " + + "extremities and may have a caption to clarify the nature of the contained components' purpose." + + " Panel contains an layout where the actual contained components are added, " + + "this layout may be switched on the fly.", + Label.CONTENT_XHTML)); + panel.setWidth(222); + return panel; + } - /** - * Add multiple demo component to given layout. - * - * @param layout - * where components are added - * @param numberOfComponents - * to add - */ - private void fillLayout(Layout layout, int numberOfComponents) { - for (int i = 1; i <= numberOfComponents; i++) { - layout.addComponent(getExampleComponent(Integer.toString(i))); - } - } + /** + * Add multiple demo component to given layout. + * + * @param layout + * where components are added + * @param numberOfComponents + * to add + */ + private void fillLayout(Layout layout, int numberOfComponents) { + for (int i = 1; i <= numberOfComponents; i++) { + layout.addComponent(getExampleComponent(Integer.toString(i))); + } + } } diff --git a/src/com/itmill/toolkit/demo/ModalWindow.java b/src/com/itmill/toolkit/demo/ModalWindow.java index 8b27faa011..6ba1cf9a1f 100644 --- a/src/com/itmill/toolkit/demo/ModalWindow.java +++ b/src/com/itmill/toolkit/demo/ModalWindow.java @@ -1,7 +1,10 @@ package com.itmill.toolkit.demo; import com.itmill.toolkit.event.Action; -import com.itmill.toolkit.ui.*; +import com.itmill.toolkit.ui.Button; +import com.itmill.toolkit.ui.Label; +import com.itmill.toolkit.ui.TextField; +import com.itmill.toolkit.ui.Window; import com.itmill.toolkit.ui.Button.ClickEvent; import com.itmill.toolkit.ui.Button.ClickListener; @@ -16,64 +19,64 @@ import com.itmill.toolkit.ui.Button.ClickListener; * @see com.itmill.toolkit.ui.Label */ public class ModalWindow extends com.itmill.toolkit.Application implements - Action.Handler, ClickListener { - - private Window test; - - public void init() { - - // Create main window - Window main = new Window("ModalWindow demo"); - setMainWindow(main); - main.addComponent(new Label("ModalWindow demo")); - - // Main window textfield - TextField f = new TextField(); - f.setTabIndex(1); - main.addComponent(f); - - // Main window button - Button b = new Button("Button on main window"); - b.addListener(this); - b.setTabIndex(2); - main.addComponent(b); - - // Modal window - test = new Window("Modal window"); - test.setStyle("modal"); - this.addWindow(test); - test.addComponent(new Label( - "You have to close this window before accessing others.")); - - // Textfield for modal window - f = new TextField(); - f.setTabIndex(4); - test.addComponent(f); - f.focus(); - - // Modal window button - b = new Button("Button on modal window"); - b.setTabIndex(3); - b.addListener(this); - test.addComponent(b); - - } - - public Action[] getActions(Object target, Object sender) { - Action actionA = new Action("Action A for " + target.toString()); - Action actionB = new Action("Action B for " + target.toString()); - Action[] actions = new Action[] { actionA, actionB }; - return actions; - } - - public void handleAction(Action action, Object sender, Object target) { - this.test.addComponent(new Label(action.getCaption() + " clicked on " - + target)); - - } - - public void buttonClick(ClickEvent event) { - this.test.addComponent(new Label("Clicked " + event)); - - } + Action.Handler, ClickListener { + + private Window test; + + public void init() { + + // Create main window + Window main = new Window("ModalWindow demo"); + setMainWindow(main); + main.addComponent(new Label("ModalWindow demo")); + + // Main window textfield + TextField f = new TextField(); + f.setTabIndex(1); + main.addComponent(f); + + // Main window button + Button b = new Button("Button on main window"); + b.addListener(this); + b.setTabIndex(2); + main.addComponent(b); + + // Modal window + test = new Window("Modal window"); + test.setStyle("modal"); + addWindow(test); + test.addComponent(new Label( + "You have to close this window before accessing others.")); + + // Textfield for modal window + f = new TextField(); + f.setTabIndex(4); + test.addComponent(f); + f.focus(); + + // Modal window button + b = new Button("Button on modal window"); + b.setTabIndex(3); + b.addListener(this); + test.addComponent(b); + + } + + public Action[] getActions(Object target, Object sender) { + Action actionA = new Action("Action A for " + target.toString()); + Action actionB = new Action("Action B for " + target.toString()); + Action[] actions = new Action[] { actionA, actionB }; + return actions; + } + + public void handleAction(Action action, Object sender, Object target) { + test.addComponent(new Label(action.getCaption() + " clicked on " + + target)); + + } + + public void buttonClick(ClickEvent event) { + test.addComponent(new Label("Clicked " + event)); + + } } diff --git a/src/com/itmill/toolkit/demo/NotificationDemo.java b/src/com/itmill/toolkit/demo/NotificationDemo.java index 5820b09da0..e7a0dcb7e4 100644 --- a/src/com/itmill/toolkit/demo/NotificationDemo.java +++ b/src/com/itmill/toolkit/demo/NotificationDemo.java @@ -1,10 +1,10 @@ package com.itmill.toolkit.demo; import com.itmill.toolkit.data.Item; +import com.itmill.toolkit.ui.AbstractSelect; import com.itmill.toolkit.ui.Button; import com.itmill.toolkit.ui.NativeSelect; import com.itmill.toolkit.ui.RichTextArea; -import com.itmill.toolkit.ui.Select; import com.itmill.toolkit.ui.TextField; import com.itmill.toolkit.ui.Window; import com.itmill.toolkit.ui.Button.ClickEvent; @@ -18,70 +18,70 @@ import com.itmill.toolkit.ui.Button.ClickListener; */ public class NotificationDemo extends com.itmill.toolkit.Application { - // Dropdown select for notification type, using the native dropdown - NativeSelect type; - // Textfield for the notification caption - TextField caption; - // Textfield for the notification content - TextField message; + // Dropdown select for notification type, using the native dropdown + NativeSelect type; + // Textfield for the notification caption + TextField caption; + // Textfield for the notification content + TextField message; - /** - * The initialization method that is the only requirement for inheriting the - * com.itmill.toolkit.service.Application class. It will be automatically - * called by the framework when a user accesses the application. - */ - public void init() { + /** + * The initialization method that is the only requirement for inheriting the + * com.itmill.toolkit.service.Application class. It will be automatically + * called by the framework when a user accesses the application. + */ + public void init() { - // Create new window for the application and give the window a visible. - Window main = new Window("Notification demo"); - // set as main window - setMainWindow(main); + // Create new window for the application and give the window a visible. + Window main = new Window("Notification demo"); + // set as main window + setMainWindow(main); - // Create the 'type' dropdown select. - type = new NativeSelect("Notification type"); - // no empty selection allowed - type.setNullSelectionAllowed(false); - // we want a different caption than the value - type.addContainerProperty("caption", String.class, null); - type.setItemCaptionMode(Select.ITEM_CAPTION_MODE_PROPERTY); - type.setItemCaptionPropertyId("caption"); - // add some content (items) using the Container API - Item i = type.addItem(new Integer( - Window.Notification.TYPE_HUMANIZED_MESSAGE)); - i.getItemProperty("caption").setValue("Humanized message"); - i = type.addItem(new Integer(Window.Notification.TYPE_WARNING_MESSAGE)); - i.getItemProperty("caption").setValue("Warning message"); - i = type.addItem(new Integer(Window.Notification.TYPE_ERROR_MESSAGE)); - i.getItemProperty("caption").setValue("Error message"); - i = type - .addItem(new Integer(Window.Notification.TYPE_TRAY_NOTIFICATION)); - i.getItemProperty("caption").setValue("Tray notification"); - // set the initially selected item - type.setValue(new Integer(Window.Notification.TYPE_HUMANIZED_MESSAGE)); - main.addComponent(type); // add to layout + // Create the 'type' dropdown select. + type = new NativeSelect("Notification type"); + // no empty selection allowed + type.setNullSelectionAllowed(false); + // we want a different caption than the value + type.addContainerProperty("caption", String.class, null); + type.setItemCaptionMode(AbstractSelect.ITEM_CAPTION_MODE_PROPERTY); + type.setItemCaptionPropertyId("caption"); + // add some content (items) using the Container API + Item i = type.addItem(new Integer( + Window.Notification.TYPE_HUMANIZED_MESSAGE)); + i.getItemProperty("caption").setValue("Humanized message"); + i = type.addItem(new Integer(Window.Notification.TYPE_WARNING_MESSAGE)); + i.getItemProperty("caption").setValue("Warning message"); + i = type.addItem(new Integer(Window.Notification.TYPE_ERROR_MESSAGE)); + i.getItemProperty("caption").setValue("Error message"); + i = type + .addItem(new Integer(Window.Notification.TYPE_TRAY_NOTIFICATION)); + i.getItemProperty("caption").setValue("Tray notification"); + // set the initially selected item + type.setValue(new Integer(Window.Notification.TYPE_HUMANIZED_MESSAGE)); + main.addComponent(type); // add to layout - // Notification caption - caption = new TextField("Caption"); - caption.setColumns(20); - caption.setValue("Brown Fox!"); - main.addComponent(caption); + // Notification caption + caption = new TextField("Caption"); + caption.setColumns(20); + caption.setValue("Brown Fox!"); + main.addComponent(caption); - // Notification message - message = new RichTextArea(); - message.setCaption("Message"); - message.setValue("A quick one jumped over the lazy dog."); - main.addComponent(message); // add to layout + // Notification message + message = new RichTextArea(); + message.setCaption("Message"); + message.setValue("A quick one jumped over the lazy dog."); + main.addComponent(message); // add to layout - // Button to show the notification - Button b = new Button("Show notification", new ClickListener() { - // this is an inline ClickListener - public void buttonClick(ClickEvent event) { - // show the notification - getMainWindow().showNotification((String) caption.getValue(), - (String) message.getValue(), - ((Integer) type.getValue()).intValue()); - } - }); - main.addComponent(b); // add button to layout - } + // Button to show the notification + Button b = new Button("Show notification", new ClickListener() { + // this is an inline ClickListener + public void buttonClick(ClickEvent event) { + // show the notification + getMainWindow().showNotification((String) caption.getValue(), + (String) message.getValue(), + ((Integer) type.getValue()).intValue()); + } + }); + main.addComponent(b); // add button to layout + } } diff --git a/src/com/itmill/toolkit/demo/Parameters.java b/src/com/itmill/toolkit/demo/Parameters.java index 882e92f131..353a088de9 100644 --- a/src/com/itmill/toolkit/demo/Parameters.java +++ b/src/com/itmill/toolkit/demo/Parameters.java @@ -8,7 +8,12 @@ import com.itmill.toolkit.terminal.DownloadStream; import com.itmill.toolkit.terminal.ExternalResource; import com.itmill.toolkit.terminal.ParameterHandler; import com.itmill.toolkit.terminal.URIHandler; -import com.itmill.toolkit.ui.*; +import com.itmill.toolkit.ui.Label; +import com.itmill.toolkit.ui.Link; +import com.itmill.toolkit.ui.OrderedLayout; +import com.itmill.toolkit.ui.Panel; +import com.itmill.toolkit.ui.Table; +import com.itmill.toolkit.ui.Window; /** * This is a demonstration of how URL parameters can be recieved and handled. @@ -18,89 +23,90 @@ import com.itmill.toolkit.ui.*; * @since 3.1.1 */ public class Parameters extends com.itmill.toolkit.Application implements - URIHandler, ParameterHandler { + URIHandler, ParameterHandler { - private Label context = new Label(); + private Label context = new Label(); - private Label relative = new Label(); + private Label relative = new Label(); - private Table params = new Table(); + private Table params = new Table(); - public void init() { - Window main = new Window("Parameters demo"); - setMainWindow(main); + public void init() { + Window main = new Window("Parameters demo"); + setMainWindow(main); - // This class acts both as URI handler and parameter handler - main.addURIHandler(this); - main.addParameterHandler(this); + // This class acts both as URI handler and parameter handler + main.addURIHandler(this); + main.addParameterHandler(this); - OrderedLayout layout = new OrderedLayout(); - Label info = new Label("To test URI and Parameter Handlers, " - + "add get parameters to URL. For example try examples below: "); - info.setCaption("Usage info"); - layout.addComponent(info); - try { - URL u1 = new URL(getURL(), "test/uri?test=1&test=2"); - URL u2 = new URL(getURL(), "foo/bar?mary=john&count=3"); - layout.addComponent(new Link(u1.toString(), - new ExternalResource(u1))); - layout.addComponent(new Label("Or this: ")); - layout.addComponent(new Link(u2.toString(), - new ExternalResource(u2))); - } catch (Exception e) { - System.out.println("Couldn't get hostname for this machine: " - + e.toString()); - e.printStackTrace(); - } + OrderedLayout layout = new OrderedLayout(); + Label info = new Label("To test URI and Parameter Handlers, " + + "add get parameters to URL. For example try examples below: "); + info.setCaption("Usage info"); + layout.addComponent(info); + try { + URL u1 = new URL(getURL(), "test/uri?test=1&test=2"); + URL u2 = new URL(getURL(), "foo/bar?mary=john&count=3"); + layout.addComponent(new Link(u1.toString(), + new ExternalResource(u1))); + layout.addComponent(new Label("Or this: ")); + layout.addComponent(new Link(u2.toString(), + new ExternalResource(u2))); + } catch (Exception e) { + System.out.println("Couldn't get hostname for this machine: " + + e.toString()); + e.printStackTrace(); + } - // URI - Panel panel1 = new Panel("URI Handler"); - context.setCaption("Last URI handler context"); - panel1.addComponent(context); - relative.setCaption("Last relative URI"); - panel1.addComponent(relative); - layout.addComponent(panel1); + // URI + Panel panel1 = new Panel("URI Handler"); + context.setCaption("Last URI handler context"); + panel1.addComponent(context); + relative.setCaption("Last relative URI"); + panel1.addComponent(relative); + layout.addComponent(panel1); - // Parameters - params.addContainerProperty("Values", String.class, ""); - Panel panel2 = new Panel("Parameter Handler"); - params.setCaption("Last parameters"); - params.setColumnHeaderMode(Table.COLUMN_HEADER_MODE_ID); - params.setRowHeaderMode(Table.ROW_HEADER_MODE_ID); - panel2.addComponent(params); - layout.addComponent(panel2); + // Parameters + params.addContainerProperty("Values", String.class, ""); + Panel panel2 = new Panel("Parameter Handler"); + params.setCaption("Last parameters"); + params.setColumnHeaderMode(Table.COLUMN_HEADER_MODE_ID); + params.setRowHeaderMode(Table.ROW_HEADER_MODE_ID); + panel2.addComponent(params); + layout.addComponent(panel2); - main.addComponent(layout); - } + main.addComponent(layout); + } - /** - * Update URI - * - * @see com.itmill.toolkit.terminal.URIHandler#handleURI(URL, String) - */ - public DownloadStream handleURI(URL context, String relativeUri) { - this.context.setValue(context.toString()); - this.relative.setValue(relativeUri); - return null; - } + /** + * Update URI + * + * @see com.itmill.toolkit.terminal.URIHandler#handleURI(URL, String) + */ + public DownloadStream handleURI(URL context, String relativeUri) { + this.context.setValue(context.toString()); + relative.setValue(relativeUri); + return null; + } - /** - * Handles GET parameters, in this demo GET parameteres are used to - * communicate with EmbeddedToolkit.jsp - */ - public void handleParameters(Map parameters) { - // TODO: disabled, see bug #550 - // params.removeAllItems(); - for (Iterator i = parameters.keySet().iterator(); i.hasNext();) { - String name = (String) i.next(); - String[] values = (String[]) parameters.get(name); - String v = ""; - for (int j = 0; j < values.length; j++) { - if (v.length() > 0) - v += ", "; - v += "'" + values[j] + "'"; - } - params.addItem(new Object[] { v }, name); - } - } + /** + * Handles GET parameters, in this demo GET parameteres are used to + * communicate with EmbeddedToolkit.jsp + */ + public void handleParameters(Map parameters) { + // TODO: disabled, see bug #550 + // params.removeAllItems(); + for (Iterator i = parameters.keySet().iterator(); i.hasNext();) { + String name = (String) i.next(); + String[] values = (String[]) parameters.get(name); + String v = ""; + for (int j = 0; j < values.length; j++) { + if (v.length() > 0) { + v += ", "; + } + v += "'" + values[j] + "'"; + } + params.addItem(new Object[] { v }, name); + } + } } diff --git a/src/com/itmill/toolkit/demo/QueryContainerDemo.java b/src/com/itmill/toolkit/demo/QueryContainerDemo.java index 66ef37c699..a7889a8be2 100644 --- a/src/com/itmill/toolkit/demo/QueryContainerDemo.java +++ b/src/com/itmill/toolkit/demo/QueryContainerDemo.java @@ -1,9 +1,10 @@ package com.itmill.toolkit.demo; import java.sql.SQLException; + import com.itmill.toolkit.data.util.QueryContainer; -import com.itmill.toolkit.event.Action; import com.itmill.toolkit.demo.util.SampleDatabase; +import com.itmill.toolkit.event.Action; import com.itmill.toolkit.ui.Label; import com.itmill.toolkit.ui.Select; import com.itmill.toolkit.ui.Table; @@ -26,162 +27,162 @@ import com.itmill.toolkit.ui.Window; * */ public class QueryContainerDemo extends com.itmill.toolkit.Application - implements Action.Handler { - - private static final String ACTION_DESCRIPTION = "Try right mouse button to initiate " - + "actions menu.
Note: on Opera you use meta key " - + "and left mouse button."; - - private static final String TABLE_CAPTION = SampleDatabase.ROWCOUNT - + " dynamically loaded rows from example SQL table"; - - // Table component where SQL rows are attached (using QueryContainer) - private Table table = new Table(); - - private Label tableLastAction = new Label("No action selected for table."); - - // Select component where SQL rows are attached (using QueryContainer) - private Select select = new Select(); - - // Tree component that uses select as datasource - private Tree tree = new Tree(); - - private Label treeLastAction = new Label("No action selected for tree."); - - // Database provided with sample data - private SampleDatabase sampleDatabase; - - // Example Actions for table - private Action ACTION1 = new Action("Upload"); - - private Action ACTION2 = new Action("Download"); - - private Action ACTION3 = new Action("Show history"); - - private Action[] actions = new Action[] { ACTION1, ACTION2, ACTION3 }; - - /** - * Initialize Application. Demo components are added to main window. - */ - public void init() { - Window main = new Window("QueryContainer demo"); - setMainWindow(main); - - // Main window contains heading, table, select and tree - main - .addComponent(new Label( - "

QueryContainer demo

" - + "Rows are loaded from the server as they are needed.
" - + "Try scrolling the table to see it in action.

" - + ACTION_DESCRIPTION, Label.CONTENT_XHTML)); - main.addComponent(table); - main.addComponent(tableLastAction); - main.addComponent(new Label("
", Label.CONTENT_XHTML)); - main.addComponent(select); - main.addComponent(new Label("
", Label.CONTENT_XHTML)); - main.addComponent(tree); - main.addComponent(treeLastAction); - - // create demo database - sampleDatabase = new SampleDatabase(); - - // initialize demo components - initTable(); - initSelect(); - initTree(); - } - - /** - * Populates table component with all rows from employee table. - * - */ - private void initTable() { - // init table - table.setCaption(TABLE_CAPTION); - table.setPageLength(10); - table.setSelectable(true); - table.setRowHeaderMode(Table.ROW_HEADER_MODE_INDEX); - table.setColumnCollapsingAllowed(true); - table.setColumnReorderingAllowed(true); - table.setSelectable(true); - // this class handles table actions (see handleActions method below) - table.addActionHandler(this); - table.setDescription(ACTION_DESCRIPTION); - - // populate Toolkit table component with test SQL table rows - try { - QueryContainer qc = new QueryContainer("SELECT * FROM employee", - sampleDatabase.getConnection()); - table.setContainerDataSource(qc); - } catch (SQLException e) { - e.printStackTrace(); - } - // define which columns should be visible on Table component - table.setVisibleColumns(new Object[] { "FIRSTNAME", "LASTNAME", - "TITLE", "UNIT" }); - table.setItemCaptionPropertyId("ID"); - } - - /** - * Populates select component with distinct unit values from employee table. - * - */ - private void initSelect() { - // init select - select.setCaption("All distinct units from employee table."); - select.setItemCaptionPropertyId("UNIT"); - - // populate Toolkit select component with test SQL table rows - try { - QueryContainer qc = new QueryContainer( - "SELECT DISTINCT UNIT FROM employee", sampleDatabase - .getConnection()); - select.setContainerDataSource(qc); - } catch (SQLException e) { - e.printStackTrace(); - } - } - - /** - * Populates tree component using select component as data source for root - * nodes, child nodes are queried from database. Implementation is done for - * example purposes only. - * - */ - private void initTree() { - // init tree - tree.setCaption("All distinct units from employee table."); - tree.setItemCaptionPropertyId("UNIT"); - tree.setSelectable(true); - // this class handles tree actions (see handleActions method below) - tree.addActionHandler(this); - tree.setDescription("Try right mouse button to initiate " - + "actions menu. Note: on Opera you use meta key " - + "and left mouse button."); - tree.setStyle("menu"); - - // Populate Toolkit Tree using select component as data source - tree.setContainerDataSource(select.getContainerDataSource()); - } - - /** - * Return example actions - */ - public Action[] getActions(Object target, Object sender) { - return actions; - } - - /** - * Executed by right mouse button on table or tree component. - */ - public void handleAction(Action action, Object sender, Object target) { - if (sender == table) { - tableLastAction.setValue("Last action clicked was '" - + action.getCaption() + "' on item " + target); - } else if (sender == tree) { - treeLastAction.setValue("Last action clicked was '" - + action.getCaption() + "' on item " + target); - } - } + implements Action.Handler { + + private static final String ACTION_DESCRIPTION = "Try right mouse button to initiate " + + "actions menu.
Note: on Opera you use meta key " + + "and left mouse button."; + + private static final String TABLE_CAPTION = SampleDatabase.ROWCOUNT + + " dynamically loaded rows from example SQL table"; + + // Table component where SQL rows are attached (using QueryContainer) + private Table table = new Table(); + + private Label tableLastAction = new Label("No action selected for table."); + + // Select component where SQL rows are attached (using QueryContainer) + private Select select = new Select(); + + // Tree component that uses select as datasource + private Tree tree = new Tree(); + + private Label treeLastAction = new Label("No action selected for tree."); + + // Database provided with sample data + private SampleDatabase sampleDatabase; + + // Example Actions for table + private Action ACTION1 = new Action("Upload"); + + private Action ACTION2 = new Action("Download"); + + private Action ACTION3 = new Action("Show history"); + + private Action[] actions = new Action[] { ACTION1, ACTION2, ACTION3 }; + + /** + * Initialize Application. Demo components are added to main window. + */ + public void init() { + Window main = new Window("QueryContainer demo"); + setMainWindow(main); + + // Main window contains heading, table, select and tree + main + .addComponent(new Label( + "

QueryContainer demo

" + + "Rows are loaded from the server as they are needed.
" + + "Try scrolling the table to see it in action.

" + + ACTION_DESCRIPTION, Label.CONTENT_XHTML)); + main.addComponent(table); + main.addComponent(tableLastAction); + main.addComponent(new Label("
", Label.CONTENT_XHTML)); + main.addComponent(select); + main.addComponent(new Label("
", Label.CONTENT_XHTML)); + main.addComponent(tree); + main.addComponent(treeLastAction); + + // create demo database + sampleDatabase = new SampleDatabase(); + + // initialize demo components + initTable(); + initSelect(); + initTree(); + } + + /** + * Populates table component with all rows from employee table. + * + */ + private void initTable() { + // init table + table.setCaption(TABLE_CAPTION); + table.setPageLength(10); + table.setSelectable(true); + table.setRowHeaderMode(Table.ROW_HEADER_MODE_INDEX); + table.setColumnCollapsingAllowed(true); + table.setColumnReorderingAllowed(true); + table.setSelectable(true); + // this class handles table actions (see handleActions method below) + table.addActionHandler(this); + table.setDescription(ACTION_DESCRIPTION); + + // populate Toolkit table component with test SQL table rows + try { + QueryContainer qc = new QueryContainer("SELECT * FROM employee", + sampleDatabase.getConnection()); + table.setContainerDataSource(qc); + } catch (SQLException e) { + e.printStackTrace(); + } + // define which columns should be visible on Table component + table.setVisibleColumns(new Object[] { "FIRSTNAME", "LASTNAME", + "TITLE", "UNIT" }); + table.setItemCaptionPropertyId("ID"); + } + + /** + * Populates select component with distinct unit values from employee table. + * + */ + private void initSelect() { + // init select + select.setCaption("All distinct units from employee table."); + select.setItemCaptionPropertyId("UNIT"); + + // populate Toolkit select component with test SQL table rows + try { + QueryContainer qc = new QueryContainer( + "SELECT DISTINCT UNIT FROM employee", sampleDatabase + .getConnection()); + select.setContainerDataSource(qc); + } catch (SQLException e) { + e.printStackTrace(); + } + } + + /** + * Populates tree component using select component as data source for root + * nodes, child nodes are queried from database. Implementation is done for + * example purposes only. + * + */ + private void initTree() { + // init tree + tree.setCaption("All distinct units from employee table."); + tree.setItemCaptionPropertyId("UNIT"); + tree.setSelectable(true); + // this class handles tree actions (see handleActions method below) + tree.addActionHandler(this); + tree.setDescription("Try right mouse button to initiate " + + "actions menu. Note: on Opera you use meta key " + + "and left mouse button."); + tree.setStyle("menu"); + + // Populate Toolkit Tree using select component as data source + tree.setContainerDataSource(select.getContainerDataSource()); + } + + /** + * Return example actions + */ + public Action[] getActions(Object target, Object sender) { + return actions; + } + + /** + * Executed by right mouse button on table or tree component. + */ + public void handleAction(Action action, Object sender, Object target) { + if (sender == table) { + tableLastAction.setValue("Last action clicked was '" + + action.getCaption() + "' on item " + target); + } else if (sender == tree) { + treeLastAction.setValue("Last action clicked was '" + + action.getCaption() + "' on item " + target); + } + } } diff --git a/src/com/itmill/toolkit/demo/SelectDemo.java b/src/com/itmill/toolkit/demo/SelectDemo.java index 20128ea9da..cc6816206d 100644 --- a/src/com/itmill/toolkit/demo/SelectDemo.java +++ b/src/com/itmill/toolkit/demo/SelectDemo.java @@ -8,6 +8,7 @@ import com.itmill.toolkit.ui.Label; import com.itmill.toolkit.ui.Panel; import com.itmill.toolkit.ui.Select; import com.itmill.toolkit.ui.Window; +import com.itmill.toolkit.ui.AbstractSelect.Filtering; /** * This example demonstrates what is lazy loading feature on Select component. @@ -19,58 +20,57 @@ import com.itmill.toolkit.ui.Window; */ public class SelectDemo extends com.itmill.toolkit.Application { - // Select component where SQL rows are attached (using QueryContainer) - private final Select select = new Select(); + // Select component where SQL rows are attached (using QueryContainer) + private final Select select = new Select(); - private final Select lazySelect = new Select(); + private final Select lazySelect = new Select(); - // Database provided with sample data - private SampleDatabase sampleDatabase; + // Database provided with sample data + private SampleDatabase sampleDatabase; - /** - * Initialize Application. Demo components are added to main window. - */ - public void init() { - Window main = new Window("Select demo"); - setMainWindow(main); + /** + * Initialize Application. Demo components are added to main window. + */ + public void init() { + Window main = new Window("Select demo"); + setMainWindow(main); - // Main window contains heading, table, select and tree - Panel panel = new Panel("Select demo (a.k.a Google Suggests)"); - panel.addComponent(this.lazySelect); - panel.addComponent(new Label("
", Label.CONTENT_XHTML)); - panel.addComponent(this.select); - main.addComponent(panel); + // Main window contains heading, table, select and tree + Panel panel = new Panel("Select demo (a.k.a Google Suggests)"); + panel.addComponent(lazySelect); + panel.addComponent(new Label("
", Label.CONTENT_XHTML)); + panel.addComponent(select); + main.addComponent(panel); - // create demo database - this.sampleDatabase = new SampleDatabase(); + // create demo database + sampleDatabase = new SampleDatabase(); - initSelects(); - } + initSelects(); + } - private void initSelects() { - // init select - this.select.setCaption("All employees default functionality."); - this.select.setItemCaptionPropertyId("WORKER"); - // populate Toolkit select component with test SQL table rows - try { - QueryContainer qc = new QueryContainer( - "SELECT ID, UNIT||', '||LASTNAME||' '||FIRSTNAME" - + " AS WORKER FROM employee ORDER BY WORKER", - this.sampleDatabase.getConnection()); - this.select.setContainerDataSource(qc); - } catch (SQLException e) { - e.printStackTrace(); - } + private void initSelects() { + // init select + select.setCaption("All employees default functionality."); + select.setItemCaptionPropertyId("WORKER"); + // populate Toolkit select component with test SQL table rows + try { + QueryContainer qc = new QueryContainer( + "SELECT ID, UNIT||', '||LASTNAME||' '||FIRSTNAME" + + " AS WORKER FROM employee ORDER BY WORKER", + sampleDatabase.getConnection()); + select.setContainerDataSource(qc); + } catch (SQLException e) { + e.printStackTrace(); + } - // init lazySelect - this.lazySelect.setCaption("All employees with lazy loading " - + "(a.k.a Google Suggests) activated."); - this.lazySelect.setItemCaptionPropertyId("WORKER"); - this.lazySelect.setFilteringMode(Select.FILTERINGMODE_CONTAINS); + // init lazySelect + lazySelect.setCaption("All employees with lazy loading " + + "(a.k.a Google Suggests) activated."); + lazySelect.setItemCaptionPropertyId("WORKER"); + lazySelect.setFilteringMode(Filtering.FILTERINGMODE_CONTAINS); - // use same datasource as select object uses - this.lazySelect.setContainerDataSource(this.select - .getContainerDataSource()); - } + // use same datasource as select object uses + lazySelect.setContainerDataSource(select.getContainerDataSource()); + } } diff --git a/src/com/itmill/toolkit/demo/TableDemo.java b/src/com/itmill/toolkit/demo/TableDemo.java index 1b7e935cd8..9010ec5a55 100644 --- a/src/com/itmill/toolkit/demo/TableDemo.java +++ b/src/com/itmill/toolkit/demo/TableDemo.java @@ -3,8 +3,8 @@ package com.itmill.toolkit.demo; import java.sql.SQLException; import com.itmill.toolkit.data.util.QueryContainer; -import com.itmill.toolkit.event.Action; import com.itmill.toolkit.demo.util.SampleDatabase; +import com.itmill.toolkit.event.Action; import com.itmill.toolkit.terminal.ExternalResource; import com.itmill.toolkit.ui.Button; import com.itmill.toolkit.ui.Label; @@ -21,165 +21,165 @@ import com.itmill.toolkit.ui.Window; * */ public class TableDemo extends com.itmill.toolkit.Application implements - Action.Handler { - - private static final String ACTION_DESCRIPTION = "Use right mouse button to initiate " - + "actions menu.
Note: on Opera use meta key " - + "and left mouse button."; - - private static final String TABLE_CAPTION = SampleDatabase.ROWCOUNT - + " dynamically loaded rows from example SQL table"; - - private Link menuLink = new Link("Go back to menu", new ExternalResource( - "index.html")); - - // Table component where SQL rows are attached (using QueryContainer) - private Table table = new Table(); - - // Label which displays last performed action against table row - private Label tableLastAction = new Label("No action selected for table."); - - // Database provided with sample data - private SampleDatabase sampleDatabase; - - // Example Actions for table - private Action ACTION1 = new Action("Upload"); - - private Action ACTION2 = new Action("Download"); - - private Action ACTION3 = new Action("Show history"); - - private Action[] actions = new Action[] { ACTION1, ACTION2, ACTION3 }; - - // Button which is used to disable or enable table - // note: when button click event occurs, tableEnabler() method is called - private Button tableEnabler = new Button("Disable table", this, - "tableEnabler"); - - // Button which is used to hide or show table - // note: when button click event occurs, tableVisibility() method is called - private Button tableVisibility = new Button("Hide table", this, - "tableVisibility"); - - // Button which is used to hide or show table - // note: when button click event occurs, tableVisibility() method is called - private Button tableCaption = new Button("Hide caption", this, - "tableCaption"); - - /** - * Initialize Application. Demo components are added to main window. - */ - public void init() { - Window main = new Window("Table demo"); - setMainWindow(main); - - // Add link back to index.html - main.addComponent(menuLink); - - // create demo database - sampleDatabase = new SampleDatabase(); - - // Main window contains heading, two buttons, table and label - main - .addComponent(new Label( - "

Table demo

" - + "Rows are loaded from the server as they are needed.
" - + "Try scrolling the table to see it in action.

" - + ACTION_DESCRIPTION, Label.CONTENT_XHTML)); - OrderedLayout layout = new OrderedLayout( - OrderedLayout.ORIENTATION_HORIZONTAL); - // TODO: disabled until #655 fixed - // layout.addComponent(tableVisibility); - layout.addComponent(tableEnabler); - layout.addComponent(tableCaption); - main.addComponent(layout); - main.addComponent(table); - main.addComponent(tableLastAction); - - // initialize demo components - initTable(); - } - - /** - * Populates table component with all rows from employee table. - * - */ - private void initTable() { - // init table - table.setCaption(TABLE_CAPTION); - table.setPageLength(10); - table.setSelectable(true); - table.setRowHeaderMode(Table.ROW_HEADER_MODE_INDEX); - table.setColumnCollapsingAllowed(true); - table.setColumnReorderingAllowed(true); - table.setSelectable(true); - // this class handles table actions (see handleActions method below) - table.addActionHandler(this); - table.setDescription(ACTION_DESCRIPTION); - - // populate Toolkit table component with test SQL table rows - try { - QueryContainer qc = new QueryContainer("SELECT * FROM employee", - sampleDatabase.getConnection()); - table.setContainerDataSource(qc); - } catch (SQLException e) { - e.printStackTrace(); - } - // define which columns should be visible on Table component - table.setVisibleColumns(new Object[] { "FIRSTNAME", "LASTNAME", - "TITLE", "UNIT" }); - table.setItemCaptionPropertyId("ID"); - } - - public void tableVisibility() { - if (table.isVisible()) { - tableVisibility.setCaption("Show table"); - table.setVisible(false); - tableEnabler.setEnabled(false); - tableCaption.setEnabled(false); - } else { - tableVisibility.setCaption("Hide table"); - table.setVisible(true); - tableEnabler.setEnabled(true); - tableCaption.setEnabled(true); - } - } - - public void tableEnabler() { - if (table.isEnabled()) { - tableEnabler.setCaption("Enable table"); - table.setEnabled(false); - } else { - tableEnabler.setCaption("Disable table"); - table.setEnabled(true); - } - } - - public void tableCaption() { - if (table.getCaption().equals("")) { - table.setCaption(TABLE_CAPTION); - tableCaption.setCaption("Hide caption"); - } else { - table.setCaption(""); - tableCaption.setCaption("Show caption"); - } - } - - /** - * URIHandler Return example actions - */ - public Action[] getActions(Object target, Object sender) { - return actions; - } - - /** - * Executed by right mouse button on table or tree component. - */ - public void handleAction(Action action, Object sender, Object target) { - if (sender == table) { - tableLastAction.setValue("Last action clicked was '" - + action.getCaption() + "' on item " + target); - } - } + Action.Handler { + + private static final String ACTION_DESCRIPTION = "Use right mouse button to initiate " + + "actions menu.
Note: on Opera use meta key " + + "and left mouse button."; + + private static final String TABLE_CAPTION = SampleDatabase.ROWCOUNT + + " dynamically loaded rows from example SQL table"; + + private Link menuLink = new Link("Go back to menu", new ExternalResource( + "index.html")); + + // Table component where SQL rows are attached (using QueryContainer) + private Table table = new Table(); + + // Label which displays last performed action against table row + private Label tableLastAction = new Label("No action selected for table."); + + // Database provided with sample data + private SampleDatabase sampleDatabase; + + // Example Actions for table + private Action ACTION1 = new Action("Upload"); + + private Action ACTION2 = new Action("Download"); + + private Action ACTION3 = new Action("Show history"); + + private Action[] actions = new Action[] { ACTION1, ACTION2, ACTION3 }; + + // Button which is used to disable or enable table + // note: when button click event occurs, tableEnabler() method is called + private Button tableEnabler = new Button("Disable table", this, + "tableEnabler"); + + // Button which is used to hide or show table + // note: when button click event occurs, tableVisibility() method is called + private Button tableVisibility = new Button("Hide table", this, + "tableVisibility"); + + // Button which is used to hide or show table + // note: when button click event occurs, tableVisibility() method is called + private Button tableCaption = new Button("Hide caption", this, + "tableCaption"); + + /** + * Initialize Application. Demo components are added to main window. + */ + public void init() { + Window main = new Window("Table demo"); + setMainWindow(main); + + // Add link back to index.html + main.addComponent(menuLink); + + // create demo database + sampleDatabase = new SampleDatabase(); + + // Main window contains heading, two buttons, table and label + main + .addComponent(new Label( + "

Table demo

" + + "Rows are loaded from the server as they are needed.
" + + "Try scrolling the table to see it in action.

" + + ACTION_DESCRIPTION, Label.CONTENT_XHTML)); + OrderedLayout layout = new OrderedLayout( + OrderedLayout.ORIENTATION_HORIZONTAL); + // TODO: disabled until #655 fixed + // layout.addComponent(tableVisibility); + layout.addComponent(tableEnabler); + layout.addComponent(tableCaption); + main.addComponent(layout); + main.addComponent(table); + main.addComponent(tableLastAction); + + // initialize demo components + initTable(); + } + + /** + * Populates table component with all rows from employee table. + * + */ + private void initTable() { + // init table + table.setCaption(TABLE_CAPTION); + table.setPageLength(10); + table.setSelectable(true); + table.setRowHeaderMode(Table.ROW_HEADER_MODE_INDEX); + table.setColumnCollapsingAllowed(true); + table.setColumnReorderingAllowed(true); + table.setSelectable(true); + // this class handles table actions (see handleActions method below) + table.addActionHandler(this); + table.setDescription(ACTION_DESCRIPTION); + + // populate Toolkit table component with test SQL table rows + try { + QueryContainer qc = new QueryContainer("SELECT * FROM employee", + sampleDatabase.getConnection()); + table.setContainerDataSource(qc); + } catch (SQLException e) { + e.printStackTrace(); + } + // define which columns should be visible on Table component + table.setVisibleColumns(new Object[] { "FIRSTNAME", "LASTNAME", + "TITLE", "UNIT" }); + table.setItemCaptionPropertyId("ID"); + } + + public void tableVisibility() { + if (table.isVisible()) { + tableVisibility.setCaption("Show table"); + table.setVisible(false); + tableEnabler.setEnabled(false); + tableCaption.setEnabled(false); + } else { + tableVisibility.setCaption("Hide table"); + table.setVisible(true); + tableEnabler.setEnabled(true); + tableCaption.setEnabled(true); + } + } + + public void tableEnabler() { + if (table.isEnabled()) { + tableEnabler.setCaption("Enable table"); + table.setEnabled(false); + } else { + tableEnabler.setCaption("Disable table"); + table.setEnabled(true); + } + } + + public void tableCaption() { + if (table.getCaption().equals("")) { + table.setCaption(TABLE_CAPTION); + tableCaption.setCaption("Hide caption"); + } else { + table.setCaption(""); + tableCaption.setCaption("Show caption"); + } + } + + /** + * URIHandler Return example actions + */ + public Action[] getActions(Object target, Object sender) { + return actions; + } + + /** + * Executed by right mouse button on table or tree component. + */ + public void handleAction(Action action, Object sender, Object target) { + if (sender == table) { + tableLastAction.setValue("Last action clicked was '" + + action.getCaption() + "' on item " + target); + } + } } diff --git a/src/com/itmill/toolkit/demo/TreeFilesystem.java b/src/com/itmill/toolkit/demo/TreeFilesystem.java index b0c4d7dca9..fc729f970a 100644 --- a/src/com/itmill/toolkit/demo/TreeFilesystem.java +++ b/src/com/itmill/toolkit/demo/TreeFilesystem.java @@ -1,9 +1,13 @@ package com.itmill.toolkit.demo; import java.io.File; + import com.itmill.toolkit.data.Item; import com.itmill.toolkit.demo.util.SampleDirectory; -import com.itmill.toolkit.ui.*; +import com.itmill.toolkit.ui.Label; +import com.itmill.toolkit.ui.Panel; +import com.itmill.toolkit.ui.Tree; +import com.itmill.toolkit.ui.Window; import com.itmill.toolkit.ui.Tree.ExpandEvent; /** @@ -17,79 +21,83 @@ import com.itmill.toolkit.ui.Tree.ExpandEvent; * */ public class TreeFilesystem extends com.itmill.toolkit.Application implements - Tree.ExpandListener { + Tree.ExpandListener { - // Filesystem explorer panel and it's components - private Panel explorerPanel = new Panel("Filesystem explorer"); + // Filesystem explorer panel and it's components + private Panel explorerPanel = new Panel("Filesystem explorer"); - private Tree tree = new Tree(); + private Tree tree = new Tree(); - public void init() { - Window main = new Window("Tree filesystem demo"); - setMainWindow(main); + public void init() { + Window main = new Window("Tree filesystem demo"); + setMainWindow(main); - // Main window contains heading and panel - main.addComponent(new Label("

Tree demo

", Label.CONTENT_XHTML)); + // Main window contains heading and panel + main.addComponent(new Label("

Tree demo

", Label.CONTENT_XHTML)); - // configure file structure panel - main.addComponent(explorerPanel); - explorerPanel.addComponent(tree); - explorerPanel.setHeight(400); + // configure file structure panel + main.addComponent(explorerPanel); + explorerPanel.addComponent(tree); + explorerPanel.setHeight(400); - // "this" handles tree's expand event - tree.addListener((Tree.ExpandListener) this); + // "this" handles tree's expand event + tree.addListener(this); - // Get sample directory - File sampleDir = SampleDirectory.getDirectory(this); - // populate tree's root node with example directory - if (sampleDir != null) - populateNode(sampleDir.getAbsolutePath(), null); - } + // Get sample directory + File sampleDir = SampleDirectory.getDirectory(this); + // populate tree's root node with example directory + if (sampleDir != null) { + populateNode(sampleDir.getAbsolutePath(), null); + } + } - /** - * Handle tree expand event, populate expanded node's childs with new files - * and directories. - */ - public void nodeExpand(ExpandEvent event) { - Item i = tree.getItem(event.getItemId()); - if (!tree.hasChildren(i)) { - // populate tree's node which was expanded - populateNode(event.getItemId().toString(), event.getItemId()); - } - } + /** + * Handle tree expand event, populate expanded node's childs with new files + * and directories. + */ + public void nodeExpand(ExpandEvent event) { + Item i = tree.getItem(event.getItemId()); + if (!tree.hasChildren(i)) { + // populate tree's node which was expanded + populateNode(event.getItemId().toString(), event.getItemId()); + } + } - /** - * Populates files to tree as items. In this example items are of String - * type that consist of file path. New items are added to tree and item's - * parent and children properties are updated. - * - * @param file - * path which contents are added to tree - * @param parent - * for added nodes, if null then new nodes are added to root node - */ - private void populateNode(String file, Object parent) { - File subdir = new File(file); - File[] files = subdir.listFiles(); - for (int x = 0; x < files.length; x++) { - try { - // add new item (String) to tree - String path = files[x].getCanonicalPath().toString(); - tree.addItem(path); - // set parent if this item has one - if (parent != null) - tree.setParent(path, parent); - // check if item is a directory and read access exists - if (files[x].isDirectory() && files[x].canRead()) - // yes, childrens therefore exists - tree.setChildrenAllowed(path, true); - else - // no, childrens therefore do not exists - tree.setChildrenAllowed(path, false); - } catch (Exception e) { - throw new RuntimeException(e); - } - } - } + /** + * Populates files to tree as items. In this example items are of String + * type that consist of file path. New items are added to tree and item's + * parent and children properties are updated. + * + * @param file + * path which contents are added to tree + * @param parent + * for added nodes, if null then new nodes are added to root + * node + */ + private void populateNode(String file, Object parent) { + File subdir = new File(file); + File[] files = subdir.listFiles(); + for (int x = 0; x < files.length; x++) { + try { + // add new item (String) to tree + String path = files[x].getCanonicalPath().toString(); + tree.addItem(path); + // set parent if this item has one + if (parent != null) { + tree.setParent(path, parent); + } + // check if item is a directory and read access exists + if (files[x].isDirectory() && files[x].canRead()) { + // yes, childrens therefore exists + tree.setChildrenAllowed(path, true); + } else { + // no, childrens therefore do not exists + tree.setChildrenAllowed(path, false); + } + } catch (Exception e) { + throw new RuntimeException(e); + } + } + } } diff --git a/src/com/itmill/toolkit/demo/TreeFilesystemContainer.java b/src/com/itmill/toolkit/demo/TreeFilesystemContainer.java index 6311766829..33ca45e728 100644 --- a/src/com/itmill/toolkit/demo/TreeFilesystemContainer.java +++ b/src/com/itmill/toolkit/demo/TreeFilesystemContainer.java @@ -5,7 +5,11 @@ import java.io.File; import com.itmill.toolkit.data.util.FilesystemContainer; import com.itmill.toolkit.data.util.FilesystemContainer.FileItem; import com.itmill.toolkit.demo.util.SampleDirectory; -import com.itmill.toolkit.ui.*; +import com.itmill.toolkit.ui.Field; +import com.itmill.toolkit.ui.Label; +import com.itmill.toolkit.ui.Panel; +import com.itmill.toolkit.ui.Tree; +import com.itmill.toolkit.ui.Window; import com.itmill.toolkit.ui.Component.Event; import com.itmill.toolkit.ui.Component.Listener; @@ -21,68 +25,68 @@ import com.itmill.toolkit.ui.Component.Listener; * */ public class TreeFilesystemContainer extends com.itmill.toolkit.Application - implements Listener { + implements Listener { - // Filesystem explorer panel and it's components - private Panel explorerPanel = new Panel("Filesystem explorer"); + // Filesystem explorer panel and it's components + private Panel explorerPanel = new Panel("Filesystem explorer"); - private Tree filesystem = new Tree(); + private Tree filesystem = new Tree(); - // File properties panel and it's components - private Panel propertyPanel = new Panel("File properties"); + // File properties panel and it's components + private Panel propertyPanel = new Panel("File properties"); - private Label fileProperties = new Label(); + private Label fileProperties = new Label(); - public void init() { - Window main = new Window("Tree FilesystemContainer demo"); - setMainWindow(main); + public void init() { + Window main = new Window("Tree FilesystemContainer demo"); + setMainWindow(main); - // Main window contains heading and two panels - main.addComponent(new Label("

TreeFilesystemContainer demo

", - Label.CONTENT_XHTML)); - main.addComponent(propertyPanel); - main.addComponent(explorerPanel); + // Main window contains heading and two panels + main.addComponent(new Label("

TreeFilesystemContainer demo

", + Label.CONTENT_XHTML)); + main.addComponent(propertyPanel); + main.addComponent(explorerPanel); - // Explorer panel contains tree - explorerPanel.addComponent(filesystem); + // Explorer panel contains tree + explorerPanel.addComponent(filesystem); - // Property panel contains label - propertyPanel.addComponent(fileProperties); - fileProperties.setCaption("No file selected."); - propertyPanel.setEnabled(false); + // Property panel contains label + propertyPanel.addComponent(fileProperties); + fileProperties.setCaption("No file selected."); + propertyPanel.setEnabled(false); - // Get sample directory - File sampleDir = SampleDirectory.getDirectory(this); - // Populate tree with FilesystemContainer - FilesystemContainer fsc = new FilesystemContainer(sampleDir, true); - filesystem.setContainerDataSource(fsc); - // "this" handles all filesystem events - // e.g. node clicked, expanded etc. - filesystem.addListener((Listener) this); - // Value changes are immediate - filesystem.setImmediate(true); - } + // Get sample directory + File sampleDir = SampleDirectory.getDirectory(this); + // Populate tree with FilesystemContainer + FilesystemContainer fsc = new FilesystemContainer(sampleDir, true); + filesystem.setContainerDataSource(fsc); + // "this" handles all filesystem events + // e.g. node clicked, expanded etc. + filesystem.addListener(this); + // Value changes are immediate + filesystem.setImmediate(true); + } - /** - * Listener for any component events. This class has been registered as an - * listener for component fsTree. - */ - public void componentEvent(Event event) { - // Check if event occured at fsTree component - if (event.getSource() == filesystem) { - // Check if event is about changing value - if (event.getClass() == Field.ValueChangeEvent.class) { - // Update property panel contents - FileItem fileItem = (FileItem) filesystem.getItem(filesystem - .getValue()); - fileProperties.setIcon(fileItem.getIcon()); - fileProperties.setCaption(fileItem.getName() + ", size " - + fileItem.getSize() + " bytes."); - } - // here we could check for other type of events for filesystem - // component - } - // here we could check for other component's events - } + /** + * Listener for any component events. This class has been registered as an + * listener for component fsTree. + */ + public void componentEvent(Event event) { + // Check if event occured at fsTree component + if (event.getSource() == filesystem) { + // Check if event is about changing value + if (event.getClass() == Field.ValueChangeEvent.class) { + // Update property panel contents + FileItem fileItem = (FileItem) filesystem.getItem(filesystem + .getValue()); + fileProperties.setIcon(fileItem.getIcon()); + fileProperties.setCaption(fileItem.getName() + ", size " + + fileItem.getSize() + " bytes."); + } + // here we could check for other type of events for filesystem + // component + } + // here we could check for other component's events + } } diff --git a/src/com/itmill/toolkit/demo/UpgradingSample.java b/src/com/itmill/toolkit/demo/UpgradingSample.java index bfbbaf2a96..922c129932 100644 --- a/src/com/itmill/toolkit/demo/UpgradingSample.java +++ b/src/com/itmill/toolkit/demo/UpgradingSample.java @@ -9,7 +9,15 @@ package com.itmill.toolkit.demo; // import com.itmill.toolkit.Application; import com.itmill.toolkit.data.Property; -import com.itmill.toolkit.ui.*; +import com.itmill.toolkit.ui.Button; +import com.itmill.toolkit.ui.CustomComponent; +import com.itmill.toolkit.ui.GridLayout; +import com.itmill.toolkit.ui.Label; +import com.itmill.toolkit.ui.OrderedLayout; +import com.itmill.toolkit.ui.Panel; +import com.itmill.toolkit.ui.TextField; +import com.itmill.toolkit.ui.Tree; +import com.itmill.toolkit.ui.Window; /** *

@@ -23,127 +31,134 @@ import com.itmill.toolkit.ui.*; * @author IT Mill Ltd. */ public class UpgradingSample extends Application implements - Property.ValueChangeListener { - - /* Menu for navigating inside the application. */ - private Tree menu = new Tree(); - - /* Contents of the website */ - private String[][] pages = { { "Welcome", "Welcome to our website..." }, - { "Products", "Public product information." }, - { "Contact", "Public contact information." }, - { "CRM", "CRM Database requiring login." }, - { "Intranet", "Internal information database." } }; - - /* Application layout */ - private GridLayout layout = new GridLayout(2, 1); - - /* Initialize the application */ - public void init() { - - // Create the main window of the application - Window main = new Window("Login example", layout); - setMainWindow(main); - - // Add menu and loginbox to the application - OrderedLayout l = new OrderedLayout(); - layout.addComponent(l, 0, 0); - l.addComponent(menu); - l.addComponent(new LoginBox()); - - // Setup menu - menu.setStyle("menu"); - menu.addListener(this); - menu.setImmediate(true); - addToMenu(new String[] { "Welcome", "Products", "Contact" }); - } - - // Overriding usetUser method is a simple way of updating application - // privileges when the user is changed - public void setUser(Object user) { - super.setUser(user); - if (user != null) - addToMenu(new String[] { "CRM", "Intranet" }); - } - - public void addToMenu(String[] items) { - for (int i = 0; i < items.length; i++) { - menu.addItem(items[i]); - menu.setChildrenAllowed(items[i], false); - } - if (menu.getValue() == null) - menu.setValue(items[0]); - } - - // Handle menu selection and update visible page - public void valueChange(Property.ValueChangeEvent event) { - layout.removeComponent(1, 0); - String title = (String) menu.getValue(); - for (int i = 0; i < pages.length; i++) - if (pages[i][0].equals(title)) { - Panel p = new Panel(pages[i][0]); - p.addComponent(new Label(pages[i][1])); - p.setStyle("strong"); - layout.addComponent(p, 1, 0); - } - } - - // Simple loginbox component for the application - public class LoginBox extends CustomComponent implements - Application.UserChangeListener { - - // The components this loginbox is composed of - private TextField loginName = new TextField("Name"); - - private Button loginButton = new Button("Enter", this, "login"); - - private Panel loginPanel = new Panel("Login"); - - private Panel statusPanel = new Panel(); - - private Button logoutButton = new Button("Logout", - UpgradingSample.this, "close"); - - private Label statusLabel = new Label(); - - // Initialize login component - public LoginBox() { - - // Initialize the component - loginPanel.addComponent(loginName); - loginPanel.addComponent(loginButton); - loginPanel.setStyle("strong"); - loginName.setColumns(8); - statusPanel.addComponent(statusLabel); - statusPanel.addComponent(logoutButton); - - // Set the status of the loginbox and show correct components - updateStatus(); - - // Listen application user change events - UpgradingSample.this.addListener(this); - } - - // Login into application - public void login() { - String name = (String) loginName.getValue(); - if (name != null && name.length() > 0) - setUser(name); - loginName.setValue(""); - } - - // Update login status on application user change events - public void applicationUserChanged(Application.UserChangeEvent event) { - updateStatus(); - } - - // Update login status of the component by exposing correct components - private void updateStatus() { - statusLabel.setValue("User: " + getUser()); - if (getUser() != null) - setCompositionRoot(statusPanel); - else - setCompositionRoot(loginPanel); - } - } + Property.ValueChangeListener { + + /* Menu for navigating inside the application. */ + private Tree menu = new Tree(); + + /* Contents of the website */ + private String[][] pages = { { "Welcome", "Welcome to our website..." }, + { "Products", "Public product information." }, + { "Contact", "Public contact information." }, + { "CRM", "CRM Database requiring login." }, + { "Intranet", "Internal information database." } }; + + /* Application layout */ + private GridLayout layout = new GridLayout(2, 1); + + /* Initialize the application */ + public void init() { + + // Create the main window of the application + Window main = new Window("Login example", layout); + setMainWindow(main); + + // Add menu and loginbox to the application + OrderedLayout l = new OrderedLayout(); + layout.addComponent(l, 0, 0); + l.addComponent(menu); + l.addComponent(new LoginBox()); + + // Setup menu + menu.setStyle("menu"); + menu.addListener(this); + menu.setImmediate(true); + addToMenu(new String[] { "Welcome", "Products", "Contact" }); + } + + // Overriding usetUser method is a simple way of updating application + // privileges when the user is changed + public void setUser(Object user) { + super.setUser(user); + if (user != null) { + addToMenu(new String[] { "CRM", "Intranet" }); + } + } + + public void addToMenu(String[] items) { + for (int i = 0; i < items.length; i++) { + menu.addItem(items[i]); + menu.setChildrenAllowed(items[i], false); + } + if (menu.getValue() == null) { + menu.setValue(items[0]); + } + } + + // Handle menu selection and update visible page + public void valueChange(Property.ValueChangeEvent event) { + layout.removeComponent(1, 0); + String title = (String) menu.getValue(); + for (int i = 0; i < pages.length; i++) { + if (pages[i][0].equals(title)) { + Panel p = new Panel(pages[i][0]); + p.addComponent(new Label(pages[i][1])); + p.setStyle("strong"); + layout.addComponent(p, 1, 0); + } + } + } + + // Simple loginbox component for the application + public class LoginBox extends CustomComponent implements + Application.UserChangeListener { + + // The components this loginbox is composed of + private TextField loginName = new TextField("Name"); + + private Button loginButton = new Button("Enter", this, "login"); + + private Panel loginPanel = new Panel("Login"); + + private Panel statusPanel = new Panel(); + + private Button logoutButton = new Button("Logout", + UpgradingSample.this, "close"); + + private Label statusLabel = new Label(); + + // Initialize login component + public LoginBox() { + + // Initialize the component + loginPanel.addComponent(loginName); + loginPanel.addComponent(loginButton); + loginPanel.setStyle("strong"); + loginName.setColumns(8); + statusPanel.addComponent(statusLabel); + statusPanel.addComponent(logoutButton); + + // Set the status of the loginbox and show correct + // components + updateStatus(); + + // Listen application user change events + UpgradingSample.this.addListener(this); + } + + // Login into application + public void login() { + String name = (String) loginName.getValue(); + if (name != null && name.length() > 0) { + setUser(name); + } + loginName.setValue(""); + } + + // Update login status on application user change events + public void applicationUserChanged(Application.UserChangeEvent event) { + updateStatus(); + } + + // Update login status of the component by exposing correct + // components + private void updateStatus() { + statusLabel.setValue("User: " + getUser()); + if (getUser() != null) { + setCompositionRoot(statusPanel); + } else { + setCompositionRoot(loginPanel); + } + } + } } diff --git a/src/com/itmill/toolkit/demo/WindowedDemos.java b/src/com/itmill/toolkit/demo/WindowedDemos.java index 04e67bbf3b..840f153ed2 100644 --- a/src/com/itmill/toolkit/demo/WindowedDemos.java +++ b/src/com/itmill/toolkit/demo/WindowedDemos.java @@ -17,70 +17,70 @@ import com.itmill.toolkit.ui.Button.ClickEvent; */ public class WindowedDemos extends com.itmill.toolkit.Application { - // keeps track of created windows - private final HashMap windows = new HashMap(); + // keeps track of created windows + private final HashMap windows = new HashMap(); - // mapping demo name to URL - private static final HashMap servlets = new HashMap(); - static { - servlets.put("Caching demo", "CachingDemo/"); - servlets.put("Calculator", "Calc/"); - servlets.put("Calendar demo", "CalendarDemo/"); - servlets.put("Select demo", "SelectDemo/"); - servlets.put("Table demo", "TableDemo/"); - servlets.put("Browser demo", "BrowserDemo/"); - servlets.put("Notification demo", "NotificationDemo/"); - } + // mapping demo name to URL + private static final HashMap servlets = new HashMap(); + static { + servlets.put("Caching demo", "CachingDemo/"); + servlets.put("Calculator", "Calc/"); + servlets.put("Calendar demo", "CalendarDemo/"); + servlets.put("Select demo", "SelectDemo/"); + servlets.put("Table demo", "TableDemo/"); + servlets.put("Browser demo", "BrowserDemo/"); + servlets.put("Notification demo", "NotificationDemo/"); + } - public void init() { + public void init() { - // Create new window for the application and give the window a visible. - Window main = new Window("IT Mill Toolkit 5 Windowed Demos"); - // set as main window - setMainWindow(main); + // Create new window for the application and give the window a visible. + Window main = new Window("IT Mill Toolkit 5 Windowed Demos"); + // set as main window + setMainWindow(main); - // Create menu window. - Window menu = new Window("Select demo"); - menu.setWidth(200); - menu.setHeight(400); - main.addWindow(menu); // add to layout + // Create menu window. + Window menu = new Window("Select demo"); + menu.setWidth(200); + menu.setHeight(400); + main.addWindow(menu); // add to layout - // Create a menu button for each demo - for (Iterator it = servlets.keySet().iterator(); it.hasNext();) { - String name = (String) it.next(); - Button b = new Button(name, new Button.ClickListener() { - public void buttonClick(ClickEvent event) { - show(event.getButton().getCaption()); - } + // Create a menu button for each demo + for (Iterator it = servlets.keySet().iterator(); it.hasNext();) { + String name = (String) it.next(); + Button b = new Button(name, new Button.ClickListener() { + public void buttonClick(ClickEvent event) { + show(event.getButton().getCaption()); + } - }); - b.setStyleName("link"); - menu.addComponent(b); - } + }); + b.setStyleName("link"); + menu.addComponent(b); + } - } + } - /** - * Shows the specified demo in a separate window. Creates a new window if - * the demo has not been shown already, re-uses old window otherwise. - * - * @param demoName - * the name of the demo to be shown - */ - private void show(String demoName) { - Window w = (Window) windows.get(demoName); - if (w == null) { - w = new Window(demoName); - w.setWidth(520); - w.setHeight(500); - w.setPositionX(202); - windows.put(demoName, w); - getMainWindow().addWindow(w); - } else { - w.setVisible(true); - } - w.open(new ExternalResource((String) servlets.get(demoName))); + /** + * Shows the specified demo in a separate window. Creates a new window if + * the demo has not been shown already, re-uses old window otherwise. + * + * @param demoName + * the name of the demo to be shown + */ + private void show(String demoName) { + Window w = (Window) windows.get(demoName); + if (w == null) { + w = new Window(demoName); + w.setWidth(520); + w.setHeight(500); + w.setPositionX(202); + windows.put(demoName, w); + getMainWindow().addWindow(w); + } else { + w.setVisible(true); + } + w.open(new ExternalResource((String) servlets.get(demoName))); - } + } } diff --git a/src/com/itmill/toolkit/demo/colorpicker/ColorPicker.java b/src/com/itmill/toolkit/demo/colorpicker/ColorPicker.java index c2a09d48b2..12ecb24dbf 100644 --- a/src/com/itmill/toolkit/demo/colorpicker/ColorPicker.java +++ b/src/com/itmill/toolkit/demo/colorpicker/ColorPicker.java @@ -1,57 +1,59 @@ package com.itmill.toolkit.demo.colorpicker; import java.util.Map; + import com.itmill.toolkit.terminal.PaintException; import com.itmill.toolkit.terminal.PaintTarget; -import com.itmill.toolkit.ui.*; +import com.itmill.toolkit.ui.AbstractField; public class ColorPicker extends AbstractField { - public ColorPicker() { - super(); - setValue(new String("white")); - } - - /** The property value of the field is an Integer. */ - public Class getType() { - return String.class; - } - - /** Tag is the UIDL element name for client-server communications. */ - public String getTag() { - return "colorpicker"; - } - - /** Set the currently selected color. */ - public void setColor(String newcolor) { - // Sets the color name as the property of the component. - // Setting the property will automatically cause repainting of - // the component with paintContent(). - setValue(newcolor); - } - - /** Retrieve the currently selected color. */ - public String getColor() { - return (String) getValue(); - } - - /** Paint (serialize) the component for the client. */ - public void paintContent(PaintTarget target) throws PaintException { - // Superclass writes any common attributes in the paint target. - super.paintContent(target); - - // Add the currently selected color as a variable in the paint target. - target.addVariable(this, "colorname", getColor()); - } - - /** Deserialize changes received from client. */ - public void changeVariables(Object source, Map variables) { - // Sets the currently selected color - if (variables.containsKey("colorname") && !isReadOnly()) { - String newValue = (String) variables.get("colorname"); - // Changing the property of the component will - // trigger a ValueChangeEvent - setValue(newValue, true); - } - } + public ColorPicker() { + super(); + setValue(new String("white")); + } + + /** The property value of the field is an Integer. */ + public Class getType() { + return String.class; + } + + /** Tag is the UIDL element name for client-server communications. */ + public String getTag() { + return "colorpicker"; + } + + /** Set the currently selected color. */ + public void setColor(String newcolor) { + // Sets the color name as the property of the component. + // Setting the property will automatically cause repainting of + // the component with paintContent(). + setValue(newcolor); + } + + /** Retrieve the currently selected color. */ + public String getColor() { + return (String) getValue(); + } + + /** Paint (serialize) the component for the client. */ + public void paintContent(PaintTarget target) throws PaintException { + // Superclass writes any common attributes in the paint target. + super.paintContent(target); + + // Add the currently selected color as a variable in the paint + // target. + target.addVariable(this, "colorname", getColor()); + } + + /** Deserialize changes received from client. */ + public void changeVariables(Object source, Map variables) { + // Sets the currently selected color + if (variables.containsKey("colorname") && !isReadOnly()) { + String newValue = (String) variables.get("colorname"); + // Changing the property of the component will + // trigger a ValueChangeEvent + setValue(newValue, true); + } + } } diff --git a/src/com/itmill/toolkit/demo/colorpicker/ColorPickerApplication.java b/src/com/itmill/toolkit/demo/colorpicker/ColorPickerApplication.java index f2e58ff9c0..248b4a5af2 100644 --- a/src/com/itmill/toolkit/demo/colorpicker/ColorPickerApplication.java +++ b/src/com/itmill/toolkit/demo/colorpicker/ColorPickerApplication.java @@ -2,7 +2,9 @@ package com.itmill.toolkit.demo.colorpicker; import com.itmill.toolkit.data.Property.ValueChangeEvent; import com.itmill.toolkit.data.Property.ValueChangeListener; -import com.itmill.toolkit.ui.*; +import com.itmill.toolkit.ui.Button; +import com.itmill.toolkit.ui.Label; +import com.itmill.toolkit.ui.Window; import com.itmill.toolkit.ui.Button.ClickEvent; /** @@ -10,39 +12,39 @@ import com.itmill.toolkit.ui.Button.ClickEvent; * GWT component, the ColorPicker. */ public class ColorPickerApplication extends com.itmill.toolkit.Application { - Window main = new Window("Color Picker Demo"); - - /* The custom component. */ - ColorPicker colorselector = new ColorPicker(); - - /* Another component. */ - Label colorname; - - public void init() { - setMainWindow(main); - - // Listen for value change events in the custom component, - // triggered when user clicks a button to select another color. - colorselector.addListener(new ValueChangeListener() { - public void valueChange(ValueChangeEvent event) { - // Provide some server-side feedback - colorname.setValue("Selected color: " - + colorselector.getColor()); - } - }); - main.addComponent(colorselector); - - // Add another component to give feedback from server-side code - colorname = new Label("Selected color: " + colorselector.getColor()); - main.addComponent(colorname); - - // Server-side manipulation of the component state - Button button = new Button("Set to white"); - button.addListener(new Button.ClickListener() { - public void buttonClick(ClickEvent event) { - colorselector.setColor("white"); - } - }); - main.addComponent(button); - } + Window main = new Window("Color Picker Demo"); + + /* The custom component. */ + ColorPicker colorselector = new ColorPicker(); + + /* Another component. */ + Label colorname; + + public void init() { + setMainWindow(main); + + // Listen for value change events in the custom component, + // triggered when user clicks a button to select another color. + colorselector.addListener(new ValueChangeListener() { + public void valueChange(ValueChangeEvent event) { + // Provide some server-side feedback + colorname.setValue("Selected color: " + + colorselector.getColor()); + } + }); + main.addComponent(colorselector); + + // Add another component to give feedback from server-side code + colorname = new Label("Selected color: " + colorselector.getColor()); + main.addComponent(colorname); + + // Server-side manipulation of the component state + Button button = new Button("Set to white"); + button.addListener(new Button.ClickListener() { + public void buttonClick(ClickEvent event) { + colorselector.setColor("white"); + } + }); + main.addComponent(button); + } } diff --git a/src/com/itmill/toolkit/demo/colorpicker/gwt/client/ColorPickerWidgetSet.java b/src/com/itmill/toolkit/demo/colorpicker/gwt/client/ColorPickerWidgetSet.java index e54c23d686..f6d43e5f0b 100644 --- a/src/com/itmill/toolkit/demo/colorpicker/gwt/client/ColorPickerWidgetSet.java +++ b/src/com/itmill/toolkit/demo/colorpicker/gwt/client/ColorPickerWidgetSet.java @@ -6,24 +6,26 @@ import com.itmill.toolkit.terminal.gwt.client.DefaultWidgetSet; import com.itmill.toolkit.terminal.gwt.client.UIDL; public class ColorPickerWidgetSet extends DefaultWidgetSet { - /** Creates a widget according to its class name. */ + /** Creates a widget according to its class name. */ public Widget createWidget(UIDL uidl) { - String className = resolveWidgetTypeName(uidl); - if ("com.itmill.toolkit.demo.colorpicker.gwt.client.ui.IColorPicker" - .equals(className)) - return new IColorPicker(); + String className = resolveWidgetTypeName(uidl); + if ("com.itmill.toolkit.demo.colorpicker.gwt.client.ui.IColorPicker" + .equals(className)) { + return new IColorPicker(); + } - // Let the DefaultWidgetSet handle creation of default widgets - return super.createWidget(uidl); + // Let the DefaultWidgetSet handle creation of default widgets + return super.createWidget(uidl); } /** Resolves UIDL tag name to class name. */ protected String resolveWidgetTypeName(UIDL uidl) { - String tag = uidl.getTag(); - if ("colorpicker".equals(tag)) - return "com.itmill.toolkit.demo.colorpicker.gwt.client.ui.IColorPicker"; + String tag = uidl.getTag(); + if ("colorpicker".equals(tag)) { + return "com.itmill.toolkit.demo.colorpicker.gwt.client.ui.IColorPicker"; + } - // Let the DefaultWidgetSet handle resolution of default widgets - return super.resolveWidgetTypeName(uidl); + // Let the DefaultWidgetSet handle resolution of default widgets + return super.resolveWidgetTypeName(uidl); } } diff --git a/src/com/itmill/toolkit/demo/colorpicker/gwt/client/ui/GwtColorPicker.java b/src/com/itmill/toolkit/demo/colorpicker/gwt/client/ui/GwtColorPicker.java index ca36176993..38b83f1961 100644 --- a/src/com/itmill/toolkit/demo/colorpicker/gwt/client/ui/GwtColorPicker.java +++ b/src/com/itmill/toolkit/demo/colorpicker/gwt/client/ui/GwtColorPicker.java @@ -2,90 +2,99 @@ package com.itmill.toolkit.demo.colorpicker.gwt.client.ui; import com.google.gwt.user.client.DOM; import com.google.gwt.user.client.Element; -import com.google.gwt.user.client.ui.*; +import com.google.gwt.user.client.ui.Button; +import com.google.gwt.user.client.ui.ClickListener; +import com.google.gwt.user.client.ui.Composite; +import com.google.gwt.user.client.ui.Grid; +import com.google.gwt.user.client.ui.HorizontalPanel; +import com.google.gwt.user.client.ui.Label; +import com.google.gwt.user.client.ui.Widget; /** * A regular GWT component without integration with IT Mill Toolkit. */ public class GwtColorPicker extends Composite implements ClickListener { - /** Currently selected color name to give client-side feedback to the user. */ - protected Label currentcolor = new Label(); + /** Currently selected color name to give client-side feedback to the user. */ + protected Label currentcolor = new Label(); - public GwtColorPicker() { - // Create a 4x4 grid of buttons with names for 16 colors - Grid grid = new Grid(4, 4); - String[] colors = new String[] { "aqua", "black", "blue", "fuchsia", - "gray", "green", "lime", "maroon", "navy", "olive", "purple", - "red", "silver", "teal", "white", "yellow" }; - int colornum = 0; - for (int i = 0; i < 4; i++) - for (int j = 0; j < 4; j++, colornum++) { - // Create a button for each color - Button button = new Button(colors[colornum]); - button.addClickListener(this); + public GwtColorPicker() { + // Create a 4x4 grid of buttons with names for 16 colors + Grid grid = new Grid(4, 4); + String[] colors = new String[] { "aqua", "black", "blue", "fuchsia", + "gray", "green", "lime", "maroon", "navy", "olive", "purple", + "red", "silver", "teal", "white", "yellow" }; + int colornum = 0; + for (int i = 0; i < 4; i++) { + for (int j = 0; j < 4; j++, colornum++) { + // Create a button for each color + Button button = new Button(colors[colornum]); + button.addClickListener(this); - // Put the button in the Grid layout - grid.setWidget(i, j, button); + // Put the button in the Grid layout + grid.setWidget(i, j, button); - // Set the button background colors. - DOM.setStyleAttribute(button.getElement(), "background", - colors[colornum]); + // Set the button background colors. + DOM.setStyleAttribute(button.getElement(), "background", + colors[colornum]); - // For dark colors, the button label must be in white. - if ("black navy maroon blue purple".indexOf(colors[colornum]) != -1) - DOM - .setStyleAttribute(button.getElement(), "color", - "white"); - } + // For dark colors, the button label must be in white. + if ("black navy maroon blue purple".indexOf(colors[colornum]) != -1) { + DOM + .setStyleAttribute(button.getElement(), "color", + "white"); + } + } + } - // Create a panel with the color grid and currently selected color - // indicator - HorizontalPanel panel = new HorizontalPanel(); - panel.add(grid); - panel.add(currentcolor); + // Create a panel with the color grid and currently selected color + // indicator + HorizontalPanel panel = new HorizontalPanel(); + panel.add(grid); + panel.add(currentcolor); - // Set the class of the color selection feedback box to allow CSS - // styling. - // We need to obtain the DOM element for the current color label. - // This assumes that the element of the HorizontalPanel is - // the parent of the label element. Notice that the element has no - // parent - // before the widget has been added to the horizontal panel. - Element panelcell = DOM.getParent(currentcolor.getElement()); - DOM.setElementProperty(panelcell, "className", - "colorpicker-currentcolorbox"); + // Set the class of the color selection feedback box to allow CSS + // styling. + // We need to obtain the DOM element for the current color label. + // This assumes that the element of the HorizontalPanel is + // the parent of the label element. Notice that the element has no + // parent + // before the widget has been added to the horizontal panel. + Element panelcell = DOM.getParent(currentcolor.getElement()); + DOM.setElementProperty(panelcell, "className", + "colorpicker-currentcolorbox"); - // Set initial color. This will be overridden with the value read from - // server. - setColor("white"); + // Set initial color. This will be overridden with the value read from + // server. + setColor("white"); - // Composite GWT widgets must call initWidget(). - initWidget(panel); - } + // Composite GWT widgets must call initWidget(). + initWidget(panel); + } - /** Handles click on a color button. */ - public void onClick(Widget sender) { - // Use the button label as the color name to set - setColor(((Button) sender).getText()); - } + /** Handles click on a color button. */ + public void onClick(Widget sender) { + // Use the button label as the color name to set + setColor(((Button) sender).getText()); + } - /** Sets the currently selected color. */ - public void setColor(String newcolor) { - // Give client-side feedback by changing the color name in the label - currentcolor.setText(newcolor); + /** Sets the currently selected color. */ + public void setColor(String newcolor) { + // Give client-side feedback by changing the color name in the label + currentcolor.setText(newcolor); - // Obtain the DOM elements. This assumes that the element - // of the HorizontalPanel is the parent of the label element. - Element nameelement = currentcolor.getElement(); - Element cell = DOM.getParent(nameelement); + // Obtain the DOM elements. This assumes that the element + // of the HorizontalPanel is the parent of the label element. + Element nameelement = currentcolor.getElement(); + Element cell = DOM.getParent(nameelement); - // Give feedback by changing the background color - DOM.setStyleAttribute(cell, "background", newcolor); - DOM.setStyleAttribute(nameelement, "background", newcolor); - if ("black navy maroon blue purple".indexOf(newcolor) != -1) - DOM.setStyleAttribute(nameelement, "color", "white"); - else - DOM.setStyleAttribute(nameelement, "color", "black"); - } + // Give feedback by changing the background color + DOM.setStyleAttribute(cell, "background", newcolor); + DOM.setStyleAttribute(nameelement, "background", newcolor); + if ("black navy maroon blue purple".indexOf(newcolor) != -1) { + DOM.setStyleAttribute(nameelement, "color", "white"); + } else { + DOM.setStyleAttribute(nameelement, "color", "black"); + } + } } diff --git a/src/com/itmill/toolkit/demo/colorpicker/gwt/client/ui/IColorPicker.java b/src/com/itmill/toolkit/demo/colorpicker/gwt/client/ui/IColorPicker.java index e7738caead..434c4f0530 100644 --- a/src/com/itmill/toolkit/demo/colorpicker/gwt/client/ui/IColorPicker.java +++ b/src/com/itmill/toolkit/demo/colorpicker/gwt/client/ui/IColorPicker.java @@ -6,69 +6,72 @@ import com.itmill.toolkit.terminal.gwt.client.UIDL; public class IColorPicker extends GwtColorPicker implements Paintable { - /** Set the CSS class name to allow styling. */ - public static final String CLASSNAME = "example-colorpicker"; + /** Set the CSS class name to allow styling. */ + public static final String CLASSNAME = "example-colorpicker"; - /** Component identifier in UIDL communications. */ - String uidlId; + /** Component identifier in UIDL communications. */ + String uidlId; - /** Reference to the server connection object. */ - ApplicationConnection client; + /** Reference to the server connection object. */ + ApplicationConnection client; - /** - * The constructor should first call super() to initialize the component and - * then handle any initialization relevant to IT Mill Toolkit. - */ - public IColorPicker() { - // The superclass has a lot of relevant initialization - super(); + /** + * The constructor should first call super() to initialize the component and + * then handle any initialization relevant to IT Mill Toolkit. + */ + public IColorPicker() { + // The superclass has a lot of relevant initialization + super(); - // This method call of the Paintable interface sets the component - // style name in DOM tree - setStyleName(CLASSNAME); - } + // This method call of the Paintable interface sets the component + // style name in DOM tree + setStyleName(CLASSNAME); + } - /** - * This method must be implemented to update the client-side component from - * UIDL data received from server. - * - * This method is called when the page is loaded for the first time, and - * every time UI changes in the component are received from the server. - */ - public void updateFromUIDL(UIDL uidl, ApplicationConnection client) { - // This call should be made first. Ensure correct implementation, - // and let the containing layout manage caption, etc. - if (client.updateComponent(this, uidl, true)) - return; + /** + * This method must be implemented to update the client-side component from + * UIDL data received from server. + * + * This method is called when the page is loaded for the first time, and + * every time UI changes in the component are received from the server. + */ + public void updateFromUIDL(UIDL uidl, ApplicationConnection client) { + // This call should be made first. Ensure correct implementation, + // and let the containing layout manage caption, etc. + if (client.updateComponent(this, uidl, true)) { + return; + } - // Save reference to server connection object to be able to send - // user interaction later - this.client = client; + // Save reference to server connection object to be able to send + // user interaction later + this.client = client; - // Save the UIDL identifier for the component - uidlId = uidl.getId(); + // Save the UIDL identifier for the component + uidlId = uidl.getId(); - // Get value received from server and actualize it in the GWT component - setColor(uidl.getStringVariable("colorname")); - } + // Get value received from server and actualize it in the GWT component + setColor(uidl.getStringVariable("colorname")); + } - /** Override the method to communicate the new value to server. */ - public void setColor(String newcolor) { - // Ignore if no change - if (newcolor.equals(currentcolor.getText())) - return; + /** Override the method to communicate the new value to server. */ + public void setColor(String newcolor) { + // Ignore if no change + if (newcolor.equals(currentcolor.getText())) { + return; + } - // Let the original implementation to do whatever it needs to do - super.setColor(newcolor); + // Let the original implementation to do whatever it needs to do + super.setColor(newcolor); - // Updating the state to the server can not be done before - // the server connection is known, i.e., before updateFromUIDL() - // has been called. - if (uidlId == null || client == null) - return; + // Updating the state to the server can not be done before + // the server connection is known, i.e., before updateFromUIDL() + // has been called. + if (uidlId == null || client == null) { + return; + } - // Communicate the user interaction parameters to server. This call will - // initiate an AJAX request to the server. - client.updateVariable(uidlId, "colorname", newcolor, true); - } + // Communicate the user interaction parameters to server. This call will + // initiate an AJAX request to the server. + client.updateVariable(uidlId, "colorname", newcolor, true); + } } diff --git a/src/com/itmill/toolkit/demo/reservation/CalendarDemo.java b/src/com/itmill/toolkit/demo/reservation/CalendarDemo.java index 413e5a36dd..bbe5ef8778 100644 --- a/src/com/itmill/toolkit/demo/reservation/CalendarDemo.java +++ b/src/com/itmill/toolkit/demo/reservation/CalendarDemo.java @@ -8,6 +8,7 @@ import com.itmill.toolkit.data.Property.ValueChangeEvent; import com.itmill.toolkit.data.Property.ValueChangeListener; import com.itmill.toolkit.data.util.QueryContainer; import com.itmill.toolkit.demo.util.SampleCalendarDatabase; +import com.itmill.toolkit.ui.DateField; import com.itmill.toolkit.ui.OrderedLayout; import com.itmill.toolkit.ui.Window; @@ -23,90 +24,89 @@ import com.itmill.toolkit.ui.Window; */ public class CalendarDemo extends com.itmill.toolkit.Application { - // Database provided with sample data - private SampleCalendarDatabase sampleDatabase; - - // The calendar UI component - private CalendarField from; - private CalendarField to; - - /** - * Initialize Application. Demo components are added to main window. - */ - public void init() { - Window main = new Window("Calendar demo"); - setMainWindow(main); - - main.setLayout(new OrderedLayout(OrderedLayout.ORIENTATION_HORIZONTAL)); - - // create the calendar component and add to layout - from = new CalendarField(); - main.addComponent(from); - from.setResolution(CalendarField.RESOLUTION_HOUR); - from.setImmediate(true); - - - to = new CalendarField(); - main.addComponent(to); - to.setResolution(CalendarField.RESOLUTION_HOUR); - to.setEnabled(false); - to.setImmediate(true); - - from.addListener(new ValueChangeListener() { - public void valueChange(ValueChangeEvent event) { - Date fd = (Date) from.getValue(); - Date td = (Date) to.getValue(); - if (fd == null) { - to.setValue(null); - to.setEnabled(false); - return; - } else { - to.setEnabled(true); - } - to.setMinimumDate(fd); - if (td == null || td.before(fd)) { - to.setValue(fd); - } - } - }); - - // initialize the sample database and set as calendar datasource - sampleDatabase = new SampleCalendarDatabase(); - - initCalendars(); - - // Don't allow dates before today - from.setMinimumDate(Calendar.getInstance().getTime()); - - } - - /** - * Populates table component with all rows from calendar table. - */ - private void initCalendars() { - try { - QueryContainer qc = new QueryContainer("SELECT * FROM " - + SampleCalendarDatabase.DB_TABLE_NAME, sampleDatabase - .getConnection()); - from.setContainerDataSource(qc); - to.setContainerDataSource(qc); - } catch (SQLException e) { - e.printStackTrace(); - } -/* - // Calendar will use the first date property as start if you do not - // explicitly specify the property id. Our start -property will be the - // first one, so it's intentionally left out. - // Start is the only mandatory property, but you'll probably want to - // specify title as well. - from.setItemEndPropertyId(SampleCalendarDatabase.PROPERTY_ID_END); - from.setItemTitlePropertyId(SampleCalendarDatabase.PROPERTY_ID_TITLE); - from.setItemNotimePropertyId(SampleCalendarDatabase.PROPERTY_ID_NOTIME); - - to.setItemEndPropertyId(SampleCalendarDatabase.PROPERTY_ID_END); - to.setItemTitlePropertyId(SampleCalendarDatabase.PROPERTY_ID_TITLE); - to.setItemNotimePropertyId(SampleCalendarDatabase.PROPERTY_ID_NOTIME); -*/ - } + // Database provided with sample data + private SampleCalendarDatabase sampleDatabase; + + // The calendar UI component + private CalendarField from; + private CalendarField to; + + /** + * Initialize Application. Demo components are added to main window. + */ + public void init() { + Window main = new Window("Calendar demo"); + setMainWindow(main); + + main.setLayout(new OrderedLayout(OrderedLayout.ORIENTATION_HORIZONTAL)); + + // create the calendar component and add to layout + from = new CalendarField(); + main.addComponent(from); + from.setResolution(DateField.RESOLUTION_HOUR); + from.setImmediate(true); + + to = new CalendarField(); + main.addComponent(to); + to.setResolution(DateField.RESOLUTION_HOUR); + to.setEnabled(false); + to.setImmediate(true); + + from.addListener(new ValueChangeListener() { + public void valueChange(ValueChangeEvent event) { + Date fd = (Date) from.getValue(); + Date td = (Date) to.getValue(); + if (fd == null) { + to.setValue(null); + to.setEnabled(false); + return; + } else { + to.setEnabled(true); + } + to.setMinimumDate(fd); + if (td == null || td.before(fd)) { + to.setValue(fd); + } + } + }); + + // initialize the sample database and set as calendar datasource + sampleDatabase = new SampleCalendarDatabase(); + + initCalendars(); + + // Don't allow dates before today + from.setMinimumDate(Calendar.getInstance().getTime()); + + } + + /** + * Populates table component with all rows from calendar table. + */ + private void initCalendars() { + try { + QueryContainer qc = new QueryContainer("SELECT * FROM " + + SampleCalendarDatabase.DB_TABLE_NAME, sampleDatabase + .getConnection()); + from.setContainerDataSource(qc); + to.setContainerDataSource(qc); + } catch (SQLException e) { + e.printStackTrace(); + } + /* + * // Calendar will use the first date property as start if you do not // + * explicitly specify the property id. Our start -property will be the // + * first one, so it's intentionally left out. // Start is the only + * mandatory property, but you'll probably want to // specify title as + * well. + * from.setItemEndPropertyId(SampleCalendarDatabase.PROPERTY_ID_END); + * from.setItemTitlePropertyId(SampleCalendarDatabase.PROPERTY_ID_TITLE); + * from.setItemNotimePropertyId(SampleCalendarDatabase.PROPERTY_ID_NOTIME); + * + * to.setItemEndPropertyId(SampleCalendarDatabase.PROPERTY_ID_END); + * to.setItemTitlePropertyId(SampleCalendarDatabase.PROPERTY_ID_TITLE); + * to.setItemNotimePropertyId(SampleCalendarDatabase.PROPERTY_ID_NOTIME); + */ + } } diff --git a/src/com/itmill/toolkit/demo/reservation/CalendarField.java b/src/com/itmill/toolkit/demo/reservation/CalendarField.java index 8cd67500a2..a746685c4f 100644 --- a/src/com/itmill/toolkit/demo/reservation/CalendarField.java +++ b/src/com/itmill/toolkit/demo/reservation/CalendarField.java @@ -16,304 +16,301 @@ import com.itmill.toolkit.ui.DateField; // TODO Allow item selection public class CalendarField extends DateField implements Container.Viewer { - private static final String TAGNAME = "calendarfield"; - - private Date minDate; - private Date maxDate; - - private Container dataSource; - private Object itemStyleNamePropertyId; - private Object itemStartPropertyId; - private Object itemEndPropertyId; - private Object itemTitlePropertyId; - private Object itemDescriptionPropertyId; - private Object itemNotimePropertyId; - - public CalendarField() { - super(); - init(); - } - - public CalendarField(Property dataSource) throws IllegalArgumentException { - super(dataSource); - init(); - } - - public CalendarField(String caption, Date value) { - super(caption, value); - init(); - } - - public CalendarField(String caption, Property dataSource) { - super(caption, dataSource); - init(); - } - - public CalendarField(String caption) { - super(caption); - init(); - } - - /* - * Gets the components UIDL tag string. Don't add a JavaDoc comment here, we - * use the default documentation from implemented interface. - */ - public String getTag() { - return TAGNAME; - } - - public void init() { - super.setResolution(RESOLUTION_HOUR); - - } - - /** - * Sets the resolution of the CalendarField. Only RESOLUTION_DAY and - * RESOLUTION_HOUR are supported. - * - * @param resolution - * the resolution to set. - * @see com.itmill.toolkit.ui.DateField#setResolution(int) - */ - public void setResolution(int resolution) { - if (resolution != RESOLUTION_DAY && resolution != RESOLUTION_HOUR) { - throw new IllegalArgumentException(); - } - super.setResolution(resolution); - } - - public void setMinimumDate(Date date) { - this.minDate = date; - requestRepaint(); - } - - public Date getMinimumDate() { - return minDate; - } - - public void setMaximumDate(Date date) { - this.maxDate = date; - requestRepaint(); - } - - public Date getMaximumDate() { - return maxDate; - } - - public Container getContainerDataSource() { - return this.dataSource; - } - - public void setContainerDataSource(Container newDataSource) { - if (newDataSource == null || checkDataSource(newDataSource)) { - this.dataSource = newDataSource; - } else { - // TODO error message - throw new IllegalArgumentException(); - } - requestRepaint(); - } - - private boolean checkDataSource(Container dataSource) { - - // Check old propertyIds - if (this.itemEndPropertyId != null) { - Class c = dataSource.getType(this.itemEndPropertyId); - if (!Date.class.isAssignableFrom(c)) { - this.itemEndPropertyId = null; - } - } - if (this.itemNotimePropertyId != null) { - Class c = dataSource.getType(this.itemNotimePropertyId); - if (!Boolean.class.isAssignableFrom(c)) { - this.itemNotimePropertyId = null; - } - } - if (this.itemStartPropertyId != null) { - Class c = dataSource.getType(this.itemStartPropertyId); - if (Date.class.isAssignableFrom(c)) { - // All we _really_ need is one date - return true; - } else { - this.itemStartPropertyId = null; - } - } - // We need at least one Date - Collection ids = dataSource.getContainerPropertyIds(); - for (Iterator it = ids.iterator(); it.hasNext();) { - Object id = it.next(); - Class c = dataSource.getType(id); - if (Date.class.isAssignableFrom(c)) { - this.itemStartPropertyId = id; - return true; - } - } - - return false; - } - - public Object getItemStyleNamePropertyId() { - return itemStyleNamePropertyId; - } - - public void setItemStyleNamePropertyId(Object propertyId) { - this.itemStyleNamePropertyId = propertyId; - } - - public Object getItemStartPropertyId() { - return itemStartPropertyId; - } - - public void setItemStartPropertyId(Object propertyId) { - // TODO nullcheck for property id - if (this.dataSource != null - && !Date.class.isAssignableFrom(dataSource.getType(propertyId))) { - // TODO error message - throw new IllegalArgumentException(); - } - this.itemStartPropertyId = propertyId; - } - - public Object getItemEndPropertyId() { - return itemEndPropertyId; - } - - public void setItemEndPropertyId(Object propertyId) { - // TODO nullcheck for property id - if (this.dataSource != null - && !Date.class.isAssignableFrom(dataSource.getType(propertyId))) { - // TODO error message - throw new IllegalArgumentException(); - } - this.itemEndPropertyId = propertyId; - } - - public Object getItemTitlePropertyId() { - return itemTitlePropertyId; - } - - public void setItemTitlePropertyId(Object propertyId) { - this.itemTitlePropertyId = propertyId; - } - - public Object getItemDescriptionPropertyId() { - return itemDescriptionPropertyId; - } - - public void setItemDescriptionPropertyId(Object propertyId) { - this.itemDescriptionPropertyId = propertyId; - } - - public Object getitemNotimePropertyId() { - return itemNotimePropertyId; - } - - public void setItemNotimePropertyId(Object propertyId) { - // TODO nullcheck for property id - if (this.dataSource != null - && !Boolean.class.isAssignableFrom(dataSource - .getType(propertyId))) { - // TODO error message - throw new IllegalArgumentException(); - } - this.itemNotimePropertyId = propertyId; - } - - /** - * Paints the content of this component. - * - * @param target - * the Paint Event. - * @throws PaintException - * if the paint operation failed. - */ - public void paintContent(PaintTarget target) throws PaintException { - super.paintContent(target); - - if (this.minDate != null) { - target.addAttribute("min", String.valueOf(this.minDate.getTime())); - } - if (this.maxDate != null) { - target.addAttribute("max", String.valueOf(this.maxDate.getTime())); - } - - if (this.dataSource != null) { - target.startTag("items"); - - // TODO send one month now, the rest via lazyloading - int month = new Date().getMonth(); - Object value = getValue(); - if (value != null && value instanceof Date) { - month = ((Date) value).getMonth(); - } - - for (Iterator it = this.dataSource.getItemIds().iterator(); it - .hasNext();) { - Object itemId = it.next(); - Item item = (Item) this.dataSource.getItem(itemId); - Property p = item.getItemProperty(this.itemStartPropertyId); - Date start = (Date) p.getValue(); - Date end = start; // assume same day - if (this.itemEndPropertyId != null) { - p = item.getItemProperty(this.itemEndPropertyId); - end = (Date) p.getValue(); - if (end == null) { - end = start; - } else if (end.before(start)) { - Date tmp = start; - start = end; - end = tmp; - } - } - - // TODO half-done lazyloading logic (hence broken) - - if (start != null) { - if ((start.getMonth() <= month || end.getMonth() >= month)) { - target.startTag("item"); - // TODO different id? - target.addAttribute("id", itemId.hashCode()); - if (this.itemStyleNamePropertyId != null) { - p = item - .getItemProperty(this.itemStyleNamePropertyId); - String styleName = (String) p.getValue(); - target.addAttribute("styleName", styleName); - } - target.addAttribute("start", "" + start.getTime()); - if (end != start) { - target.addAttribute("end", "" + end.getTime()); - } - if (this.itemTitlePropertyId != null) { - p = item.getItemProperty(this.itemTitlePropertyId); - Object val = p.getValue(); - if (val != null) { - target.addAttribute("title", val.toString()); - } - } - if (this.itemDescriptionPropertyId != null) { - p = item - .getItemProperty(this.itemDescriptionPropertyId); - Object val = p.getValue(); - if (val != null) { - target.addAttribute("description", val - .toString()); - } - } - if (this.itemNotimePropertyId != null) { - p = item.getItemProperty(this.itemNotimePropertyId); - Object val = p.getValue(); - if (val != null) { - target.addAttribute("notime", ((Boolean) val) - .booleanValue()); - } - } - - target.endTag("item"); - } - } - } - - target.endTag("items"); - } - } + private static final String TAGNAME = "calendarfield"; + + private Date minDate; + private Date maxDate; + + private Container dataSource; + private Object itemStyleNamePropertyId; + private Object itemStartPropertyId; + private Object itemEndPropertyId; + private Object itemTitlePropertyId; + private Object itemDescriptionPropertyId; + private Object itemNotimePropertyId; + + public CalendarField() { + super(); + init(); + } + + public CalendarField(Property dataSource) throws IllegalArgumentException { + super(dataSource); + init(); + } + + public CalendarField(String caption, Date value) { + super(caption, value); + init(); + } + + public CalendarField(String caption, Property dataSource) { + super(caption, dataSource); + init(); + } + + public CalendarField(String caption) { + super(caption); + init(); + } + + /* + * Gets the components UIDL tag string. Don't add a JavaDoc comment here, we + * use the default documentation from implemented interface. + */ + public String getTag() { + return TAGNAME; + } + + public void init() { + super.setResolution(RESOLUTION_HOUR); + + } + + /** + * Sets the resolution of the CalendarField. Only RESOLUTION_DAY and + * RESOLUTION_HOUR are supported. + * + * @param resolution + * the resolution to set. + * @see com.itmill.toolkit.ui.DateField#setResolution(int) + */ + public void setResolution(int resolution) { + if (resolution != RESOLUTION_DAY && resolution != RESOLUTION_HOUR) { + throw new IllegalArgumentException(); + } + super.setResolution(resolution); + } + + public void setMinimumDate(Date date) { + minDate = date; + requestRepaint(); + } + + public Date getMinimumDate() { + return minDate; + } + + public void setMaximumDate(Date date) { + maxDate = date; + requestRepaint(); + } + + public Date getMaximumDate() { + return maxDate; + } + + public Container getContainerDataSource() { + return dataSource; + } + + public void setContainerDataSource(Container newDataSource) { + if (newDataSource == null || checkDataSource(newDataSource)) { + dataSource = newDataSource; + } else { + // TODO error message + throw new IllegalArgumentException(); + } + requestRepaint(); + } + + private boolean checkDataSource(Container dataSource) { + + // Check old propertyIds + if (itemEndPropertyId != null) { + Class c = dataSource.getType(itemEndPropertyId); + if (!Date.class.isAssignableFrom(c)) { + itemEndPropertyId = null; + } + } + if (itemNotimePropertyId != null) { + Class c = dataSource.getType(itemNotimePropertyId); + if (!Boolean.class.isAssignableFrom(c)) { + itemNotimePropertyId = null; + } + } + if (itemStartPropertyId != null) { + Class c = dataSource.getType(itemStartPropertyId); + if (Date.class.isAssignableFrom(c)) { + // All we _really_ need is one date + return true; + } else { + itemStartPropertyId = null; + } + } + // We need at least one Date + Collection ids = dataSource.getContainerPropertyIds(); + for (Iterator it = ids.iterator(); it.hasNext();) { + Object id = it.next(); + Class c = dataSource.getType(id); + if (Date.class.isAssignableFrom(c)) { + itemStartPropertyId = id; + return true; + } + } + + return false; + } + + public Object getItemStyleNamePropertyId() { + return itemStyleNamePropertyId; + } + + public void setItemStyleNamePropertyId(Object propertyId) { + itemStyleNamePropertyId = propertyId; + } + + public Object getItemStartPropertyId() { + return itemStartPropertyId; + } + + public void setItemStartPropertyId(Object propertyId) { + // TODO nullcheck for property id + if (dataSource != null + && !Date.class.isAssignableFrom(dataSource.getType(propertyId))) { + // TODO error message + throw new IllegalArgumentException(); + } + itemStartPropertyId = propertyId; + } + + public Object getItemEndPropertyId() { + return itemEndPropertyId; + } + + public void setItemEndPropertyId(Object propertyId) { + // TODO nullcheck for property id + if (dataSource != null + && !Date.class.isAssignableFrom(dataSource.getType(propertyId))) { + // TODO error message + throw new IllegalArgumentException(); + } + itemEndPropertyId = propertyId; + } + + public Object getItemTitlePropertyId() { + return itemTitlePropertyId; + } + + public void setItemTitlePropertyId(Object propertyId) { + itemTitlePropertyId = propertyId; + } + + public Object getItemDescriptionPropertyId() { + return itemDescriptionPropertyId; + } + + public void setItemDescriptionPropertyId(Object propertyId) { + itemDescriptionPropertyId = propertyId; + } + + public Object getitemNotimePropertyId() { + return itemNotimePropertyId; + } + + public void setItemNotimePropertyId(Object propertyId) { + // TODO nullcheck for property id + if (dataSource != null + && !Boolean.class.isAssignableFrom(dataSource + .getType(propertyId))) { + // TODO error message + throw new IllegalArgumentException(); + } + itemNotimePropertyId = propertyId; + } + + /** + * Paints the content of this component. + * + * @param target + * the Paint Event. + * @throws PaintException + * if the paint operation failed. + */ + public void paintContent(PaintTarget target) throws PaintException { + super.paintContent(target); + + if (minDate != null) { + target.addAttribute("min", String.valueOf(minDate.getTime())); + } + if (maxDate != null) { + target.addAttribute("max", String.valueOf(maxDate.getTime())); + } + + if (dataSource != null) { + target.startTag("items"); + + // TODO send one month now, the rest via lazyloading + int month = new Date().getMonth(); + Object value = getValue(); + if (value != null && value instanceof Date) { + month = ((Date) value).getMonth(); + } + + for (Iterator it = dataSource.getItemIds().iterator(); it.hasNext();) { + Object itemId = it.next(); + Item item = dataSource.getItem(itemId); + Property p = item.getItemProperty(itemStartPropertyId); + Date start = (Date) p.getValue(); + Date end = start; // assume same day + if (itemEndPropertyId != null) { + p = item.getItemProperty(itemEndPropertyId); + end = (Date) p.getValue(); + if (end == null) { + end = start; + } else if (end.before(start)) { + Date tmp = start; + start = end; + end = tmp; + } + } + + // TODO half-done lazyloading logic (hence broken) + + if (start != null) { + if ((start.getMonth() <= month || end.getMonth() >= month)) { + target.startTag("item"); + // TODO different id? + target.addAttribute("id", itemId.hashCode()); + if (itemStyleNamePropertyId != null) { + p = item.getItemProperty(itemStyleNamePropertyId); + String styleName = (String) p.getValue(); + target.addAttribute("styleName", styleName); + } + target.addAttribute("start", "" + start.getTime()); + if (end != start) { + target.addAttribute("end", "" + end.getTime()); + } + if (itemTitlePropertyId != null) { + p = item.getItemProperty(itemTitlePropertyId); + Object val = p.getValue(); + if (val != null) { + target.addAttribute("title", val.toString()); + } + } + if (itemDescriptionPropertyId != null) { + p = item.getItemProperty(itemDescriptionPropertyId); + Object val = p.getValue(); + if (val != null) { + target.addAttribute("description", val + .toString()); + } + } + if (itemNotimePropertyId != null) { + p = item.getItemProperty(itemNotimePropertyId); + Object val = p.getValue(); + if (val != null) { + target.addAttribute("notime", ((Boolean) val) + .booleanValue()); + } + } + + target.endTag("item"); + } + } + } + + target.endTag("items"); + } + } } diff --git a/src/com/itmill/toolkit/demo/reservation/GoogleMap.java b/src/com/itmill/toolkit/demo/reservation/GoogleMap.java index 4d421c3f66..5355b9eea3 100644 --- a/src/com/itmill/toolkit/demo/reservation/GoogleMap.java +++ b/src/com/itmill/toolkit/demo/reservation/GoogleMap.java @@ -14,216 +14,216 @@ import com.itmill.toolkit.terminal.Sizeable; import com.itmill.toolkit.ui.AbstractComponent; public class GoogleMap extends AbstractComponent implements Sizeable, - Container.Viewer { - private String TAG_MARKERS = "markers"; - private String TAG_MARKER = "marker"; - private int width = 400; - private int height = 300; - private int zoomLevel = 15; - private Point2D.Double mapCenter; - - private Container dataSource; - private Object itemMarkerHtmlPropertyId = new Object(); - private Object itemMarkerXPropertyId = new Object(); - private Object itemMarkerYPropertyId = new Object(); - - public String getTag() { - return "googlemap"; - } - - public void paintContent(PaintTarget target) throws PaintException { - super.paintContent(target); - if (null != mapCenter) { - target.addAttribute("centerX", mapCenter.getX()); - target.addAttribute("centerY", mapCenter.getY()); - } - target.addAttribute("zoom", zoomLevel); - target.addAttribute("width", width); - target.addAttribute("height", height); - - if (this.dataSource != null) { - target.startTag(TAG_MARKERS); - Collection itemIds = this.dataSource.getItemIds(); - for (Iterator it = itemIds.iterator(); it.hasNext();) { - Object itemId = it.next(); - Item item = this.dataSource.getItem(itemId); - Property p = item.getItemProperty(getItemMarkerXPropertyId()); - Double x = (Double) (p != null ? p.getValue() : null); - p = item.getItemProperty(getItemMarkerYPropertyId()); - Double y = (Double) (p != null ? p.getValue() : null); - if (x == null || y == null) { - continue; - } - target.startTag(TAG_MARKER); - target.addAttribute("x", x.doubleValue()); - target.addAttribute("y", y.doubleValue()); - p = item.getItemProperty(getItemMarkerHtmlPropertyId()); - String h = (String) (p != null ? p.getValue() : null); - target.addAttribute("html", h); - target.endTag(TAG_MARKER); - } - target.endTag(TAG_MARKERS); - } - } - - public void setZoomLevel(int zoomLevel) { - this.zoomLevel = zoomLevel; - requestRepaint(); - } - - public int getZoomLevel() { - return this.zoomLevel; - } - - // Sizeable methods: - - public int getHeight() { - return this.height; - } - - public int getHeightUnits() { - return Sizeable.UNITS_PIXELS; - } - - public int getWidth() { - return this.width; - } - - public int getWidthUnits() { - return Sizeable.UNITS_PIXELS; - } - - public void setHeight(int height) { - this.height = height; - requestRepaint(); - } - - public void setHeightUnits(int units) { - throw new UnsupportedOperationException(); - } - - public void setWidth(int width) { - this.width = width; - requestRepaint(); - } - - public void setWidthUnits(int units) { - throw new UnsupportedOperationException(); - } - - public void setMapCenter(Point2D.Double center) { - this.mapCenter = center; - } - - public Point2D.Double getMapCenter() { - return this.mapCenter; - } - - // Container.Viewer methods: - - public Container getContainerDataSource() { - return this.dataSource; - } - - public void setContainerDataSource(Container newDataSource) { - - this.dataSource = newDataSource; - - requestRepaint(); - } - - // Item methods - - public Object getItemMarkerHtmlPropertyId() { - return itemMarkerHtmlPropertyId; - } - - public void setItemMarkerHtmlPropertyId(Object itemMarkerHtmlPropertyId) { - this.itemMarkerHtmlPropertyId = itemMarkerHtmlPropertyId; - requestRepaint(); - } - - public Object getItemMarkerXPropertyId() { - return itemMarkerXPropertyId; - } - - public void setItemMarkerXPropertyId(Object itemMarkerXPropertyId) { - this.itemMarkerXPropertyId = itemMarkerXPropertyId; - requestRepaint(); - } - - public Object getItemMarkerYPropertyId() { - return itemMarkerYPropertyId; - } - - public void setItemMarkerYPropertyId(Object itemMarkerYPropertyId) { - this.itemMarkerYPropertyId = itemMarkerYPropertyId; - requestRepaint(); - } - - // Marker add - - public Object addMarker(String html, Point2D.Double location) { - if (location == null) { - throw new IllegalArgumentException("Location must be non-null"); - } - if (this.dataSource == null) { - initDataSource(); - } - Object markerId = this.dataSource.addItem(); - if (markerId == null) { - return null; - } - Item marker = this.dataSource.getItem(markerId); - Property p = marker.getItemProperty(getItemMarkerXPropertyId()); - p.setValue(new Double(location.x)); - p = marker.getItemProperty(getItemMarkerYPropertyId()); - p.setValue(new Double(location.y)); - p = marker.getItemProperty(getItemMarkerHtmlPropertyId()); - p.setValue(html); - - requestRepaint(); - - return markerId; - } - - public void removeMarker(Object markerId) { - if (this.dataSource != null) { - this.dataSource.removeItem(markerId); - requestRepaint(); - } - } - - public Item getMarkerItem(Object markerId) { - if (this.dataSource != null) { - return this.dataSource.getItem(markerId); - } else { - return null; - } - } - - // dataSource init helper: - private void initDataSource() { - this.dataSource = new IndexedContainer(); - this.dataSource.addContainerProperty(this.itemMarkerHtmlPropertyId, - String.class, null); - this.dataSource.addContainerProperty(this.itemMarkerXPropertyId, - Double.class, new Double(0)); - this.dataSource.addContainerProperty(this.itemMarkerYPropertyId, - Double.class, new Double(0)); - } - - public void clear() { - setContainerDataSource(null); - } - - public void setSizeFull() { - // TODO Auto-generated method stub - - } - - public void setSizeUndefined() { - // TODO Auto-generated method stub - - } + Container.Viewer { + private String TAG_MARKERS = "markers"; + private String TAG_MARKER = "marker"; + private int width = 400; + private int height = 300; + private int zoomLevel = 15; + private Point2D.Double mapCenter; + + private Container dataSource; + private Object itemMarkerHtmlPropertyId = new Object(); + private Object itemMarkerXPropertyId = new Object(); + private Object itemMarkerYPropertyId = new Object(); + + public String getTag() { + return "googlemap"; + } + + public void paintContent(PaintTarget target) throws PaintException { + super.paintContent(target); + if (null != mapCenter) { + target.addAttribute("centerX", mapCenter.getX()); + target.addAttribute("centerY", mapCenter.getY()); + } + target.addAttribute("zoom", zoomLevel); + target.addAttribute("width", width); + target.addAttribute("height", height); + + if (dataSource != null) { + target.startTag(TAG_MARKERS); + Collection itemIds = dataSource.getItemIds(); + for (Iterator it = itemIds.iterator(); it.hasNext();) { + Object itemId = it.next(); + Item item = dataSource.getItem(itemId); + Property p = item.getItemProperty(getItemMarkerXPropertyId()); + Double x = (Double) (p != null ? p.getValue() : null); + p = item.getItemProperty(getItemMarkerYPropertyId()); + Double y = (Double) (p != null ? p.getValue() : null); + if (x == null || y == null) { + continue; + } + target.startTag(TAG_MARKER); + target.addAttribute("x", x.doubleValue()); + target.addAttribute("y", y.doubleValue()); + p = item.getItemProperty(getItemMarkerHtmlPropertyId()); + String h = (String) (p != null ? p.getValue() : null); + target.addAttribute("html", h); + target.endTag(TAG_MARKER); + } + target.endTag(TAG_MARKERS); + } + } + + public void setZoomLevel(int zoomLevel) { + this.zoomLevel = zoomLevel; + requestRepaint(); + } + + public int getZoomLevel() { + return zoomLevel; + } + + // Sizeable methods: + + public int getHeight() { + return height; + } + + public int getHeightUnits() { + return Sizeable.UNITS_PIXELS; + } + + public int getWidth() { + return width; + } + + public int getWidthUnits() { + return Sizeable.UNITS_PIXELS; + } + + public void setHeight(int height) { + this.height = height; + requestRepaint(); + } + + public void setHeightUnits(int units) { + throw new UnsupportedOperationException(); + } + + public void setWidth(int width) { + this.width = width; + requestRepaint(); + } + + public void setWidthUnits(int units) { + throw new UnsupportedOperationException(); + } + + public void setMapCenter(Point2D.Double center) { + mapCenter = center; + } + + public Point2D.Double getMapCenter() { + return mapCenter; + } + + // Container.Viewer methods: + + public Container getContainerDataSource() { + return dataSource; + } + + public void setContainerDataSource(Container newDataSource) { + + dataSource = newDataSource; + + requestRepaint(); + } + + // Item methods + + public Object getItemMarkerHtmlPropertyId() { + return itemMarkerHtmlPropertyId; + } + + public void setItemMarkerHtmlPropertyId(Object itemMarkerHtmlPropertyId) { + this.itemMarkerHtmlPropertyId = itemMarkerHtmlPropertyId; + requestRepaint(); + } + + public Object getItemMarkerXPropertyId() { + return itemMarkerXPropertyId; + } + + public void setItemMarkerXPropertyId(Object itemMarkerXPropertyId) { + this.itemMarkerXPropertyId = itemMarkerXPropertyId; + requestRepaint(); + } + + public Object getItemMarkerYPropertyId() { + return itemMarkerYPropertyId; + } + + public void setItemMarkerYPropertyId(Object itemMarkerYPropertyId) { + this.itemMarkerYPropertyId = itemMarkerYPropertyId; + requestRepaint(); + } + + // Marker add + + public Object addMarker(String html, Point2D.Double location) { + if (location == null) { + throw new IllegalArgumentException("Location must be non-null"); + } + if (dataSource == null) { + initDataSource(); + } + Object markerId = dataSource.addItem(); + if (markerId == null) { + return null; + } + Item marker = dataSource.getItem(markerId); + Property p = marker.getItemProperty(getItemMarkerXPropertyId()); + p.setValue(new Double(location.x)); + p = marker.getItemProperty(getItemMarkerYPropertyId()); + p.setValue(new Double(location.y)); + p = marker.getItemProperty(getItemMarkerHtmlPropertyId()); + p.setValue(html); + + requestRepaint(); + + return markerId; + } + + public void removeMarker(Object markerId) { + if (dataSource != null) { + dataSource.removeItem(markerId); + requestRepaint(); + } + } + + public Item getMarkerItem(Object markerId) { + if (dataSource != null) { + return dataSource.getItem(markerId); + } else { + return null; + } + } + + // dataSource init helper: + private void initDataSource() { + dataSource = new IndexedContainer(); + dataSource.addContainerProperty(itemMarkerHtmlPropertyId, String.class, + null); + dataSource.addContainerProperty(itemMarkerXPropertyId, Double.class, + new Double(0)); + dataSource.addContainerProperty(itemMarkerYPropertyId, Double.class, + new Double(0)); + } + + public void clear() { + setContainerDataSource(null); + } + + public void setSizeFull() { + // TODO Auto-generated method stub + + } + + public void setSizeUndefined() { + // TODO Auto-generated method stub + + } } \ No newline at end of file diff --git a/src/com/itmill/toolkit/demo/reservation/ReservationApplication.java b/src/com/itmill/toolkit/demo/reservation/ReservationApplication.java index 0f3297461c..a3830f0483 100644 --- a/src/com/itmill/toolkit/demo/reservation/ReservationApplication.java +++ b/src/com/itmill/toolkit/demo/reservation/ReservationApplication.java @@ -25,329 +25,332 @@ import com.itmill.toolkit.ui.TabSheet.SelectedTabChangeEvent; public class ReservationApplication extends Application { - private SampleDB db; - - ResourceSelectorPanel resourcePanel; - - private CalendarField reservedFrom; - - private static final long DEFAULT_GAP_MILLIS = 3600000; // (almost) one - - // hour - private long currentGapMillis = DEFAULT_GAP_MILLIS; // current length of - - // reservation - private CalendarField reservedTo; - - private Label resourceName; - - private Label statusLabel; - - private TextField description; - - private Button reservationButton; - - private Table allTable; - - private CalendarField allCalendar; - - private GoogleMap map; - - private Window popupWindow; - private Label popupMessage; - - public void init() { - - db = new SampleDB(true); - db.generateResources(); - db.generateDemoUser(); - db.generateReservations(); - - Window mainWindow = new Window("Reservr"); - setMainWindow(mainWindow); - setTheme("reservr"); - - TabSheet mainTabs = new TabSheet(); - mainWindow.addComponent(mainTabs); - - OrderedLayout reservationTab = new OrderedLayout(); - mainTabs.addTab(reservationTab, "Make reservation", null); - - resourcePanel = new ResourceSelectorPanel("Resources"); - resourcePanel.setResourceContainer(db.getResources(null)); - resourcePanel.addListener( - ResourceSelectorPanel.SelectedResourcesChangedEvent.class, - this, "selectedResourcesChanged"); - reservationTab.addComponent(resourcePanel); - - Panel reservationPanel = new Panel("Reservation", new OrderedLayout( - OrderedLayout.ORIENTATION_HORIZONTAL)); - reservationPanel.addStyleName(Panel.STYLE_LIGHT); - reservationPanel.getLayout().setMargin(true); - reservationTab.addComponent(reservationPanel); - - OrderedLayout infoLayout = new OrderedLayout(); - reservationPanel.addComponent(infoLayout); - resourceName = new Label("From the list above"); - resourceName.setCaption("Choose resource"); - infoLayout.addComponent(resourceName); - description = new TextField(); - description.setColumns(45); - description.setRows(5); - infoLayout.addComponent(description); - reservationButton = new Button("Make reservation", this, - "makeReservation"); - infoLayout.addComponent(reservationButton); - statusLabel = new Label(""); - statusLabel.setCaption(""); - infoLayout.addComponent(statusLabel); - - map = new GoogleMap(); - map.setWidth(325); - map.setHeight(210); - map.setItemMarkerHtmlPropertyId(SampleDB.Resource.PROPERTY_ID_NAME); - map.setItemMarkerXPropertyId(SampleDB.Resource.PROPERTY_ID_LOCATIONX); - map.setItemMarkerYPropertyId(SampleDB.Resource.PROPERTY_ID_LOCATIONY); - map.setContainerDataSource(db.getResources(null)); - infoLayout.addComponent(map); - - Calendar from = Calendar.getInstance(); - from.add(Calendar.HOUR, 1); - from.set(Calendar.MINUTE, 0); - from.set(Calendar.SECOND, 0); - from.set(Calendar.MILLISECOND, 0); - reservedFrom = new CalendarField("From"); - reservedFrom.setMinimumDate(from.getTime()); - reservedFrom.setValue(from.getTime()); - reservedFrom.setImmediate(true); - initCalendarFieldPropertyIds(reservedFrom); - reservationPanel.addComponent(reservedFrom); - - Label arrowLabel = new Label("»"); - arrowLabel.setContentMode(Label.CONTENT_XHTML); - arrowLabel.setStyleName("arrow"); - reservationPanel.addComponent(arrowLabel); - - Calendar to = Calendar.getInstance(); - to.setTime(from.getTime()); - to.add(Calendar.MILLISECOND, (int) DEFAULT_GAP_MILLIS); - reservedTo = new CalendarField("To"); - reservedTo.setMinimumDate(to.getTime()); - reservedTo.setValue(to.getTime()); - reservedTo.setImmediate(true); - initCalendarFieldPropertyIds(reservedTo); - reservationPanel.addComponent(reservedTo); - - reservedFrom.addListener(new ValueChangeListener() { - public void valueChange(ValueChangeEvent event) { - Date fd = (Date) reservedFrom.getValue(); - if (fd == null) { - reservedTo.setValue(null); - reservedTo.setEnabled(false); - refreshSelectedResources(); - return; - } else { - reservedTo.setEnabled(true); - } - reservedTo.setMinimumDate(new Date(fd.getTime() - + DEFAULT_GAP_MILLIS)); - Calendar to = Calendar.getInstance(); - to.setTime(fd); - to.add(Calendar.MILLISECOND, (int) currentGapMillis); - reservedTo.setValue(to.getTime()); - refreshSelectedResources(); - resetStatus(); - } - }); - reservedTo.addListener(new ValueChangeListener() { - public void valueChange(ValueChangeEvent event) { - Date from = (Date) reservedFrom.getValue(); - Date to = (Date) reservedTo.getValue(); - currentGapMillis = to.getTime() - from.getTime(); - if (currentGapMillis <= 0) { - Calendar t = Calendar.getInstance(); - t.setTime(from); - t.add(Calendar.MILLISECOND, (int) DEFAULT_GAP_MILLIS); - reservedTo.setValue(t.getTime()); - } - refreshSelectedResources(); - resetStatus(); - } - }); - - Panel allLayout = new Panel(new OrderedLayout( - OrderedLayout.ORIENTATION_HORIZONTAL)); - allLayout.addStyleName(Panel.STYLE_LIGHT); - allLayout.getLayout().setMargin(true); - allCalendar = new CalendarField(); - initCalendarFieldPropertyIds(allCalendar); - allLayout.addComponent(allCalendar); - allTable = new Table(); - allTable.setWidth(700); - allTable.setColumnCollapsingAllowed(true); - allTable.setColumnReorderingAllowed(true); - allLayout.addComponent(allTable); - mainTabs.addTab(allLayout, "All reservations", null); - mainTabs.addListener(new TabSheet.SelectedTabChangeListener() { - public void selectedTabChange(SelectedTabChangeEvent event) { - refreshReservations(); - } - }); - - refreshReservations(); - } - - public void makeReservation() { - try { - Item resource = getActiveResource(); - if (resource != null) { - db.addReservation(resource, 0, (Date) reservedFrom.getValue(), - (Date) reservedTo.getValue(), (String) description - .getValue()); - statusLabel.setCaption("Success!"); - statusLabel - .setValue("You have reserved the resource for the selected period."); - } else { - showMessage("No resource selected","Please select a resource (or category) to reserve."); - } - } catch (ResourceNotAvailableException e) { - showMessage("Reservation failed", "The selected resource was not available for the selected period."); - } - refreshReservations(); - } - - public void showMessage(String caption, String message) { - if (this.popupWindow == null) { - this.popupWindow = new Window("No resource selected"); - this.popupWindow.setHeight(50); - this.popupWindow.setPositionX(70); - this.popupWindow.setPositionY(400); - this.popupMessage = new Label("Please select a resource (or category) to reserve."); - this.popupWindow.addComponent(this.popupMessage); - Button b = new Button("Ok", new Button.ClickListener() { - public void buttonClick(ClickEvent event) { - getMainWindow().removeWindow(popupWindow); - } - }); - this.popupWindow.addComponent(b); - } else { - this.popupMessage.setValue(message); - this.popupWindow.setCaption(caption); - } - getMainWindow().addWindow(this.popupWindow); - } - - - private Item getActiveResource() throws ResourceNotAvailableException { - List rids = resourcePanel.getSelectedResources(); - if (rids != null && rids.size() > 0) { - for (Iterator it = rids.iterator(); it.hasNext();) { - Item resource = (Item) it.next(); - int id = ((Integer) resource.getItemProperty( - SampleDB.Resource.PROPERTY_ID_ID).getValue()) - .intValue(); - if (db.isAvailableResource(id, (Date) reservedFrom.getValue(), - (Date) reservedTo.getValue())) - return resource; - } - throw new ResourceNotAvailableException("No available resource"); - } else { - return null; - } - } - - private void refreshReservations() { - Container reservations = db.getReservations(resourcePanel - .getSelectedResources()); - reservedFrom.setContainerDataSource(reservations); - reservedTo.setContainerDataSource(reservations); - refreshSelectedResources(); - Container allReservations = db.getReservations(null); - allTable.setContainerDataSource(allReservations); - if (allReservations != null && allReservations.size() > 0) { - allTable.setVisibleColumns(new Object[] { - SampleDB.Reservation.PROPERTY_ID_RESERVED_FROM, - SampleDB.Reservation.PROPERTY_ID_RESERVED_TO, - SampleDB.Resource.PROPERTY_ID_NAME, - SampleDB.Resource.PROPERTY_ID_DESCRIPTION, - SampleDB.Reservation.PROPERTY_ID_DESCRIPTION }); - allTable.setColumnHeaders(new String[] { "From", "To", "Resource", - "Description", "Message" }); - } - allCalendar.setContainerDataSource(allReservations); - } - - private void refreshSelectedResources() { - Item resource = null; - try { - resource = getActiveResource(); - } catch (ResourceNotAvailableException e) { - resourceName.setCaption("Not available"); - resourceName - .setValue("Please choose another time period or resource"); - //reservationButton.setEnabled(false); - return; - } - map.clear(); - if (resource == null) { - resourceName.setCaption("Choose resource"); - resourceName.setValue("from the list above"); - //reservationButton.setEnabled(false); - map.setContainerDataSource(db.getResources(null)); - map.setZoomLevel(1); - - } else { - // Display active resource name + desc - String name = (String) resource.getItemProperty( - SampleDB.Resource.PROPERTY_ID_NAME).getValue(); - String desc = (String) resource.getItemProperty( - SampleDB.Resource.PROPERTY_ID_DESCRIPTION).getValue(); - resourceName.setCaption(name); - resourceName.setValue(desc); - // Put all resources on map (may be many if category was selected) - LinkedList srs = resourcePanel.getSelectedResources(); - for (Iterator it = srs.iterator(); it.hasNext();) { - resource = (Item) it.next(); - name = (String) resource.getItemProperty( - SampleDB.Resource.PROPERTY_ID_NAME).getValue(); - desc = (String) resource.getItemProperty( - SampleDB.Resource.PROPERTY_ID_DESCRIPTION).getValue(); - Double x = (Double) resource.getItemProperty( - SampleDB.Resource.PROPERTY_ID_LOCATIONX).getValue(); - Double y = (Double) resource.getItemProperty( - SampleDB.Resource.PROPERTY_ID_LOCATIONY).getValue(); - if (x != null && y != null) { - map.addMarker(name + "
" + desc, new Point2D.Double(x - .doubleValue(), y.doubleValue())); - - } - - } - map.setZoomLevel((srs.size() == 1 ? 14 : 9)); - //reservationButton.setEnabled(true); - } - - } - - private void initCalendarFieldPropertyIds(CalendarField cal) { - cal.setItemStyleNamePropertyId(SampleDB.Resource.PROPERTY_ID_STYLENAME); - cal - .setItemStartPropertyId(SampleDB.Reservation.PROPERTY_ID_RESERVED_FROM); - cal.setItemEndPropertyId(SampleDB.Reservation.PROPERTY_ID_RESERVED_TO); - cal.setItemTitlePropertyId(SampleDB.Resource.PROPERTY_ID_NAME); - cal - .setItemDescriptionPropertyId(SampleDB.Reservation.PROPERTY_ID_DESCRIPTION); - } - - private void resetStatus() { - statusLabel.setCaption(""); - statusLabel.setValue(""); - } - - public void selectedResourcesChanged( - ResourceSelectorPanel.SelectedResourcesChangedEvent event) { - refreshReservations(); - resetStatus(); - } + private SampleDB db; + + ResourceSelectorPanel resourcePanel; + + private CalendarField reservedFrom; + + private static final long DEFAULT_GAP_MILLIS = 3600000; // (almost) one + + // hour + private long currentGapMillis = DEFAULT_GAP_MILLIS; // current length of + + // reservation + private CalendarField reservedTo; + + private Label resourceName; + + private Label statusLabel; + + private TextField description; + + private Button reservationButton; + + private Table allTable; + + private CalendarField allCalendar; + + private GoogleMap map; + + private Window popupWindow; + private Label popupMessage; + + public void init() { + + db = new SampleDB(true); + db.generateResources(); + db.generateDemoUser(); + db.generateReservations(); + + Window mainWindow = new Window("Reservr"); + setMainWindow(mainWindow); + setTheme("reservr"); + + TabSheet mainTabs = new TabSheet(); + mainWindow.addComponent(mainTabs); + + OrderedLayout reservationTab = new OrderedLayout(); + mainTabs.addTab(reservationTab, "Make reservation", null); + + resourcePanel = new ResourceSelectorPanel("Resources"); + resourcePanel.setResourceContainer(db.getResources(null)); + resourcePanel.addListener( + ResourceSelectorPanel.SelectedResourcesChangedEvent.class, + this, "selectedResourcesChanged"); + reservationTab.addComponent(resourcePanel); + + Panel reservationPanel = new Panel("Reservation", new OrderedLayout( + OrderedLayout.ORIENTATION_HORIZONTAL)); + reservationPanel.addStyleName(Panel.STYLE_LIGHT); + reservationPanel.getLayout().setMargin(true); + reservationTab.addComponent(reservationPanel); + + OrderedLayout infoLayout = new OrderedLayout(); + reservationPanel.addComponent(infoLayout); + resourceName = new Label("From the list above"); + resourceName.setCaption("Choose resource"); + infoLayout.addComponent(resourceName); + description = new TextField(); + description.setColumns(45); + description.setRows(5); + infoLayout.addComponent(description); + reservationButton = new Button("Make reservation", this, + "makeReservation"); + infoLayout.addComponent(reservationButton); + statusLabel = new Label(""); + statusLabel.setCaption(""); + infoLayout.addComponent(statusLabel); + + map = new GoogleMap(); + map.setWidth(325); + map.setHeight(210); + map.setItemMarkerHtmlPropertyId(SampleDB.Resource.PROPERTY_ID_NAME); + map.setItemMarkerXPropertyId(SampleDB.Resource.PROPERTY_ID_LOCATIONX); + map.setItemMarkerYPropertyId(SampleDB.Resource.PROPERTY_ID_LOCATIONY); + map.setContainerDataSource(db.getResources(null)); + infoLayout.addComponent(map); + + Calendar from = Calendar.getInstance(); + from.add(Calendar.HOUR, 1); + from.set(Calendar.MINUTE, 0); + from.set(Calendar.SECOND, 0); + from.set(Calendar.MILLISECOND, 0); + reservedFrom = new CalendarField("From"); + reservedFrom.setMinimumDate(from.getTime()); + reservedFrom.setValue(from.getTime()); + reservedFrom.setImmediate(true); + initCalendarFieldPropertyIds(reservedFrom); + reservationPanel.addComponent(reservedFrom); + + Label arrowLabel = new Label("»"); + arrowLabel.setContentMode(Label.CONTENT_XHTML); + arrowLabel.setStyleName("arrow"); + reservationPanel.addComponent(arrowLabel); + + Calendar to = Calendar.getInstance(); + to.setTime(from.getTime()); + to.add(Calendar.MILLISECOND, (int) DEFAULT_GAP_MILLIS); + reservedTo = new CalendarField("To"); + reservedTo.setMinimumDate(to.getTime()); + reservedTo.setValue(to.getTime()); + reservedTo.setImmediate(true); + initCalendarFieldPropertyIds(reservedTo); + reservationPanel.addComponent(reservedTo); + + reservedFrom.addListener(new ValueChangeListener() { + public void valueChange(ValueChangeEvent event) { + Date fd = (Date) reservedFrom.getValue(); + if (fd == null) { + reservedTo.setValue(null); + reservedTo.setEnabled(false); + refreshSelectedResources(); + return; + } else { + reservedTo.setEnabled(true); + } + reservedTo.setMinimumDate(new Date(fd.getTime() + + DEFAULT_GAP_MILLIS)); + Calendar to = Calendar.getInstance(); + to.setTime(fd); + to.add(Calendar.MILLISECOND, (int) currentGapMillis); + reservedTo.setValue(to.getTime()); + refreshSelectedResources(); + resetStatus(); + } + }); + reservedTo.addListener(new ValueChangeListener() { + public void valueChange(ValueChangeEvent event) { + Date from = (Date) reservedFrom.getValue(); + Date to = (Date) reservedTo.getValue(); + currentGapMillis = to.getTime() - from.getTime(); + if (currentGapMillis <= 0) { + Calendar t = Calendar.getInstance(); + t.setTime(from); + t.add(Calendar.MILLISECOND, (int) DEFAULT_GAP_MILLIS); + reservedTo.setValue(t.getTime()); + } + refreshSelectedResources(); + resetStatus(); + } + }); + + Panel allLayout = new Panel(new OrderedLayout( + OrderedLayout.ORIENTATION_HORIZONTAL)); + allLayout.addStyleName(Panel.STYLE_LIGHT); + allLayout.getLayout().setMargin(true); + allCalendar = new CalendarField(); + initCalendarFieldPropertyIds(allCalendar); + allLayout.addComponent(allCalendar); + allTable = new Table(); + allTable.setWidth(700); + allTable.setColumnCollapsingAllowed(true); + allTable.setColumnReorderingAllowed(true); + allLayout.addComponent(allTable); + mainTabs.addTab(allLayout, "All reservations", null); + mainTabs.addListener(new TabSheet.SelectedTabChangeListener() { + public void selectedTabChange(SelectedTabChangeEvent event) { + refreshReservations(); + } + }); + + refreshReservations(); + } + + public void makeReservation() { + try { + Item resource = getActiveResource(); + if (resource != null) { + db.addReservation(resource, 0, (Date) reservedFrom.getValue(), + (Date) reservedTo.getValue(), (String) description + .getValue()); + statusLabel.setCaption("Success!"); + statusLabel + .setValue("You have reserved the resource for the selected period."); + } else { + showMessage("No resource selected", + "Please select a resource (or category) to reserve."); + } + } catch (ResourceNotAvailableException e) { + showMessage("Reservation failed", + "The selected resource was not available for the selected period."); + } + refreshReservations(); + } + + public void showMessage(String caption, String message) { + if (popupWindow == null) { + popupWindow = new Window("No resource selected"); + popupWindow.setHeight(50); + popupWindow.setPositionX(70); + popupWindow.setPositionY(400); + popupMessage = new Label( + "Please select a resource (or category) to reserve."); + popupWindow.addComponent(popupMessage); + Button b = new Button("Ok", new Button.ClickListener() { + public void buttonClick(ClickEvent event) { + getMainWindow().removeWindow(popupWindow); + } + }); + popupWindow.addComponent(b); + } else { + popupMessage.setValue(message); + popupWindow.setCaption(caption); + } + getMainWindow().addWindow(popupWindow); + } + + private Item getActiveResource() throws ResourceNotAvailableException { + List rids = resourcePanel.getSelectedResources(); + if (rids != null && rids.size() > 0) { + for (Iterator it = rids.iterator(); it.hasNext();) { + Item resource = (Item) it.next(); + int id = ((Integer) resource.getItemProperty( + SampleDB.Resource.PROPERTY_ID_ID).getValue()) + .intValue(); + if (db.isAvailableResource(id, (Date) reservedFrom.getValue(), + (Date) reservedTo.getValue())) { + return resource; + } + } + throw new ResourceNotAvailableException("No available resource"); + } else { + return null; + } + } + + private void refreshReservations() { + Container reservations = db.getReservations(resourcePanel + .getSelectedResources()); + reservedFrom.setContainerDataSource(reservations); + reservedTo.setContainerDataSource(reservations); + refreshSelectedResources(); + Container allReservations = db.getReservations(null); + allTable.setContainerDataSource(allReservations); + if (allReservations != null && allReservations.size() > 0) { + allTable.setVisibleColumns(new Object[] { + SampleDB.Reservation.PROPERTY_ID_RESERVED_FROM, + SampleDB.Reservation.PROPERTY_ID_RESERVED_TO, + SampleDB.Resource.PROPERTY_ID_NAME, + SampleDB.Resource.PROPERTY_ID_DESCRIPTION, + SampleDB.Reservation.PROPERTY_ID_DESCRIPTION }); + allTable.setColumnHeaders(new String[] { "From", "To", "Resource", + "Description", "Message" }); + } + allCalendar.setContainerDataSource(allReservations); + } + + private void refreshSelectedResources() { + Item resource = null; + try { + resource = getActiveResource(); + } catch (ResourceNotAvailableException e) { + resourceName.setCaption("Not available"); + resourceName + .setValue("Please choose another time period or resource"); + // reservationButton.setEnabled(false); + return; + } + map.clear(); + if (resource == null) { + resourceName.setCaption("Choose resource"); + resourceName.setValue("from the list above"); + // reservationButton.setEnabled(false); + map.setContainerDataSource(db.getResources(null)); + map.setZoomLevel(1); + + } else { + // Display active resource name + desc + String name = (String) resource.getItemProperty( + SampleDB.Resource.PROPERTY_ID_NAME).getValue(); + String desc = (String) resource.getItemProperty( + SampleDB.Resource.PROPERTY_ID_DESCRIPTION).getValue(); + resourceName.setCaption(name); + resourceName.setValue(desc); + // Put all resources on map (may be many if category was selected) + LinkedList srs = resourcePanel.getSelectedResources(); + for (Iterator it = srs.iterator(); it.hasNext();) { + resource = (Item) it.next(); + name = (String) resource.getItemProperty( + SampleDB.Resource.PROPERTY_ID_NAME).getValue(); + desc = (String) resource.getItemProperty( + SampleDB.Resource.PROPERTY_ID_DESCRIPTION).getValue(); + Double x = (Double) resource.getItemProperty( + SampleDB.Resource.PROPERTY_ID_LOCATIONX).getValue(); + Double y = (Double) resource.getItemProperty( + SampleDB.Resource.PROPERTY_ID_LOCATIONY).getValue(); + if (x != null && y != null) { + map.addMarker(name + "
" + desc, new Point2D.Double(x + .doubleValue(), y.doubleValue())); + + } + + } + map.setZoomLevel((srs.size() == 1 ? 14 : 9)); + // reservationButton.setEnabled(true); + } + + } + + private void initCalendarFieldPropertyIds(CalendarField cal) { + cal.setItemStyleNamePropertyId(SampleDB.Resource.PROPERTY_ID_STYLENAME); + cal + .setItemStartPropertyId(SampleDB.Reservation.PROPERTY_ID_RESERVED_FROM); + cal.setItemEndPropertyId(SampleDB.Reservation.PROPERTY_ID_RESERVED_TO); + cal.setItemTitlePropertyId(SampleDB.Resource.PROPERTY_ID_NAME); + cal + .setItemDescriptionPropertyId(SampleDB.Reservation.PROPERTY_ID_DESCRIPTION); + } + + private void resetStatus() { + statusLabel.setCaption(""); + statusLabel.setValue(""); + } + + public void selectedResourcesChanged( + ResourceSelectorPanel.SelectedResourcesChangedEvent event) { + refreshReservations(); + resetStatus(); + } } diff --git a/src/com/itmill/toolkit/demo/reservation/ResourceNotAvailableException.java b/src/com/itmill/toolkit/demo/reservation/ResourceNotAvailableException.java index 39e5a82060..673d6e9190 100644 --- a/src/com/itmill/toolkit/demo/reservation/ResourceNotAvailableException.java +++ b/src/com/itmill/toolkit/demo/reservation/ResourceNotAvailableException.java @@ -1,7 +1,7 @@ package com.itmill.toolkit.demo.reservation; public class ResourceNotAvailableException extends Exception { - public ResourceNotAvailableException(String message) { - super(message); - } + public ResourceNotAvailableException(String message) { + super(message); + } } diff --git a/src/com/itmill/toolkit/demo/reservation/ResourceSelectorPanel.java b/src/com/itmill/toolkit/demo/reservation/ResourceSelectorPanel.java index d28313cc62..17bd72f9a5 100644 --- a/src/com/itmill/toolkit/demo/reservation/ResourceSelectorPanel.java +++ b/src/com/itmill/toolkit/demo/reservation/ResourceSelectorPanel.java @@ -13,106 +13,106 @@ import com.itmill.toolkit.ui.Panel; import com.itmill.toolkit.ui.Button.ClickEvent; public class ResourceSelectorPanel extends Panel implements - Button.ClickListener { - private HashMap categoryLayouts = new HashMap(); - private HashMap categoryResources = new HashMap(); + Button.ClickListener { + private HashMap categoryLayouts = new HashMap(); + private HashMap categoryResources = new HashMap(); - private Container allResources; - private LinkedList selectedResources = null; + private Container allResources; + private LinkedList selectedResources = null; - public ResourceSelectorPanel(String caption) { - super(caption, new OrderedLayout(OrderedLayout.ORIENTATION_HORIZONTAL)); - addStyleName(Panel.STYLE_LIGHT); - } + public ResourceSelectorPanel(String caption) { + super(caption, new OrderedLayout(OrderedLayout.ORIENTATION_HORIZONTAL)); + addStyleName(Panel.STYLE_LIGHT); + } - public void setResourceContainer(Container resources) { - this.removeAllComponents(); - categoryLayouts.clear(); - categoryResources.clear(); - if (resources != null && resources.size() > 0) { - for (Iterator it = resources.getItemIds().iterator(); it.hasNext();) { - Item resource = (Item) resources.getItem(it.next()); - Integer id = (Integer) resource.getItemProperty( - SampleDB.Resource.PROPERTY_ID_ID).getValue(); - String category = (String) resource.getItemProperty( - SampleDB.Resource.PROPERTY_ID_CATEGORY).getValue(); - String name = (String) resource.getItemProperty( - SampleDB.Resource.PROPERTY_ID_NAME).getValue(); - String description = (String) resource.getItemProperty( - SampleDB.Resource.PROPERTY_ID_DESCRIPTION).getValue(); - Button rButton = new Button(name, this); - rButton.setStyleName("link"); - rButton.setDescription(description); - rButton.setData(resource); - Layout resourceLayout = (Layout) categoryLayouts.get(category); - LinkedList resourceList = (LinkedList) categoryResources - .get(category); - if (resourceLayout == null) { - resourceLayout = new OrderedLayout(); - resourceLayout.setMargin(true); - this.addComponent(resourceLayout); - categoryLayouts.put(category, resourceLayout); - resourceList = new LinkedList(); - categoryResources.put(category, resourceList); - Button cButton = new Button(category + " (any)", this); - cButton.setStyleName("important-link"); - cButton.setData(category); - resourceLayout.addComponent(cButton); - } - resourceLayout.addComponent(rButton); - resourceList.add(resource); - } - } - } + public void setResourceContainer(Container resources) { + removeAllComponents(); + categoryLayouts.clear(); + categoryResources.clear(); + if (resources != null && resources.size() > 0) { + for (Iterator it = resources.getItemIds().iterator(); it.hasNext();) { + Item resource = resources.getItem(it.next()); + Integer id = (Integer) resource.getItemProperty( + SampleDB.Resource.PROPERTY_ID_ID).getValue(); + String category = (String) resource.getItemProperty( + SampleDB.Resource.PROPERTY_ID_CATEGORY).getValue(); + String name = (String) resource.getItemProperty( + SampleDB.Resource.PROPERTY_ID_NAME).getValue(); + String description = (String) resource.getItemProperty( + SampleDB.Resource.PROPERTY_ID_DESCRIPTION).getValue(); + Button rButton = new Button(name, this); + rButton.setStyleName("link"); + rButton.setDescription(description); + rButton.setData(resource); + Layout resourceLayout = (Layout) categoryLayouts.get(category); + LinkedList resourceList = (LinkedList) categoryResources + .get(category); + if (resourceLayout == null) { + resourceLayout = new OrderedLayout(); + resourceLayout.setMargin(true); + addComponent(resourceLayout); + categoryLayouts.put(category, resourceLayout); + resourceList = new LinkedList(); + categoryResources.put(category, resourceList); + Button cButton = new Button(category + " (any)", this); + cButton.setStyleName("important-link"); + cButton.setData(category); + resourceLayout.addComponent(cButton); + } + resourceLayout.addComponent(rButton); + resourceList.add(resource); + } + } + } - private void setSelectedResources(LinkedList resources) { - selectedResources = resources; - fireEvent(new SelectedResourcesChangedEvent()); - } + private void setSelectedResources(LinkedList resources) { + selectedResources = resources; + fireEvent(new SelectedResourcesChangedEvent()); + } - public LinkedList getSelectedResources() { - return selectedResources; - } + public LinkedList getSelectedResources() { + return selectedResources; + } - public void buttonClick(ClickEvent event) { - Object source = event.getSource(); - if (source instanceof Button) { - Object data = ((Button) source).getData(); - String name = ((Button) source).getCaption(); - resetStyles(); - if (data instanceof Item) { - LinkedList rlist = new LinkedList(); - rlist.add(data); - setSelectedResources(rlist); - } else { - String category = (String) data; - LinkedList resources = (LinkedList) categoryResources - .get(category); - setSelectedResources(resources); - } - ((Button) source).setStyleName("selected-link"); - } + public void buttonClick(ClickEvent event) { + Object source = event.getSource(); + if (source instanceof Button) { + Object data = ((Button) source).getData(); + String name = ((Button) source).getCaption(); + resetStyles(); + if (data instanceof Item) { + LinkedList rlist = new LinkedList(); + rlist.add(data); + setSelectedResources(rlist); + } else { + String category = (String) data; + LinkedList resources = (LinkedList) categoryResources + .get(category); + setSelectedResources(resources); + } + ((Button) source).setStyleName("selected-link"); + } - } + } - private void resetStyles() { - for (Iterator it = categoryLayouts.values().iterator(); it.hasNext();) { - Layout lo = (Layout) it.next(); - for (Iterator bit = lo.getComponentIterator(); bit.hasNext();) { - Button b = (Button) bit.next(); - if (b.getData() instanceof Item) { - b.setStyleName("link"); - } else { - b.setStyleName("important-link"); - } - } - } + private void resetStyles() { + for (Iterator it = categoryLayouts.values().iterator(); it.hasNext();) { + Layout lo = (Layout) it.next(); + for (Iterator bit = lo.getComponentIterator(); bit.hasNext();) { + Button b = (Button) bit.next(); + if (b.getData() instanceof Item) { + b.setStyleName("link"); + } else { + b.setStyleName("important-link"); + } + } + } - } + } - public class SelectedResourcesChangedEvent extends Event { - public SelectedResourcesChangedEvent() { - super(ResourceSelectorPanel.this); - } - } + public class SelectedResourcesChangedEvent extends Event { + public SelectedResourcesChangedEvent() { + super(ResourceSelectorPanel.this); + } + } } diff --git a/src/com/itmill/toolkit/demo/reservation/SampleDB.java b/src/com/itmill/toolkit/demo/reservation/SampleDB.java index c8eb7c725e..4ee0e9bc33 100644 --- a/src/com/itmill/toolkit/demo/reservation/SampleDB.java +++ b/src/com/itmill/toolkit/demo/reservation/SampleDB.java @@ -17,529 +17,529 @@ import com.itmill.toolkit.data.Item; import com.itmill.toolkit.data.util.QueryContainer; public class SampleDB { - public class User { - public static final String TABLE = "USER"; - public static final String PROPERTY_ID_ID = TABLE + "_ID"; - public static final String PROPERTY_ID_FULLNAME = TABLE + "_FULLNAME"; - public static final String PROPERTY_ID_EMAIL = TABLE + "_EMAIL"; - public static final String PROPERTY_ID_PASSWORD = TABLE + "_PASSWORD"; - public static final String PROPERTY_ID_DELETED = TABLE + "_DELETED"; - } - - public class Resource { - public static final String TABLE = "RESOURCE"; - public static final String PROPERTY_ID_ID = TABLE + "_ID"; - public static final String PROPERTY_ID_STYLENAME = TABLE + "_STYLENAME"; - public static final String PROPERTY_ID_NAME = TABLE + "_NAME"; - public static final String PROPERTY_ID_DESCRIPTION = TABLE - + "_DESCRIPTION"; - public static final String PROPERTY_ID_LOCATIONX = TABLE - + "_LOCATION_X"; - public static final String PROPERTY_ID_LOCATIONY = TABLE - + "_LOCATION_Y"; - public static final String PROPERTY_ID_CATEGORY = TABLE + "_CATEGORY"; - public static final String PROPERTY_ID_DELETED = TABLE + "_DELETED"; - } - - public class Reservation { - public static final String TABLE = "RESERVATION"; - public static final String PROPERTY_ID_ID = TABLE + "_ID"; - public static final String PROPERTY_ID_DESCRIPTION = TABLE - + "_DESCRIPTION"; - public static final String PROPERTY_ID_RESOURCE_ID = TABLE - + "_RESOURCE_ID"; - public static final String PROPERTY_ID_RESERVED_BY_ID = TABLE - + "_RESERVED_BY_USER_ID"; - public static final String PROPERTY_ID_RESERVED_FROM = TABLE - + "_RESERVED_FROM"; - public static final String PROPERTY_ID_RESERVED_TO = TABLE - + "_RESERVED_TO"; - } - - // TODO -> param - private static final String DB_URL = "jdbc:hsqldb:file:reservation.db"; - - private static final String CREATE_TABLE_USER = "CREATE TABLE " - + User.TABLE + " (" + " " + User.PROPERTY_ID_ID - + " INTEGER IDENTITY" + ", " + User.PROPERTY_ID_FULLNAME - + " VARCHAR(100) NOT NULL" + ", " + User.PROPERTY_ID_EMAIL - + " VARCHAR(50) NOT NULL" + ", " + User.PROPERTY_ID_PASSWORD - + " VARCHAR(20) NOT NULL" + ", " + User.PROPERTY_ID_DELETED - + " BOOLEAN DEFAULT false NOT NULL" + ", UNIQUE(" - + User.PROPERTY_ID_FULLNAME + "), UNIQUE(" + User.PROPERTY_ID_EMAIL - + ") )"; - private static final String CREATE_TABLE_RESOURCE = "CREATE TABLE " - + Resource.TABLE + " (" + " " + Resource.PROPERTY_ID_ID - + " INTEGER IDENTITY" + ", " + Resource.PROPERTY_ID_STYLENAME - + " VARCHAR(20) NOT NULL" + ", " + Resource.PROPERTY_ID_NAME - + " VARCHAR(30) NOT NULL" + ", " + Resource.PROPERTY_ID_DESCRIPTION - + " VARCHAR(100)" + ", " + Resource.PROPERTY_ID_LOCATIONX - + " DOUBLE" + ", " + Resource.PROPERTY_ID_LOCATIONY + " DOUBLE" - + ", " + Resource.PROPERTY_ID_CATEGORY + " VARCHAR(30)" + ", " - + Resource.PROPERTY_ID_DELETED + " BOOLEAN DEFAULT false NOT NULL" - + ", UNIQUE(" + Resource.PROPERTY_ID_NAME + "))"; - private static final String CREATE_TABLE_RESERVATION = "CREATE TABLE " - + Reservation.TABLE + " (" + " " + Reservation.PROPERTY_ID_ID - + " INTEGER IDENTITY" + ", " + Reservation.PROPERTY_ID_RESOURCE_ID - + " INTEGER" + ", " + Reservation.PROPERTY_ID_RESERVED_BY_ID - + " INTEGER" + ", " + Reservation.PROPERTY_ID_RESERVED_FROM - + " TIMESTAMP NOT NULL" + ", " - + Reservation.PROPERTY_ID_RESERVED_TO + " TIMESTAMP NOT NULL" - + ", " + Reservation.PROPERTY_ID_DESCRIPTION + " VARCHAR(100)" - + ", FOREIGN KEY (" + Reservation.PROPERTY_ID_RESOURCE_ID - + ") REFERENCES " + Resource.TABLE + "(" + Resource.PROPERTY_ID_ID - + "), FOREIGN KEY (" + Reservation.PROPERTY_ID_RESERVED_BY_ID - + ") REFERENCES " + User.TABLE + "(" + User.PROPERTY_ID_ID + "))"; - - private Connection connection = null; - - /** - * Create database. - */ - public SampleDB() { - this(false); - } - - public SampleDB(boolean recreate) { - // connect to SQL database - connect(); - - if (recreate) { - dropTables(); - } - - // initialize SQL database - createTables(); - - // test by executing sample JDBC query - testDatabase(); - } - - private void dropTables() { - try { - update("DROP TABLE " + Reservation.TABLE); - } catch (SQLException IGNORED) { - // IGNORED, assuming it was not there - } - try { - update("DROP TABLE " + Resource.TABLE); - } catch (SQLException IGNORED) { - // IGNORED, assuming it was not there - } - try { - update("DROP TABLE " + User.TABLE); - } catch (SQLException IGNORED) { - // IGNORED, assuming it was not there - } - } - - /** - * Connect to SQL database. In this sample we use HSQLDB and an toolkit - * named database in implicitly created into system memory. - * - */ - private void connect() { - try { - Class.forName("org.hsqldb.jdbcDriver").newInstance(); - connection = DriverManager.getConnection(DB_URL); - } catch (Exception e) { - throw new RuntimeException(e); - } - } - - /** - * use for SQL commands CREATE, DROP, INSERT and UPDATE - * - * @param expression - * @throws SQLException - */ - private void update(String expression) throws SQLException { - Statement st = null; - st = connection.createStatement(); - int i = st.executeUpdate(expression); - if (i == -1) { - System.out.println("SampleDatabase error : " + expression); - } - st.close(); - } - - /** - * Create test table and few rows. Issue note: using capitalized column - * names as HSQLDB returns column names in capitalized form with this demo. - * - */ - private void createTables() { - try { - String stmt = null; - stmt = CREATE_TABLE_RESOURCE; - update(stmt); - } catch (SQLException e) { - if (e.toString().indexOf("Table already exists") == -1) { - throw new RuntimeException(e); - } - } - try { - String stmt = null; - stmt = CREATE_TABLE_USER; - update(stmt); - } catch (SQLException e) { - if (e.toString().indexOf("Table already exists") == -1) { - throw new RuntimeException(e); - } - } - try { - String stmt = null; - stmt = CREATE_TABLE_RESERVATION; - update(stmt); - } catch (SQLException e) { - if (e.toString().indexOf("Table already exists") == -1) { - throw new RuntimeException(e); - } - } - } - - /** - * Test database connection with simple SELECT command. - * - */ - private String testDatabase() { - String result = null; - try { - Statement stmt = connection.createStatement( - ResultSet.TYPE_SCROLL_INSENSITIVE, - ResultSet.CONCUR_UPDATABLE); - ResultSet rs = stmt.executeQuery("SELECT COUNT(*) FROM " - + Resource.TABLE); - rs.next(); - result = "rowcount for table test is " + rs.getObject(1).toString(); - stmt.close(); - } catch (SQLException e) { - throw new RuntimeException(e); - } - return result; - } - - public Connection getConnection() { - return connection; - } - - public Container getCategories() { - // TODO where deleted=? - String q = "SELECT DISTINCT(" + Resource.PROPERTY_ID_CATEGORY - + ") FROM " + Resource.TABLE + " ORDER BY " - + Resource.PROPERTY_ID_CATEGORY; - try { - return new QueryContainer(q, connection, - ResultSet.TYPE_SCROLL_INSENSITIVE, - ResultSet.CONCUR_READ_ONLY); - } catch (SQLException e) { - throw new RuntimeException(e); - } - - } - - public Container getResources(String category) { - // TODO where deleted=? - String q = "SELECT * FROM " + Resource.TABLE; - if (category != null) { - q += " WHERE " + Resource.PROPERTY_ID_CATEGORY + "='" + category - + "'"; // FIXME -> - // PreparedStatement! - } - - try { - return new QueryContainer(q, connection, - ResultSet.TYPE_SCROLL_INSENSITIVE, - ResultSet.CONCUR_READ_ONLY); - } catch (SQLException e) { - throw new RuntimeException(e); - } - - } - - public Container getReservations(List resources) { - // TODO where reserved_by=? - // TODO where from=? - // TODO where to=? - // TODO where deleted=? - String q = "SELECT * FROM " + Reservation.TABLE + "," + Resource.TABLE; - q += " WHERE " + Reservation.PROPERTY_ID_RESOURCE_ID + "=" - + Resource.PROPERTY_ID_ID; - if (resources != null && resources.size() > 0) { - StringBuffer s = new StringBuffer(); - for (Iterator it = resources.iterator(); it.hasNext();) { - if (s.length() > 0) { - s.append(","); - } - s.append(((Item) it.next()) - .getItemProperty(Resource.PROPERTY_ID_ID)); - } - q += " HAVING " + Reservation.PROPERTY_ID_RESOURCE_ID + " IN (" + s - + ")"; - } - q += " ORDER BY " + Reservation.PROPERTY_ID_RESERVED_FROM; - try { - QueryContainer qc = new QueryContainer(q, connection, - ResultSet.TYPE_SCROLL_INSENSITIVE, - ResultSet.CONCUR_READ_ONLY); - if (qc.size() < 1) { - return null; - } else { - return qc; - } - } catch (SQLException e) { - throw new RuntimeException(e); - } - } - - public void addReservation(Item resource, int reservedById, - Date reservedFrom, Date reservedTo, String description) { - if (reservedFrom.after(reservedTo)) { - Date tmp = reservedTo; - reservedTo = reservedFrom; - reservedFrom = tmp; - } - int resourceId = ((Integer) resource.getItemProperty( - Resource.PROPERTY_ID_ID).getValue()).intValue(); - String q = "INSERT INTO " + Reservation.TABLE + " (" - + Reservation.PROPERTY_ID_RESOURCE_ID + "," - + Reservation.PROPERTY_ID_RESERVED_BY_ID + "," - + Reservation.PROPERTY_ID_RESERVED_FROM + "," - + Reservation.PROPERTY_ID_RESERVED_TO + "," - + Reservation.PROPERTY_ID_DESCRIPTION + ")" - + "VALUES (?,?,?,?,?)"; - synchronized (DB_URL) { - try { - if (!isAvailableResource(resourceId, reservedFrom, reservedTo)) { - throw new ResourceNotAvailableException( - "The resource is not available at that time."); - } - PreparedStatement p = connection.prepareStatement(q); - p.setInt(1, resourceId); - p.setInt(2, reservedById); - p.setTimestamp(3, - new java.sql.Timestamp(reservedFrom.getTime())); - p.setTimestamp(4, new java.sql.Timestamp(reservedTo.getTime())); - p.setString(5, description); - p.execute(); - } catch (Exception e) { - throw new RuntimeException(e); - } - } - } - - public boolean isAvailableResource(int resourceId, Date reservedFrom, - Date reservedTo) { - // TODO where deleted=? - if (reservedFrom.after(reservedTo)) { - Date tmp = reservedTo; - reservedTo = reservedFrom; - reservedFrom = tmp; - } - String checkQ = "SELECT count(*) FROM " + Reservation.TABLE + " WHERE " - + Reservation.PROPERTY_ID_RESOURCE_ID + "=? AND ((" - + Reservation.PROPERTY_ID_RESERVED_FROM + ">=? AND " - + Reservation.PROPERTY_ID_RESERVED_FROM + "? AND " - + Reservation.PROPERTY_ID_RESERVED_TO + "<=?) OR (" - + Reservation.PROPERTY_ID_RESERVED_FROM + "<=? AND " - + Reservation.PROPERTY_ID_RESERVED_TO + ">=?)" + ")"; - try { - PreparedStatement p = connection.prepareStatement(checkQ); - p.setInt(1, resourceId); - p.setTimestamp(2, new java.sql.Timestamp(reservedFrom.getTime())); - p.setTimestamp(3, new java.sql.Timestamp(reservedTo.getTime())); - p.setTimestamp(4, new java.sql.Timestamp(reservedFrom.getTime())); - p.setTimestamp(5, new java.sql.Timestamp(reservedTo.getTime())); - p.setTimestamp(6, new java.sql.Timestamp(reservedFrom.getTime())); - p.setTimestamp(7, new java.sql.Timestamp(reservedTo.getTime())); - p.execute(); - ResultSet rs = p.getResultSet(); - if (rs.next() && rs.getInt(1) > 0) { - return false; - } - } catch (Exception e) { - throw new RuntimeException(e); - } - return true; - } - - public Container getUsers() { - // TODO where deleted=? - String q = "SELECT * FROM " + User.TABLE + " ORDER BY " - + User.PROPERTY_ID_FULLNAME; - try { - QueryContainer qc = new QueryContainer(q, connection, - ResultSet.TYPE_SCROLL_INSENSITIVE, - ResultSet.CONCUR_READ_ONLY); - return qc; - } catch (SQLException e) { - throw new RuntimeException(e); - } - } - - public void generateReservations() { - int days = 30; - String descriptions[] = { "Picking up guests from airport", - "Sightseeing with the guests", - "Moving new servers from A to B", "Shopping", - "Customer meeting", "Guests arriving at harbour", - "Moving furniture", "Taking guests to see town" }; - Container cat = getCategories(); - Collection cIds = cat.getItemIds(); - for (Iterator it = cIds.iterator(); it.hasNext();) { - Object id = it.next(); - Item ci = cat.getItem(id); - String c = (String) ci.getItemProperty( - Resource.PROPERTY_ID_CATEGORY).getValue(); - Container resources = getResources(c); - Collection rIds = resources.getItemIds(); - Calendar cal = Calendar.getInstance(); - cal.set(Calendar.MINUTE, 0); - cal.set(Calendar.SECOND, 0); - cal.set(Calendar.MILLISECOND, 0); - int hourNow = new Date().getHours(); - // cal.add(Calendar.DAY_OF_MONTH, -days); - for (int i = 0; i < days; i++) { - int r = 3; - for (Iterator rit = rIds.iterator(); rit.hasNext() && r > 0; r--) { - Object rid = rit.next(); - Item resource = resources.getItem(rid); - int s = hourNow - 6 + (int) Math.round(Math.random() * 6.0); - int e = s + 1 + (int) Math.round(Math.random() * 4.0); - Date start = new Date(cal.getTimeInMillis()); - start.setHours(s); - Date end = new Date(cal.getTimeInMillis()); - end.setHours(e); - addReservation(resource, 0, start, end, - descriptions[(int) Math.floor(Math.random() - * descriptions.length)]); - } - cal.add(Calendar.DATE, 1); - } - } - - } - - public void generateResources() { - - Object[][] resources = { - // Turku - { "01", "01 Ford Mondeo", "w/ company logo", "Turku", - new Double(60.510857), new Double(22.275424) }, - { "02", "02 Citroen Jumper", - "w/ company logo. 12m3 storage space.", "Turku", - new Double(60.452171), new Double(22.2995) }, - { "03", "03 Saab 93", "Cabriolet. Keys from the rental desk.", - "Turku", new Double(60.4507), new Double(22.295551) }, - { "04", "04 Volvo S60", "Key from the rental desk.", "Turku", - new Double(60.434722), new Double(22.224398) }, - { "05", "05 Smart fourtwo", "Cabrio. Keys from infodesk.", - "Turku", new Double(60.508970), new Double(22.264790) }, - // Helsinki - { "06", "06 Smart fourtwo", "Cabrio. Keys from infodesk.", - "Helsinki", new Double(60.17175), new Double(24.939029) }, - { "07", "07 Smart fourtwo", "Cabrio. Keys from infodesk.", - "Helsinki", new Double(60.17175), new Double(24.939029) }, - { "08", "08 Smart fourtwo", "Cabrio. Keys from infodesk.", - "Helsinki", new Double(60.166579), - new Double(24.953899) }, - { "09", "09 Volvo S60", "Keys from infodesk.", "Helsinki", - new Double(60.317832), new Double(24.967289) }, - { "10", "10 Saab 93", "Keys from infodesk.", "Helsinki", - new Double(60.249193), new Double(25.045921) }, - // Silicon Valley - { "11", "11 Ford Mustang", "Keys from Acme clerk.", - "Silicon Valley", new Double(37.615853), - new Double(-122.386384) }, - { "12", "12 Ford Fusion", "Keys from infodesk.", - "Silicon Valley", new Double(37.365028), - new Double(-121.922654) }, - { "13", "13 Land Rover", "Keys from infodesk.", - "Silicon Valley", new Double(37.365028), - new Double(-121.922654) }, - { "14", "14 Land Rover", "Keys from infodesk.", - "Silicon Valley", new Double(37.365028), - new Double(-121.922654) }, - { "15", "15 Ford Mustang", "GT Cal Special. Keys from guard.", - "Silicon Valley", new Double(37.403812), - new Double(-121.977425) }, - { "16", "16 Ford Focus", "Keys from guard.", "Silicon Valley", - new Double(37.403812), new Double(-121.977425) }, - // Paris - { "17", "17 Peugeot 308", "Keys from infodesk.", "Paris", - new Double(48.844756), new Double(2.372784) }, - { "18", "18 Citroen C6", "Keys from rental desk.", "Paris", - new Double(49.007253), new Double(2.545025) }, - { "19", "19 Citroen C6", "Keys from infodesk.", "Paris", - new Double(48.729061), new Double(2.368087) }, - { "20", "20 Peugeot 308", "Keys from ticket sales.", "Paris", - new Double(48.880931), new Double(2.356988) }, - { "21", "21 Peugeot 308", "Keys from ticket sales.", "Paris", - new Double(48.876479), new Double(2.358161) }, - // STHLM - { "22", "22 Volvo S60", "Keys from infodesk.", "Stockholm", - new Double(59.350414), new Double(18.106574) }, - { "23", "23 Saab 93", "Keys from infodesk.", "Stockholm", - new Double(59.355905), new Double(17.946784) }, - { "24", "24 Smart fourtwo", "Keys from infodesk.", "Stockholm", - new Double(59.315939), new Double(18.095904) }, - { "25", "25 Smart fourtwo", "Keys from infodesk.", "Stockholm", - new Double(59.330716), new Double(18.058702) }, - // Boston - { "26", "26 Ford Mustang", "Keys from infodesk.", "Boston", - new Double(42.366588), new Double(-71.020955) }, - { "27", "27 Smart fourtwo", "Keys from infodesk.", "Boston", - new Double(42.365419), new Double(-71.061748) }, - { "28", "28 Volvo S60", "Keys from Seaport Hotel reception.", - "Boston", new Double(42.34811), new Double(-71.041127) }, - { "29", "29 Smart fourtwo", - "Keys from Seaport Hotel reception.", "Boston", - new Double(42.348072), new Double(-71.041315) }, - - }; - - String q = "INSERT INTO " + Resource.TABLE + "(" - + Resource.PROPERTY_ID_STYLENAME + "," - + Resource.PROPERTY_ID_NAME + "," - + Resource.PROPERTY_ID_DESCRIPTION + "," - + Resource.PROPERTY_ID_CATEGORY + "," - + Resource.PROPERTY_ID_LOCATIONX + "," - + Resource.PROPERTY_ID_LOCATIONY + ")" - + " VALUES (?,?,?,?,?,?)"; - try { - PreparedStatement stmt = connection.prepareStatement(q); - for (int i = 0; i < resources.length; i++) { - int j = 0; - stmt.setString(j + 1, (String) resources[i][j++]); - stmt.setString(j + 1, (String) resources[i][j++]); - stmt.setString(j + 1, (String) resources[i][j++]); - stmt.setString(j + 1, (String) resources[i][j++]); - stmt.setDouble(j + 1, ((Double) resources[i][j++]) - .doubleValue()); - stmt.setDouble(j + 1, ((Double) resources[i][j++]) - .doubleValue()); - stmt.execute(); - } - } catch (SQLException e) { - throw new RuntimeException(e); - } - } - - public void generateDemoUser() { - String q = "INSERT INTO USER (" + User.PROPERTY_ID_FULLNAME + "," - + User.PROPERTY_ID_EMAIL + "," + User.PROPERTY_ID_PASSWORD - + ") VALUES (?,?,?)"; - try { - PreparedStatement stmt = connection.prepareStatement(q); - stmt.setString(1, "Demo User"); - stmt.setString(2, "demo.user@itmill.com"); - stmt.setString(3, "demo"); - stmt.execute(); - } catch (SQLException e) { - throw new RuntimeException(e); - } - - } + public class User { + public static final String TABLE = "USER"; + public static final String PROPERTY_ID_ID = TABLE + "_ID"; + public static final String PROPERTY_ID_FULLNAME = TABLE + "_FULLNAME"; + public static final String PROPERTY_ID_EMAIL = TABLE + "_EMAIL"; + public static final String PROPERTY_ID_PASSWORD = TABLE + "_PASSWORD"; + public static final String PROPERTY_ID_DELETED = TABLE + "_DELETED"; + } + + public class Resource { + public static final String TABLE = "RESOURCE"; + public static final String PROPERTY_ID_ID = TABLE + "_ID"; + public static final String PROPERTY_ID_STYLENAME = TABLE + "_STYLENAME"; + public static final String PROPERTY_ID_NAME = TABLE + "_NAME"; + public static final String PROPERTY_ID_DESCRIPTION = TABLE + + "_DESCRIPTION"; + public static final String PROPERTY_ID_LOCATIONX = TABLE + + "_LOCATION_X"; + public static final String PROPERTY_ID_LOCATIONY = TABLE + + "_LOCATION_Y"; + public static final String PROPERTY_ID_CATEGORY = TABLE + "_CATEGORY"; + public static final String PROPERTY_ID_DELETED = TABLE + "_DELETED"; + } + + public class Reservation { + public static final String TABLE = "RESERVATION"; + public static final String PROPERTY_ID_ID = TABLE + "_ID"; + public static final String PROPERTY_ID_DESCRIPTION = TABLE + + "_DESCRIPTION"; + public static final String PROPERTY_ID_RESOURCE_ID = TABLE + + "_RESOURCE_ID"; + public static final String PROPERTY_ID_RESERVED_BY_ID = TABLE + + "_RESERVED_BY_USER_ID"; + public static final String PROPERTY_ID_RESERVED_FROM = TABLE + + "_RESERVED_FROM"; + public static final String PROPERTY_ID_RESERVED_TO = TABLE + + "_RESERVED_TO"; + } + + // TODO -> param + private static final String DB_URL = "jdbc:hsqldb:file:reservation.db"; + + private static final String CREATE_TABLE_USER = "CREATE TABLE " + + User.TABLE + " (" + " " + User.PROPERTY_ID_ID + + " INTEGER IDENTITY" + ", " + User.PROPERTY_ID_FULLNAME + + " VARCHAR(100) NOT NULL" + ", " + User.PROPERTY_ID_EMAIL + + " VARCHAR(50) NOT NULL" + ", " + User.PROPERTY_ID_PASSWORD + + " VARCHAR(20) NOT NULL" + ", " + User.PROPERTY_ID_DELETED + + " BOOLEAN DEFAULT false NOT NULL" + ", UNIQUE(" + + User.PROPERTY_ID_FULLNAME + "), UNIQUE(" + User.PROPERTY_ID_EMAIL + + ") )"; + private static final String CREATE_TABLE_RESOURCE = "CREATE TABLE " + + Resource.TABLE + " (" + " " + Resource.PROPERTY_ID_ID + + " INTEGER IDENTITY" + ", " + Resource.PROPERTY_ID_STYLENAME + + " VARCHAR(20) NOT NULL" + ", " + Resource.PROPERTY_ID_NAME + + " VARCHAR(30) NOT NULL" + ", " + Resource.PROPERTY_ID_DESCRIPTION + + " VARCHAR(100)" + ", " + Resource.PROPERTY_ID_LOCATIONX + + " DOUBLE" + ", " + Resource.PROPERTY_ID_LOCATIONY + " DOUBLE" + + ", " + Resource.PROPERTY_ID_CATEGORY + " VARCHAR(30)" + ", " + + Resource.PROPERTY_ID_DELETED + " BOOLEAN DEFAULT false NOT NULL" + + ", UNIQUE(" + Resource.PROPERTY_ID_NAME + "))"; + private static final String CREATE_TABLE_RESERVATION = "CREATE TABLE " + + Reservation.TABLE + " (" + " " + Reservation.PROPERTY_ID_ID + + " INTEGER IDENTITY" + ", " + Reservation.PROPERTY_ID_RESOURCE_ID + + " INTEGER" + ", " + Reservation.PROPERTY_ID_RESERVED_BY_ID + + " INTEGER" + ", " + Reservation.PROPERTY_ID_RESERVED_FROM + + " TIMESTAMP NOT NULL" + ", " + + Reservation.PROPERTY_ID_RESERVED_TO + " TIMESTAMP NOT NULL" + + ", " + Reservation.PROPERTY_ID_DESCRIPTION + " VARCHAR(100)" + + ", FOREIGN KEY (" + Reservation.PROPERTY_ID_RESOURCE_ID + + ") REFERENCES " + Resource.TABLE + "(" + Resource.PROPERTY_ID_ID + + "), FOREIGN KEY (" + Reservation.PROPERTY_ID_RESERVED_BY_ID + + ") REFERENCES " + User.TABLE + "(" + User.PROPERTY_ID_ID + "))"; + + private Connection connection = null; + + /** + * Create database. + */ + public SampleDB() { + this(false); + } + + public SampleDB(boolean recreate) { + // connect to SQL database + connect(); + + if (recreate) { + dropTables(); + } + + // initialize SQL database + createTables(); + + // test by executing sample JDBC query + testDatabase(); + } + + private void dropTables() { + try { + update("DROP TABLE " + Reservation.TABLE); + } catch (SQLException IGNORED) { + // IGNORED, assuming it was not there + } + try { + update("DROP TABLE " + Resource.TABLE); + } catch (SQLException IGNORED) { + // IGNORED, assuming it was not there + } + try { + update("DROP TABLE " + User.TABLE); + } catch (SQLException IGNORED) { + // IGNORED, assuming it was not there + } + } + + /** + * Connect to SQL database. In this sample we use HSQLDB and an toolkit + * named database in implicitly created into system memory. + * + */ + private void connect() { + try { + Class.forName("org.hsqldb.jdbcDriver").newInstance(); + connection = DriverManager.getConnection(DB_URL); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + /** + * use for SQL commands CREATE, DROP, INSERT and UPDATE + * + * @param expression + * @throws SQLException + */ + private void update(String expression) throws SQLException { + Statement st = null; + st = connection.createStatement(); + int i = st.executeUpdate(expression); + if (i == -1) { + System.out.println("SampleDatabase error : " + expression); + } + st.close(); + } + + /** + * Create test table and few rows. Issue note: using capitalized column + * names as HSQLDB returns column names in capitalized form with this demo. + * + */ + private void createTables() { + try { + String stmt = null; + stmt = CREATE_TABLE_RESOURCE; + update(stmt); + } catch (SQLException e) { + if (e.toString().indexOf("Table already exists") == -1) { + throw new RuntimeException(e); + } + } + try { + String stmt = null; + stmt = CREATE_TABLE_USER; + update(stmt); + } catch (SQLException e) { + if (e.toString().indexOf("Table already exists") == -1) { + throw new RuntimeException(e); + } + } + try { + String stmt = null; + stmt = CREATE_TABLE_RESERVATION; + update(stmt); + } catch (SQLException e) { + if (e.toString().indexOf("Table already exists") == -1) { + throw new RuntimeException(e); + } + } + } + + /** + * Test database connection with simple SELECT command. + * + */ + private String testDatabase() { + String result = null; + try { + Statement stmt = connection.createStatement( + ResultSet.TYPE_SCROLL_INSENSITIVE, + ResultSet.CONCUR_UPDATABLE); + ResultSet rs = stmt.executeQuery("SELECT COUNT(*) FROM " + + Resource.TABLE); + rs.next(); + result = "rowcount for table test is " + rs.getObject(1).toString(); + stmt.close(); + } catch (SQLException e) { + throw new RuntimeException(e); + } + return result; + } + + public Connection getConnection() { + return connection; + } + + public Container getCategories() { + // TODO where deleted=? + String q = "SELECT DISTINCT(" + Resource.PROPERTY_ID_CATEGORY + + ") FROM " + Resource.TABLE + " ORDER BY " + + Resource.PROPERTY_ID_CATEGORY; + try { + return new QueryContainer(q, connection, + ResultSet.TYPE_SCROLL_INSENSITIVE, + ResultSet.CONCUR_READ_ONLY); + } catch (SQLException e) { + throw new RuntimeException(e); + } + + } + + public Container getResources(String category) { + // TODO where deleted=? + String q = "SELECT * FROM " + Resource.TABLE; + if (category != null) { + q += " WHERE " + Resource.PROPERTY_ID_CATEGORY + "='" + category + + "'"; // FIXME -> + // PreparedStatement! + } + + try { + return new QueryContainer(q, connection, + ResultSet.TYPE_SCROLL_INSENSITIVE, + ResultSet.CONCUR_READ_ONLY); + } catch (SQLException e) { + throw new RuntimeException(e); + } + + } + + public Container getReservations(List resources) { + // TODO where reserved_by=? + // TODO where from=? + // TODO where to=? + // TODO where deleted=? + String q = "SELECT * FROM " + Reservation.TABLE + "," + Resource.TABLE; + q += " WHERE " + Reservation.PROPERTY_ID_RESOURCE_ID + "=" + + Resource.PROPERTY_ID_ID; + if (resources != null && resources.size() > 0) { + StringBuffer s = new StringBuffer(); + for (Iterator it = resources.iterator(); it.hasNext();) { + if (s.length() > 0) { + s.append(","); + } + s.append(((Item) it.next()) + .getItemProperty(Resource.PROPERTY_ID_ID)); + } + q += " HAVING " + Reservation.PROPERTY_ID_RESOURCE_ID + " IN (" + s + + ")"; + } + q += " ORDER BY " + Reservation.PROPERTY_ID_RESERVED_FROM; + try { + QueryContainer qc = new QueryContainer(q, connection, + ResultSet.TYPE_SCROLL_INSENSITIVE, + ResultSet.CONCUR_READ_ONLY); + if (qc.size() < 1) { + return null; + } else { + return qc; + } + } catch (SQLException e) { + throw new RuntimeException(e); + } + } + + public void addReservation(Item resource, int reservedById, + Date reservedFrom, Date reservedTo, String description) { + if (reservedFrom.after(reservedTo)) { + Date tmp = reservedTo; + reservedTo = reservedFrom; + reservedFrom = tmp; + } + int resourceId = ((Integer) resource.getItemProperty( + Resource.PROPERTY_ID_ID).getValue()).intValue(); + String q = "INSERT INTO " + Reservation.TABLE + " (" + + Reservation.PROPERTY_ID_RESOURCE_ID + "," + + Reservation.PROPERTY_ID_RESERVED_BY_ID + "," + + Reservation.PROPERTY_ID_RESERVED_FROM + "," + + Reservation.PROPERTY_ID_RESERVED_TO + "," + + Reservation.PROPERTY_ID_DESCRIPTION + ")" + + "VALUES (?,?,?,?,?)"; + synchronized (DB_URL) { + try { + if (!isAvailableResource(resourceId, reservedFrom, reservedTo)) { + throw new ResourceNotAvailableException( + "The resource is not available at that time."); + } + PreparedStatement p = connection.prepareStatement(q); + p.setInt(1, resourceId); + p.setInt(2, reservedById); + p.setTimestamp(3, + new java.sql.Timestamp(reservedFrom.getTime())); + p.setTimestamp(4, new java.sql.Timestamp(reservedTo.getTime())); + p.setString(5, description); + p.execute(); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + } + + public boolean isAvailableResource(int resourceId, Date reservedFrom, + Date reservedTo) { + // TODO where deleted=? + if (reservedFrom.after(reservedTo)) { + Date tmp = reservedTo; + reservedTo = reservedFrom; + reservedFrom = tmp; + } + String checkQ = "SELECT count(*) FROM " + Reservation.TABLE + " WHERE " + + Reservation.PROPERTY_ID_RESOURCE_ID + "=? AND ((" + + Reservation.PROPERTY_ID_RESERVED_FROM + ">=? AND " + + Reservation.PROPERTY_ID_RESERVED_FROM + "? AND " + + Reservation.PROPERTY_ID_RESERVED_TO + "<=?) OR (" + + Reservation.PROPERTY_ID_RESERVED_FROM + "<=? AND " + + Reservation.PROPERTY_ID_RESERVED_TO + ">=?)" + ")"; + try { + PreparedStatement p = connection.prepareStatement(checkQ); + p.setInt(1, resourceId); + p.setTimestamp(2, new java.sql.Timestamp(reservedFrom.getTime())); + p.setTimestamp(3, new java.sql.Timestamp(reservedTo.getTime())); + p.setTimestamp(4, new java.sql.Timestamp(reservedFrom.getTime())); + p.setTimestamp(5, new java.sql.Timestamp(reservedTo.getTime())); + p.setTimestamp(6, new java.sql.Timestamp(reservedFrom.getTime())); + p.setTimestamp(7, new java.sql.Timestamp(reservedTo.getTime())); + p.execute(); + ResultSet rs = p.getResultSet(); + if (rs.next() && rs.getInt(1) > 0) { + return false; + } + } catch (Exception e) { + throw new RuntimeException(e); + } + return true; + } + + public Container getUsers() { + // TODO where deleted=? + String q = "SELECT * FROM " + User.TABLE + " ORDER BY " + + User.PROPERTY_ID_FULLNAME; + try { + QueryContainer qc = new QueryContainer(q, connection, + ResultSet.TYPE_SCROLL_INSENSITIVE, + ResultSet.CONCUR_READ_ONLY); + return qc; + } catch (SQLException e) { + throw new RuntimeException(e); + } + } + + public void generateReservations() { + int days = 30; + String descriptions[] = { "Picking up guests from airport", + "Sightseeing with the guests", + "Moving new servers from A to B", "Shopping", + "Customer meeting", "Guests arriving at harbour", + "Moving furniture", "Taking guests to see town" }; + Container cat = getCategories(); + Collection cIds = cat.getItemIds(); + for (Iterator it = cIds.iterator(); it.hasNext();) { + Object id = it.next(); + Item ci = cat.getItem(id); + String c = (String) ci.getItemProperty( + Resource.PROPERTY_ID_CATEGORY).getValue(); + Container resources = getResources(c); + Collection rIds = resources.getItemIds(); + Calendar cal = Calendar.getInstance(); + cal.set(Calendar.MINUTE, 0); + cal.set(Calendar.SECOND, 0); + cal.set(Calendar.MILLISECOND, 0); + int hourNow = new Date().getHours(); + // cal.add(Calendar.DAY_OF_MONTH, -days); + for (int i = 0; i < days; i++) { + int r = 3; + for (Iterator rit = rIds.iterator(); rit.hasNext() && r > 0; r--) { + Object rid = rit.next(); + Item resource = resources.getItem(rid); + int s = hourNow - 6 + (int) Math.round(Math.random() * 6.0); + int e = s + 1 + (int) Math.round(Math.random() * 4.0); + Date start = new Date(cal.getTimeInMillis()); + start.setHours(s); + Date end = new Date(cal.getTimeInMillis()); + end.setHours(e); + addReservation(resource, 0, start, end, + descriptions[(int) Math.floor(Math.random() + * descriptions.length)]); + } + cal.add(Calendar.DATE, 1); + } + } + + } + + public void generateResources() { + + Object[][] resources = { + // Turku + { "01", "01 Ford Mondeo", "w/ company logo", "Turku", + new Double(60.510857), new Double(22.275424) }, + { "02", "02 Citroen Jumper", + "w/ company logo. 12m3 storage space.", "Turku", + new Double(60.452171), new Double(22.2995) }, + { "03", "03 Saab 93", "Cabriolet. Keys from the rental desk.", + "Turku", new Double(60.4507), new Double(22.295551) }, + { "04", "04 Volvo S60", "Key from the rental desk.", "Turku", + new Double(60.434722), new Double(22.224398) }, + { "05", "05 Smart fourtwo", "Cabrio. Keys from infodesk.", + "Turku", new Double(60.508970), new Double(22.264790) }, + // Helsinki + { "06", "06 Smart fourtwo", "Cabrio. Keys from infodesk.", + "Helsinki", new Double(60.17175), new Double(24.939029) }, + { "07", "07 Smart fourtwo", "Cabrio. Keys from infodesk.", + "Helsinki", new Double(60.17175), new Double(24.939029) }, + { "08", "08 Smart fourtwo", "Cabrio. Keys from infodesk.", + "Helsinki", new Double(60.166579), + new Double(24.953899) }, + { "09", "09 Volvo S60", "Keys from infodesk.", "Helsinki", + new Double(60.317832), new Double(24.967289) }, + { "10", "10 Saab 93", "Keys from infodesk.", "Helsinki", + new Double(60.249193), new Double(25.045921) }, + // Silicon Valley + { "11", "11 Ford Mustang", "Keys from Acme clerk.", + "Silicon Valley", new Double(37.615853), + new Double(-122.386384) }, + { "12", "12 Ford Fusion", "Keys from infodesk.", + "Silicon Valley", new Double(37.365028), + new Double(-121.922654) }, + { "13", "13 Land Rover", "Keys from infodesk.", + "Silicon Valley", new Double(37.365028), + new Double(-121.922654) }, + { "14", "14 Land Rover", "Keys from infodesk.", + "Silicon Valley", new Double(37.365028), + new Double(-121.922654) }, + { "15", "15 Ford Mustang", "GT Cal Special. Keys from guard.", + "Silicon Valley", new Double(37.403812), + new Double(-121.977425) }, + { "16", "16 Ford Focus", "Keys from guard.", "Silicon Valley", + new Double(37.403812), new Double(-121.977425) }, + // Paris + { "17", "17 Peugeot 308", "Keys from infodesk.", "Paris", + new Double(48.844756), new Double(2.372784) }, + { "18", "18 Citroen C6", "Keys from rental desk.", "Paris", + new Double(49.007253), new Double(2.545025) }, + { "19", "19 Citroen C6", "Keys from infodesk.", "Paris", + new Double(48.729061), new Double(2.368087) }, + { "20", "20 Peugeot 308", "Keys from ticket sales.", "Paris", + new Double(48.880931), new Double(2.356988) }, + { "21", "21 Peugeot 308", "Keys from ticket sales.", "Paris", + new Double(48.876479), new Double(2.358161) }, + // STHLM + { "22", "22 Volvo S60", "Keys from infodesk.", "Stockholm", + new Double(59.350414), new Double(18.106574) }, + { "23", "23 Saab 93", "Keys from infodesk.", "Stockholm", + new Double(59.355905), new Double(17.946784) }, + { "24", "24 Smart fourtwo", "Keys from infodesk.", "Stockholm", + new Double(59.315939), new Double(18.095904) }, + { "25", "25 Smart fourtwo", "Keys from infodesk.", "Stockholm", + new Double(59.330716), new Double(18.058702) }, + // Boston + { "26", "26 Ford Mustang", "Keys from infodesk.", "Boston", + new Double(42.366588), new Double(-71.020955) }, + { "27", "27 Smart fourtwo", "Keys from infodesk.", "Boston", + new Double(42.365419), new Double(-71.061748) }, + { "28", "28 Volvo S60", "Keys from Seaport Hotel reception.", + "Boston", new Double(42.34811), new Double(-71.041127) }, + { "29", "29 Smart fourtwo", + "Keys from Seaport Hotel reception.", "Boston", + new Double(42.348072), new Double(-71.041315) }, + + }; + + String q = "INSERT INTO " + Resource.TABLE + "(" + + Resource.PROPERTY_ID_STYLENAME + "," + + Resource.PROPERTY_ID_NAME + "," + + Resource.PROPERTY_ID_DESCRIPTION + "," + + Resource.PROPERTY_ID_CATEGORY + "," + + Resource.PROPERTY_ID_LOCATIONX + "," + + Resource.PROPERTY_ID_LOCATIONY + ")" + + " VALUES (?,?,?,?,?,?)"; + try { + PreparedStatement stmt = connection.prepareStatement(q); + for (int i = 0; i < resources.length; i++) { + int j = 0; + stmt.setString(j + 1, (String) resources[i][j++]); + stmt.setString(j + 1, (String) resources[i][j++]); + stmt.setString(j + 1, (String) resources[i][j++]); + stmt.setString(j + 1, (String) resources[i][j++]); + stmt.setDouble(j + 1, ((Double) resources[i][j++]) + .doubleValue()); + stmt.setDouble(j + 1, ((Double) resources[i][j++]) + .doubleValue()); + stmt.execute(); + } + } catch (SQLException e) { + throw new RuntimeException(e); + } + } + + public void generateDemoUser() { + String q = "INSERT INTO USER (" + User.PROPERTY_ID_FULLNAME + "," + + User.PROPERTY_ID_EMAIL + "," + User.PROPERTY_ID_PASSWORD + + ") VALUES (?,?,?)"; + try { + PreparedStatement stmt = connection.prepareStatement(q); + stmt.setString(1, "Demo User"); + stmt.setString(2, "demo.user@itmill.com"); + stmt.setString(3, "demo"); + stmt.execute(); + } catch (SQLException e) { + throw new RuntimeException(e); + } + + } } diff --git a/src/com/itmill/toolkit/demo/reservation/gwt/client/ReservationWidgetSet.java b/src/com/itmill/toolkit/demo/reservation/gwt/client/ReservationWidgetSet.java index 447b7b83c9..e8333f3ea4 100644 --- a/src/com/itmill/toolkit/demo/reservation/gwt/client/ReservationWidgetSet.java +++ b/src/com/itmill/toolkit/demo/reservation/gwt/client/ReservationWidgetSet.java @@ -8,33 +8,33 @@ import com.itmill.toolkit.terminal.gwt.client.DefaultWidgetSet; import com.itmill.toolkit.terminal.gwt.client.UIDL; public class ReservationWidgetSet extends DefaultWidgetSet { - public Widget createWidget(UIDL uidl) { - String className = resolveWidgetTypeName(uidl); - if ("com.itmill.toolkit.terminal.gwt.client.ui.IGoogleMap" - .equals(className)) { - return new IGoogleMap(); - } else if ("com.itmill.toolkit.demo.reservation.gwt.client.ui.ICalendarField" - .equals(className)) { - return new ICalendarField(); - } + public Widget createWidget(UIDL uidl) { + String className = resolveWidgetTypeName(uidl); + if ("com.itmill.toolkit.terminal.gwt.client.ui.IGoogleMap" + .equals(className)) { + return new IGoogleMap(); + } else if ("com.itmill.toolkit.demo.reservation.gwt.client.ui.ICalendarField" + .equals(className)) { + return new ICalendarField(); + } - return super.createWidget(uidl); - } + return super.createWidget(uidl); + } - protected String resolveWidgetTypeName(UIDL uidl) { + protected String resolveWidgetTypeName(UIDL uidl) { - String tag = uidl.getTag(); - if ("googlemap".equals(tag)) { - return "com.itmill.toolkit.terminal.gwt.client.ui.IGoogleMap"; - } else if ("calendarfield".equals(tag)) { - return "com.itmill.toolkit.demo.reservation.gwt.client.ui.ICalendarField"; - } + String tag = uidl.getTag(); + if ("googlemap".equals(tag)) { + return "com.itmill.toolkit.terminal.gwt.client.ui.IGoogleMap"; + } else if ("calendarfield".equals(tag)) { + return "com.itmill.toolkit.demo.reservation.gwt.client.ui.ICalendarField"; + } - return super.resolveWidgetTypeName(uidl); - } + return super.resolveWidgetTypeName(uidl); + } - public boolean isCorrectImplementation(Widget currentWidget, UIDL uidl) { - return GWT.getTypeName(currentWidget).equals( - resolveWidgetTypeName(uidl)); - } + public boolean isCorrectImplementation(Widget currentWidget, UIDL uidl) { + return GWT.getTypeName(currentWidget).equals( + resolveWidgetTypeName(uidl)); + } } diff --git a/src/com/itmill/toolkit/demo/reservation/gwt/client/ui/ICalendarField.java b/src/com/itmill/toolkit/demo/reservation/gwt/client/ui/ICalendarField.java index a036488224..735b773849 100644 --- a/src/com/itmill/toolkit/demo/reservation/gwt/client/ui/ICalendarField.java +++ b/src/com/itmill/toolkit/demo/reservation/gwt/client/ui/ICalendarField.java @@ -18,255 +18,258 @@ import com.itmill.toolkit.terminal.gwt.client.UIDL; import com.itmill.toolkit.terminal.gwt.client.ui.CalendarEntry; import com.itmill.toolkit.terminal.gwt.client.ui.CalendarPanel; import com.itmill.toolkit.terminal.gwt.client.ui.IDateField; -import com.itmill.toolkit.terminal.gwt.client.ui.CalendarPanel.CalendarEntrySource; public class ICalendarField extends IDateField { - private CalendarPanel calPanel; - - private SimplePanel hourPanel; - - private FlexTable hourTable; - - private EntrySource entrySource; - - private TableListener ftListener = new HourTableListener(); - - private int realResolution = RESOLUTION_DAY; - - private static final String CLASSNAME = IDateField.CLASSNAME - + "-entrycalendar"; - - public ICalendarField() { - super(); - setStyleName(CLASSNAME); - calPanel = new CalendarPanel(this); - add(calPanel); - this.entrySource = new EntrySource(); - calPanel.setCalendarEntrySource(this.entrySource); - calPanel.addTableListener(new TableListener() { - public void onCellClicked(SourcesTableEvents sender, int row, - int cell) { - buildDayView(date); - } - }); - } - - public void updateFromUIDL(UIDL uidl, ApplicationConnection client) { - super.updateFromUIDL(uidl, client); - // We want to draw our own hour list - this.realResolution = currentResolution; - this.currentResolution = RESOLUTION_DAY; - if (uidl.hasAttribute("min")) { - String mins = uidl.getStringAttribute("min"); - long min = (mins != null ? Long.parseLong(mins) : 0); - String maxs = uidl.getStringAttribute("max"); - long max = (maxs != null ? Long.parseLong(maxs) : 0); - Date minDate = (min > 0 ? new Date(min) : null); - Date maxDate = (max > 0 ? new Date(max) : null); - calPanel.setLimits(minDate, maxDate); - } - this.entrySource.clear(); - for (Iterator cit = uidl.getChildIterator(); cit.hasNext();) { - UIDL child = (UIDL) cit.next(); - if (child.getTag().equals("items")) { - for (Iterator iit = child.getChildIterator(); iit.hasNext();) { - UIDL item = (UIDL) iit.next(); - this.entrySource.addItem(item); - } - break; - } - } - calPanel.updateCalendar(); - buildDayView(this.date); - } - - protected void buildDayView(Date date) { - boolean firstRender = true; - if (this.hourPanel == null) { - this.hourPanel = new SimplePanel(); - this.hourPanel.setStyleName(CLASSNAME + "-hours"); - this.calPanel.getFlexCellFormatter().setColSpan(8, 0, 7); - this.calPanel.setWidget(8, 0, this.hourPanel); - } else { - firstRender = false; - this.hourPanel.clear(); - } - this.hourTable = new FlexTable(); - this.hourTable.addTableListener(this.ftListener); - this.hourPanel.add(this.hourTable); - this.hourTable.setCellSpacing(1); - - for (int i = 0; i < 24; i++) { - String style = (i % 2 == 0 ? "even" : "odd"); - if (realResolution >= RESOLUTION_HOUR) { - if (this.date != null && this.date.getHours() == i) { - style = "selected"; - } - } - hourTable.getRowFormatter().setStyleName(i, - CLASSNAME + "-row-" + style); - String hstr = (i < 10 ? "0" : "") + i + ":00"; - if (this.dts.isTwelveHourClock()) { - String ampm = (i < 12 ? "am" : "pm"); - hstr = (i <= 12 ? i : i - 12) + ":00 " + ampm; - } - hourTable.setHTML(i, 0, "" + hstr + ""); - hourTable.getCellFormatter() - .setStyleName(i, 0, CLASSNAME + "-time"); - } - - List entries = this.entrySource.getEntries(date, - DateTimeService.RESOLUTION_DAY); - int currentCol = 1; - for (Iterator it = entries.iterator(); it.hasNext();) { - CalendarEntry entry = (CalendarEntry) it.next(); - int start = 0; - int hours = 24; - if (!entry.isNotime()) { - Date d = entry.getStart(); - // TODO consider month&year as well - start = (d.getDate() < date.getDate() ? 0 : d.getHours()); - d = entry.getEnd(); - hours = (d.getDate() > date.getDate() ? 24 : d.getHours()) - - start; - if (hours == 0) { - // We can't draw entries smaller than one - hours = 1; - } - } - int col = currentCol; - if (col > 1) { - while (!this.hourTable.isCellPresent(start, col - 1)) - col--; - } - this.hourTable.setHTML(start, col, "" - + (entry.getTitle() != null ? entry.getTitle() : " ") - + ""); - this.hourTable.getFlexCellFormatter().setRowSpan(start, col, hours); - this.hourTable.getFlexCellFormatter().setStyleName(start, col, - CLASSNAME + "-entry"); - String sn = entry.getStyleName(); - if (sn != null && !sn.equals("")) { - this.hourTable.getFlexCellFormatter().addStyleName(start, col, - CLASSNAME + "-" + entry.getStyleName()); - } - Element el = this.hourTable.getFlexCellFormatter().getElement( - start, col); - - String tooltip; - if (DateTimeService.isSameDay(entry.getStart(), entry.getEnd())) { - tooltip = (start < 10 ? "0" : "") + start + ":00"; - if (this.dts.isTwelveHourClock()) { - String ampm = (start < 12 ? "am" : "pm"); - tooltip = (start <= 12 ? start : start - 12) + ":00 " - + ampm; - - } - tooltip += " (" + hours + "h) "; - if (entry.getTitle()!=null) { - tooltip += entry.getTitle() + "\n "; - } - } else { - tooltip = entry.getStringForDate(entry.getEnd()) + "\n "; - } - if (entry.getDescription()!=null) { - tooltip += "\"" + entry.getDescription() + "\""; - } - DOM.setElementProperty(el, "title", tooltip); - - currentCol++; - } - - // int hour = new Date().getHours()+1; // scroll to current hour - int hour = this.date.getHours() + 1; // scroll to selected hour - int h1 = (int) this.hourPanel.getOffsetHeight() / 2; - int oh = this.hourTable.getOffsetHeight(); - int h2 = (int) (hour / 24.0 * oh); - int scrollTop = (int) h2 - h1; - Element el = this.hourPanel.getElement(); - setScrollTop(el, scrollTop); - - } - - private native void setScrollTop(Element el, int scrollTop) /*-{ - el.scrollTop = scrollTop; - }-*/; - - private class HourTableListener implements TableListener { - - public void onCellClicked(SourcesTableEvents sender, int row, int cell) { - if (realResolution < RESOLUTION_HOUR || date == null) { - return; - } - date.setHours(row); - client.updateVariable(id, "hour", row, immediate); - } - - } - - private class EntrySource implements CalendarPanel.CalendarEntrySource { - - private HashMap dates = new HashMap(); - - public void addItem(UIDL item) { - String styleName = item.getStringAttribute("styleName"); - Integer id = new Integer(item.getIntAttribute("id")); - long start = Long.parseLong(item.getStringAttribute("start")); - Date startDate = new Date(start); - long end = -1; - try { - end = Long.parseLong(item.getStringAttribute("end")); - } catch (Exception IGNORED) { - // IGNORED attribute not required - } - Date endDate = (end > 0 && end != start ? new Date(end) : new Date( - start)); - String title = item.getStringAttribute("title"); - String desc = item.getStringAttribute("description"); - boolean notime = item.getBooleanAttribute("notime"); - CalendarEntry entry = new CalendarEntry(styleName, startDate, - endDate, title, desc, notime); - - // TODO should remove+readd if the same entry (id) is added again - - for (Date d = entry.getStart(); d.getYear() <= entry.getEnd() - .getYear() - && d.getMonth() <= entry.getEnd().getYear() - && d.getDate() <= entry.getEnd().getDate(); d.setTime(d - .getTime() + 86400000)) { - String key = d.getYear() + "" + d.getMonth() + "" + d.getDate(); - ArrayList l = (ArrayList) dates.get(key); - if (l == null) { - l = new ArrayList(); - dates.put(key, l); - } - l.add(entry); - } - } - - public List getEntries(Date date, int resolution) { - List entries = (List) dates.get(date.getYear() + "" - + date.getMonth() + "" + date.getDate()); - ArrayList res = new ArrayList(); - if (entries == null) { - return res; - } - for (Iterator it = entries.iterator(); it.hasNext();) { - CalendarEntry item = (CalendarEntry) it.next(); - if (DateTimeService.isInRange(date, item.getStart(), item - .getEnd(), resolution)) { - res.add(item); - } - } - - return res; - } - - public void clear() { - dates.clear(); - } - - } + private CalendarPanel calPanel; + + private SimplePanel hourPanel; + + private FlexTable hourTable; + + private EntrySource entrySource; + + private TableListener ftListener = new HourTableListener(); + + private int realResolution = RESOLUTION_DAY; + + private static final String CLASSNAME = IDateField.CLASSNAME + + "-entrycalendar"; + + public ICalendarField() { + super(); + setStyleName(CLASSNAME); + calPanel = new CalendarPanel(this); + add(calPanel); + entrySource = new EntrySource(); + calPanel.setCalendarEntrySource(entrySource); + calPanel.addTableListener(new TableListener() { + public void onCellClicked(SourcesTableEvents sender, int row, + int cell) { + buildDayView(date); + } + }); + } + + public void updateFromUIDL(UIDL uidl, ApplicationConnection client) { + super.updateFromUIDL(uidl, client); + // We want to draw our own hour list + realResolution = currentResolution; + currentResolution = RESOLUTION_DAY; + if (uidl.hasAttribute("min")) { + String mins = uidl.getStringAttribute("min"); + long min = (mins != null ? Long.parseLong(mins) : 0); + String maxs = uidl.getStringAttribute("max"); + long max = (maxs != null ? Long.parseLong(maxs) : 0); + Date minDate = (min > 0 ? new Date(min) : null); + Date maxDate = (max > 0 ? new Date(max) : null); + calPanel.setLimits(minDate, maxDate); + } + entrySource.clear(); + for (Iterator cit = uidl.getChildIterator(); cit.hasNext();) { + UIDL child = (UIDL) cit.next(); + if (child.getTag().equals("items")) { + for (Iterator iit = child.getChildIterator(); iit.hasNext();) { + UIDL item = (UIDL) iit.next(); + entrySource.addItem(item); + } + break; + } + } + calPanel.updateCalendar(); + buildDayView(date); + } + + protected void buildDayView(Date date) { + boolean firstRender = true; + if (hourPanel == null) { + hourPanel = new SimplePanel(); + hourPanel.setStyleName(CLASSNAME + "-hours"); + calPanel.getFlexCellFormatter().setColSpan(8, 0, 7); + calPanel.setWidget(8, 0, hourPanel); + } else { + firstRender = false; + hourPanel.clear(); + } + hourTable = new FlexTable(); + hourTable.addTableListener(ftListener); + hourPanel.add(hourTable); + hourTable.setCellSpacing(1); + + for (int i = 0; i < 24; i++) { + String style = (i % 2 == 0 ? "even" : "odd"); + if (realResolution >= RESOLUTION_HOUR) { + if (this.date != null && this.date.getHours() == i) { + style = "selected"; + } + } + hourTable.getRowFormatter().setStyleName(i, + CLASSNAME + "-row-" + style); + String hstr = (i < 10 ? "0" : "") + i + ":00"; + if (dts.isTwelveHourClock()) { + String ampm = (i < 12 ? "am" : "pm"); + hstr = (i <= 12 ? i : i - 12) + ":00 " + ampm; + } + hourTable.setHTML(i, 0, "" + hstr + ""); + hourTable.getCellFormatter() + .setStyleName(i, 0, CLASSNAME + "-time"); + } + + List entries = entrySource.getEntries(date, + DateTimeService.RESOLUTION_DAY); + int currentCol = 1; + for (Iterator it = entries.iterator(); it.hasNext();) { + CalendarEntry entry = (CalendarEntry) it.next(); + int start = 0; + int hours = 24; + if (!entry.isNotime()) { + Date d = entry.getStart(); + // TODO consider month&year as well + start = (d.getDate() < date.getDate() ? 0 : d.getHours()); + d = entry.getEnd(); + hours = (d.getDate() > date.getDate() ? 24 : d.getHours()) + - start; + if (hours == 0) { + // We can't draw entries smaller than + // one + hours = 1; + } + } + int col = currentCol; + if (col > 1) { + while (!hourTable.isCellPresent(start, col - 1)) { + col--; + } + } + hourTable.setHTML(start, col, "" + + (entry.getTitle() != null ? entry.getTitle() : " ") + + ""); + hourTable.getFlexCellFormatter().setRowSpan(start, col, hours); + hourTable.getFlexCellFormatter().setStyleName(start, col, + CLASSNAME + "-entry"); + String sn = entry.getStyleName(); + if (sn != null && !sn.equals("")) { + hourTable.getFlexCellFormatter().addStyleName(start, col, + CLASSNAME + "-" + entry.getStyleName()); + } + Element el = hourTable.getFlexCellFormatter() + .getElement(start, col); + + String tooltip; + if (DateTimeService.isSameDay(entry.getStart(), entry.getEnd())) { + tooltip = (start < 10 ? "0" : "") + start + ":00"; + if (dts.isTwelveHourClock()) { + String ampm = (start < 12 ? "am" : "pm"); + tooltip = (start <= 12 ? start : start - 12) + ":00 " + + ampm; + + } + tooltip += " (" + hours + "h) "; + if (entry.getTitle() != null) { + tooltip += entry.getTitle() + "\n "; + } + } else { + tooltip = entry.getStringForDate(entry.getEnd()) + "\n "; + } + if (entry.getDescription() != null) { + tooltip += "\"" + entry.getDescription() + "\""; + } + DOM.setElementProperty(el, "title", tooltip); + + currentCol++; + } + + // int hour = new Date().getHours()+1; // scroll to current hour + int hour = this.date.getHours() + 1; // scroll to selected + // hour + int h1 = hourPanel.getOffsetHeight() / 2; + int oh = hourTable.getOffsetHeight(); + int h2 = (int) (hour / 24.0 * oh); + int scrollTop = h2 - h1; + Element el = hourPanel.getElement(); + setScrollTop(el, scrollTop); + + } + + private native void setScrollTop(Element el, int scrollTop) /*-{ + el.scrollTop = scrollTop; + }-*/; + + private class HourTableListener implements TableListener { + + public void onCellClicked(SourcesTableEvents sender, int row, int cell) { + if (realResolution < RESOLUTION_HOUR || date == null) { + return; + } + date.setHours(row); + client.updateVariable(id, "hour", row, immediate); + } + + } + + private class EntrySource implements CalendarPanel.CalendarEntrySource { + + private HashMap dates = new HashMap(); + + public void addItem(UIDL item) { + String styleName = item.getStringAttribute("styleName"); + Integer id = new Integer(item.getIntAttribute("id")); + long start = Long.parseLong(item.getStringAttribute("start")); + Date startDate = new Date(start); + long end = -1; + try { + end = Long.parseLong(item.getStringAttribute("end")); + } catch (Exception IGNORED) { + // IGNORED attribute not required + } + Date endDate = (end > 0 && end != start ? new Date(end) : new Date( + start)); + String title = item.getStringAttribute("title"); + String desc = item.getStringAttribute("description"); + boolean notime = item.getBooleanAttribute("notime"); + CalendarEntry entry = new CalendarEntry(styleName, startDate, + endDate, title, desc, notime); + + // TODO should remove+readd if the same entry (id) is + // added again + + for (Date d = entry.getStart(); d.getYear() <= entry.getEnd() + .getYear() + && d.getMonth() <= entry.getEnd().getYear() + && d.getDate() <= entry.getEnd().getDate(); d.setTime(d + .getTime() + 86400000)) { + String key = d.getYear() + "" + d.getMonth() + "" + d.getDate(); + ArrayList l = (ArrayList) dates.get(key); + if (l == null) { + l = new ArrayList(); + dates.put(key, l); + } + l.add(entry); + } + } + + public List getEntries(Date date, int resolution) { + List entries = (List) dates.get(date.getYear() + "" + + date.getMonth() + "" + date.getDate()); + ArrayList res = new ArrayList(); + if (entries == null) { + return res; + } + for (Iterator it = entries.iterator(); it.hasNext();) { + CalendarEntry item = (CalendarEntry) it.next(); + if (DateTimeService.isInRange(date, item.getStart(), item + .getEnd(), resolution)) { + res.add(item); + } + } + + return res; + } + + public void clear() { + dates.clear(); + } + + } } diff --git a/src/com/itmill/toolkit/demo/reservation/gwt/client/ui/IGoogleMap.java b/src/com/itmill/toolkit/demo/reservation/gwt/client/ui/IGoogleMap.java index 8c06561db6..1517f071a0 100644 --- a/src/com/itmill/toolkit/demo/reservation/gwt/client/ui/IGoogleMap.java +++ b/src/com/itmill/toolkit/demo/reservation/gwt/client/ui/IGoogleMap.java @@ -16,83 +16,83 @@ import com.mapitz.gwt.googleMaps.client.GMarkerEventManager; public class IGoogleMap extends GMap2Widget implements Paintable { - public static final String CLASSNAME = "i-googlemap"; - - GMap2EventManager mapEventManager; - GMarkerEventManager markerEventManager; - GMap2 map; - - public IGoogleMap() { - setStyleName(CLASSNAME); - mapEventManager = GMap2EventManager.getInstance(); - map = this.getGmap(); - map.addControl(GControl.GSmallZoomControl()); - } - - public void updateFromUIDL(UIDL uidl, ApplicationConnection client) { - map.clearOverlays(); - GLatLng pos = null; - for (Iterator it = uidl.getChildIterator(); it.hasNext();) { - UIDL u = (UIDL) it.next(); - if (u.getTag().equals("markers")) { - - for (Iterator m = u.getChildIterator(); m.hasNext();) { - UIDL umarker = (UIDL) m.next(); - String html = "" + umarker.getStringAttribute("html") - + ""; - double x = umarker.getDoubleAttribute("x"); - double y = umarker.getDoubleAttribute("y"); - pos = new GLatLng(x, y); - GMarker marker = new GMarker(pos); - map.addOverlay(marker); - if (html != null) { - addMarkerPopup(marker, html); - } - } - } - } - if (uidl.hasAttribute("width")) { - setWidth("" + uidl.getIntAttribute("width")); - } - if (uidl.hasAttribute("height")) { - setHeight("" + uidl.getIntAttribute("height")); - } - if (uidl.hasAttribute("zoom")) { - map.setZoom(uidl.getIntAttribute("zoom")); - } - if (uidl.hasAttribute("centerX") && uidl.hasAttribute("centerY")) { - GLatLng center = new GLatLng(uidl.getDoubleAttribute("centerX"), - uidl.getDoubleAttribute("centerY")); - map.setCenter(center); - } else if (pos != null) { - // use last marker position - map.setCenter(pos); - } - - } - - private void addMarkerPopup(GMarker marker, String html) { - if (markerEventManager == null) { - markerEventManager = GMarkerEventManager.getInstance(); - } - - markerEventManager.addOnClickListener(marker, new MarkerEventListener( - html)); - - } - - private class MarkerEventListener implements GMarkerEventClickListener { - String html; - - public MarkerEventListener(String html) { - this.html = html; - } - - public void onClick(GMarker marker) { - marker.openInfoWindowHtml(html); - } - - public void onDblClick(GMarker marker) { - } - } + public static final String CLASSNAME = "i-googlemap"; + + GMap2EventManager mapEventManager; + GMarkerEventManager markerEventManager; + GMap2 map; + + public IGoogleMap() { + setStyleName(CLASSNAME); + mapEventManager = GMap2EventManager.getInstance(); + map = getGmap(); + map.addControl(GControl.GSmallZoomControl()); + } + + public void updateFromUIDL(UIDL uidl, ApplicationConnection client) { + map.clearOverlays(); + GLatLng pos = null; + for (Iterator it = uidl.getChildIterator(); it.hasNext();) { + UIDL u = (UIDL) it.next(); + if (u.getTag().equals("markers")) { + + for (Iterator m = u.getChildIterator(); m.hasNext();) { + UIDL umarker = (UIDL) m.next(); + String html = "" + umarker.getStringAttribute("html") + + ""; + double x = umarker.getDoubleAttribute("x"); + double y = umarker.getDoubleAttribute("y"); + pos = new GLatLng(x, y); + GMarker marker = new GMarker(pos); + map.addOverlay(marker); + if (html != null) { + addMarkerPopup(marker, html); + } + } + } + } + if (uidl.hasAttribute("width")) { + setWidth("" + uidl.getIntAttribute("width")); + } + if (uidl.hasAttribute("height")) { + setHeight("" + uidl.getIntAttribute("height")); + } + if (uidl.hasAttribute("zoom")) { + map.setZoom(uidl.getIntAttribute("zoom")); + } + if (uidl.hasAttribute("centerX") && uidl.hasAttribute("centerY")) { + GLatLng center = new GLatLng(uidl.getDoubleAttribute("centerX"), + uidl.getDoubleAttribute("centerY")); + map.setCenter(center); + } else if (pos != null) { + // use last marker position + map.setCenter(pos); + } + + } + + private void addMarkerPopup(GMarker marker, String html) { + if (markerEventManager == null) { + markerEventManager = GMarkerEventManager.getInstance(); + } + + markerEventManager.addOnClickListener(marker, new MarkerEventListener( + html)); + + } + + private class MarkerEventListener implements GMarkerEventClickListener { + String html; + + public MarkerEventListener(String html) { + this.html = html; + } + + public void onClick(GMarker marker) { + marker.openInfoWindowHtml(html); + } + + public void onDblClick(GMarker marker) { + } + } } diff --git a/src/com/itmill/toolkit/demo/util/SampleCalendarDatabase.java b/src/com/itmill/toolkit/demo/util/SampleCalendarDatabase.java index c452a44d24..3147c8bed1 100644 --- a/src/com/itmill/toolkit/demo/util/SampleCalendarDatabase.java +++ b/src/com/itmill/toolkit/demo/util/SampleCalendarDatabase.java @@ -1,7 +1,6 @@ package com.itmill.toolkit.demo.util; import java.sql.Connection; -import java.sql.Date; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.SQLException; @@ -19,146 +18,146 @@ import java.sql.Timestamp; */ public class SampleCalendarDatabase { - public static final int ENTRYCOUNT = 100; - - public static final String DB_TABLE_NAME = "calendar"; - public static final String PROPERTY_ID_START = "EVENTSTART"; - public static final String PROPERTY_ID_END = "EVENTEND"; - public static final String PROPERTY_ID_TITLE = "TITLE"; - public static final String PROPERTY_ID_NOTIME = "NOTIME"; - - private Connection connection = null; - - private static final String[] titles = new String[] { "Meeting", "Dentist", - "Haircut", "Bank", "Birthday", "Library", "Rent", "Acme test", - "Party" }; - - /** - * Create temporary database. - * - */ - public SampleCalendarDatabase() { - // connect to SQL database - connect(); - - // initialize SQL database - createTables(); - - // test by executing sample JDBC query - testDatabase(); - } - - /** - * Creates sample table named employee and populates it with data.Use the - * specified database connection. - * - * @param connection - */ - public SampleCalendarDatabase(Connection connection) { - // initialize SQL database - createTables(); - - // test by executing sample JDBC query - testDatabase(); - } - - /** - * Connect to SQL database. In this sample we use HSQLDB and an toolkit - * named database in implicitly created into system memory. - * - */ - private void connect() { - // use memory-Only Database - String url = "jdbc:hsqldb:mem:toolkit"; - try { - Class.forName("org.hsqldb.jdbcDriver").newInstance(); - connection = DriverManager.getConnection(url, "sa", ""); - } catch (Exception e) { - throw new RuntimeException(e); - } - } - - /** - * use for SQL commands CREATE, DROP, INSERT and UPDATE - * - * @param expression - * @throws SQLException - */ - public void update(String expression) throws SQLException { - Statement st = null; - st = connection.createStatement(); - int i = st.executeUpdate(expression); - if (i == -1) { - System.out.println("SampleDatabase error : " + expression); - } - st.close(); - } - - /** - * Create test table and few rows. Issue note: using capitalized column - * names as HSQLDB returns column names in capitalized form with this demo. - * - */ - private void createTables() { - try { - String stmt = null; - stmt = "CREATE TABLE " - + DB_TABLE_NAME - + " ( ID INTEGER IDENTITY, TITLE VARCHAR(100), " - + "EVENTSTART DATETIME, EVENTEND DATETIME, NOTIME BOOLEAN )"; - update(stmt); - for (int j = 0; j < ENTRYCOUNT; j++) { - Timestamp start = new Timestamp(new java.util.Date().getTime()); - start.setDate((int) ((Math.random() - 0.4) * 200)); - start.setMinutes(0); - start.setHours(8 + (int) Math.random() * 12); - Timestamp end = new Timestamp(start.getTime()); - if (Math.random() < 0.7) { - long t = end.getTime(); - long hour = 60 * 60 * 1000; - t = t + hour - + (long) (Math.round(Math.random() * 3 * hour)); - end.setTime(t); - } - - stmt = "INSERT INTO " - + DB_TABLE_NAME - + "(TITLE, EVENTSTART, EVENTEND, NOTIME) VALUES (" - + "'" - + titles[(int) (Math.round(Math.random() - * (titles.length - 1)))] + "','" + start - + "','" + end + "'," + (Math.random() > 0.7) + ")"; - update(stmt); - } - } catch (SQLException e) { - if (e.toString().indexOf("Table already exists") == -1) - throw new RuntimeException(e); - } - } - - /** - * Test database connection with simple SELECT command. - * - */ - private String testDatabase() { - String result = null; - try { - Statement stmt = connection.createStatement( - ResultSet.TYPE_SCROLL_INSENSITIVE, - ResultSet.CONCUR_UPDATABLE); - ResultSet rs = stmt.executeQuery("SELECT COUNT(*) FROM " - + DB_TABLE_NAME); - rs.next(); - result = "rowcount for table test is " + rs.getObject(1).toString(); - stmt.close(); - } catch (SQLException e) { - throw new RuntimeException(e); - } - return result; - } - - public Connection getConnection() { - return connection; - } + public static final int ENTRYCOUNT = 100; + + public static final String DB_TABLE_NAME = "calendar"; + public static final String PROPERTY_ID_START = "EVENTSTART"; + public static final String PROPERTY_ID_END = "EVENTEND"; + public static final String PROPERTY_ID_TITLE = "TITLE"; + public static final String PROPERTY_ID_NOTIME = "NOTIME"; + + private Connection connection = null; + + private static final String[] titles = new String[] { "Meeting", "Dentist", + "Haircut", "Bank", "Birthday", "Library", "Rent", "Acme test", + "Party" }; + + /** + * Create temporary database. + * + */ + public SampleCalendarDatabase() { + // connect to SQL database + connect(); + + // initialize SQL database + createTables(); + + // test by executing sample JDBC query + testDatabase(); + } + + /** + * Creates sample table named employee and populates it with data.Use the + * specified database connection. + * + * @param connection + */ + public SampleCalendarDatabase(Connection connection) { + // initialize SQL database + createTables(); + + // test by executing sample JDBC query + testDatabase(); + } + + /** + * Connect to SQL database. In this sample we use HSQLDB and an toolkit + * named database in implicitly created into system memory. + * + */ + private void connect() { + // use memory-Only Database + String url = "jdbc:hsqldb:mem:toolkit"; + try { + Class.forName("org.hsqldb.jdbcDriver").newInstance(); + connection = DriverManager.getConnection(url, "sa", ""); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + /** + * use for SQL commands CREATE, DROP, INSERT and UPDATE + * + * @param expression + * @throws SQLException + */ + public void update(String expression) throws SQLException { + Statement st = null; + st = connection.createStatement(); + int i = st.executeUpdate(expression); + if (i == -1) { + System.out.println("SampleDatabase error : " + expression); + } + st.close(); + } + + /** + * Create test table and few rows. Issue note: using capitalized column + * names as HSQLDB returns column names in capitalized form with this demo. + * + */ + private void createTables() { + try { + String stmt = null; + stmt = "CREATE TABLE " + + DB_TABLE_NAME + + " ( ID INTEGER IDENTITY, TITLE VARCHAR(100), " + + "EVENTSTART DATETIME, EVENTEND DATETIME, NOTIME BOOLEAN )"; + update(stmt); + for (int j = 0; j < ENTRYCOUNT; j++) { + Timestamp start = new Timestamp(new java.util.Date().getTime()); + start.setDate((int) ((Math.random() - 0.4) * 200)); + start.setMinutes(0); + start.setHours(8 + (int) Math.random() * 12); + Timestamp end = new Timestamp(start.getTime()); + if (Math.random() < 0.7) { + long t = end.getTime(); + long hour = 60 * 60 * 1000; + t = t + hour + (Math.round(Math.random() * 3 * hour)); + end.setTime(t); + } + + stmt = "INSERT INTO " + + DB_TABLE_NAME + + "(TITLE, EVENTSTART, EVENTEND, NOTIME) VALUES (" + + "'" + + titles[(int) (Math.round(Math.random() + * (titles.length - 1)))] + "','" + start + + "','" + end + "'," + (Math.random() > 0.7) + ")"; + update(stmt); + } + } catch (SQLException e) { + if (e.toString().indexOf("Table already exists") == -1) { + throw new RuntimeException(e); + } + } + } + + /** + * Test database connection with simple SELECT command. + * + */ + private String testDatabase() { + String result = null; + try { + Statement stmt = connection.createStatement( + ResultSet.TYPE_SCROLL_INSENSITIVE, + ResultSet.CONCUR_UPDATABLE); + ResultSet rs = stmt.executeQuery("SELECT COUNT(*) FROM " + + DB_TABLE_NAME); + rs.next(); + result = "rowcount for table test is " + rs.getObject(1).toString(); + stmt.close(); + } catch (SQLException e) { + throw new RuntimeException(e); + } + return result; + } + + public Connection getConnection() { + return connection; + } } diff --git a/src/com/itmill/toolkit/demo/util/SampleDatabase.java b/src/com/itmill/toolkit/demo/util/SampleDatabase.java index 68e3577908..8ce233b8a5 100644 --- a/src/com/itmill/toolkit/demo/util/SampleDatabase.java +++ b/src/com/itmill/toolkit/demo/util/SampleDatabase.java @@ -17,151 +17,152 @@ import java.sql.Statement; */ public class SampleDatabase { - public static final int ROWCOUNT = 1000; - - private Connection connection = null; - - private static final String[] firstnames = new String[] { "Amanda", - "Andrew", "Bill", "Frank", "Matt", "Xavier", "John", "Mary", "Joe", - "Gloria", "Marcus", "Belinda", "David", "Anthony", "Julian", - "Paul", "Carrie", "Susan", "Gregg", "Michael", "William", "Ethan", - "Thomas", "Oscar", "Norman", "Roy", "Sarah", "Jeff", "Jane", - "Peter", "Marc", "Josie", "Linus" }; - - private static final String[] lastnames = new String[] { "Torvalds", - "Smith", "Jones", "Beck", "Burton", "Bell", "Davis", "Burke", - "Bernard", "Hood", "Scott", "Smith", "Carter", "Roller", "Conrad", - "Martin", "Fisher", "Martell", "Freeman", "Hackman", "Jones", - "Harper", "Russek", "Johnson", "Sheridan", "Hill", "Parker", - "Foster", "Moss", "Fielding" }; - - private static final String[] titles = new String[] { "Project Manager", - "Marketing Manager", "Sales Manager", "Sales", "Trainer", - "Technical Support", "Account Manager", "Customer Support", - "Testing Engineer", "Software Designer", "Programmer", "Consultant" }; - - private static final String[] units = new String[] { "Tokyo", - "Mexico City", "Seoul", "New York", "Sao Paulo", "Bombay", "Delhi", - "Shanghai", "Los Angeles", "London", "Shanghai", "Sydney", - "Bangalore", "Hong Kong", "Madrid", "Milano", "Beijing", "Paris", - "Moscow", "Berlin", "Helsinki" }; - - /** - * Create temporary database. - * - */ - public SampleDatabase() { - // connect to SQL database - connect(); - - // initialize SQL database - createTables(); - - // test by executing sample JDBC query - testDatabase(); - } - - /** - * Creates sample table named employee and populates it with data.Use the - * specified database connection. - * - * @param connection - */ - public SampleDatabase(Connection connection) { - // initialize SQL database - createTables(); - - // test by executing sample JDBC query - testDatabase(); - } - - /** - * Connect to SQL database. In this sample we use HSQLDB and an toolkit - * named database in implicitly created into system memory. - * - */ - private void connect() { - // use memory-Only Database - String url = "jdbc:hsqldb:mem:toolkit"; - try { - Class.forName("org.hsqldb.jdbcDriver").newInstance(); - connection = DriverManager.getConnection(url, "sa", ""); - } catch (Exception e) { - throw new RuntimeException(e); - } - } - - /** - * use for SQL commands CREATE, DROP, INSERT and UPDATE - * - * @param expression - * @throws SQLException - */ - public void update(String expression) throws SQLException { - Statement st = null; - st = connection.createStatement(); - int i = st.executeUpdate(expression); - if (i == -1) { - System.out.println("SampleDatabase error : " + expression); - } - st.close(); - } - - /** - * Create test table and few rows. Issue note: using capitalized column - * names as HSQLDB returns column names in capitalized form with this demo. - * - */ - private void createTables() { - try { - String stmt = null; - stmt = "CREATE TABLE employee ( ID INTEGER IDENTITY, FIRSTNAME VARCHAR(100), " - + "LASTNAME VARCHAR(100), TITLE VARCHAR(100), UNIT VARCHAR(100) )"; - update(stmt); - for (int j = 0; j < ROWCOUNT; j++) { - stmt = "INSERT INTO employee(FIRSTNAME, LASTNAME, TITLE, UNIT) VALUES (" - + "'" - + firstnames[(int) (Math.random() * (firstnames.length - 1))] - + "'," - + "'" - + lastnames[(int) (Math.random() * (lastnames.length - 1))] - + "'," - + "'" - + titles[(int) (Math.random() * (titles.length - 1))] - + "'," - + "'" - + units[(int) (Math.random() * (units.length - 1))] - + "'" + ")"; - update(stmt); - } - } catch (SQLException e) { - if (e.toString().indexOf("Table already exists") == -1) - throw new RuntimeException(e); - } - } - - /** - * Test database connection with simple SELECT command. - * - */ - private String testDatabase() { - String result = null; - try { - Statement stmt = connection.createStatement( - ResultSet.TYPE_SCROLL_INSENSITIVE, - ResultSet.CONCUR_UPDATABLE); - ResultSet rs = stmt.executeQuery("SELECT COUNT(*) FROM employee"); - rs.next(); - result = "rowcount for table test is " + rs.getObject(1).toString(); - stmt.close(); - } catch (SQLException e) { - throw new RuntimeException(e); - } - return result; - } - - public Connection getConnection() { - return connection; - } + public static final int ROWCOUNT = 1000; + + private Connection connection = null; + + private static final String[] firstnames = new String[] { "Amanda", + "Andrew", "Bill", "Frank", "Matt", "Xavier", "John", "Mary", "Joe", + "Gloria", "Marcus", "Belinda", "David", "Anthony", "Julian", + "Paul", "Carrie", "Susan", "Gregg", "Michael", "William", "Ethan", + "Thomas", "Oscar", "Norman", "Roy", "Sarah", "Jeff", "Jane", + "Peter", "Marc", "Josie", "Linus" }; + + private static final String[] lastnames = new String[] { "Torvalds", + "Smith", "Jones", "Beck", "Burton", "Bell", "Davis", "Burke", + "Bernard", "Hood", "Scott", "Smith", "Carter", "Roller", "Conrad", + "Martin", "Fisher", "Martell", "Freeman", "Hackman", "Jones", + "Harper", "Russek", "Johnson", "Sheridan", "Hill", "Parker", + "Foster", "Moss", "Fielding" }; + + private static final String[] titles = new String[] { "Project Manager", + "Marketing Manager", "Sales Manager", "Sales", "Trainer", + "Technical Support", "Account Manager", "Customer Support", + "Testing Engineer", "Software Designer", "Programmer", "Consultant" }; + + private static final String[] units = new String[] { "Tokyo", + "Mexico City", "Seoul", "New York", "Sao Paulo", "Bombay", "Delhi", + "Shanghai", "Los Angeles", "London", "Shanghai", "Sydney", + "Bangalore", "Hong Kong", "Madrid", "Milano", "Beijing", "Paris", + "Moscow", "Berlin", "Helsinki" }; + + /** + * Create temporary database. + * + */ + public SampleDatabase() { + // connect to SQL database + connect(); + + // initialize SQL database + createTables(); + + // test by executing sample JDBC query + testDatabase(); + } + + /** + * Creates sample table named employee and populates it with data.Use the + * specified database connection. + * + * @param connection + */ + public SampleDatabase(Connection connection) { + // initialize SQL database + createTables(); + + // test by executing sample JDBC query + testDatabase(); + } + + /** + * Connect to SQL database. In this sample we use HSQLDB and an toolkit + * named database in implicitly created into system memory. + * + */ + private void connect() { + // use memory-Only Database + String url = "jdbc:hsqldb:mem:toolkit"; + try { + Class.forName("org.hsqldb.jdbcDriver").newInstance(); + connection = DriverManager.getConnection(url, "sa", ""); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + /** + * use for SQL commands CREATE, DROP, INSERT and UPDATE + * + * @param expression + * @throws SQLException + */ + public void update(String expression) throws SQLException { + Statement st = null; + st = connection.createStatement(); + int i = st.executeUpdate(expression); + if (i == -1) { + System.out.println("SampleDatabase error : " + expression); + } + st.close(); + } + + /** + * Create test table and few rows. Issue note: using capitalized column + * names as HSQLDB returns column names in capitalized form with this demo. + * + */ + private void createTables() { + try { + String stmt = null; + stmt = "CREATE TABLE employee ( ID INTEGER IDENTITY, FIRSTNAME VARCHAR(100), " + + "LASTNAME VARCHAR(100), TITLE VARCHAR(100), UNIT VARCHAR(100) )"; + update(stmt); + for (int j = 0; j < ROWCOUNT; j++) { + stmt = "INSERT INTO employee(FIRSTNAME, LASTNAME, TITLE, UNIT) VALUES (" + + "'" + + firstnames[(int) (Math.random() * (firstnames.length - 1))] + + "'," + + "'" + + lastnames[(int) (Math.random() * (lastnames.length - 1))] + + "'," + + "'" + + titles[(int) (Math.random() * (titles.length - 1))] + + "'," + + "'" + + units[(int) (Math.random() * (units.length - 1))] + + "'" + ")"; + update(stmt); + } + } catch (SQLException e) { + if (e.toString().indexOf("Table already exists") == -1) { + throw new RuntimeException(e); + } + } + } + + /** + * Test database connection with simple SELECT command. + * + */ + private String testDatabase() { + String result = null; + try { + Statement stmt = connection.createStatement( + ResultSet.TYPE_SCROLL_INSENSITIVE, + ResultSet.CONCUR_UPDATABLE); + ResultSet rs = stmt.executeQuery("SELECT COUNT(*) FROM employee"); + rs.next(); + result = "rowcount for table test is " + rs.getObject(1).toString(); + stmt.close(); + } catch (SQLException e) { + throw new RuntimeException(e); + } + return result; + } + + public Connection getConnection() { + return connection; + } } diff --git a/src/com/itmill/toolkit/demo/util/SampleDirectory.java b/src/com/itmill/toolkit/demo/util/SampleDirectory.java index 95faf970c8..15cdf87dad 100644 --- a/src/com/itmill/toolkit/demo/util/SampleDirectory.java +++ b/src/com/itmill/toolkit/demo/util/SampleDirectory.java @@ -17,53 +17,53 @@ import com.itmill.toolkit.ui.Panel; */ public class SampleDirectory { - /** - * Get sample directory. - * - * @param application - * @return file pointing to sample directory - */ - public static File getDirectory(Application application) { - String errorMessage = "Access to application " - + "context base directory failed, " - + "possible security constraint with Application " - + "Server or Servlet Container.
"; - File file = application.getContext().getBaseDirectory(); - if ((file == null) || (!file.canRead()) - || (file.getAbsolutePath() == null)) { - // cannot access example directory, possible security issue with - // Application Server or Servlet Container - // Try to read sample directory from web.xml parameter - if (application.getProperty("sampleDirectory") != null) { - file = new File(application.getProperty("sampleDirectory")); - if ((file != null) && (file.canRead()) - && (file.getAbsolutePath() != null)) { - // Success using property - return file; - } - // Failure using property - errorMessage += "Failed also to access sample directory [" - + application.getProperty("sampleDirectory") - + "] defined in sampleDirectory property."; - } else { - // Failure using application context base dir, no property set - errorMessage += "Note: You can set this manually in " - + "web.xml by defining " + "sampleDirectory property."; - } - } else { - // Success using application context base dir - return file; - } - // Add failure notification as an Panel to main window - Panel errorPanel = new Panel("Demo application error"); - errorPanel.setStyle("strong"); - errorPanel.setComponentError(new SystemError( - "Cannot provide sample directory")); - errorPanel.addComponent(new Label(errorMessage, Label.CONTENT_XHTML)); - // Remove all components from applications main window - application.getMainWindow().getLayout().removeAllComponents(); - // Add error panel - application.getMainWindow().getLayout().addComponent(errorPanel); - return null; - } + /** + * Get sample directory. + * + * @param application + * @return file pointing to sample directory + */ + public static File getDirectory(Application application) { + String errorMessage = "Access to application " + + "context base directory failed, " + + "possible security constraint with Application " + + "Server or Servlet Container.
"; + File file = application.getContext().getBaseDirectory(); + if ((file == null) || (!file.canRead()) + || (file.getAbsolutePath() == null)) { + // cannot access example directory, possible security issue with + // Application Server or Servlet Container + // Try to read sample directory from web.xml parameter + if (application.getProperty("sampleDirectory") != null) { + file = new File(application.getProperty("sampleDirectory")); + if ((file != null) && (file.canRead()) + && (file.getAbsolutePath() != null)) { + // Success using property + return file; + } + // Failure using property + errorMessage += "Failed also to access sample directory [" + + application.getProperty("sampleDirectory") + + "] defined in sampleDirectory property."; + } else { + // Failure using application context base dir, no property set + errorMessage += "Note: You can set this manually in " + + "web.xml by defining " + "sampleDirectory property."; + } + } else { + // Success using application context base dir + return file; + } + // Add failure notification as an Panel to main window + Panel errorPanel = new Panel("Demo application error"); + errorPanel.setStyle("strong"); + errorPanel.setComponentError(new SystemError( + "Cannot provide sample directory")); + errorPanel.addComponent(new Label(errorMessage, Label.CONTENT_XHTML)); + // Remove all components from applications main window + application.getMainWindow().getLayout().removeAllComponents(); + // Add error panel + application.getMainWindow().getLayout().addComponent(errorPanel); + return null; + } } diff --git a/src/com/itmill/toolkit/event/Action.java b/src/com/itmill/toolkit/event/Action.java index cc1bbd723b..f2551f2b7b 100644 --- a/src/com/itmill/toolkit/event/Action.java +++ b/src/com/itmill/toolkit/event/Action.java @@ -28,7 +28,7 @@ package com.itmill.toolkit.event; -import com.itmill.toolkit.terminal.*; +import com.itmill.toolkit.terminal.Resource; /** * Implements the action framework. This class contains subinterfaces for action @@ -42,146 +42,146 @@ import com.itmill.toolkit.terminal.*; */ public class Action { - /** - * Action title. - */ - private String caption; - - /** - * Action icon. - */ - private Resource icon = null; - - /** - * Constructs a new action with the given caption. - * - * @param caption - * the caption for the new action. - */ - public Action(String caption) { - this.caption = caption; - } - - /** - * Constructs a new action with the given caption string and icon. - * - * @param caption - * the caption for the new action. - * @param icon - * the icon for the new action. - */ - public Action(String caption, Resource icon) { - this.caption = caption; - this.icon = icon; - } - - /** - * Returns the action's caption. - * - * @return the action's caption as a String. - */ - public String getCaption() { - return caption; - } - - /** - * Returns the action's icon. - * - * @return the action's Icon. - */ - public Resource getIcon() { - return icon; - } - - /** - * Interface implemented by classes who wish to handle actions. - * - * @author IT Mill Ltd. - * @version - * @VERSION@ - * @since 3.0 - */ - public interface Handler { - - /** - * Gets the list of actions applicable to this handler. - * - * @param target - * the target handler to list actions for. For item - * containers this is the item id. - * @param sender - * the party that would be sending the actions. Most of this - * is the action container. - * @return the list of Action - */ - public Action[] getActions(Object target, Object sender); - - /** - * Handles an action for the given target. The handler method may just - * discard the action if it's not suitable. - * - * @param action - * the action to be handled. - * @param sender - * the sender of the action. This is most often the action - * container. - * @param target - * the target of the action. For item containers this is the - * item id. - */ - public void handleAction(Action action, Object sender, Object target); - } - - /** - * Interface implemented by all components where actions can be registered. - * This means that the components lets others to register as action handlers - * to it. When the component receives an action targeting its contents it - * should loop all action handlers registered to it and let them handle the - * action. - * - * @author IT Mill Ltd. - * @version - * @VERSION@ - * @since 3.0 - */ - public interface Container { - - /** - * Registers a new action handler for this container - * - * @param actionHandler - * the new handler to be added. - */ - public void addActionHandler(Action.Handler actionHandler); - - /** - * Removes a previously registered action handler for the contents of - * this container. - * - * @param actionHandler - * the handler to be removed. - */ - public void removeActionHandler(Action.Handler actionHandler); - } - - /** - * Sets the caption. - * - * @param caption - * the caption to set. - */ - public void setCaption(String caption) { - this.caption = caption; - } - - /** - * Sets the icon. - * - * @param icon - * the icon to set. - */ - public void setIcon(Resource icon) { - this.icon = icon; - } + /** + * Action title. + */ + private String caption; + + /** + * Action icon. + */ + private Resource icon = null; + + /** + * Constructs a new action with the given caption. + * + * @param caption + * the caption for the new action. + */ + public Action(String caption) { + this.caption = caption; + } + + /** + * Constructs a new action with the given caption string and icon. + * + * @param caption + * the caption for the new action. + * @param icon + * the icon for the new action. + */ + public Action(String caption, Resource icon) { + this.caption = caption; + this.icon = icon; + } + + /** + * Returns the action's caption. + * + * @return the action's caption as a String. + */ + public String getCaption() { + return caption; + } + + /** + * Returns the action's icon. + * + * @return the action's Icon. + */ + public Resource getIcon() { + return icon; + } + + /** + * Interface implemented by classes who wish to handle actions. + * + * @author IT Mill Ltd. + * @version + * @VERSION@ + * @since 3.0 + */ + public interface Handler { + + /** + * Gets the list of actions applicable to this handler. + * + * @param target + * the target handler to list actions for. For item + * containers this is the item id. + * @param sender + * the party that would be sending the actions. Most of + * this is the action container. + * @return the list of Action + */ + public Action[] getActions(Object target, Object sender); + + /** + * Handles an action for the given target. The handler method may just + * discard the action if it's not suitable. + * + * @param action + * the action to be handled. + * @param sender + * the sender of the action. This is most often the + * action container. + * @param target + * the target of the action. For item containers this is + * the item id. + */ + public void handleAction(Action action, Object sender, Object target); + } + + /** + * Interface implemented by all components where actions can be registered. + * This means that the components lets others to register as action handlers + * to it. When the component receives an action targeting its contents it + * should loop all action handlers registered to it and let them handle the + * action. + * + * @author IT Mill Ltd. + * @version + * @VERSION@ + * @since 3.0 + */ + public interface Container { + + /** + * Registers a new action handler for this container + * + * @param actionHandler + * the new handler to be added. + */ + public void addActionHandler(Action.Handler actionHandler); + + /** + * Removes a previously registered action handler for the contents of + * this container. + * + * @param actionHandler + * the handler to be removed. + */ + public void removeActionHandler(Action.Handler actionHandler); + } + + /** + * Sets the caption. + * + * @param caption + * the caption to set. + */ + public void setCaption(String caption) { + this.caption = caption; + } + + /** + * Sets the icon. + * + * @param icon + * the icon to set. + */ + public void setIcon(Resource icon) { + this.icon = icon; + } } diff --git a/src/com/itmill/toolkit/event/EventRouter.java b/src/com/itmill/toolkit/event/EventRouter.java index 563bb7c639..a71a3e1874 100644 --- a/src/com/itmill/toolkit/event/EventRouter.java +++ b/src/com/itmill/toolkit/event/EventRouter.java @@ -28,10 +28,10 @@ package com.itmill.toolkit.event; +import java.lang.reflect.Method; import java.util.EventObject; -import java.util.LinkedList; import java.util.Iterator; -import java.lang.reflect.Method; +import java.util.LinkedList; /** * EventRouter class implementing the inheritable event listening @@ -45,134 +45,143 @@ import java.lang.reflect.Method; */ public class EventRouter implements MethodEventSource { - /** - * List of registered listeners. - */ - private LinkedList listenerList = null; - - /* - * Registers a new listener with the specified activation method to listen - * events generated by this component. Don't add a JavaDoc comment here, we - * use the default documentation from implemented interface. - */ - public void addListener(Class eventType, Object object, Method method) { - - if (listenerList == null) - listenerList = new LinkedList(); - - listenerList.add(new ListenerMethod(eventType, object, method)); - } - - /* - * Registers a new listener with the specified named activation method to - * listen events generated by this component. Don't add a JavaDoc comment - * here, we use the default documentation from implemented interface. - */ - public void addListener(Class eventType, Object object, String methodName) { - - if (listenerList == null) - listenerList = new LinkedList(); - - listenerList.add(new ListenerMethod(eventType, object, methodName)); - } - - /* - * Removes all registered listeners matching the given parameters. Don't add - * a JavaDoc comment here, we use the default documentation from implemented - * interface. - */ - public void removeListener(Class eventType, Object target) { - - if (listenerList != null) { - Iterator i = listenerList.iterator(); - while (i.hasNext()) { - try { - ListenerMethod lm = (ListenerMethod) i.next(); - if (lm.matches(eventType, target)) - i.remove(); - } catch (java.lang.ClassCastException e) { - // Class cast exceptions are ignored - } - } - } - } - - /* - * Removes the event listener methods matching the given given paramaters. - * Don't add a JavaDoc comment here, we use the default documentation from - * implemented interface. - */ - public void removeListener(Class eventType, Object target, Method method) { - - if (listenerList != null) { - Iterator i = listenerList.iterator(); - while (i.hasNext()) { - try { - ListenerMethod lm = (ListenerMethod) i.next(); - if (lm.matches(eventType, target, method)) - i.remove(); - } catch (java.lang.ClassCastException e) { - // Class cast exceptions are ignored - } - } - } - } - - /* - * Removes the event listener method matching the given given paramaters. - * Don't add a JavaDoc comment here, we use the default documentation from - * implemented interface. - */ - public void removeListener(Class eventType, Object target, String methodName) { - - // Find the correct method - Method[] methods = target.getClass().getMethods(); - Method method = null; - for (int i = 0; i < methods.length; i++) - if (methods[i].getName().equals(methodName)) - method = methods[i]; - if (method == null) - throw new IllegalArgumentException(); - - // Remove the listeners - if (listenerList != null) { - Iterator i = listenerList.iterator(); - while (i.hasNext()) { - try { - ListenerMethod lm = (ListenerMethod) i.next(); - if (lm.matches(eventType, target, method)) - i.remove(); - } catch (java.lang.ClassCastException e) { - // Class cast exceptions are ignored - } - } - } - } - - /** - * Removes all listeners from event router. - */ - public void removeAllListeners() { - listenerList = null; - } - - /** - * Sends an event to all registered listeners. The listeners will decide if - * the activation method should be called or not. - * - * @param event - * the Event to be sent to all listeners. - */ - public void fireEvent(EventObject event) { - - // It is not necessary to send any events if there are no listeners - if (listenerList != null) { - - // Send the event to all listeners. The listeners themselves - // will filter out unwanted events. - Iterator i = new LinkedList(listenerList).iterator(); - while (i.hasNext()) - ((ListenerMethod) i.next()).receiveEvent(event); - } - } + /** + * List of registered listeners. + */ + private LinkedList listenerList = null; + + /* + * Registers a new listener with the specified activation method to listen + * events generated by this component. Don't add a JavaDoc comment here, we + * use the default documentation from implemented interface. + */ + public void addListener(Class eventType, Object object, Method method) { + + if (listenerList == null) { + listenerList = new LinkedList(); + } + + listenerList.add(new ListenerMethod(eventType, object, method)); + } + + /* + * Registers a new listener with the specified named activation method to + * listen events generated by this component. Don't add a JavaDoc comment + * here, we use the default documentation from implemented interface. + */ + public void addListener(Class eventType, Object object, String methodName) { + + if (listenerList == null) { + listenerList = new LinkedList(); + } + + listenerList.add(new ListenerMethod(eventType, object, methodName)); + } + + /* + * Removes all registered listeners matching the given parameters. Don't add + * a JavaDoc comment here, we use the default documentation from implemented + * interface. + */ + public void removeListener(Class eventType, Object target) { + + if (listenerList != null) { + Iterator i = listenerList.iterator(); + while (i.hasNext()) { + try { + ListenerMethod lm = (ListenerMethod) i.next(); + if (lm.matches(eventType, target)) { + i.remove(); + } + } catch (java.lang.ClassCastException e) { + // Class cast exceptions are ignored + } + } + } + } + + /* + * Removes the event listener methods matching the given given paramaters. + * Don't add a JavaDoc comment here, we use the default documentation from + * implemented interface. + */ + public void removeListener(Class eventType, Object target, Method method) { + + if (listenerList != null) { + Iterator i = listenerList.iterator(); + while (i.hasNext()) { + try { + ListenerMethod lm = (ListenerMethod) i.next(); + if (lm.matches(eventType, target, method)) { + i.remove(); + } + } catch (java.lang.ClassCastException e) { + // Class cast exceptions are ignored + } + } + } + } + + /* + * Removes the event listener method matching the given given paramaters. + * Don't add a JavaDoc comment here, we use the default documentation from + * implemented interface. + */ + public void removeListener(Class eventType, Object target, String methodName) { + + // Find the correct method + Method[] methods = target.getClass().getMethods(); + Method method = null; + for (int i = 0; i < methods.length; i++) { + if (methods[i].getName().equals(methodName)) { + method = methods[i]; + } + } + if (method == null) { + throw new IllegalArgumentException(); + } + + // Remove the listeners + if (listenerList != null) { + Iterator i = listenerList.iterator(); + while (i.hasNext()) { + try { + ListenerMethod lm = (ListenerMethod) i.next(); + if (lm.matches(eventType, target, method)) { + i.remove(); + } + } catch (java.lang.ClassCastException e) { + // Class cast exceptions are ignored + } + } + } + } + + /** + * Removes all listeners from event router. + */ + public void removeAllListeners() { + listenerList = null; + } + + /** + * Sends an event to all registered listeners. The listeners will decide if + * the activation method should be called or not. + * + * @param event + * the Event to be sent to all listeners. + */ + public void fireEvent(EventObject event) { + + // It is not necessary to send any events if there are no listeners + if (listenerList != null) { + + // Send the event to all listeners. The listeners themselves + // will filter out unwanted events. + Iterator i = new LinkedList(listenerList).iterator(); + while (i.hasNext()) { + ((ListenerMethod) i.next()).receiveEvent(event); + } + } + } } diff --git a/src/com/itmill/toolkit/event/ListenerMethod.java b/src/com/itmill/toolkit/event/ListenerMethod.java index f88b691987..07c9866e37 100644 --- a/src/com/itmill/toolkit/event/ListenerMethod.java +++ b/src/com/itmill/toolkit/event/ListenerMethod.java @@ -28,9 +28,9 @@ package com.itmill.toolkit.event; +import java.lang.reflect.Method; import java.util.EventListener; import java.util.EventObject; -import java.lang.reflect.Method; /** *

@@ -60,483 +60,513 @@ import java.lang.reflect.Method; */ public class ListenerMethod implements EventListener { - /** - * Type of the event that should trigger this listener. Also the subclasses - * of this class are accepted to trigger the listener. - */ - private Class eventType; - - /** - * The object containing the trigger method. - */ - private Object object; - - /** - * The trigger method to call when an event passing the given criteria - * fires. - */ - private Method method; - - /** - * Optional argument set to pass to the trigger method. - */ - private Object[] arguments; - - /** - * Optional index to arguments that point out which one - * should be replaced with the triggering event object and thus be passed to - * the trigger method. - */ - private int eventArgumentIndex; - - /** - *

- * Constructs a new event listener from a trigger method, it's arguments and - * the argument index specifying which one is replaced with the event object - * when the trigger method is called. - *

- * - *

- * This constructor gets the trigger method as a parameter so it does not - * need to reflect to find it out. - *

- * - * @param eventType - * the event type that is listener listens to. All events of this - * kind (or its subclasses) result in calling the trigger method. - * @param object - * the object instance that contains the trigger method - * @param method - * the trigger method - * @param arguments - * the arguments to be passed to the trigger method - * @param eventArgumentIndex - * An index to the argument list. This index points out the - * argument that is replaced with the event object before the - * argument set is passed to the trigger method. If the - * eventArgumentIndex is negative, the triggering event object - * will not be passed to the trigger method, though it is still - * called. - * @throws java.lang.IllegalArgumentException - * if method is not a member of - * object. - */ - public ListenerMethod(Class eventType, Object object, Method method, - Object[] arguments, int eventArgumentIndex) - throws java.lang.IllegalArgumentException { - - // Checks that the object is of correct type - if (!method.getDeclaringClass().isAssignableFrom(object.getClass())) - throw new java.lang.IllegalArgumentException(); - - // Checks that the event argument is null - if (eventArgumentIndex >= 0 && arguments[eventArgumentIndex] != null) - throw new java.lang.IllegalArgumentException(); - - // Checks the event type is supported by the method - if (eventArgumentIndex >= 0 - && !method.getParameterTypes()[eventArgumentIndex] - .isAssignableFrom(eventType)) - throw new java.lang.IllegalArgumentException(); - - this.eventType = eventType; - this.object = object; - this.method = method; - this.arguments = arguments; - this.eventArgumentIndex = eventArgumentIndex; - } - - /** - *

- * Constructs a new event listener from a trigger method name, it's - * arguments and the argument index specifying which one is replaced with - * the event object. The actual trigger method is reflected from - * object, and - * java.lang.IllegalArgumentException is thrown unless - * exactly one match is found. - *

- * - * @param eventType - * the event type that is listener listens to. All events of this - * kind (or its subclasses) result in calling the trigger method. - * @param object - * the object instance that contains the trigger method. - * @param methodName - * the name of the trigger method. If the object does not contain - * the method or it contains more than one matching methods - * java.lang.IllegalArgumentException is thrown. - * @param arguments - * the arguments to be passed to the trigger method. - * @param eventArgumentIndex - * An index to the argument list. This index points out the - * argument that is replaced with the event object before the - * argument set is passed to the trigger method. If the - * eventArgumentIndex is negative, the triggering event object - * will not be passed to the trigger method, though it is still - * called. - * @throws java.lang.IllegalArgumentException - * unless exactly one match methodName is found - * in object. - */ - public ListenerMethod(Class eventType, Object object, String methodName, - Object[] arguments, int eventArgumentIndex) - throws java.lang.IllegalArgumentException { - - // Finds the correct method - Method[] methods = object.getClass().getMethods(); - Method method = null; - for (int i = 0; i < methods.length; i++) - if (methods[i].getName().equals(methodName)) - method = methods[i]; - if (method == null) - throw new IllegalArgumentException(); - - // Checks that the event argument is null - if (eventArgumentIndex >= 0 && arguments[eventArgumentIndex] != null) - throw new java.lang.IllegalArgumentException(); - - // Checks the event type is supported by the method - if (eventArgumentIndex >= 0 - && !method.getParameterTypes()[eventArgumentIndex] - .isAssignableFrom(eventType)) - throw new java.lang.IllegalArgumentException(); - - this.eventType = eventType; - this.object = object; - this.method = method; - this.arguments = arguments; - this.eventArgumentIndex = eventArgumentIndex; - } - - /** - *

- * Constructs a new event listener from the trigger method and it's - * arguments. Since the the index to the replaced parameter is not specified - * the event triggering this listener will not be passed to the trigger - * method. - *

- * - *

- * This constructor gets the trigger method as a parameter so it does not - * need to reflect to find it out. - *

- * - * @param eventType - * the event type that is listener listens to. All events of this - * kind (or its subclasses) result in calling the trigger method. - * @param object - * the object instance that contains the trigger method. - * @param method - * the trigger method. - * @param arguments - * the arguments to be passed to the trigger method. - * @throws java.lang.IllegalArgumentException - * if method is not a member of - * object. - */ - public ListenerMethod(Class eventType, Object object, Method method, - Object[] arguments) throws java.lang.IllegalArgumentException { - - // Check that the object is of correct type - if (!method.getDeclaringClass().isAssignableFrom(object.getClass())) - throw new java.lang.IllegalArgumentException(); - - this.eventType = eventType; - this.object = object; - this.method = method; - this.arguments = arguments; - this.eventArgumentIndex = -1; - } - - /** - *

- * Constructs a new event listener from a trigger method name and it's - * arguments. Since the the index to the replaced parameter is not specified - * the event triggering this listener will not be passed to the trigger - * method. - *

- * - *

- * The actual trigger method is reflected from object, and - * java.lang.IllegalArgumentException is thrown unless - * exactly one match is found. - *

- * - * @param eventType - * the event type that is listener listens to. All events of this - * kind (or its subclasses) result in calling the trigger method. - * @param object - * the object instance that contains the trigger method. - * @param methodName - * the name of the trigger method. If the object does not contain - * the method or it contains more than one matching methods - * java.lang.IllegalArgumentException is thrown. - * @param arguments - * the arguments to be passed to the trigger method. - * @throws java.lang.IllegalArgumentException - * unless exactly one match methodName is found - * in object. - */ - public ListenerMethod(Class eventType, Object object, String methodName, - Object[] arguments) throws java.lang.IllegalArgumentException { - - // Find the correct method - Method[] methods = object.getClass().getMethods(); - Method method = null; - for (int i = 0; i < methods.length; i++) - if (methods[i].getName().equals(methodName)) - method = methods[i]; - if (method == null) - throw new IllegalArgumentException(); - - this.eventType = eventType; - this.object = object; - this.method = method; - this.arguments = arguments; - this.eventArgumentIndex = -1; - } - - /** - *

- * Constructs a new event listener from a trigger method. Since the argument - * list is unspecified no parameters are passed to the trigger method when - * the listener is triggered. - *

- * - *

- * This constructor gets the trigger method as a parameter so it does not - * need to reflect to find it out. - *

- * - * @param eventType - * the event type that is listener listens to. All events of this - * kind (or its subclasses) result in calling the trigger method. - * @param object - * the object instance that contains the trigger method. - * @param method - * the trigger method. - * @throws java.lang.IllegalArgumentException - * if method is not a member of - * object. - */ - public ListenerMethod(Class eventType, Object object, Method method) - throws java.lang.IllegalArgumentException { - - // Checks that the object is of correct type - if (!method.getDeclaringClass().isAssignableFrom(object.getClass())) - throw new java.lang.IllegalArgumentException(); - - this.eventType = eventType; - this.object = object; - this.method = method; - this.eventArgumentIndex = -1; - - Class[] params = method.getParameterTypes(); - - if (params.length == 0) - this.arguments = new Object[0]; - else if (params.length == 1 && params[0].isAssignableFrom(eventType)) { - this.arguments = new Object[] { null }; - this.eventArgumentIndex = 0; - } else - throw new IllegalArgumentException(); - } - - /** - *

- * Constructs a new event listener from a trigger method name. Since the - * argument list is unspecified no parameters are passed to the trigger - * method when the listener is triggered. - *

- * - *

- * The actual trigger method is reflected from object, and - * java.lang.IllegalArgumentException is thrown unless - * exactly one match is found. - *

- * - * @param eventType - * the event type that is listener listens to. All events of this - * kind (or its subclasses) result in calling the trigger method. - * @param object - * the object instance that contains the trigger method. - * @param methodName - * the name of the trigger method. If the object does not contain - * the method or it contains more than one matching methods - * java.lang.IllegalArgumentException is thrown. - * @throws java.lang.IllegalArgumentException - * unless exactly one match methodName is found - * in object. - */ - public ListenerMethod(Class eventType, Object object, String methodName) - throws java.lang.IllegalArgumentException { - - // Finds the correct method - Method[] methods = object.getClass().getMethods(); - Method method = null; - for (int i = 0; i < methods.length; i++) - if (methods[i].getName().equals(methodName)) - method = methods[i]; - if (method == null) - throw new IllegalArgumentException(); - - this.eventType = eventType; - this.object = object; - this.method = method; - this.eventArgumentIndex = -1; - - Class[] params = method.getParameterTypes(); - - if (params.length == 0) - this.arguments = new Object[0]; - else if (params.length == 1 && params[0].isAssignableFrom(eventType)) { - this.arguments = new Object[] { null }; - this.eventArgumentIndex = 0; - } else - throw new IllegalArgumentException(); - } - - /** - * Receives one event from the EventRouter and calls the - * trigger method if it matches with the criteria defined for the listener. - * Only the events of the same or subclass of the specified event class - * result in the trigger method to be called. - * - * @param event - * the fired event. Unless the trigger method's argument list and - * the index to the to be replaced argument is specified, this - * event will not be passed to the trigger method. - */ - public void receiveEvent(EventObject event) { - - // Only send events supported by the method - if (eventType.isAssignableFrom(event.getClass())) { - try { - if (eventArgumentIndex >= 0) { - if (eventArgumentIndex == 0 && arguments.length == 1) - method.invoke(object, new Object[] { event }); - else { - Object[] arg = new Object[arguments.length]; - for (int i = 0; i < arg.length; i++) - arg[i] = arguments[i]; - arg[eventArgumentIndex] = event; - method.invoke(object, arg); - } - } else - method.invoke(object, arguments); - - } catch (java.lang.IllegalAccessException e) { - // This should never happen - throw new java.lang.RuntimeException( - "Internal error - please report: " + e.toString()); - } catch (java.lang.reflect.InvocationTargetException e) { - // This should never happen - throw new MethodException("Invocation if method " + method - + " failed.", e.getTargetException()); - } - } - } - - /** - * Checks if the given object and event match with the ones stored in this - * listener. - * - * @param target - * the object to be matched against the object stored by this - * listener. - * @param eventType - * the type to be tested for equality against the type stored by - * this listener. - * @return true if target is the same object - * as the one stored in this object and eventType - * equals the event type stored in this object. - */ - public boolean matches(Class eventType, Object target) { - return (target == object) && (eventType.equals(this.eventType)); - } - - /** - * Checks if the given object, event and method match with the ones stored - * in this listener. - * - * @param target - * the object to be matched against the object stored by this - * listener. - * @param eventType - * the type to be tested for equality against the type stored by - * this listener. - * @param method - * the method to be tested for equality against the method stored - * by this listener. - * @return true if target is the same object - * as the one stored in this object, eventType equals - * with the event type stored in this object and method - * equals with the method stored in this object - */ - public boolean matches(Class eventType, Object target, Method method) { - return (target == object) - && (eventType.equals(this.eventType) && method - .equals(this.method)); - } - - /** - * Exception that wraps an exception thrown by an invoked method. When - * ListenerMethod invokes the target method, it may throw - * arbitrary exception. The original exception is wrapped into - * MethodException instance and rethrown by the ListenerMethod. - * - * @author IT Mill Ltd. - * @version - * @VERSION@ - * @since 3.0 - */ - public class MethodException extends RuntimeException { - - /** - * Serial generated by eclipse. - */ - private static final long serialVersionUID = 3257005445242894135L; - - private Throwable cause; - - private String message; - - private MethodException(String message, Throwable cause) { - super(message); - this.cause = cause; - } - - /** - * Retrieves the cause of this throwable or null if the - * cause does not exist or not known. - * - * @return the cause of this throwable or null if the - * cause is nonexistent or unknown. - * @see java.lang.Throwable#getCause() - */ - public Throwable getCause() { - return this.cause; - } - - /** - * Returns the error message string of this throwable object. - * - * @return the error message. - * @see java.lang.Throwable#getMessage() - */ - public String getMessage() { - return message; - } - - /** - * @see java.lang.Throwable#toString() - */ - public String toString() { - String msg = super.toString(); - if (cause != null) - msg += "\nCause: " + cause.toString(); - return msg; - } - - } + /** + * Type of the event that should trigger this listener. Also the subclasses + * of this class are accepted to trigger the listener. + */ + private Class eventType; + + /** + * The object containing the trigger method. + */ + private Object object; + + /** + * The trigger method to call when an event passing the given criteria + * fires. + */ + private Method method; + + /** + * Optional argument set to pass to the trigger method. + */ + private Object[] arguments; + + /** + * Optional index to arguments that point out which one + * should be replaced with the triggering event object and thus be passed to + * the trigger method. + */ + private int eventArgumentIndex; + + /** + *

+ * Constructs a new event listener from a trigger method, it's arguments and + * the argument index specifying which one is replaced with the event object + * when the trigger method is called. + *

+ * + *

+ * This constructor gets the trigger method as a parameter so it does not + * need to reflect to find it out. + *

+ * + * @param eventType + * the event type that is listener listens to. All events of + * this kind (or its subclasses) result in calling the + * trigger method. + * @param object + * the object instance that contains the trigger method + * @param method + * the trigger method + * @param arguments + * the arguments to be passed to the trigger method + * @param eventArgumentIndex + * An index to the argument list. This index points out the + * argument that is replaced with the event object before the + * argument set is passed to the trigger method. If the + * eventArgumentIndex is negative, the triggering event + * object will not be passed to the trigger method, though it + * is still called. + * @throws java.lang.IllegalArgumentException + * if method is not a member of + * object. + */ + public ListenerMethod(Class eventType, Object object, Method method, + Object[] arguments, int eventArgumentIndex) + throws java.lang.IllegalArgumentException { + + // Checks that the object is of correct type + if (!method.getDeclaringClass().isAssignableFrom(object.getClass())) { + throw new java.lang.IllegalArgumentException(); + } + + // Checks that the event argument is null + if (eventArgumentIndex >= 0 && arguments[eventArgumentIndex] != null) { + throw new java.lang.IllegalArgumentException(); + } + + // Checks the event type is supported by the method + if (eventArgumentIndex >= 0 + && !method.getParameterTypes()[eventArgumentIndex] + .isAssignableFrom(eventType)) { + throw new java.lang.IllegalArgumentException(); + } + + this.eventType = eventType; + this.object = object; + this.method = method; + this.arguments = arguments; + this.eventArgumentIndex = eventArgumentIndex; + } + + /** + *

+ * Constructs a new event listener from a trigger method name, it's + * arguments and the argument index specifying which one is replaced with + * the event object. The actual trigger method is reflected from + * object, and + * java.lang.IllegalArgumentException is thrown unless + * exactly one match is found. + *

+ * + * @param eventType + * the event type that is listener listens to. All events of + * this kind (or its subclasses) result in calling the + * trigger method. + * @param object + * the object instance that contains the trigger method. + * @param methodName + * the name of the trigger method. If the object does not + * contain the method or it contains more than one matching + * methods java.lang.IllegalArgumentException + * is thrown. + * @param arguments + * the arguments to be passed to the trigger method. + * @param eventArgumentIndex + * An index to the argument list. This index points out the + * argument that is replaced with the event object before the + * argument set is passed to the trigger method. If the + * eventArgumentIndex is negative, the triggering event + * object will not be passed to the trigger method, though it + * is still called. + * @throws java.lang.IllegalArgumentException + * unless exactly one match methodName is + * found in object. + */ + public ListenerMethod(Class eventType, Object object, String methodName, + Object[] arguments, int eventArgumentIndex) + throws java.lang.IllegalArgumentException { + + // Finds the correct method + Method[] methods = object.getClass().getMethods(); + Method method = null; + for (int i = 0; i < methods.length; i++) { + if (methods[i].getName().equals(methodName)) { + method = methods[i]; + } + } + if (method == null) { + throw new IllegalArgumentException(); + } + + // Checks that the event argument is null + if (eventArgumentIndex >= 0 && arguments[eventArgumentIndex] != null) { + throw new java.lang.IllegalArgumentException(); + } + + // Checks the event type is supported by the method + if (eventArgumentIndex >= 0 + && !method.getParameterTypes()[eventArgumentIndex] + .isAssignableFrom(eventType)) { + throw new java.lang.IllegalArgumentException(); + } + + this.eventType = eventType; + this.object = object; + this.method = method; + this.arguments = arguments; + this.eventArgumentIndex = eventArgumentIndex; + } + + /** + *

+ * Constructs a new event listener from the trigger method and it's + * arguments. Since the the index to the replaced parameter is not specified + * the event triggering this listener will not be passed to the trigger + * method. + *

+ * + *

+ * This constructor gets the trigger method as a parameter so it does not + * need to reflect to find it out. + *

+ * + * @param eventType + * the event type that is listener listens to. All events of + * this kind (or its subclasses) result in calling the + * trigger method. + * @param object + * the object instance that contains the trigger method. + * @param method + * the trigger method. + * @param arguments + * the arguments to be passed to the trigger method. + * @throws java.lang.IllegalArgumentException + * if method is not a member of + * object. + */ + public ListenerMethod(Class eventType, Object object, Method method, + Object[] arguments) throws java.lang.IllegalArgumentException { + + // Check that the object is of correct type + if (!method.getDeclaringClass().isAssignableFrom(object.getClass())) { + throw new java.lang.IllegalArgumentException(); + } + + this.eventType = eventType; + this.object = object; + this.method = method; + this.arguments = arguments; + eventArgumentIndex = -1; + } + + /** + *

+ * Constructs a new event listener from a trigger method name and it's + * arguments. Since the the index to the replaced parameter is not specified + * the event triggering this listener will not be passed to the trigger + * method. + *

+ * + *

+ * The actual trigger method is reflected from object, and + * java.lang.IllegalArgumentException is thrown unless + * exactly one match is found. + *

+ * + * @param eventType + * the event type that is listener listens to. All events of + * this kind (or its subclasses) result in calling the + * trigger method. + * @param object + * the object instance that contains the trigger method. + * @param methodName + * the name of the trigger method. If the object does not + * contain the method or it contains more than one matching + * methods java.lang.IllegalArgumentException + * is thrown. + * @param arguments + * the arguments to be passed to the trigger method. + * @throws java.lang.IllegalArgumentException + * unless exactly one match methodName is + * found in object. + */ + public ListenerMethod(Class eventType, Object object, String methodName, + Object[] arguments) throws java.lang.IllegalArgumentException { + + // Find the correct method + Method[] methods = object.getClass().getMethods(); + Method method = null; + for (int i = 0; i < methods.length; i++) { + if (methods[i].getName().equals(methodName)) { + method = methods[i]; + } + } + if (method == null) { + throw new IllegalArgumentException(); + } + + this.eventType = eventType; + this.object = object; + this.method = method; + this.arguments = arguments; + eventArgumentIndex = -1; + } + + /** + *

+ * Constructs a new event listener from a trigger method. Since the argument + * list is unspecified no parameters are passed to the trigger method when + * the listener is triggered. + *

+ * + *

+ * This constructor gets the trigger method as a parameter so it does not + * need to reflect to find it out. + *

+ * + * @param eventType + * the event type that is listener listens to. All events of + * this kind (or its subclasses) result in calling the + * trigger method. + * @param object + * the object instance that contains the trigger method. + * @param method + * the trigger method. + * @throws java.lang.IllegalArgumentException + * if method is not a member of + * object. + */ + public ListenerMethod(Class eventType, Object object, Method method) + throws java.lang.IllegalArgumentException { + + // Checks that the object is of correct type + if (!method.getDeclaringClass().isAssignableFrom(object.getClass())) { + throw new java.lang.IllegalArgumentException(); + } + + this.eventType = eventType; + this.object = object; + this.method = method; + eventArgumentIndex = -1; + + Class[] params = method.getParameterTypes(); + + if (params.length == 0) { + arguments = new Object[0]; + } else if (params.length == 1 && params[0].isAssignableFrom(eventType)) { + arguments = new Object[] { null }; + eventArgumentIndex = 0; + } else { + throw new IllegalArgumentException(); + } + } + + /** + *

+ * Constructs a new event listener from a trigger method name. Since the + * argument list is unspecified no parameters are passed to the trigger + * method when the listener is triggered. + *

+ * + *

+ * The actual trigger method is reflected from object, and + * java.lang.IllegalArgumentException is thrown unless + * exactly one match is found. + *

+ * + * @param eventType + * the event type that is listener listens to. All events of + * this kind (or its subclasses) result in calling the + * trigger method. + * @param object + * the object instance that contains the trigger method. + * @param methodName + * the name of the trigger method. If the object does not + * contain the method or it contains more than one matching + * methods java.lang.IllegalArgumentException + * is thrown. + * @throws java.lang.IllegalArgumentException + * unless exactly one match methodName is + * found in object. + */ + public ListenerMethod(Class eventType, Object object, String methodName) + throws java.lang.IllegalArgumentException { + + // Finds the correct method + Method[] methods = object.getClass().getMethods(); + Method method = null; + for (int i = 0; i < methods.length; i++) { + if (methods[i].getName().equals(methodName)) { + method = methods[i]; + } + } + if (method == null) { + throw new IllegalArgumentException(); + } + + this.eventType = eventType; + this.object = object; + this.method = method; + eventArgumentIndex = -1; + + Class[] params = method.getParameterTypes(); + + if (params.length == 0) { + arguments = new Object[0]; + } else if (params.length == 1 && params[0].isAssignableFrom(eventType)) { + arguments = new Object[] { null }; + eventArgumentIndex = 0; + } else { + throw new IllegalArgumentException(); + } + } + + /** + * Receives one event from the EventRouter and calls the + * trigger method if it matches with the criteria defined for the listener. + * Only the events of the same or subclass of the specified event class + * result in the trigger method to be called. + * + * @param event + * the fired event. Unless the trigger method's argument list + * and the index to the to be replaced argument is specified, + * this event will not be passed to the trigger method. + */ + public void receiveEvent(EventObject event) { + + // Only send events supported by the method + if (eventType.isAssignableFrom(event.getClass())) { + try { + if (eventArgumentIndex >= 0) { + if (eventArgumentIndex == 0 && arguments.length == 1) { + method.invoke(object, new Object[] { event }); + } else { + Object[] arg = new Object[arguments.length]; + for (int i = 0; i < arg.length; i++) { + arg[i] = arguments[i]; + } + arg[eventArgumentIndex] = event; + method.invoke(object, arg); + } + } else { + method.invoke(object, arguments); + } + + } catch (java.lang.IllegalAccessException e) { + // This should never happen + throw new java.lang.RuntimeException( + "Internal error - please report: " + e.toString()); + } catch (java.lang.reflect.InvocationTargetException e) { + // This should never happen + throw new MethodException("Invocation if method " + method + + " failed.", e.getTargetException()); + } + } + } + + /** + * Checks if the given object and event match with the ones stored in this + * listener. + * + * @param target + * the object to be matched against the object stored by this + * listener. + * @param eventType + * the type to be tested for equality against the type stored + * by this listener. + * @return true if target is the same object + * as the one stored in this object and eventType + * equals the event type stored in this object. + */ + public boolean matches(Class eventType, Object target) { + return (target == object) && (eventType.equals(this.eventType)); + } + + /** + * Checks if the given object, event and method match with the ones stored + * in this listener. + * + * @param target + * the object to be matched against the object stored by this + * listener. + * @param eventType + * the type to be tested for equality against the type stored + * by this listener. + * @param method + * the method to be tested for equality against the method + * stored by this listener. + * @return true if target is the same object + * as the one stored in this object, eventType equals + * with the event type stored in this object and method + * equals with the method stored in this object + */ + public boolean matches(Class eventType, Object target, Method method) { + return (target == object) + && (eventType.equals(this.eventType) && method + .equals(this.method)); + } + + /** + * Exception that wraps an exception thrown by an invoked method. When + * ListenerMethod invokes the target method, it may throw + * arbitrary exception. The original exception is wrapped into + * MethodException instance and rethrown by the ListenerMethod. + * + * @author IT Mill Ltd. + * @version + * @VERSION@ + * @since 3.0 + */ + public class MethodException extends RuntimeException { + + /** + * Serial generated by eclipse. + */ + private static final long serialVersionUID = 3257005445242894135L; + + private Throwable cause; + + private String message; + + private MethodException(String message, Throwable cause) { + super(message); + this.cause = cause; + } + + /** + * Retrieves the cause of this throwable or null if the + * cause does not exist or not known. + * + * @return the cause of this throwable or null if the + * cause is nonexistent or unknown. + * @see java.lang.Throwable#getCause() + */ + public Throwable getCause() { + return cause; + } + + /** + * Returns the error message string of this throwable object. + * + * @return the error message. + * @see java.lang.Throwable#getMessage() + */ + public String getMessage() { + return message; + } + + /** + * @see java.lang.Throwable#toString() + */ + public String toString() { + String msg = super.toString(); + if (cause != null) { + msg += "\nCause: " + cause.toString(); + } + return msg; + } + + } } diff --git a/src/com/itmill/toolkit/event/MethodEventSource.java b/src/com/itmill/toolkit/event/MethodEventSource.java index a11c23df92..8e80ea604e 100644 --- a/src/com/itmill/toolkit/event/MethodEventSource.java +++ b/src/com/itmill/toolkit/event/MethodEventSource.java @@ -47,133 +47,134 @@ import java.lang.reflect.Method; */ public interface MethodEventSource { - /** - *

- * Registers a new event listener with the specified activation method to - * listen events generated by this component. If the activation method does - * not have any arguments the event object will not be passed to it when - * it's called. - *

- * - *

- * For more information on the inheritable event mechanism see the - * {@link com.itmill.toolkit.event com.itmill.toolkit.event package documentation}. - *

- * - * @param eventType - * the type of the listened event. Events of this type or its - * subclasses activate the listener. - * @param object - * the object instance who owns the activation method. - * @param method - * the activation method. - * @throws java.lang.IllegalArgumentException - * unless method has exactly one match in - * object - */ - public void addListener(Class eventType, Object object, Method method); + /** + *

+ * Registers a new event listener with the specified activation method to + * listen events generated by this component. If the activation method does + * not have any arguments the event object will not be passed to it when + * it's called. + *

+ * + *

+ * For more information on the inheritable event mechanism see the + * {@link com.itmill.toolkit.event com.itmill.toolkit.event package documentation}. + *

+ * + * @param eventType + * the type of the listened event. Events of this type or its + * subclasses activate the listener. + * @param object + * the object instance who owns the activation method. + * @param method + * the activation method. + * @throws java.lang.IllegalArgumentException + * unless method has exactly one match in + * object + */ + public void addListener(Class eventType, Object object, Method method); - /** - *

- * Registers a new listener with the specified activation method to listen - * events generated by this component. If the activation method does not - * have any arguments the event object will not be passed to it when it's - * called. - *

- * - *

- * This version of addListener gets the name of the - * activation method as a parameter. The actual method is reflected from - * object, and unless exactly one match is found, - * java.lang.IllegalArgumentException is thrown. - *

- * - *

- * For more information on the inheritable event mechanism see the - * {@link com.itmill.toolkit.event com.itmill.toolkit.event package documentation}. - *

- * - * @param eventType - * the type of the listened event. Events of this type or its - * subclasses activate the listener. - * @param object - * the object instance who owns the activation method. - * @param methodName - * the name of the activation method. - * @throws java.lang.IllegalArgumentException - * unless method has exactly one match in - * object - */ - public void addListener(Class eventType, Object object, String methodName); + /** + *

+ * Registers a new listener with the specified activation method to listen + * events generated by this component. If the activation method does not + * have any arguments the event object will not be passed to it when it's + * called. + *

+ * + *

+ * This version of addListener gets the name of the + * activation method as a parameter. The actual method is reflected from + * object, and unless exactly one match is found, + * java.lang.IllegalArgumentException is thrown. + *

+ * + *

+ * For more information on the inheritable event mechanism see the + * {@link com.itmill.toolkit.event com.itmill.toolkit.event package documentation}. + *

+ * + * @param eventType + * the type of the listened event. Events of this type or its + * subclasses activate the listener. + * @param object + * the object instance who owns the activation method. + * @param methodName + * the name of the activation method. + * @throws java.lang.IllegalArgumentException + * unless method has exactly one match in + * object + */ + public void addListener(Class eventType, Object object, String methodName); - /** - * Removes all registered listeners matching the given parameters. Since - * this method receives the event type and the listener object as - * parameters, it will unregister all object's methods that - * are registered to listen to events of type eventType - * generated by this component. - * - *

- * For more information on the inheritable event mechanism see the - * {@link com.itmill.toolkit.event com.itmill.toolkit.event package documentation}. - *

- * - * @param eventType - * the exact event type the object listens to. - * @param target - * the target object that has registered to listen to events of - * type eventType with one or more methods. - */ - public void removeListener(Class eventType, Object target); + /** + * Removes all registered listeners matching the given parameters. Since + * this method receives the event type and the listener object as + * parameters, it will unregister all object's methods that + * are registered to listen to events of type eventType + * generated by this component. + * + *

+ * For more information on the inheritable event mechanism see the + * {@link com.itmill.toolkit.event com.itmill.toolkit.event package documentation}. + *

+ * + * @param eventType + * the exact event type the object listens to. + * @param target + * the target object that has registered to listen to events + * of type eventType with one or more methods. + */ + public void removeListener(Class eventType, Object target); - /** - * Removes one registered listener method. The given method owned by the - * given object will no longer be called when the specified events are - * generated by this component. - * - *

- * For more information on the inheritable event mechanism see the - * {@link com.itmill.toolkit.event com.itmill.toolkit.event package documentation}. - *

- * - * @param eventType - * the exact event type the object listens to. - * @param target - * the target object that has registered to listen to events of - * type eventType with one or more methods. - * @param method - * the method owned by the target that's registered to listen to - * events of type eventType. - */ - public void removeListener(Class eventType, Object target, Method method); + /** + * Removes one registered listener method. The given method owned by the + * given object will no longer be called when the specified events are + * generated by this component. + * + *

+ * For more information on the inheritable event mechanism see the + * {@link com.itmill.toolkit.event com.itmill.toolkit.event package documentation}. + *

+ * + * @param eventType + * the exact event type the object listens to. + * @param target + * the target object that has registered to listen to events + * of type eventType with one or more methods. + * @param method + * the method owned by the target that's registered to listen + * to events of type eventType. + */ + public void removeListener(Class eventType, Object target, Method method); - /** - *

- * Removes one registered listener method. The given method owned by the - * given object will no longer be called when the specified events are - * generated by this component. - *

- * - *

- * This version of removeListener gets the name of the - * activation method as a parameter. The actual method is reflected from the - * target, and unless exactly one match is found, - * java.lang.IllegalArgumentException is thrown. - *

- * - *

- * For more information on the inheritable event mechanism see the - * {@link com.itmill.toolkit.event com.itmill.toolkit.event package documentation}. - *

- * - * @param eventType - * the exact event type the object listens to. - * @param target - * the target object that has registered to listen to events of - * type eventType with one or more methods. - * @param methodName - * the name of the method owned by target that's - * registered to listen to events of type eventType. - */ - public void removeListener(Class eventType, Object target, String methodName); + /** + *

+ * Removes one registered listener method. The given method owned by the + * given object will no longer be called when the specified events are + * generated by this component. + *

+ * + *

+ * This version of removeListener gets the name of the + * activation method as a parameter. The actual method is reflected from the + * target, and unless exactly one match is found, + * java.lang.IllegalArgumentException is thrown. + *

+ * + *

+ * For more information on the inheritable event mechanism see the + * {@link com.itmill.toolkit.event com.itmill.toolkit.event package documentation}. + *

+ * + * @param eventType + * the exact event type the object listens to. + * @param target + * the target object that has registered to listen to events + * of type eventType with one or more methods. + * @param methodName + * the name of the method owned by target + * that's registered to listen to events of type + * eventType. + */ + public void removeListener(Class eventType, Object target, String methodName); } diff --git a/src/com/itmill/toolkit/event/ShortcutAction.java b/src/com/itmill/toolkit/event/ShortcutAction.java index 8071b25097..da03d86764 100644 --- a/src/com/itmill/toolkit/event/ShortcutAction.java +++ b/src/com/itmill/toolkit/event/ShortcutAction.java @@ -11,169 +11,169 @@ import com.itmill.toolkit.terminal.Resource; */ public class ShortcutAction extends Action { - private int keyCode; + private int keyCode; - private int[] modifiers; + private int[] modifiers; - public ShortcutAction(String caption, int kc, int[] m) { - super(caption); - keyCode = kc; - modifiers = m; - } + public ShortcutAction(String caption, int kc, int[] m) { + super(caption); + keyCode = kc; + modifiers = m; + } - public ShortcutAction(String caption, Resource icon, int kc, int[] m) { - super(caption, icon); - keyCode = kc; - modifiers = m; - } + public ShortcutAction(String caption, Resource icon, int kc, int[] m) { + super(caption, icon); + keyCode = kc; + modifiers = m; + } - public int getKeyCode() { - return keyCode; - } + public int getKeyCode() { + return keyCode; + } - public int[] getModifiers() { - return modifiers; - } + public int[] getModifiers() { + return modifiers; + } - /** - * Key codes that can be used for shortcuts - * - */ - public interface KeyCode { - public static final int ENTER = 13; + /** + * Key codes that can be used for shortcuts + * + */ + public interface KeyCode { + public static final int ENTER = 13; - public static final int ESCAPE = 27; + public static final int ESCAPE = 27; - public static final int PAGE_UP = 33; + public static final int PAGE_UP = 33; - public static final int PAGE_DOWN = 34; + public static final int PAGE_DOWN = 34; - public static final int TAB = 9; + public static final int TAB = 9; - public static final int ARROW_LEFT = 37; + public static final int ARROW_LEFT = 37; - public static final int ARROW_UP = 38; + public static final int ARROW_UP = 38; - public static final int ARROW_RIGHT = 39; + public static final int ARROW_RIGHT = 39; - public static final int ARROW_DOWN = 40; + public static final int ARROW_DOWN = 40; - public static final int BACKSPACE = 8; + public static final int BACKSPACE = 8; - public static final int DELETE = 46; + public static final int DELETE = 46; - public static final int INSERT = 45; + public static final int INSERT = 45; - public static final int END = 35; + public static final int END = 35; - public static final int HOME = 36; + public static final int HOME = 36; - public static final int F1 = 112; + public static final int F1 = 112; - public static final int F2 = 113; + public static final int F2 = 113; - public static final int F3 = 114; + public static final int F3 = 114; - public static final int F4 = 115; + public static final int F4 = 115; - public static final int F5 = 116; + public static final int F5 = 116; - public static final int F6 = 117; + public static final int F6 = 117; - public static final int F7 = 118; + public static final int F7 = 118; - public static final int F8 = 119; + public static final int F8 = 119; - public static final int F9 = 120; + public static final int F9 = 120; - public static final int F10 = 121; + public static final int F10 = 121; - public static final int F11 = 122; + public static final int F11 = 122; - public static final int F12 = 123; + public static final int F12 = 123; - public static final int A = 65; + public static final int A = 65; - public static final int B = 66; + public static final int B = 66; - public static final int C = 67; + public static final int C = 67; - public static final int D = 68; + public static final int D = 68; - public static final int E = 69; + public static final int E = 69; - public static final int F = 70; + public static final int F = 70; - public static final int G = 71; + public static final int G = 71; - public static final int H = 72; + public static final int H = 72; - public static final int I = 73; + public static final int I = 73; - public static final int J = 74; + public static final int J = 74; - public static final int K = 75; + public static final int K = 75; - public static final int L = 76; + public static final int L = 76; - public static final int M = 77; + public static final int M = 77; - public static final int N = 78; + public static final int N = 78; - public static final int O = 79; + public static final int O = 79; - public static final int P = 80; + public static final int P = 80; - public static final int Q = 81; + public static final int Q = 81; - public static final int R = 82; + public static final int R = 82; - public static final int S = 83; + public static final int S = 83; - public static final int T = 84; + public static final int T = 84; - public static final int U = 85; + public static final int U = 85; - public static final int V = 86; + public static final int V = 86; - public static final int W = 87; + public static final int W = 87; - public static final int X = 88; + public static final int X = 88; - public static final int Y = 89; + public static final int Y = 89; - public static final int Z = 90; + public static final int Z = 90; - public static final int NUM0 = 48; + public static final int NUM0 = 48; - public static final int NUM1 = 49; + public static final int NUM1 = 49; - public static final int NUM2 = 50; + public static final int NUM2 = 50; - public static final int NUM3 = 51; + public static final int NUM3 = 51; - public static final int NUM4 = 52; + public static final int NUM4 = 52; - public static final int NUM5 = 53; + public static final int NUM5 = 53; - public static final int NUM6 = 54; + public static final int NUM6 = 54; - public static final int NUM7 = 55; + public static final int NUM7 = 55; - public static final int NUM8 = 56; + public static final int NUM8 = 56; - public static final int NUM9 = 57; - } + public static final int NUM9 = 57; + } - /** - * Modifier key constants - * - */ - public interface ModifierKey { - public static final int SHIFT = 16; + /** + * Modifier key constants + * + */ + public interface ModifierKey { + public static final int SHIFT = 16; - public static final int CTRL = 17; + public static final int CTRL = 17; - public static final int ALT = 18; - } + public static final int ALT = 18; + } } diff --git a/src/com/itmill/toolkit/launcher/ITMillToolkitDesktopMode.java b/src/com/itmill/toolkit/launcher/ITMillToolkitDesktopMode.java index 9636e36acc..ae14121ebe 100644 --- a/src/com/itmill/toolkit/launcher/ITMillToolkitDesktopMode.java +++ b/src/com/itmill/toolkit/launcher/ITMillToolkitDesktopMode.java @@ -19,6 +19,7 @@ import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JPanel; +import javax.swing.WindowConstants; import com.itmill.toolkit.launcher.util.BrowserLauncher; @@ -28,165 +29,165 @@ import com.itmill.toolkit.launcher.util.BrowserLauncher; */ public class ITMillToolkitDesktopMode { - public static void main(String[] args) { - - Map serverArgs = ITMillToolkitWebMode.parseArguments(args); - boolean deployed = false; - try { - // Default deployment: embedded.war - deployed = deployEmbeddedWarfile(serverArgs); - } catch (IOException e1) { - e1.printStackTrace(); - deployed = false; - } - - // Check if deployment was succesful - if (!deployed && !serverArgs.containsKey("webroot")) { - // Default deployment failed, try other means - if (new File("WebContent").exists()) { - // Using WebContent directory as webroot - serverArgs.put("webroot", "WebContent"); - } else { - System.err.print("Failed to deploy Toolkit application. " - + "Please add --webroot parameter. Exiting."); - return; - } - } - - // Start the Winstone servlet container - String url = ITMillToolkitWebMode.runServer(serverArgs); - - // Open browser into application URL - if (url != null) { - BrowserLauncher.openBrowser(url); - } - - // Open control dialog - if (url != null) { - openServerControlDialog(url); - } - - } - - /** - * Open a control dialog for embedded server. - * - * @param applicationUrl - * Application URL - */ - private static void openServerControlDialog(final String applicationUrl) { - - // Main frame - final String title = "Desktop Server"; - final JFrame frame = new JFrame(title); - frame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE); - - // Create link label and listen mouse click - final JLabel link = new JLabel("" - + "
Desktop Server is running at:
" + "" + applicationUrl - + "
Close this window to shutdown the server.
" - + ""); - link.addMouseListener(new MouseAdapter() { - public void mouseClicked(MouseEvent e) { - BrowserLauncher.openBrowser(applicationUrl); - } - }); - - // Create a panel and add components to it. - final JPanel contentPane = new JPanel(new FlowLayout()); - frame.setContentPane(contentPane); - contentPane.add(link); - - // Close confirmation - final JLabel question = new JLabel( - "This will stop the server. Are you sure?"); - final JButton okButton = new JButton("OK"); - final JButton cancelButton = new JButton("Cancel"); - - // List for close verify buttons - ActionListener buttonListener = new ActionListener() { - public void actionPerformed(ActionEvent e) { - if (e.getSource() == okButton) { - System.exit(0); - } else { - Rectangle bounds = frame.getBounds(); - frame.setTitle(title); - contentPane.removeAll(); - contentPane.add(link); - contentPane.setBounds(bounds); - frame.setBounds(bounds); - frame.setVisible(true); - frame.repaint(); - } - } - }; - okButton.addActionListener(buttonListener); - cancelButton.addActionListener(buttonListener); - - frame.addWindowListener(new WindowAdapter() { - public void windowClosing(WindowEvent e) { - Rectangle bounds = frame.getBounds(); - frame.setTitle("Confirm close"); - contentPane.removeAll(); - contentPane.add(question); - contentPane.add(okButton); - contentPane.add(cancelButton); - frame.setBounds(bounds); - frame.setVisible(true); - frame.repaint(); - } - }); - - // Position the window nicely - java.awt.Dimension screenSize = java.awt.Toolkit.getDefaultToolkit() - .getScreenSize(); - int w = 270; - int h = 95; - int margin = 20; - frame.setBounds(new Rectangle(screenSize.width - w - margin, - screenSize.height - h - margin * 2, w, h)); - frame.toFront(); - frame.setVisible(true); - } - - /** - * Deploy file named "embedded.war" from classpath (inside jar file). - * - * @param args - * @return - * @throws IOException - */ - protected static boolean deployEmbeddedWarfile(Map args) throws IOException { - String embeddedWarfileName = "/embedded.war"; - InputStream embeddedWarfile = ITMillToolkitDesktopMode.class - .getResourceAsStream(embeddedWarfileName); - if (embeddedWarfile != null) { - File tempWarfile = File.createTempFile("embedded", ".war") - .getAbsoluteFile(); - tempWarfile.getParentFile().mkdirs(); - tempWarfile.deleteOnExit(); - - String embeddedWebroot = "winstoneEmbeddedWAR"; - File tempWebroot = new File(tempWarfile.getParentFile(), - embeddedWebroot); - tempWebroot.mkdirs(); - - OutputStream out = new FileOutputStream(tempWarfile, true); - int read = 0; - byte buffer[] = new byte[2048]; - while ((read = embeddedWarfile.read(buffer)) != -1) { - out.write(buffer, 0, read); - } - out.close(); - embeddedWarfile.close(); - - args.put("warfile", tempWarfile.getAbsolutePath()); - args.put("webroot", tempWebroot.getAbsolutePath()); - args.remove("webappsDir"); - args.remove("hostsDir"); - return true; - } - return false; - } + public static void main(String[] args) { + + Map serverArgs = ITMillToolkitWebMode.parseArguments(args); + boolean deployed = false; + try { + // Default deployment: embedded.war + deployed = deployEmbeddedWarfile(serverArgs); + } catch (IOException e1) { + e1.printStackTrace(); + deployed = false; + } + + // Check if deployment was succesful + if (!deployed && !serverArgs.containsKey("webroot")) { + // Default deployment failed, try other means + if (new File("WebContent").exists()) { + // Using WebContent directory as webroot + serverArgs.put("webroot", "WebContent"); + } else { + System.err.print("Failed to deploy Toolkit application. " + + "Please add --webroot parameter. Exiting."); + return; + } + } + + // Start the Winstone servlet container + String url = ITMillToolkitWebMode.runServer(serverArgs); + + // Open browser into application URL + if (url != null) { + BrowserLauncher.openBrowser(url); + } + + // Open control dialog + if (url != null) { + openServerControlDialog(url); + } + + } + + /** + * Open a control dialog for embedded server. + * + * @param applicationUrl + * Application URL + */ + private static void openServerControlDialog(final String applicationUrl) { + + // Main frame + final String title = "Desktop Server"; + final JFrame frame = new JFrame(title); + frame.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE); + + // Create link label and listen mouse click + final JLabel link = new JLabel("" + + "
Desktop Server is running at:
" + "" + applicationUrl + + "
Close this window to shutdown the server.
" + + ""); + link.addMouseListener(new MouseAdapter() { + public void mouseClicked(MouseEvent e) { + BrowserLauncher.openBrowser(applicationUrl); + } + }); + + // Create a panel and add components to it. + final JPanel contentPane = new JPanel(new FlowLayout()); + frame.setContentPane(contentPane); + contentPane.add(link); + + // Close confirmation + final JLabel question = new JLabel( + "This will stop the server. Are you sure?"); + final JButton okButton = new JButton("OK"); + final JButton cancelButton = new JButton("Cancel"); + + // List for close verify buttons + ActionListener buttonListener = new ActionListener() { + public void actionPerformed(ActionEvent e) { + if (e.getSource() == okButton) { + System.exit(0); + } else { + Rectangle bounds = frame.getBounds(); + frame.setTitle(title); + contentPane.removeAll(); + contentPane.add(link); + contentPane.setBounds(bounds); + frame.setBounds(bounds); + frame.setVisible(true); + frame.repaint(); + } + } + }; + okButton.addActionListener(buttonListener); + cancelButton.addActionListener(buttonListener); + + frame.addWindowListener(new WindowAdapter() { + public void windowClosing(WindowEvent e) { + Rectangle bounds = frame.getBounds(); + frame.setTitle("Confirm close"); + contentPane.removeAll(); + contentPane.add(question); + contentPane.add(okButton); + contentPane.add(cancelButton); + frame.setBounds(bounds); + frame.setVisible(true); + frame.repaint(); + } + }); + + // Position the window nicely + java.awt.Dimension screenSize = java.awt.Toolkit.getDefaultToolkit() + .getScreenSize(); + int w = 270; + int h = 95; + int margin = 20; + frame.setBounds(new Rectangle(screenSize.width - w - margin, + screenSize.height - h - margin * 2, w, h)); + frame.toFront(); + frame.setVisible(true); + } + + /** + * Deploy file named "embedded.war" from classpath (inside jar file). + * + * @param args + * @return + * @throws IOException + */ + protected static boolean deployEmbeddedWarfile(Map args) throws IOException { + String embeddedWarfileName = "/embedded.war"; + InputStream embeddedWarfile = ITMillToolkitDesktopMode.class + .getResourceAsStream(embeddedWarfileName); + if (embeddedWarfile != null) { + File tempWarfile = File.createTempFile("embedded", ".war") + .getAbsoluteFile(); + tempWarfile.getParentFile().mkdirs(); + tempWarfile.deleteOnExit(); + + String embeddedWebroot = "winstoneEmbeddedWAR"; + File tempWebroot = new File(tempWarfile.getParentFile(), + embeddedWebroot); + tempWebroot.mkdirs(); + + OutputStream out = new FileOutputStream(tempWarfile, true); + int read = 0; + byte buffer[] = new byte[2048]; + while ((read = embeddedWarfile.read(buffer)) != -1) { + out.write(buffer, 0, read); + } + out.close(); + embeddedWarfile.close(); + + args.put("warfile", tempWarfile.getAbsolutePath()); + args.put("webroot", tempWebroot.getAbsolutePath()); + args.remove("webappsDir"); + args.remove("hostsDir"); + return true; + } + return false; + } } diff --git a/src/com/itmill/toolkit/launcher/ITMillToolkitHostedMode.java b/src/com/itmill/toolkit/launcher/ITMillToolkitHostedMode.java index fe9360d2f5..3972616afa 100644 --- a/src/com/itmill/toolkit/launcher/ITMillToolkitHostedMode.java +++ b/src/com/itmill/toolkit/launcher/ITMillToolkitHostedMode.java @@ -16,128 +16,128 @@ import com.google.gwt.dev.GWTShell; */ public class ITMillToolkitHostedMode { - private final static String serverPort = "8888"; - - /** - * Main function for running Jetty. - * - * Command line Arguments are passed through to Jetty, see runServer method - * for options. - * - * @param args - */ - public static void main(String[] args) { - - // Start Jetty - System.out.println("Starting Jetty servlet container."); - String url = runServer(new HashMap()); - - // Start GWT - System.out.println("Starting GWT Hosted Mode browser."); - GWTShell.main(args); - - } - - /** - * Run the server with specified arguments. - * - * @param serverArgs - * @return - */ - protected static String runServer(Map serverArgs) { - - // Add help for System.out - System.out - .println("-------------------------------------------------\n" - + "Starting IT Mill Toolkit in GWT Hosted Mode.\n" - + "Running in http://localhost:" - + serverPort - + "\n-------------------------------------------------\n"); - - // Assign default values for some arguments - assignDefault(serverArgs, "webroot", "WebContent"); - assignDefault(serverArgs, "httpPort", serverPort); - - try { - long started = System.currentTimeMillis(); - - Server server = new Server(); - - // String threadPoolName = - // System.getProperty("jetty.threadpool.name", - // "Jetty thread"); - // int maxIdleTimeMs = Integer.getInteger( - // "jetty.threadpool.maxIdleTimeMs", 60000); - // int maxThreads = - // Integer.getInteger("jetty.threadpool.maxThreads", - // 100); - // int minThreads = - // Integer.getInteger("jetty.threadpool.minThreads", - // 1); - // int lowThreads = Integer.getInteger( - // "jetty.threadpool.maxIdleTimeMs", 25); - // BoundedThreadPool threadPool = new BoundedThreadPool(); - // threadPool.setName(threadPoolName); - // threadPool.setMaxIdleTimeMs(maxIdleTimeMs); - // threadPool.setMaxThreads(maxThreads); - // threadPool.setMinThreads(minThreads); - // threadPool.setLowThreads(lowThreads); - // server.setThreadPool(threadPool); - - Connector connector = new SelectChannelConnector(); - // FIXME httpPort hardcoded to 8888 - // connector.setPort(Integer.valueOf(serverArgs.get("httpPort") - // .toString())); - connector.setPort(8888); - server.setConnectors(new Connector[] { connector }); - - WebAppContext webappcontext = new WebAppContext(); - webappcontext.setContextPath(""); - webappcontext.setWar(serverArgs.get("webroot").toString()); - - server.setHandler(webappcontext); - - server.start(); - } catch (Exception e) { - e.printStackTrace(); - return null; - } - - return "http://localhost:" + serverArgs.get("httpPort"); - } - - /** - * Assign default value for given key. - * - * @param map - * @param key - * @param value - */ - private static void assignDefault(Map map, String key, String value) { - if (!map.containsKey(key)) { - map.put(key, value); - } - } - - /** - * Parse all command line arguments into a map. - * - * Arguments format "key=value" are put into map. - * - * @param args - * @return map of arguments key value pairs. - */ - protected static Map parseArguments(String[] args) { - Map map = new HashMap(); - for (int i = 0; i < args.length; i++) { - int d = args[i].indexOf("="); - if (d > 0 && d < args[i].length() && args[i].startsWith("--")) { - String name = args[i].substring(2, d); - String value = args[i].substring(d + 1); - map.put(name, value); - } - } - return map; - } + private final static String serverPort = "8888"; + + /** + * Main function for running Jetty. + * + * Command line Arguments are passed through to Jetty, see runServer method + * for options. + * + * @param args + */ + public static void main(String[] args) { + + // Start Jetty + System.out.println("Starting Jetty servlet container."); + String url = runServer(new HashMap()); + + // Start GWT + System.out.println("Starting GWT Hosted Mode browser."); + GWTShell.main(args); + + } + + /** + * Run the server with specified arguments. + * + * @param serverArgs + * @return + */ + protected static String runServer(Map serverArgs) { + + // Add help for System.out + System.out + .println("-------------------------------------------------\n" + + "Starting IT Mill Toolkit in GWT Hosted Mode.\n" + + "Running in http://localhost:" + + serverPort + + "\n-------------------------------------------------\n"); + + // Assign default values for some arguments + assignDefault(serverArgs, "webroot", "WebContent"); + assignDefault(serverArgs, "httpPort", serverPort); + + try { + long started = System.currentTimeMillis(); + + Server server = new Server(); + + // String threadPoolName = + // System.getProperty("jetty.threadpool.name", + // "Jetty thread"); + // int maxIdleTimeMs = Integer.getInteger( + // "jetty.threadpool.maxIdleTimeMs", 60000); + // int maxThreads = + // Integer.getInteger("jetty.threadpool.maxThreads", + // 100); + // int minThreads = + // Integer.getInteger("jetty.threadpool.minThreads", + // 1); + // int lowThreads = Integer.getInteger( + // "jetty.threadpool.maxIdleTimeMs", 25); + // BoundedThreadPool threadPool = new BoundedThreadPool(); + // threadPool.setName(threadPoolName); + // threadPool.setMaxIdleTimeMs(maxIdleTimeMs); + // threadPool.setMaxThreads(maxThreads); + // threadPool.setMinThreads(minThreads); + // threadPool.setLowThreads(lowThreads); + // server.setThreadPool(threadPool); + + Connector connector = new SelectChannelConnector(); + // FIXME httpPort hardcoded to 8888 + // connector.setPort(Integer.valueOf(serverArgs.get("httpPort") + // .toString())); + connector.setPort(8888); + server.setConnectors(new Connector[] { connector }); + + WebAppContext webappcontext = new WebAppContext(); + webappcontext.setContextPath(""); + webappcontext.setWar(serverArgs.get("webroot").toString()); + + server.setHandler(webappcontext); + + server.start(); + } catch (Exception e) { + e.printStackTrace(); + return null; + } + + return "http://localhost:" + serverArgs.get("httpPort"); + } + + /** + * Assign default value for given key. + * + * @param map + * @param key + * @param value + */ + private static void assignDefault(Map map, String key, String value) { + if (!map.containsKey(key)) { + map.put(key, value); + } + } + + /** + * Parse all command line arguments into a map. + * + * Arguments format "key=value" are put into map. + * + * @param args + * @return map of arguments key value pairs. + */ + protected static Map parseArguments(String[] args) { + Map map = new HashMap(); + for (int i = 0; i < args.length; i++) { + int d = args[i].indexOf("="); + if (d > 0 && d < args[i].length() && args[i].startsWith("--")) { + String name = args[i].substring(2, d); + String value = args[i].substring(d + 1); + map.put(name, value); + } + } + return map; + } } diff --git a/src/com/itmill/toolkit/launcher/ITMillToolkitWebMode.java b/src/com/itmill/toolkit/launcher/ITMillToolkitWebMode.java index 0054de4c9e..b177a34103 100644 --- a/src/com/itmill/toolkit/launcher/ITMillToolkitWebMode.java +++ b/src/com/itmill/toolkit/launcher/ITMillToolkitWebMode.java @@ -16,137 +16,137 @@ import com.itmill.toolkit.launcher.util.BrowserLauncher; */ public class ITMillToolkitWebMode { - private final static String serverPort = "8888"; - - /** - * Main function for running Jetty. - * - * Command line Arguments are passed through to Jetty, see runServer method - * for options. - * - * @param args - */ - public static void main(String[] args) { - - // Pass-through of arguments for Jetty - Map serverArgs = parseArguments(args); - - // Start Jetty - System.out.println("Starting Jetty servlet container."); - String url = runServer(serverArgs); - - // Start Browser - System.out.println("Starting Web Browser."); - if (url != null) { - BrowserLauncher.openBrowser(url); - } - - } - - /** - * Run the server with specified arguments. - * - * @param serverArgs - * @return - */ - protected static String runServer(Map serverArgs) { - - // Add help for System.out - System.out - .println("-------------------------------------------------\n" - + "Starting IT Mill Toolkit in Web Mode.\n" - + "Running in http://localhost:" - + serverPort - + "\n-------------------------------------------------\n"); - - // Assign default values for some arguments - assignDefault(serverArgs, "webroot", "WebContent"); - assignDefault(serverArgs, "httpPort", serverPort); - - try { - long started = System.currentTimeMillis(); - - Server server = new Server(); - - // String threadPoolName = - // System.getProperty("jetty.threadpool.name", - // "Jetty thread"); - // int maxIdleTimeMs = Integer.getInteger( - // "jetty.threadpool.maxIdleTimeMs", 60000); - // int maxThreads = - // Integer.getInteger("jetty.threadpool.maxThreads", - // 100); - // int minThreads = - // Integer.getInteger("jetty.threadpool.minThreads", - // 1); - // int lowThreads = Integer.getInteger( - // "jetty.threadpool.maxIdleTimeMs", 25); - // BoundedThreadPool threadPool = new BoundedThreadPool(); - // threadPool.setName(threadPoolName); - // threadPool.setMaxIdleTimeMs(maxIdleTimeMs); - // threadPool.setMaxThreads(maxThreads); - // threadPool.setMinThreads(minThreads); - // threadPool.setLowThreads(lowThreads); - // server.setThreadPool(threadPool); - - Connector connector = new SelectChannelConnector(); - // FIXME httpPort hardcoded to 8888 - // connector.setPort(Integer.valueOf(serverArgs.get("httpPort") - // .toString())); - connector.setPort(8888); - server.setConnectors(new Connector[] { connector }); - - WebAppContext webappcontext = new WebAppContext(); - webappcontext.setContextPath(""); - webappcontext.setWar(serverArgs.get("webroot").toString()); - // enable hot code replace - webappcontext.setCopyWebDir(true); - - server.setHandler(webappcontext); - - server.start(); - // System.err.println("Started Jetty in " - // + (System.currentTimeMillis() - started) + "ms."); - } catch (Exception e) { - e.printStackTrace(); - return null; - } - - return "http://localhost:" + serverArgs.get("httpPort"); - } - - /** - * Assign default value for given key. - * - * @param map - * @param key - * @param value - */ - private static void assignDefault(Map map, String key, String value) { - if (!map.containsKey(key)) { - map.put(key, value); - } - } - - /** - * Parse all command line arguments into a map. - * - * Arguments format "key=value" are put into map. - * - * @param args - * @return map of arguments key value pairs. - */ - protected static Map parseArguments(String[] args) { - Map map = new HashMap(); - for (int i = 0; i < args.length; i++) { - int d = args[i].indexOf("="); - if (d > 0 && d < args[i].length() && args[i].startsWith("--")) { - String name = args[i].substring(2, d); - String value = args[i].substring(d + 1); - map.put(name, value); - } - } - return map; - } + private final static String serverPort = "8888"; + + /** + * Main function for running Jetty. + * + * Command line Arguments are passed through to Jetty, see runServer method + * for options. + * + * @param args + */ + public static void main(String[] args) { + + // Pass-through of arguments for Jetty + Map serverArgs = parseArguments(args); + + // Start Jetty + System.out.println("Starting Jetty servlet container."); + String url = runServer(serverArgs); + + // Start Browser + System.out.println("Starting Web Browser."); + if (url != null) { + BrowserLauncher.openBrowser(url); + } + + } + + /** + * Run the server with specified arguments. + * + * @param serverArgs + * @return + */ + protected static String runServer(Map serverArgs) { + + // Add help for System.out + System.out + .println("-------------------------------------------------\n" + + "Starting IT Mill Toolkit in Web Mode.\n" + + "Running in http://localhost:" + + serverPort + + "\n-------------------------------------------------\n"); + + // Assign default values for some arguments + assignDefault(serverArgs, "webroot", "WebContent"); + assignDefault(serverArgs, "httpPort", serverPort); + + try { + long started = System.currentTimeMillis(); + + Server server = new Server(); + + // String threadPoolName = + // System.getProperty("jetty.threadpool.name", + // "Jetty thread"); + // int maxIdleTimeMs = Integer.getInteger( + // "jetty.threadpool.maxIdleTimeMs", 60000); + // int maxThreads = + // Integer.getInteger("jetty.threadpool.maxThreads", + // 100); + // int minThreads = + // Integer.getInteger("jetty.threadpool.minThreads", + // 1); + // int lowThreads = Integer.getInteger( + // "jetty.threadpool.maxIdleTimeMs", 25); + // BoundedThreadPool threadPool = new BoundedThreadPool(); + // threadPool.setName(threadPoolName); + // threadPool.setMaxIdleTimeMs(maxIdleTimeMs); + // threadPool.setMaxThreads(maxThreads); + // threadPool.setMinThreads(minThreads); + // threadPool.setLowThreads(lowThreads); + // server.setThreadPool(threadPool); + + Connector connector = new SelectChannelConnector(); + // FIXME httpPort hardcoded to 8888 + // connector.setPort(Integer.valueOf(serverArgs.get("httpPort") + // .toString())); + connector.setPort(8888); + server.setConnectors(new Connector[] { connector }); + + WebAppContext webappcontext = new WebAppContext(); + webappcontext.setContextPath(""); + webappcontext.setWar(serverArgs.get("webroot").toString()); + // enable hot code replace + webappcontext.setCopyWebDir(true); + + server.setHandler(webappcontext); + + server.start(); + // System.err.println("Started Jetty in " + // + (System.currentTimeMillis() - started) + "ms."); + } catch (Exception e) { + e.printStackTrace(); + return null; + } + + return "http://localhost:" + serverArgs.get("httpPort"); + } + + /** + * Assign default value for given key. + * + * @param map + * @param key + * @param value + */ + private static void assignDefault(Map map, String key, String value) { + if (!map.containsKey(key)) { + map.put(key, value); + } + } + + /** + * Parse all command line arguments into a map. + * + * Arguments format "key=value" are put into map. + * + * @param args + * @return map of arguments key value pairs. + */ + protected static Map parseArguments(String[] args) { + Map map = new HashMap(); + for (int i = 0; i < args.length; i++) { + int d = args[i].indexOf("="); + if (d > 0 && d < args[i].length() && args[i].startsWith("--")) { + String name = args[i].substring(2, d); + String value = args[i].substring(d + 1); + map.put(name, value); + } + } + return map; + } } diff --git a/src/com/itmill/toolkit/launcher/util/BrowserLauncher.java b/src/com/itmill/toolkit/launcher/util/BrowserLauncher.java index 06870ce7e2..86c48556a5 100644 --- a/src/com/itmill/toolkit/launcher/util/BrowserLauncher.java +++ b/src/com/itmill/toolkit/launcher/util/BrowserLauncher.java @@ -9,84 +9,85 @@ import java.io.IOException; */ public class BrowserLauncher { - /** - * Open browser on specified URL. - * - * @param url - */ - public static void openBrowser(String url) { + /** + * Open browser on specified URL. + * + * @param url + */ + public static void openBrowser(String url) { - Runtime runtime = Runtime.getRuntime(); - boolean started = false; + Runtime runtime = Runtime.getRuntime(); + boolean started = false; - String os = System.getProperty("os.name", "windows").toLowerCase(); + String os = System.getProperty("os.name", "windows").toLowerCase(); - // Linux - if (os.indexOf("linux") >= 0) { + // Linux + if (os.indexOf("linux") >= 0) { - // Try x-www-browser - if (!started) { - try { - runtime.exec("x-www-browser " + url); - started = true; - } catch (IOException e) { - } - } + // Try x-www-browser + if (!started) { + try { + runtime.exec("x-www-browser " + url); + started = true; + } catch (IOException e) { + } + } - // Try firefox - if (!started) { - try { - runtime.exec("firefox " + url); - started = true; - } catch (IOException e) { - } - } + // Try firefox + if (!started) { + try { + runtime.exec("firefox " + url); + started = true; + } catch (IOException e) { + } + } - // Try mozilla - if (!started) { - try { - runtime.exec("mozilla " + url); - started = true; - } catch (IOException e) { - } - } + // Try mozilla + if (!started) { + try { + runtime.exec("mozilla " + url); + started = true; + } catch (IOException e) { + } + } - // Try konqueror - if (!started) { - try { - runtime.exec("konqueror " + url); - started = true; - } catch (IOException e) { - } - } - } + // Try konqueror + if (!started) { + try { + runtime.exec("konqueror " + url); + started = true; + } catch (IOException e) { + } + } + } - // OS X - if (os.indexOf("mac os x") >= 0) { + // OS X + if (os.indexOf("mac os x") >= 0) { - // Try open - if (!started) { - try { - runtime.exec("open " + url); - started = true; - } catch (IOException e) { - } - } - } + // Try open + if (!started) { + try { + runtime.exec("open " + url); + started = true; + } catch (IOException e) { + } + } + } - // Try cmd /start command on windows - if (os.indexOf("win") >= 0) { - if (!started) { - try { - runtime.exec("cmd /c start " + url); - started = true; - } catch (IOException e) { - } - } - } + // Try cmd /start command on windows + if (os.indexOf("win") >= 0) { + if (!started) { + try { + runtime.exec("cmd /c start " + url); + started = true; + } catch (IOException e) { + } + } + } - if (!started) - System.out.println("Failed to open browser. Please go to " + url); - } + if (!started) { + System.out.println("Failed to open browser. Please go to " + url); + } + } } diff --git a/src/com/itmill/toolkit/service/ApplicationContext.java b/src/com/itmill/toolkit/service/ApplicationContext.java index 36c1d49b83..7c092c484d 100644 --- a/src/com/itmill/toolkit/service/ApplicationContext.java +++ b/src/com/itmill/toolkit/service/ApplicationContext.java @@ -45,76 +45,76 @@ import com.itmill.toolkit.Application; */ public interface ApplicationContext { - /** - * Returns application context base directory. - * - * Typically an application is deployed in a such way that is has - * application directory. For web applications this directory is the root - * directory of the web applications. In some cases application might not - * have application directory (for example web applications running inside - * of war). - * - * @return The application base directory - */ - public File getBaseDirectory(); - - /** - * Gets the applications in this context. - * - * Gets all applications in this context. Each application context contains - * all applications that are open for one user. - * - * @return Collection containing all applications in this context - */ - public Collection getApplications(); - - /** - * Adds transaction listener to this context. - * - * @param listener - * the listener to be added. - * @see TransactionListener - */ - public void addTransactionListener(TransactionListener listener); - - /** - * Removes transaction listener from this context. - * - * @param listener - * the listener to be removed. - * @see TransactionListener - */ - public void removeTransactionListener(TransactionListener listener); - - /** - * Interface for listening the application transaction events. - * Implementations of this interface can be used to listen all transactions - * between the client and the application. - * - */ - public interface TransactionListener { - - /** - * Invoked at the beginning of every transaction. - * - * @param application - * the Application object. - * @param transactionData - * the Data identifying the transaction. - */ - public void transactionStart(Application application, - Object transactionData); - - /** - * Invoked at the end of every transaction. - * - * @param applcation - * the Application object. - * @param transactionData - * the Data identifying the transaction. - */ - public void transactionEnd(Application application, - Object transactionData); - - } + /** + * Returns application context base directory. + * + * Typically an application is deployed in a such way that is has + * application directory. For web applications this directory is the root + * directory of the web applications. In some cases application might not + * have application directory (for example web applications running inside + * of war). + * + * @return The application base directory + */ + public File getBaseDirectory(); + + /** + * Gets the applications in this context. + * + * Gets all applications in this context. Each application context contains + * all applications that are open for one user. + * + * @return Collection containing all applications in this context + */ + public Collection getApplications(); + + /** + * Adds transaction listener to this context. + * + * @param listener + * the listener to be added. + * @see TransactionListener + */ + public void addTransactionListener(TransactionListener listener); + + /** + * Removes transaction listener from this context. + * + * @param listener + * the listener to be removed. + * @see TransactionListener + */ + public void removeTransactionListener(TransactionListener listener); + + /** + * Interface for listening the application transaction events. + * Implementations of this interface can be used to listen all transactions + * between the client and the application. + * + */ + public interface TransactionListener { + + /** + * Invoked at the beginning of every transaction. + * + * @param application + * the Application object. + * @param transactionData + * the Data identifying the transaction. + */ + public void transactionStart(Application application, + Object transactionData); + + /** + * Invoked at the end of every transaction. + * + * @param applcation + * the Application object. + * @param transactionData + * the Data identifying the transaction. + */ + public void transactionEnd(Application application, + Object transactionData); + + } } diff --git a/src/com/itmill/toolkit/service/FileTypeResolver.java b/src/com/itmill/toolkit/service/FileTypeResolver.java index 68030cbc15..7bdadc8b05 100644 --- a/src/com/itmill/toolkit/service/FileTypeResolver.java +++ b/src/com/itmill/toolkit/service/FileTypeResolver.java @@ -51,342 +51,350 @@ import com.itmill.toolkit.terminal.ThemeResource; */ public class FileTypeResolver { - /** - * Default icon given if no icon is specified for a mime-type. - */ - static public Resource DEFAULT_ICON = new ThemeResource( - "icon/files/file.gif"); - - /** - * Default mime-type. - */ - static public String DEFAULT_MIME_TYPE = "application/octet-stream"; - - /** - * Initial file extension to mime-type mapping. - */ - static private String initialExtToMIMEMap = "application/cu-seeme csm cu," - + "application/dsptype tsp," - + "application/futuresplash spl," - + "application/mac-binhex40 hqx," - + "application/msaccess mdb," - + "application/msword doc dot," - + "application/octet-stream bin," - + "application/oda oda," - + "application/pdf pdf," - + "application/pgp-signature pgp," - + "application/postscript ps ai eps," - + "application/rtf rtf," - + "application/vnd.ms-excel xls xlb," - + "application/vnd.ms-powerpoint ppt pps pot," - + "application/vnd.wap.wmlc wmlc," - + "application/vnd.wap.wmlscriptc wmlsc," - + "application/wordperfect5.1 wp5," - + "application/zip zip," - + "application/x-123 wk," - + "application/x-bcpio bcpio," - + "application/x-chess-pgn pgn," - + "application/x-cpio cpio," - + "application/x-debian-package deb," - + "application/x-director dcr dir dxr," - + "application/x-dms dms," - + "application/x-dvi dvi," - + "application/x-xfig fig," - + "application/x-font pfa pfb gsf pcf pcf.Z," - + "application/x-gnumeric gnumeric," - + "application/x-gtar gtar tgz taz," - + "application/x-hdf hdf," - + "application/x-httpd-php phtml pht php," - + "application/x-httpd-php3 php3," - + "application/x-httpd-php3-source phps," - + "application/x-httpd-php3-preprocessed php3p," - + "application/x-httpd-php4 php4," - + "application/x-ica ica," - + "application/x-java-archive jar," - + "application/x-java-serialized-object ser," - + "application/x-java-vm class," - + "application/x-javascript js," - + "application/x-kchart chrt," - + "application/x-killustrator kil," - + "application/x-kpresenter kpr kpt," - + "application/x-kspread ksp," - + "application/x-kword kwd kwt," - + "application/x-latex latex," - + "application/x-lha lha," - + "application/x-lzh lzh," - + "application/x-lzx lzx," - + "application/x-maker frm maker frame fm fb book fbdoc," - + "application/x-mif mif," - + "application/x-msdos-program com exe bat dll," - + "application/x-msi msi," - + "application/x-netcdf nc cdf," - + "application/x-ns-proxy-autoconfig pac," - + "application/x-object o," - + "application/x-ogg ogg," - + "application/x-oz-application oza," - + "application/x-perl pl pm," - + "application/x-pkcs7-crl crl," - + "application/x-redhat-package-manager rpm," - + "application/x-shar shar," - + "application/x-shockwave-flash swf swfl," - + "application/x-star-office sdd sda," - + "application/x-stuffit sit," - + "application/x-sv4cpio sv4cpio," - + "application/x-sv4crc sv4crc," - + "application/x-tar tar," - + "application/x-tex-gf gf," - + "application/x-tex-pk pk PK," - + "application/x-texinfo texinfo texi," - + "application/x-trash ~ % bak old sik," - + "application/x-troff t tr roff," - + "application/x-troff-man man," - + "application/x-troff-me me," - + "application/x-troff-ms ms," - + "application/x-ustar ustar," - + "application/x-wais-source src," - + "application/x-wingz wz," - + "application/x-x509-ca-cert crt," - + "audio/basic au snd," - + "audio/midi mid midi," - + "audio/mpeg mpga mpega mp2 mp3," - + "audio/mpegurl m3u," - + "audio/prs.sid sid," - + "audio/x-aiff aif aiff aifc," - + "audio/x-gsm gsm," - + "audio/x-pn-realaudio ra rm ram," - + "audio/x-scpls pls," - + "audio/x-wav wav," - + "image/bitmap bmp," - + "image/gif gif," - + "image/ief ief," - + "image/jpeg jpeg jpg jpe," - + "image/pcx pcx," - + "image/png png," - + "image/tiff tiff tif," - + "image/vnd.wap.wbmp wbmp," - + "image/x-cmu-raster ras," - + "image/x-coreldraw cdr," - + "image/x-coreldrawpattern pat," - + "image/x-coreldrawtemplate cdt," - + "image/x-corelphotopaint cpt," - + "image/x-jng jng," - + "image/x-portable-anymap pnm," - + "image/x-portable-bitmap pbm," - + "image/x-portable-graymap pgm," - + "image/x-portable-pixmap ppm," - + "image/x-rgb rgb," - + "image/x-xbitmap xbm," - + "image/x-xpixmap xpm," - + "image/x-xwindowdump xwd," - + "text/comma-separated-values csv," - + "text/css css," - + "text/html htm html xhtml," - + "text/mathml mml," - + "text/plain txt text diff," - + "text/richtext rtx," - + "text/tab-separated-values tsv," - + "text/vnd.wap.wml wml," - + "text/vnd.wap.wmlscript wmls," - + "text/xml xml," - + "text/x-c++hdr h++ hpp hxx hh," - + "text/x-c++src c++ cpp cxx cc," - + "text/x-chdr h," - + "text/x-csh csh," - + "text/x-csrc c," - + "text/x-java java," - + "text/x-moc moc," - + "text/x-pascal p pas," - + "text/x-setext etx," - + "text/x-sh sh," - + "text/x-tcl tcl tk," - + "text/x-tex tex ltx sty cls," - + "text/x-vcalendar vcs," - + "text/x-vcard vcf," - + "video/dl dl," - + "video/fli fli," - + "video/gl gl," - + "video/mpeg mpeg mpg mpe," - + "video/quicktime qt mov," - + "video/x-mng mng," - + "video/x-ms-asf asf asx," - + "video/x-msvideo avi," - + "video/x-sgi-movie movie," - + "x-world/x-vrml vrm vrml wrl"; - - /** - * File extension to MIME type mapping. - */ - static private Hashtable extToMIMEMap = new Hashtable(); - - /** - * MIME type to Icon mapping. - */ - static private Hashtable MIMEToIconMap = new Hashtable(); - - static { - - // Initialize extension to MIME map - StringTokenizer lines = new StringTokenizer(initialExtToMIMEMap, ","); - while (lines.hasMoreTokens()) { - String line = lines.nextToken(); - StringTokenizer exts = new StringTokenizer(line); - String type = exts.nextToken(); - while (exts.hasMoreTokens()) { - String ext = exts.nextToken(); - addExtension(ext, type); - } - } - - // Initialize Icons - addIcon("inode/drive", new ThemeResource("icon/files/drive.gif")); - addIcon("inode/directory", new ThemeResource("icon/files/folder.gif")); - } - - /** - * Gets the mime-type of a file. Currently the mime-type is resolved based - * only on the file name extension. - * - * @param fileName - * the name of the file whose mime-type is requested. - * @return mime-type String for the given filename - */ - public static String getMIMEType(String fileName) { - - // Checks for nulls - if (fileName == null) - throw new NullPointerException("Filename can not be null"); - - // Calculates the extension of the file - int dotIndex = fileName.indexOf("."); - while (dotIndex >= 0 && fileName.indexOf(".", dotIndex + 1) >= 0) - dotIndex = fileName.indexOf(".", dotIndex + 1); - dotIndex++; - - if (fileName.length() > dotIndex) { - String ext = fileName.substring(dotIndex); - - // Return type from extension map, if found - String type = (String) extToMIMEMap.get(ext); - if (type != null) - return type; - } - - return DEFAULT_MIME_TYPE; - } - - /** - * Gets the descriptive icon representing file, based on the filename. First - * the mime-type for the given filename is resolved, and then the - * corresponding icon is fetched from the internal icon storage. If it is - * not found the default icon is returned. - * - * @param fileName - * the name of the file whose icon is requested. - * @return the icon corresponding to the given file - */ - public static Resource getIcon(String fileName) { - - String mimeType = getMIMEType(fileName); - Resource icon = (Resource) MIMEToIconMap.get(mimeType); - if (icon != null) - return icon; - - // If nothing is known about the file-type, general file - // icon is used - return DEFAULT_ICON; - } - - /** - * Gets the descriptive icon representing a file. First the mime-type for - * the given file name is resolved, and then the corresponding icon is - * fetched from the internal icon storage. If it is not found the default - * icon is returned. - * - * @param file - * the file whose icon is requested. - * @return the icon corresponding to the given file - */ - public static Resource getIcon(File file) { - - String mimeType = getMIMEType(file); - Resource icon = (Resource) MIMEToIconMap.get(mimeType); - if (icon != null) - return icon; - - // If nothing is known about the file-type, general file - // icon is used - return DEFAULT_ICON; - } - - /** - * Gets the mime-type for a file. Currently the returned file type is - * resolved by the filename extension only. - * - * @param file - * the file whose mime-type is requested. - * @return the files mime-type String - */ - public static String getMIMEType(File file) { - - // Checks for nulls - if (file == null) - throw new NullPointerException("File can not be null"); - - // Drives - if (file.getParentFile() == null) - return "inode/drive"; - - // Directories - if (file.isDirectory()) - return "inode/directory"; - - // Return type from extension - return getMIMEType(file.getName()); - } - - /** - * Adds a mime-type mapping for the given filename extension. If the - * extension is already in the internal mapping it is overwritten. - * - * @param extension - * the filename extension to be associated with - * MIMEType. - * @param MIMEType - * the new mime-type for extension. - */ - public static void addExtension(String extension, String MIMEType) { - extToMIMEMap.put(extension, MIMEType); - } - - /** - * Adds a icon for the given mime-type. If the mime-type also has a - * corresponding icon, it is replaced with the new icon. - * - * @param MIMEType - * the mime-type whose icon is to be changed. - * @param icon - * the new icon to be associated with MIMEType. - */ - public static void addIcon(String MIMEType, Resource icon) { - MIMEToIconMap.put(MIMEType, icon); - } - - /** - * Gets the internal file extension to mime-type mapping. - * - * @return unmodifiable map containing the current file extension to - * mime-type mapping - */ - public static Map getExtensionToMIMETypeMapping() { - return Collections.unmodifiableMap(extToMIMEMap); - } - - /** - * Gets the internal mime-type to icon mapping. - * - * @return unmodifiable map containing the current mime-type to icon mapping - */ - public static Map getMIMETypeToIconMapping() { - return Collections.unmodifiableMap(MIMEToIconMap); - } + /** + * Default icon given if no icon is specified for a mime-type. + */ + static public Resource DEFAULT_ICON = new ThemeResource( + "icon/files/file.gif"); + + /** + * Default mime-type. + */ + static public String DEFAULT_MIME_TYPE = "application/octet-stream"; + + /** + * Initial file extension to mime-type mapping. + */ + static private String initialExtToMIMEMap = "application/cu-seeme csm cu," + + "application/dsptype tsp," + + "application/futuresplash spl," + + "application/mac-binhex40 hqx," + + "application/msaccess mdb," + + "application/msword doc dot," + + "application/octet-stream bin," + + "application/oda oda," + + "application/pdf pdf," + + "application/pgp-signature pgp," + + "application/postscript ps ai eps," + + "application/rtf rtf," + + "application/vnd.ms-excel xls xlb," + + "application/vnd.ms-powerpoint ppt pps pot," + + "application/vnd.wap.wmlc wmlc," + + "application/vnd.wap.wmlscriptc wmlsc," + + "application/wordperfect5.1 wp5," + + "application/zip zip," + + "application/x-123 wk," + + "application/x-bcpio bcpio," + + "application/x-chess-pgn pgn," + + "application/x-cpio cpio," + + "application/x-debian-package deb," + + "application/x-director dcr dir dxr," + + "application/x-dms dms," + + "application/x-dvi dvi," + + "application/x-xfig fig," + + "application/x-font pfa pfb gsf pcf pcf.Z," + + "application/x-gnumeric gnumeric," + + "application/x-gtar gtar tgz taz," + + "application/x-hdf hdf," + + "application/x-httpd-php phtml pht php," + + "application/x-httpd-php3 php3," + + "application/x-httpd-php3-source phps," + + "application/x-httpd-php3-preprocessed php3p," + + "application/x-httpd-php4 php4," + + "application/x-ica ica," + + "application/x-java-archive jar," + + "application/x-java-serialized-object ser," + + "application/x-java-vm class," + + "application/x-javascript js," + + "application/x-kchart chrt," + + "application/x-killustrator kil," + + "application/x-kpresenter kpr kpt," + + "application/x-kspread ksp," + + "application/x-kword kwd kwt," + + "application/x-latex latex," + + "application/x-lha lha," + + "application/x-lzh lzh," + + "application/x-lzx lzx," + + "application/x-maker frm maker frame fm fb book fbdoc," + + "application/x-mif mif," + + "application/x-msdos-program com exe bat dll," + + "application/x-msi msi," + + "application/x-netcdf nc cdf," + + "application/x-ns-proxy-autoconfig pac," + + "application/x-object o," + + "application/x-ogg ogg," + + "application/x-oz-application oza," + + "application/x-perl pl pm," + + "application/x-pkcs7-crl crl," + + "application/x-redhat-package-manager rpm," + + "application/x-shar shar," + + "application/x-shockwave-flash swf swfl," + + "application/x-star-office sdd sda," + + "application/x-stuffit sit," + + "application/x-sv4cpio sv4cpio," + + "application/x-sv4crc sv4crc," + + "application/x-tar tar," + + "application/x-tex-gf gf," + + "application/x-tex-pk pk PK," + + "application/x-texinfo texinfo texi," + + "application/x-trash ~ % bak old sik," + + "application/x-troff t tr roff," + + "application/x-troff-man man," + + "application/x-troff-me me," + + "application/x-troff-ms ms," + + "application/x-ustar ustar," + + "application/x-wais-source src," + + "application/x-wingz wz," + + "application/x-x509-ca-cert crt," + + "audio/basic au snd," + + "audio/midi mid midi," + + "audio/mpeg mpga mpega mp2 mp3," + + "audio/mpegurl m3u," + + "audio/prs.sid sid," + + "audio/x-aiff aif aiff aifc," + + "audio/x-gsm gsm," + + "audio/x-pn-realaudio ra rm ram," + + "audio/x-scpls pls," + + "audio/x-wav wav," + + "image/bitmap bmp," + + "image/gif gif," + + "image/ief ief," + + "image/jpeg jpeg jpg jpe," + + "image/pcx pcx," + + "image/png png," + + "image/tiff tiff tif," + + "image/vnd.wap.wbmp wbmp," + + "image/x-cmu-raster ras," + + "image/x-coreldraw cdr," + + "image/x-coreldrawpattern pat," + + "image/x-coreldrawtemplate cdt," + + "image/x-corelphotopaint cpt," + + "image/x-jng jng," + + "image/x-portable-anymap pnm," + + "image/x-portable-bitmap pbm," + + "image/x-portable-graymap pgm," + + "image/x-portable-pixmap ppm," + + "image/x-rgb rgb," + + "image/x-xbitmap xbm," + + "image/x-xpixmap xpm," + + "image/x-xwindowdump xwd," + + "text/comma-separated-values csv," + + "text/css css," + + "text/html htm html xhtml," + + "text/mathml mml," + + "text/plain txt text diff," + + "text/richtext rtx," + + "text/tab-separated-values tsv," + + "text/vnd.wap.wml wml," + + "text/vnd.wap.wmlscript wmls," + + "text/xml xml," + + "text/x-c++hdr h++ hpp hxx hh," + + "text/x-c++src c++ cpp cxx cc," + + "text/x-chdr h," + + "text/x-csh csh," + + "text/x-csrc c," + + "text/x-java java," + + "text/x-moc moc," + + "text/x-pascal p pas," + + "text/x-setext etx," + + "text/x-sh sh," + + "text/x-tcl tcl tk," + + "text/x-tex tex ltx sty cls," + + "text/x-vcalendar vcs," + + "text/x-vcard vcf," + + "video/dl dl," + + "video/fli fli," + + "video/gl gl," + + "video/mpeg mpeg mpg mpe," + + "video/quicktime qt mov," + + "video/x-mng mng," + + "video/x-ms-asf asf asx," + + "video/x-msvideo avi," + + "video/x-sgi-movie movie," + + "x-world/x-vrml vrm vrml wrl"; + + /** + * File extension to MIME type mapping. + */ + static private Hashtable extToMIMEMap = new Hashtable(); + + /** + * MIME type to Icon mapping. + */ + static private Hashtable MIMEToIconMap = new Hashtable(); + + static { + + // Initialize extension to MIME map + StringTokenizer lines = new StringTokenizer(initialExtToMIMEMap, ","); + while (lines.hasMoreTokens()) { + String line = lines.nextToken(); + StringTokenizer exts = new StringTokenizer(line); + String type = exts.nextToken(); + while (exts.hasMoreTokens()) { + String ext = exts.nextToken(); + addExtension(ext, type); + } + } + + // Initialize Icons + addIcon("inode/drive", new ThemeResource("icon/files/drive.gif")); + addIcon("inode/directory", new ThemeResource("icon/files/folder.gif")); + } + + /** + * Gets the mime-type of a file. Currently the mime-type is resolved based + * only on the file name extension. + * + * @param fileName + * the name of the file whose mime-type is requested. + * @return mime-type String for the given filename + */ + public static String getMIMEType(String fileName) { + + // Checks for nulls + if (fileName == null) { + throw new NullPointerException("Filename can not be null"); + } + + // Calculates the extension of the file + int dotIndex = fileName.indexOf("."); + while (dotIndex >= 0 && fileName.indexOf(".", dotIndex + 1) >= 0) { + dotIndex = fileName.indexOf(".", dotIndex + 1); + } + dotIndex++; + + if (fileName.length() > dotIndex) { + String ext = fileName.substring(dotIndex); + + // Return type from extension map, if found + String type = (String) extToMIMEMap.get(ext); + if (type != null) { + return type; + } + } + + return DEFAULT_MIME_TYPE; + } + + /** + * Gets the descriptive icon representing file, based on the filename. First + * the mime-type for the given filename is resolved, and then the + * corresponding icon is fetched from the internal icon storage. If it is + * not found the default icon is returned. + * + * @param fileName + * the name of the file whose icon is requested. + * @return the icon corresponding to the given file + */ + public static Resource getIcon(String fileName) { + + String mimeType = getMIMEType(fileName); + Resource icon = (Resource) MIMEToIconMap.get(mimeType); + if (icon != null) { + return icon; + } + + // If nothing is known about the file-type, general file + // icon is used + return DEFAULT_ICON; + } + + /** + * Gets the descriptive icon representing a file. First the mime-type for + * the given file name is resolved, and then the corresponding icon is + * fetched from the internal icon storage. If it is not found the default + * icon is returned. + * + * @param file + * the file whose icon is requested. + * @return the icon corresponding to the given file + */ + public static Resource getIcon(File file) { + + String mimeType = getMIMEType(file); + Resource icon = (Resource) MIMEToIconMap.get(mimeType); + if (icon != null) { + return icon; + } + + // If nothing is known about the file-type, general file + // icon is used + return DEFAULT_ICON; + } + + /** + * Gets the mime-type for a file. Currently the returned file type is + * resolved by the filename extension only. + * + * @param file + * the file whose mime-type is requested. + * @return the files mime-type String + */ + public static String getMIMEType(File file) { + + // Checks for nulls + if (file == null) { + throw new NullPointerException("File can not be null"); + } + + // Drives + if (file.getParentFile() == null) { + return "inode/drive"; + } + + // Directories + if (file.isDirectory()) { + return "inode/directory"; + } + + // Return type from extension + return getMIMEType(file.getName()); + } + + /** + * Adds a mime-type mapping for the given filename extension. If the + * extension is already in the internal mapping it is overwritten. + * + * @param extension + * the filename extension to be associated with + * MIMEType. + * @param MIMEType + * the new mime-type for extension. + */ + public static void addExtension(String extension, String MIMEType) { + extToMIMEMap.put(extension, MIMEType); + } + + /** + * Adds a icon for the given mime-type. If the mime-type also has a + * corresponding icon, it is replaced with the new icon. + * + * @param MIMEType + * the mime-type whose icon is to be changed. + * @param icon + * the new icon to be associated with MIMEType. + */ + public static void addIcon(String MIMEType, Resource icon) { + MIMEToIconMap.put(MIMEType, icon); + } + + /** + * Gets the internal file extension to mime-type mapping. + * + * @return unmodifiable map containing the current file extension to + * mime-type mapping + */ + public static Map getExtensionToMIMETypeMapping() { + return Collections.unmodifiableMap(extToMIMEMap); + } + + /** + * Gets the internal mime-type to icon mapping. + * + * @return unmodifiable map containing the current mime-type to icon mapping + */ + public static Map getMIMETypeToIconMapping() { + return Collections.unmodifiableMap(MIMEToIconMap); + } } diff --git a/src/com/itmill/toolkit/terminal/ApplicationResource.java b/src/com/itmill/toolkit/terminal/ApplicationResource.java index 53e1540cb6..17093f8907 100644 --- a/src/com/itmill/toolkit/terminal/ApplicationResource.java +++ b/src/com/itmill/toolkit/terminal/ApplicationResource.java @@ -47,51 +47,51 @@ import com.itmill.toolkit.Application; */ public interface ApplicationResource extends Resource { - /** - * Default cache time. - */ - public static final long DEFAULT_CACHETIME = 1000 * 60 * 60 * 24; + /** + * Default cache time. + */ + public static final long DEFAULT_CACHETIME = 1000 * 60 * 60 * 24; - /** - * Gets resource as stream. - */ - public DownloadStream getStream(); + /** + * Gets resource as stream. + */ + public DownloadStream getStream(); - /** - * Gets the application of the resource. - */ - public Application getApplication(); + /** + * Gets the application of the resource. + */ + public Application getApplication(); - /** - * Gets the virtual filename for this resource. - * - * @return the file name associated to this resource. - */ - public String getFilename(); + /** + * Gets the virtual filename for this resource. + * + * @return the file name associated to this resource. + */ + public String getFilename(); - /** - * Gets the length of cache expiration time. - * - *

- * This gives the adapter the possibility cache streams sent to the client. - * The caching may be made in adapter or at the client if the client - * supports caching. Default is DEFAULT_CACHETIME. - *

- * - * @return Cache time in milliseconds - */ - public long getCacheTime(); + /** + * Gets the length of cache expiration time. + * + *

+ * This gives the adapter the possibility cache streams sent to the client. + * The caching may be made in adapter or at the client if the client + * supports caching. Default is DEFAULT_CACHETIME. + *

+ * + * @return Cache time in milliseconds + */ + public long getCacheTime(); - /** - * Gets the size of the download buffer used for this resource. - * - *

- * If the buffer size is 0, the buffer size is decided by the terminal - * adapter. The default value is 0. - *

- * - * @return int the size of the buffer in bytes. - */ - public int getBufferSize(); + /** + * Gets the size of the download buffer used for this resource. + * + *

+ * If the buffer size is 0, the buffer size is decided by the terminal + * adapter. The default value is 0. + *

+ * + * @return int the size of the buffer in bytes. + */ + public int getBufferSize(); } diff --git a/src/com/itmill/toolkit/terminal/ClassResource.java b/src/com/itmill/toolkit/terminal/ClassResource.java index c53375350e..afb596f5c3 100644 --- a/src/com/itmill/toolkit/terminal/ClassResource.java +++ b/src/com/itmill/toolkit/terminal/ClassResource.java @@ -46,151 +46,156 @@ import com.itmill.toolkit.service.FileTypeResolver; */ public class ClassResource implements ApplicationResource { - /** - * Default buffer size for this stream resource. - */ - private int bufferSize = 0; - - /** - * Default cache time for this stream resource. - */ - private long cacheTime = DEFAULT_CACHETIME; - - /** - * Associated class used for indetifying the source of the resource. - */ - private Class associatedClass; - - /** - * Name of the resource is relative to the associated class. - */ - private String resourceName; - - /** - * Application used for serving the class. - */ - private Application application; - - /** - * Creates a new application resource instance. The resource id is relative - * to the location of the application class. - * - * @param resourceName - * the Unique identifier of the resource within the application. - * @param application - * the application this resource will be added to. - */ - public ClassResource(String resourceName, Application application) { - this.associatedClass = application.getClass(); - this.resourceName = resourceName; - this.application = application; - if (resourceName == null) - throw new NullPointerException(); - application.addResource(this); - } - - /** - * Creates a new application resource instance. - * - * @param associatedClass - * the class of the which the resource is associated. - * @param resourceName - * the Unique identifier of the resource within the application. - * @param application - * the application this resource will be added to. - */ - public ClassResource(Class associatedClass, String resourceName, - Application application) { - this.associatedClass = associatedClass; - this.resourceName = resourceName; - this.application = application; - if (resourceName == null || associatedClass == null) - throw new NullPointerException(); - application.addResource(this); - } - - /** - * Gets the MIME type of this resource. - * - * @see com.itmill.toolkit.terminal.Resource#getMIMEType() - */ - public String getMIMEType() { - return FileTypeResolver.getMIMEType(this.resourceName); - } - - /** - * Gets the application of this resource. - * - * @see com.itmill.toolkit.terminal.ApplicationResource#getApplication() - */ - public Application getApplication() { - return application; - } - - /** - * Gets the virtual filename for this resource. - * - * @return the file name associated to this resource. - * @see com.itmill.toolkit.terminal.ApplicationResource#getFilename() - */ - public String getFilename() { - int index = 0; - int next = 0; - while ((next = resourceName.indexOf('/', index)) > 0 - && next + 1 < resourceName.length()) - index = next + 1; - return resourceName.substring(index); - } - - /** - * Gets resource as stream. - * - * @see com.itmill.toolkit.terminal.ApplicationResource#getStream() - */ - public DownloadStream getStream() { - DownloadStream ds = new DownloadStream(associatedClass - .getResourceAsStream(resourceName), getMIMEType(), - getFilename()); - ds.setBufferSize(getBufferSize()); - ds.setCacheTime(cacheTime); - return ds; - } - - /* documented in superclass */ - public int getBufferSize() { - return bufferSize; - } - - /** - * Sets the size of the download buffer used for this resource. - * - * @param bufferSize - * the size of the buffer in bytes. - */ - public void setBufferSize(int bufferSize) { - this.bufferSize = bufferSize; - } - - /* documented in superclass */ - public long getCacheTime() { - return cacheTime; - } - - /** - * Sets the length of cache expiration time. - * - *

- * This gives the adapter the possibility cache streams sent to the client. - * The caching may be made in adapter or at the client if the client - * supports caching. Zero or negavive value disbales the caching of this - * stream. - *

- * - * @param cacheTime - * the cache time in milliseconds. - * - */ - public void setCacheTime(long cacheTime) { - this.cacheTime = cacheTime; - } + /** + * Default buffer size for this stream resource. + */ + private int bufferSize = 0; + + /** + * Default cache time for this stream resource. + */ + private long cacheTime = DEFAULT_CACHETIME; + + /** + * Associated class used for indetifying the source of the resource. + */ + private Class associatedClass; + + /** + * Name of the resource is relative to the associated class. + */ + private String resourceName; + + /** + * Application used for serving the class. + */ + private Application application; + + /** + * Creates a new application resource instance. The resource id is relative + * to the location of the application class. + * + * @param resourceName + * the Unique identifier of the resource within the + * application. + * @param application + * the application this resource will be added to. + */ + public ClassResource(String resourceName, Application application) { + associatedClass = application.getClass(); + this.resourceName = resourceName; + this.application = application; + if (resourceName == null) { + throw new NullPointerException(); + } + application.addResource(this); + } + + /** + * Creates a new application resource instance. + * + * @param associatedClass + * the class of the which the resource is associated. + * @param resourceName + * the Unique identifier of the resource within the + * application. + * @param application + * the application this resource will be added to. + */ + public ClassResource(Class associatedClass, String resourceName, + Application application) { + this.associatedClass = associatedClass; + this.resourceName = resourceName; + this.application = application; + if (resourceName == null || associatedClass == null) { + throw new NullPointerException(); + } + application.addResource(this); + } + + /** + * Gets the MIME type of this resource. + * + * @see com.itmill.toolkit.terminal.Resource#getMIMEType() + */ + public String getMIMEType() { + return FileTypeResolver.getMIMEType(resourceName); + } + + /** + * Gets the application of this resource. + * + * @see com.itmill.toolkit.terminal.ApplicationResource#getApplication() + */ + public Application getApplication() { + return application; + } + + /** + * Gets the virtual filename for this resource. + * + * @return the file name associated to this resource. + * @see com.itmill.toolkit.terminal.ApplicationResource#getFilename() + */ + public String getFilename() { + int index = 0; + int next = 0; + while ((next = resourceName.indexOf('/', index)) > 0 + && next + 1 < resourceName.length()) { + index = next + 1; + } + return resourceName.substring(index); + } + + /** + * Gets resource as stream. + * + * @see com.itmill.toolkit.terminal.ApplicationResource#getStream() + */ + public DownloadStream getStream() { + DownloadStream ds = new DownloadStream(associatedClass + .getResourceAsStream(resourceName), getMIMEType(), + getFilename()); + ds.setBufferSize(getBufferSize()); + ds.setCacheTime(cacheTime); + return ds; + } + + /* documented in superclass */ + public int getBufferSize() { + return bufferSize; + } + + /** + * Sets the size of the download buffer used for this resource. + * + * @param bufferSize + * the size of the buffer in bytes. + */ + public void setBufferSize(int bufferSize) { + this.bufferSize = bufferSize; + } + + /* documented in superclass */ + public long getCacheTime() { + return cacheTime; + } + + /** + * Sets the length of cache expiration time. + * + *

+ * This gives the adapter the possibility cache streams sent to the client. + * The caching may be made in adapter or at the client if the client + * supports caching. Zero or negavive value disbales the caching of this + * stream. + *

+ * + * @param cacheTime + * the cache time in milliseconds. + * + */ + public void setCacheTime(long cacheTime) { + this.cacheTime = cacheTime; + } } diff --git a/src/com/itmill/toolkit/terminal/CompositeErrorMessage.java b/src/com/itmill/toolkit/terminal/CompositeErrorMessage.java index 469efdbf7b..8916e6291b 100644 --- a/src/com/itmill/toolkit/terminal/CompositeErrorMessage.java +++ b/src/com/itmill/toolkit/terminal/CompositeErrorMessage.java @@ -43,153 +43,159 @@ import java.util.List; */ public class CompositeErrorMessage implements ErrorMessage { - /** - * Array of all the errors. - */ - private List errors; - - /** - * Level of the error. - */ - private int level; - - /** - * Constructor for CompositeErrorMessage. - * - * @param errorMessages - * the Array of error messages that are listed togeter. Nulls are - * ignored, but at least one message is required. - */ - public CompositeErrorMessage(ErrorMessage[] errorMessages) { - errors = new ArrayList(errorMessages.length); - level = Integer.MIN_VALUE; - - for (int i = 0; i < errorMessages.length; i++) { - addErrorMessage(errorMessages[i]); - } - - if (errors.size() == 0) - throw new IllegalArgumentException( - "Composite error message must have at least one error"); - - } - - /** - * Constructor for CompositeErrorMessage. - * - * @param errorMessages - * the Collection of error messages that are listed togeter. At - * least one message is required. - */ - public CompositeErrorMessage(Collection errorMessages) { - errors = new ArrayList(errorMessages.size()); - level = Integer.MIN_VALUE; - - for (Iterator i = errorMessages.iterator(); i.hasNext();) { - addErrorMessage((ErrorMessage) i.next()); - } - - if (errors.size() == 0) - throw new IllegalArgumentException( - "Composite error message must have at least one error"); - } - - /** - * The error level is the largest error level in - * - * @see com.itmill.toolkit.terminal.ErrorMessage#getErrorLevel() - */ - public final int getErrorLevel() { - return level; - } - - /** - * Adds a error message into this composite message. Updates the level - * field. - * - * @param error - * the error message to be added. Duplicate errors are ignored. - */ - private void addErrorMessage(ErrorMessage error) { - if (error != null && !errors.contains(error)) { - this.errors.add(error); - int l = error.getErrorLevel(); - if (l > level) - level = l; - } - } - - /** - * Gets Error Iterator. - * - * @return the error iterator. - */ - public Iterator iterator() { - return errors.iterator(); - } - - /** - * @see com.itmill.toolkit.terminal.Paintable#paint(com.itmill.toolkit.terminal.PaintTarget) - */ - public void paint(PaintTarget target) throws PaintException { - - if (errors.size() == 1) - ((ErrorMessage) errors.iterator().next()).paint(target); - else { - target.startTag("error"); - - if (level > 0 && level <= ErrorMessage.INFORMATION) - target.addAttribute("level", "info"); - else if (level <= ErrorMessage.WARNING) - target.addAttribute("level", "warning"); - else if (level <= ErrorMessage.ERROR) - target.addAttribute("level", "error"); - else if (level <= ErrorMessage.CRITICAL) - target.addAttribute("level", "critical"); - else - target.addAttribute("level", "system"); - - // Paint all the exceptions - for (Iterator i = errors.iterator(); i.hasNext();) { - ((ErrorMessage) i.next()).paint(target); - } - - target.endTag("error"); - } - } - - /* Documented in super interface */ - public void addListener(RepaintRequestListener listener) { - } - - /* Documented in super interface */ - public void removeListener(RepaintRequestListener listener) { - } - - /* Documented in super interface */ - public void requestRepaint() { - } - - /* Documented in super interface */ - public void requestRepaintRequests() { - } - - /** - * Returns a comma separated list of the error messages. - * - * @return String, comma separated list of error messages. - */ - public String toString() { - String retval = "["; - int pos = 0; - for (Iterator i = errors.iterator(); i.hasNext();) { - if (pos > 0) - retval += ","; - pos++; - retval += i.next().toString(); - } - retval += "]"; - - return retval; - } + /** + * Array of all the errors. + */ + private List errors; + + /** + * Level of the error. + */ + private int level; + + /** + * Constructor for CompositeErrorMessage. + * + * @param errorMessages + * the Array of error messages that are listed togeter. Nulls + * are ignored, but at least one message is required. + */ + public CompositeErrorMessage(ErrorMessage[] errorMessages) { + errors = new ArrayList(errorMessages.length); + level = Integer.MIN_VALUE; + + for (int i = 0; i < errorMessages.length; i++) { + addErrorMessage(errorMessages[i]); + } + + if (errors.size() == 0) { + throw new IllegalArgumentException( + "Composite error message must have at least one error"); + } + + } + + /** + * Constructor for CompositeErrorMessage. + * + * @param errorMessages + * the Collection of error messages that are listed togeter. + * At least one message is required. + */ + public CompositeErrorMessage(Collection errorMessages) { + errors = new ArrayList(errorMessages.size()); + level = Integer.MIN_VALUE; + + for (Iterator i = errorMessages.iterator(); i.hasNext();) { + addErrorMessage((ErrorMessage) i.next()); + } + + if (errors.size() == 0) { + throw new IllegalArgumentException( + "Composite error message must have at least one error"); + } + } + + /** + * The error level is the largest error level in + * + * @see com.itmill.toolkit.terminal.ErrorMessage#getErrorLevel() + */ + public final int getErrorLevel() { + return level; + } + + /** + * Adds a error message into this composite message. Updates the level + * field. + * + * @param error + * the error message to be added. Duplicate errors are + * ignored. + */ + private void addErrorMessage(ErrorMessage error) { + if (error != null && !errors.contains(error)) { + errors.add(error); + int l = error.getErrorLevel(); + if (l > level) { + level = l; + } + } + } + + /** + * Gets Error Iterator. + * + * @return the error iterator. + */ + public Iterator iterator() { + return errors.iterator(); + } + + /** + * @see com.itmill.toolkit.terminal.Paintable#paint(com.itmill.toolkit.terminal.PaintTarget) + */ + public void paint(PaintTarget target) throws PaintException { + + if (errors.size() == 1) { + ((ErrorMessage) errors.iterator().next()).paint(target); + } else { + target.startTag("error"); + + if (level > 0 && level <= ErrorMessage.INFORMATION) { + target.addAttribute("level", "info"); + } else if (level <= ErrorMessage.WARNING) { + target.addAttribute("level", "warning"); + } else if (level <= ErrorMessage.ERROR) { + target.addAttribute("level", "error"); + } else if (level <= ErrorMessage.CRITICAL) { + target.addAttribute("level", "critical"); + } else { + target.addAttribute("level", "system"); + } + + // Paint all the exceptions + for (Iterator i = errors.iterator(); i.hasNext();) { + ((ErrorMessage) i.next()).paint(target); + } + + target.endTag("error"); + } + } + + /* Documented in super interface */ + public void addListener(RepaintRequestListener listener) { + } + + /* Documented in super interface */ + public void removeListener(RepaintRequestListener listener) { + } + + /* Documented in super interface */ + public void requestRepaint() { + } + + /* Documented in super interface */ + public void requestRepaintRequests() { + } + + /** + * Returns a comma separated list of the error messages. + * + * @return String, comma separated list of error messages. + */ + public String toString() { + String retval = "["; + int pos = 0; + for (Iterator i = errors.iterator(); i.hasNext();) { + if (pos > 0) { + retval += ","; + } + pos++; + retval += i.next().toString(); + } + retval += "]"; + + return retval; + } } diff --git a/src/com/itmill/toolkit/terminal/DownloadStream.java b/src/com/itmill/toolkit/terminal/DownloadStream.java index 86995036e9..4ec51c848d 100644 --- a/src/com/itmill/toolkit/terminal/DownloadStream.java +++ b/src/com/itmill/toolkit/terminal/DownloadStream.java @@ -43,184 +43,186 @@ import java.util.Map; */ public class DownloadStream { - /** - * Maximum cache time. - */ - public static final long MAX_CACHETIME = Long.MAX_VALUE; - - /** - * Default cache time. - */ - public static final long DEFAULT_CACHETIME = 1000 * 60 * 60 * 24; - - private InputStream stream; - - private String contentType; - - private String fileName; - - private Map params; - - private long cacheTime = DEFAULT_CACHETIME; - - private int bufferSize = 0; - - /** - * Creates a new instance of DownloadStream. - */ - public DownloadStream(InputStream stream, String contentType, - String fileName) { - setStream(stream); - setContentType(contentType); - setFileName(fileName); - } - - /** - * Gets downloadable stream. - * - * @return output stream. - */ - public InputStream getStream() { - return this.stream; - } - - /** - * Sets the stream. - * - * @param stream - * The stream to set - */ - public void setStream(InputStream stream) { - this.stream = stream; - } - - /** - * Gets stream content type. - * - * @return type of the stream content. - */ - public String getContentType() { - return this.contentType; - } - - /** - * Sets stream content type. - * - * @param contentType - * the contentType to set - */ - public void setContentType(String contentType) { - this.contentType = contentType; - } - - /** - * Returns the file name. - * - * @return the name of the file. - */ - public String getFileName() { - return fileName; - } - - /** - * Sets the file name. - * - * @param fileName - * the file name to set. - */ - public void setFileName(String fileName) { - this.fileName = fileName; - } - - /** - * Sets a paramater for download stream. Parameters are optional information - * about the downloadable stream and their meaning depends on the used - * adapter. For example in WebAdapter they are interpreted as HTTP response - * headers. - * - * If the parameters by this name exists, the old value is replaced. - * - * @param name - * the Name of the parameter to set. - * @param value - * the Value of the parameter to set. - */ - public void setParameter(String name, String value) { - if (this.params == null) { - this.params = new HashMap(); - } - this.params.put(name, value); - } - - /** - * Gets a paramater for download stream. Parameters are optional information - * about the downloadable stream and their meaning depends on the used - * adapter. For example in WebAdapter they are interpreted as HTTP response - * headers. - * - * @param name - * the Name of the parameter to set. - * @return Value of the parameter or null if the parameter does not exist. - */ - public String getParameter(String name) { - if (this.params != null) - return (String) this.params.get(name); - return null; - } - - /** - * Gets the names of the parameters. - * - * @return Iterator of names or null if no parameters are set. - */ - public Iterator getParameterNames() { - if (this.params != null) - return this.params.keySet().iterator(); - return null; - } - - /** - * Gets length of cache expiration time. This gives the adapter the - * possibility cache streams sent to the client. The caching may be made in - * adapter or at the client if the client supports caching. Default is - * DEFAULT_CACHETIME. - * - * @return Cache time in milliseconds - */ - public long getCacheTime() { - return cacheTime; - } - - /** - * Sets length of cache expiration time. This gives the adapter the - * possibility cache streams sent to the client. The caching may be made in - * adapter or at the client if the client supports caching. Zero or negavive - * value disbales the caching of this stream. - * - * @param cacheTime - * the cache time in milliseconds. - */ - public void setCacheTime(long cacheTime) { - this.cacheTime = cacheTime; - } - - /** - * Gets the size of the download buffer. - * - * @return int The size of the buffer in bytes. - */ - public int getBufferSize() { - return bufferSize; - } - - /** - * Sets the size of the download buffer. - * - * @param bufferSize - * the size of the buffer in bytes. - */ - public void setBufferSize(int bufferSize) { - this.bufferSize = bufferSize; - } + /** + * Maximum cache time. + */ + public static final long MAX_CACHETIME = Long.MAX_VALUE; + + /** + * Default cache time. + */ + public static final long DEFAULT_CACHETIME = 1000 * 60 * 60 * 24; + + private InputStream stream; + + private String contentType; + + private String fileName; + + private Map params; + + private long cacheTime = DEFAULT_CACHETIME; + + private int bufferSize = 0; + + /** + * Creates a new instance of DownloadStream. + */ + public DownloadStream(InputStream stream, String contentType, + String fileName) { + setStream(stream); + setContentType(contentType); + setFileName(fileName); + } + + /** + * Gets downloadable stream. + * + * @return output stream. + */ + public InputStream getStream() { + return stream; + } + + /** + * Sets the stream. + * + * @param stream + * The stream to set + */ + public void setStream(InputStream stream) { + this.stream = stream; + } + + /** + * Gets stream content type. + * + * @return type of the stream content. + */ + public String getContentType() { + return contentType; + } + + /** + * Sets stream content type. + * + * @param contentType + * the contentType to set + */ + public void setContentType(String contentType) { + this.contentType = contentType; + } + + /** + * Returns the file name. + * + * @return the name of the file. + */ + public String getFileName() { + return fileName; + } + + /** + * Sets the file name. + * + * @param fileName + * the file name to set. + */ + public void setFileName(String fileName) { + this.fileName = fileName; + } + + /** + * Sets a paramater for download stream. Parameters are optional information + * about the downloadable stream and their meaning depends on the used + * adapter. For example in WebAdapter they are interpreted as HTTP response + * headers. + * + * If the parameters by this name exists, the old value is replaced. + * + * @param name + * the Name of the parameter to set. + * @param value + * the Value of the parameter to set. + */ + public void setParameter(String name, String value) { + if (params == null) { + params = new HashMap(); + } + params.put(name, value); + } + + /** + * Gets a paramater for download stream. Parameters are optional information + * about the downloadable stream and their meaning depends on the used + * adapter. For example in WebAdapter they are interpreted as HTTP response + * headers. + * + * @param name + * the Name of the parameter to set. + * @return Value of the parameter or null if the parameter does not exist. + */ + public String getParameter(String name) { + if (params != null) { + return (String) params.get(name); + } + return null; + } + + /** + * Gets the names of the parameters. + * + * @return Iterator of names or null if no parameters are set. + */ + public Iterator getParameterNames() { + if (params != null) { + return params.keySet().iterator(); + } + return null; + } + + /** + * Gets length of cache expiration time. This gives the adapter the + * possibility cache streams sent to the client. The caching may be made in + * adapter or at the client if the client supports caching. Default is + * DEFAULT_CACHETIME. + * + * @return Cache time in milliseconds + */ + public long getCacheTime() { + return cacheTime; + } + + /** + * Sets length of cache expiration time. This gives the adapter the + * possibility cache streams sent to the client. The caching may be made in + * adapter or at the client if the client supports caching. Zero or negavive + * value disbales the caching of this stream. + * + * @param cacheTime + * the cache time in milliseconds. + */ + public void setCacheTime(long cacheTime) { + this.cacheTime = cacheTime; + } + + /** + * Gets the size of the download buffer. + * + * @return int The size of the buffer in bytes. + */ + public int getBufferSize() { + return bufferSize; + } + + /** + * Sets the size of the download buffer. + * + * @param bufferSize + * the size of the buffer in bytes. + */ + public void setBufferSize(int bufferSize) { + this.bufferSize = bufferSize; + } } diff --git a/src/com/itmill/toolkit/terminal/ErrorMessage.java b/src/com/itmill/toolkit/terminal/ErrorMessage.java index d26c1c74a4..4153ca220a 100644 --- a/src/com/itmill/toolkit/terminal/ErrorMessage.java +++ b/src/com/itmill/toolkit/terminal/ErrorMessage.java @@ -39,64 +39,64 @@ package com.itmill.toolkit.terminal; */ public interface ErrorMessage extends Paintable { - /** - * Error code for system errors and bugs. - */ - public static final int SYSTEMERROR = 5000; - - /** - * Error code for critical error messages. - */ - public static final int CRITICAL = 4000; - - /** - * Error code for regular error messages. - */ - public static final int ERROR = 3000; - - /** - * Error code for warning messages. - */ - public static final int WARNING = 2000; - - /** - * Error code for informational messages. - */ - public static final int INFORMATION = 1000; - - /** - * Gets the errors level. - * - * @return the level of error as an integer. - */ - public int getErrorLevel(); - - /** - * Error messages are inmodifiable and thus listeners are not needed. This - * method should be implemented as empty. - * - * @param listener - * the listener to be added. - * @see com.itmill.toolkit.terminal.Paintable#addListener(Paintable.RepaintRequestListener) - */ - public void addListener(RepaintRequestListener listener); - - /** - * Error messages are inmodifiable and thus listeners are not needed. This - * method should be implemented as empty. - * - * @param listener - * the listener to be removed. - * @see com.itmill.toolkit.terminal.Paintable#removeListener(Paintable.RepaintRequestListener) - */ - public void removeListener(RepaintRequestListener listener); - - /** - * Error messages are inmodifiable and thus listeners are not needed. This - * method should be implemented as empty. - * - * @see com.itmill.toolkit.terminal.Paintable#requestRepaint() - */ - public void requestRepaint(); + /** + * Error code for system errors and bugs. + */ + public static final int SYSTEMERROR = 5000; + + /** + * Error code for critical error messages. + */ + public static final int CRITICAL = 4000; + + /** + * Error code for regular error messages. + */ + public static final int ERROR = 3000; + + /** + * Error code for warning messages. + */ + public static final int WARNING = 2000; + + /** + * Error code for informational messages. + */ + public static final int INFORMATION = 1000; + + /** + * Gets the errors level. + * + * @return the level of error as an integer. + */ + public int getErrorLevel(); + + /** + * Error messages are inmodifiable and thus listeners are not needed. This + * method should be implemented as empty. + * + * @param listener + * the listener to be added. + * @see com.itmill.toolkit.terminal.Paintable#addListener(Paintable.RepaintRequestListener) + */ + public void addListener(RepaintRequestListener listener); + + /** + * Error messages are inmodifiable and thus listeners are not needed. This + * method should be implemented as empty. + * + * @param listener + * the listener to be removed. + * @see com.itmill.toolkit.terminal.Paintable#removeListener(Paintable.RepaintRequestListener) + */ + public void removeListener(RepaintRequestListener listener); + + /** + * Error messages are inmodifiable and thus listeners are not needed. This + * method should be implemented as empty. + * + * @see com.itmill.toolkit.terminal.Paintable#requestRepaint() + */ + public void requestRepaint(); } diff --git a/src/com/itmill/toolkit/terminal/ExternalResource.java b/src/com/itmill/toolkit/terminal/ExternalResource.java index 6509d44534..005e97217b 100644 --- a/src/com/itmill/toolkit/terminal/ExternalResource.java +++ b/src/com/itmill/toolkit/terminal/ExternalResource.java @@ -44,53 +44,55 @@ import com.itmill.toolkit.service.FileTypeResolver; */ public class ExternalResource implements Resource { - /** - * Url of the download. - */ - private String sourceURL = null; - - /** - * Creates a new download component for downloading directly from given URL. - * - * @param sourceURL - * the source URL. - */ - public ExternalResource(URL sourceURL) { - if (sourceURL == null) - throw new RuntimeException("Source must be non-null"); - - this.sourceURL = sourceURL.toString(); - } - - /** - * Creates a new download component for downloading directly from given URL. - * - * @param sourceURL - * the source URL. - */ - public ExternalResource(String sourceURL) { - if (sourceURL == null) - throw new RuntimeException("Source must be non-null"); - - this.sourceURL = sourceURL.toString(); - } - - /** - * Gets the URL of the external resource. - * - * @return the URL of the external resource. - */ - public String getURL() { - return sourceURL; - } - - /** - * Gets the MIME type of the resource. - * - * @see com.itmill.toolkit.terminal.Resource#getMIMEType() - */ - public String getMIMEType() { - return FileTypeResolver.getMIMEType(getURL().toString()); - } + /** + * Url of the download. + */ + private String sourceURL = null; + + /** + * Creates a new download component for downloading directly from given URL. + * + * @param sourceURL + * the source URL. + */ + public ExternalResource(URL sourceURL) { + if (sourceURL == null) { + throw new RuntimeException("Source must be non-null"); + } + + this.sourceURL = sourceURL.toString(); + } + + /** + * Creates a new download component for downloading directly from given URL. + * + * @param sourceURL + * the source URL. + */ + public ExternalResource(String sourceURL) { + if (sourceURL == null) { + throw new RuntimeException("Source must be non-null"); + } + + this.sourceURL = sourceURL.toString(); + } + + /** + * Gets the URL of the external resource. + * + * @return the URL of the external resource. + */ + public String getURL() { + return sourceURL; + } + + /** + * Gets the MIME type of the resource. + * + * @see com.itmill.toolkit.terminal.Resource#getMIMEType() + */ + public String getMIMEType() { + return FileTypeResolver.getMIMEType(getURL().toString()); + } } diff --git a/src/com/itmill/toolkit/terminal/FileResource.java b/src/com/itmill/toolkit/terminal/FileResource.java index 2ca1332f08..800e63582b 100644 --- a/src/com/itmill/toolkit/terminal/FileResource.java +++ b/src/com/itmill/toolkit/terminal/FileResource.java @@ -48,131 +48,131 @@ import com.itmill.toolkit.service.FileTypeResolver; */ public class FileResource implements ApplicationResource { - /** - * Default buffer size for this stream resource. - */ - private int bufferSize = 0; - - /** - * File where the downloaded content is fetched from. - */ - private File sourceFile; - - /** - * Application. - */ - private Application application; - - /** - * Default cache time for this stream resource. - */ - private long cacheTime = DownloadStream.DEFAULT_CACHETIME; - - /** - * Creates a new file resource for providing given file for client - * terminals. - */ - public FileResource(File sourceFile, Application application) { - this.application = application; - setSourceFile(sourceFile); - application.addResource(this); - } - - /** - * Gets the resource as stream. - * - * @see com.itmill.toolkit.terminal.ApplicationResource#getStream() - */ - public DownloadStream getStream() { - try { - DownloadStream ds = new DownloadStream(new FileInputStream( - this.sourceFile), getMIMEType(), getFilename()); - ds.setCacheTime(cacheTime); - return ds; - } catch (FileNotFoundException e) { - // No logging for non-existing files at this level. - return null; - } - } - - /** - * Gets the source file. - * - * @return the source File. - */ - public File getSourceFile() { - return sourceFile; - } - - /** - * Sets the source file. - * - * @param sourceFile - * the source file to set. - */ - public void setSourceFile(File sourceFile) { - this.sourceFile = sourceFile; - } - - /** - * @see com.itmill.toolkit.terminal.ApplicationResource#getApplication() - */ - public Application getApplication() { - return application; - } - - /** - * @see com.itmill.toolkit.terminal.ApplicationResource#getFilename() - */ - public String getFilename() { - return sourceFile.getName(); - } - - /** - * @see com.itmill.toolkit.terminal.Resource#getMIMEType() - */ - public String getMIMEType() { - return FileTypeResolver.getMIMEType(sourceFile); - } - - /** - * Gets the length of cache expiration time. This gives the adapter the - * possibility cache streams sent to the client. The caching may be made in - * adapter or at the client if the client supports caching. Default is - * DownloadStream.DEFAULT_CACHETIME. - * - * @return Cache time in milliseconds. - */ - public long getCacheTime() { - return cacheTime; - } - - /** - * Sets the length of cache expiration time. This gives the adapter the - * possibility cache streams sent to the client. The caching may be made in - * adapter or at the client if the client supports caching. Zero or negavive - * value disbales the caching of this stream. - * - * @param cacheTime - * the cache time in milliseconds. - */ - public void setCacheTime(long cacheTime) { - this.cacheTime = cacheTime; - } - - /* documented in superclass */ - public int getBufferSize() { - return bufferSize; - } - - /** - * Sets the size of the download buffer used for this resource. - * - * @param bufferSize - * the size of the buffer in bytes. - */ - public void setBufferSize(int bufferSize) { - this.bufferSize = bufferSize; - } + /** + * Default buffer size for this stream resource. + */ + private int bufferSize = 0; + + /** + * File where the downloaded content is fetched from. + */ + private File sourceFile; + + /** + * Application. + */ + private Application application; + + /** + * Default cache time for this stream resource. + */ + private long cacheTime = DownloadStream.DEFAULT_CACHETIME; + + /** + * Creates a new file resource for providing given file for client + * terminals. + */ + public FileResource(File sourceFile, Application application) { + this.application = application; + setSourceFile(sourceFile); + application.addResource(this); + } + + /** + * Gets the resource as stream. + * + * @see com.itmill.toolkit.terminal.ApplicationResource#getStream() + */ + public DownloadStream getStream() { + try { + DownloadStream ds = new DownloadStream(new FileInputStream( + sourceFile), getMIMEType(), getFilename()); + ds.setCacheTime(cacheTime); + return ds; + } catch (FileNotFoundException e) { + // No logging for non-existing files at this level. + return null; + } + } + + /** + * Gets the source file. + * + * @return the source File. + */ + public File getSourceFile() { + return sourceFile; + } + + /** + * Sets the source file. + * + * @param sourceFile + * the source file to set. + */ + public void setSourceFile(File sourceFile) { + this.sourceFile = sourceFile; + } + + /** + * @see com.itmill.toolkit.terminal.ApplicationResource#getApplication() + */ + public Application getApplication() { + return application; + } + + /** + * @see com.itmill.toolkit.terminal.ApplicationResource#getFilename() + */ + public String getFilename() { + return sourceFile.getName(); + } + + /** + * @see com.itmill.toolkit.terminal.Resource#getMIMEType() + */ + public String getMIMEType() { + return FileTypeResolver.getMIMEType(sourceFile); + } + + /** + * Gets the length of cache expiration time. This gives the adapter the + * possibility cache streams sent to the client. The caching may be made in + * adapter or at the client if the client supports caching. Default is + * DownloadStream.DEFAULT_CACHETIME. + * + * @return Cache time in milliseconds. + */ + public long getCacheTime() { + return cacheTime; + } + + /** + * Sets the length of cache expiration time. This gives the adapter the + * possibility cache streams sent to the client. The caching may be made in + * adapter or at the client if the client supports caching. Zero or negavive + * value disbales the caching of this stream. + * + * @param cacheTime + * the cache time in milliseconds. + */ + public void setCacheTime(long cacheTime) { + this.cacheTime = cacheTime; + } + + /* documented in superclass */ + public int getBufferSize() { + return bufferSize; + } + + /** + * Sets the size of the download buffer used for this resource. + * + * @param bufferSize + * the size of the buffer in bytes. + */ + public void setBufferSize(int bufferSize) { + this.bufferSize = bufferSize; + } } diff --git a/src/com/itmill/toolkit/terminal/KeyMapper.java b/src/com/itmill/toolkit/terminal/KeyMapper.java index 59967f2d32..16460de64c 100644 --- a/src/com/itmill/toolkit/terminal/KeyMapper.java +++ b/src/com/itmill/toolkit/terminal/KeyMapper.java @@ -41,83 +41,85 @@ import java.util.Hashtable; */ public class KeyMapper { - private int lastKey = 0; - - private Hashtable objectKeyMap = new Hashtable(); - - private Hashtable keyObjectMap = new Hashtable(); - - /** - * Gets key for an object. - * - * @param o - * the object. - */ - public String key(Object o) { - - if (o == null) - return "null"; - - // If the object is already mapped, use existing key - String key = (String) objectKeyMap.get(o); - if (key != null) - return key; - - // If the object is not yet mapped, map it - key = String.valueOf(++lastKey); - objectKeyMap.put(o, key); - keyObjectMap.put(key, o); - - return key; - } - - /** - * Checks if the key belongs to a new id. - *

- * Usage of new id:s are specific to components, but for example Select - * component uses newItemId:s for selection of newly added items in - * allowNewItems-mode. - * - * @param key - * @return true if the key belongs to the new id,otherwise - * false. - */ - public boolean isNewIdKey(String key) { - return "NEW".equals(key); - } - - /** - * Retrieves object with the key. - * - * @param key - * the name with the desired value. - * @return the object with the key. - */ - public Object get(String key) { - - return keyObjectMap.get(key); - } - - /** - * Removes object from the mapper. - * - * @param removeobj - * the object to be removed. - */ - public void remove(Object removeobj) { - String key = (String) objectKeyMap.get(removeobj); - - if (key != null) { - objectKeyMap.remove(key); - keyObjectMap.remove(removeobj); - } - } - - /** - * Removes all objects from the mapper. - */ - public void removeAll() { - objectKeyMap.clear(); - keyObjectMap.clear(); - } + private int lastKey = 0; + + private Hashtable objectKeyMap = new Hashtable(); + + private Hashtable keyObjectMap = new Hashtable(); + + /** + * Gets key for an object. + * + * @param o + * the object. + */ + public String key(Object o) { + + if (o == null) { + return "null"; + } + + // If the object is already mapped, use existing key + String key = (String) objectKeyMap.get(o); + if (key != null) { + return key; + } + + // If the object is not yet mapped, map it + key = String.valueOf(++lastKey); + objectKeyMap.put(o, key); + keyObjectMap.put(key, o); + + return key; + } + + /** + * Checks if the key belongs to a new id. + *

+ * Usage of new id:s are specific to components, but for example Select + * component uses newItemId:s for selection of newly added items in + * allowNewItems-mode. + * + * @param key + * @return true if the key belongs to the new id,otherwise + * false. + */ + public boolean isNewIdKey(String key) { + return "NEW".equals(key); + } + + /** + * Retrieves object with the key. + * + * @param key + * the name with the desired value. + * @return the object with the key. + */ + public Object get(String key) { + + return keyObjectMap.get(key); + } + + /** + * Removes object from the mapper. + * + * @param removeobj + * the object to be removed. + */ + public void remove(Object removeobj) { + String key = (String) objectKeyMap.get(removeobj); + + if (key != null) { + objectKeyMap.remove(key); + keyObjectMap.remove(removeobj); + } + } + + /** + * Removes all objects from the mapper. + */ + public void removeAll() { + objectKeyMap.clear(); + keyObjectMap.clear(); + } } diff --git a/src/com/itmill/toolkit/terminal/PaintException.java b/src/com/itmill/toolkit/terminal/PaintException.java index 8d49ebc41e..2830e762a5 100644 --- a/src/com/itmill/toolkit/terminal/PaintException.java +++ b/src/com/itmill/toolkit/terminal/PaintException.java @@ -40,30 +40,30 @@ import java.io.IOException; */ public class PaintException extends IOException { - /** - * Serial generated by eclipse. - */ - private static final long serialVersionUID = 3762535607221891897L; + /** + * Serial generated by eclipse. + */ + private static final long serialVersionUID = 3762535607221891897L; - /** - * Constructs an instance of PaintExeception with the - * specified detail message. - * - * @param msg - * the detail message. - */ - public PaintException(String msg) { - super(msg); - } + /** + * Constructs an instance of PaintExeception with the + * specified detail message. + * + * @param msg + * the detail message. + */ + public PaintException(String msg) { + super(msg); + } - /** - * Constructs an instance of PaintExeception from - * IOException. - * - * @param exception - * the original exception. - */ - public PaintException(IOException exception) { - super(exception.getMessage()); - } + /** + * Constructs an instance of PaintExeception from + * IOException. + * + * @param exception + * the original exception. + */ + public PaintException(IOException exception) { + super(exception.getMessage()); + } } diff --git a/src/com/itmill/toolkit/terminal/PaintTarget.java b/src/com/itmill/toolkit/terminal/PaintTarget.java index c0736d6c97..e7760c9e7f 100644 --- a/src/com/itmill/toolkit/terminal/PaintTarget.java +++ b/src/com/itmill/toolkit/terminal/PaintTarget.java @@ -38,349 +38,349 @@ package com.itmill.toolkit.terminal; */ public interface PaintTarget { - /** - * Prints single XMLsection. - * - * Prints full XML section. The section data is escaped from XML tags and - * surrounded by XML start and end-tags. - * - * @param sectionTagName - * the name of the tag. - * @param sectionData - * the scetion data. - * @throws PaintException - * if the paint operation failed. - */ - public void addSection(String sectionTagName, String sectionData) - throws PaintException; + /** + * Prints single XMLsection. + * + * Prints full XML section. The section data is escaped from XML tags and + * surrounded by XML start and end-tags. + * + * @param sectionTagName + * the name of the tag. + * @param sectionData + * the scetion data. + * @throws PaintException + * if the paint operation failed. + */ + public void addSection(String sectionTagName, String sectionData) + throws PaintException; - /** - * Prints element start tag of a paintable section. Starts a paintable - * section using the given tag. The PaintTarget may implement a caching - * scheme, that checks the paintable has actually changed or can a cached - * version be used instead. This method should call the startTag method. - *

- * If the Paintable is found in cache and this function returns true it may - * omit the content and close the tag, in which case cached content should - * be used. - *

- * - * @param paintable - * the paintable to start. - * @param tag - * the name of the start tag. - * @return true if paintable found in cache, - * false otherwise. - * @throws PaintException - * if the paint operation failed. - * @see #startTag(String) - * @since 3.1 - */ - public boolean startTag(Paintable paintable, String tag) - throws PaintException; + /** + * Prints element start tag of a paintable section. Starts a paintable + * section using the given tag. The PaintTarget may implement a caching + * scheme, that checks the paintable has actually changed or can a cached + * version be used instead. This method should call the startTag method. + *

+ * If the Paintable is found in cache and this function returns true it may + * omit the content and close the tag, in which case cached content should + * be used. + *

+ * + * @param paintable + * the paintable to start. + * @param tag + * the name of the start tag. + * @return true if paintable found in cache, + * false otherwise. + * @throws PaintException + * if the paint operation failed. + * @see #startTag(String) + * @since 3.1 + */ + public boolean startTag(Paintable paintable, String tag) + throws PaintException; - /** - * Prints element start tag. - * - *
-	 * Todo:
-	 * Checking of input values
-	 * 
- * - * @param tagName - * the name of the start tag. - * @throws PaintException - * if the paint operation failed. - */ - public void startTag(String tagName) throws PaintException; + /** + * Prints element start tag. + * + *
+     * Todo:
+     * Checking of input values
+     * 
+ * + * @param tagName + * the name of the start tag. + * @throws PaintException + * if the paint operation failed. + */ + public void startTag(String tagName) throws PaintException; - /** - * Prints element end tag. - * - * If the parent tag is closed before every child tag is closed an - * PaintException is raised. - * - * @param tagName - * the name of the end tag. - * @throws PaintException - * if the paint operation failed. - */ - public void endTag(String tagName) throws PaintException; + /** + * Prints element end tag. + * + * If the parent tag is closed before every child tag is closed an + * PaintException is raised. + * + * @param tagName + * the name of the end tag. + * @throws PaintException + * if the paint operation failed. + */ + public void endTag(String tagName) throws PaintException; - /** - * Adds a boolean attribute to component. Atributes must be added before any - * content is written. - * - * @param name - * the Attribute name. - * @param value - * the Attribute value. - * - * @throws PaintException - * if the paint operation failed. - */ - public void addAttribute(String name, boolean value) throws PaintException; + /** + * Adds a boolean attribute to component. Atributes must be added before any + * content is written. + * + * @param name + * the Attribute name. + * @param value + * the Attribute value. + * + * @throws PaintException + * if the paint operation failed. + */ + public void addAttribute(String name, boolean value) throws PaintException; - /** - * Adds a integer attribute to component. Atributes must be added before any - * content is written. - * - * @param name - * the Attribute name. - * @param value - * the Attribute value. - * - * @throws PaintException - * if the paint operation failed. - */ - public void addAttribute(String name, int value) throws PaintException; + /** + * Adds a integer attribute to component. Atributes must be added before any + * content is written. + * + * @param name + * the Attribute name. + * @param value + * the Attribute value. + * + * @throws PaintException + * if the paint operation failed. + */ + public void addAttribute(String name, int value) throws PaintException; - /** - * Adds a resource attribute to component. Atributes must be added before - * any content is written. - * - * @param name - * the Attribute name - * @param value - * the Attribute value - * - * @throws PaintException - * if the paint operation failed. - */ - public void addAttribute(String name, Resource value) throws PaintException; + /** + * Adds a resource attribute to component. Atributes must be added before + * any content is written. + * + * @param name + * the Attribute name + * @param value + * the Attribute value + * + * @throws PaintException + * if the paint operation failed. + */ + public void addAttribute(String name, Resource value) throws PaintException; - /** - * Adds a long attribute to component. Atributes must be added before any - * content is written. - * - * @param name - * the Attribute name. - * @param value - * the Attribute value. - * - * @throws PaintException - * if the paint operation failed. - */ - public void addAttribute(String name, long value) throws PaintException; + /** + * Adds a long attribute to component. Atributes must be added before any + * content is written. + * + * @param name + * the Attribute name. + * @param value + * the Attribute value. + * + * @throws PaintException + * if the paint operation failed. + */ + public void addAttribute(String name, long value) throws PaintException; - /** - * Adds a float attribute to component. Atributes must be added before any - * content is written. - * - * @param name - * the Attribute name. - * @param value - * the Attribute value. - * - * @throws PaintException - * if the paint operation failed. - */ - public void addAttribute(String name, float value) throws PaintException; + /** + * Adds a float attribute to component. Atributes must be added before any + * content is written. + * + * @param name + * the Attribute name. + * @param value + * the Attribute value. + * + * @throws PaintException + * if the paint operation failed. + */ + public void addAttribute(String name, float value) throws PaintException; - /** - * Adds a double attribute to component. Atributes must be added before any - * content is written. - * - * @param name - * the Attribute name. - * @param value - * the Attribute value. - * - * @throws PaintException - * if the paint operation failed. - */ - public void addAttribute(String name, double value) throws PaintException; + /** + * Adds a double attribute to component. Atributes must be added before any + * content is written. + * + * @param name + * the Attribute name. + * @param value + * the Attribute value. + * + * @throws PaintException + * if the paint operation failed. + */ + public void addAttribute(String name, double value) throws PaintException; - /** - * Adds a string attribute to component. Atributes must be added before any - * content is written. - * - * @param name - * the Boolean attribute name. - * @param value - * the Boolean attribute value. - * - * @throws PaintException - * if the paint operation failed. - */ - public void addAttribute(String name, String value) throws PaintException; + /** + * Adds a string attribute to component. Atributes must be added before any + * content is written. + * + * @param name + * the Boolean attribute name. + * @param value + * the Boolean attribute value. + * + * @throws PaintException + * if the paint operation failed. + */ + public void addAttribute(String name, String value) throws PaintException; - /** - * Adds a string type variable. - * - * @param owner - * the Listener for variable changes. - * @param name - * the Variable name. - * @param value - * the Variable initial value. - * - * @throws PaintException - * if the paint operation failed. - */ - public void addVariable(VariableOwner owner, String name, String value) - throws PaintException; + /** + * Adds a string type variable. + * + * @param owner + * the Listener for variable changes. + * @param name + * the Variable name. + * @param value + * the Variable initial value. + * + * @throws PaintException + * if the paint operation failed. + */ + public void addVariable(VariableOwner owner, String name, String value) + throws PaintException; - /** - * Adds a int type variable. - * - * @param owner - * the Listener for variable changes. - * @param name - * the Variable name. - * @param value - * the Variable initial value. - * - * @throws PaintException - * if the paint operation failed. - */ - public void addVariable(VariableOwner owner, String name, int value) - throws PaintException; + /** + * Adds a int type variable. + * + * @param owner + * the Listener for variable changes. + * @param name + * the Variable name. + * @param value + * the Variable initial value. + * + * @throws PaintException + * if the paint operation failed. + */ + public void addVariable(VariableOwner owner, String name, int value) + throws PaintException; - /** - * Adds a long type variable. - * - * @param owner - * the Listener for variable changes. - * @param name - * the Variable name. - * @param value - * the Variable initial value. - * - * @throws PaintException - * if the paint operation failed. - */ - public void addVariable(VariableOwner owner, String name, long value) - throws PaintException; + /** + * Adds a long type variable. + * + * @param owner + * the Listener for variable changes. + * @param name + * the Variable name. + * @param value + * the Variable initial value. + * + * @throws PaintException + * if the paint operation failed. + */ + public void addVariable(VariableOwner owner, String name, long value) + throws PaintException; - /** - * Adds a float type variable. - * - * @param owner - * the Listener for variable changes. - * @param name - * the Variable name. - * @param value - * the Variable initial value. - * - * @throws PaintException - * if the paint operation failed. - */ - public void addVariable(VariableOwner owner, String name, float value) - throws PaintException; + /** + * Adds a float type variable. + * + * @param owner + * the Listener for variable changes. + * @param name + * the Variable name. + * @param value + * the Variable initial value. + * + * @throws PaintException + * if the paint operation failed. + */ + public void addVariable(VariableOwner owner, String name, float value) + throws PaintException; - /** - * Adds a double type variable. - * - * @param owner - * the Listener for variable changes. - * @param name - * the Variable name. - * @param value - * the Variable initial value. - * - * @throws PaintException - * if the paint operation failed. - */ - public void addVariable(VariableOwner owner, String name, double value) - throws PaintException; + /** + * Adds a double type variable. + * + * @param owner + * the Listener for variable changes. + * @param name + * the Variable name. + * @param value + * the Variable initial value. + * + * @throws PaintException + * if the paint operation failed. + */ + public void addVariable(VariableOwner owner, String name, double value) + throws PaintException; - /** - * Adds a boolean type variable. - * - * @param owner - * the Listener for variable changes. - * @param name - * the Variable name. - * @param value - * the Variable initial value. - * - * @throws PaintException - * if the paint operation failed. - */ - public void addVariable(VariableOwner owner, String name, boolean value) - throws PaintException; + /** + * Adds a boolean type variable. + * + * @param owner + * the Listener for variable changes. + * @param name + * the Variable name. + * @param value + * the Variable initial value. + * + * @throws PaintException + * if the paint operation failed. + */ + public void addVariable(VariableOwner owner, String name, boolean value) + throws PaintException; - /** - * Adds a string array type variable. - * - * @param owner - * the Listener for variable changes. - * @param name - * the Variable name. - * @param value - * the Variable initial value. - * - * @throws PaintException - * if the paint operation failed. - */ - public void addVariable(VariableOwner owner, String name, String[] value) - throws PaintException; + /** + * Adds a string array type variable. + * + * @param owner + * the Listener for variable changes. + * @param name + * the Variable name. + * @param value + * the Variable initial value. + * + * @throws PaintException + * if the paint operation failed. + */ + public void addVariable(VariableOwner owner, String name, String[] value) + throws PaintException; - /** - * Adds a upload stream type variable. - * - * @param owner - * the Listener for variable changes. - * @param name - * the Variable name. - * - * @throws PaintException - * if the paint operation failed. - */ - public void addUploadStreamVariable(VariableOwner owner, String name) - throws PaintException; + /** + * Adds a upload stream type variable. + * + * @param owner + * the Listener for variable changes. + * @param name + * the Variable name. + * + * @throws PaintException + * if the paint operation failed. + */ + public void addUploadStreamVariable(VariableOwner owner, String name) + throws PaintException; - /** - * Prints single XML section. - *

- * Prints full XML section. The section data must be XML and it is - * surrounded by XML start and end-tags. - *

- * - * @param sectionTagName - * the tag name. - * @param sectionData - * the section data to be printed. - * @param namespace - * the namespace. - * @throws PaintException - * if the paint operation failed. - */ - public void addXMLSection(String sectionTagName, String sectionData, - String namespace) throws PaintException; + /** + * Prints single XML section. + *

+ * Prints full XML section. The section data must be XML and it is + * surrounded by XML start and end-tags. + *

+ * + * @param sectionTagName + * the tag name. + * @param sectionData + * the section data to be printed. + * @param namespace + * the namespace. + * @throws PaintException + * if the paint operation failed. + */ + public void addXMLSection(String sectionTagName, String sectionData, + String namespace) throws PaintException; - /** - * Adds UIDL directly. The UIDL must be valid in accordance with the - * UIDL.dtd - * - * @param uidl - * the UIDL to be added. - * @throws PaintException - * if the paint operation failed. - */ - public void addUIDL(java.lang.String uidl) throws PaintException; + /** + * Adds UIDL directly. The UIDL must be valid in accordance with the + * UIDL.dtd + * + * @param uidl + * the UIDL to be added. + * @throws PaintException + * if the paint operation failed. + */ + public void addUIDL(java.lang.String uidl) throws PaintException; - /** - * Adds text node. All the contents of the text are XML-escaped. - * - * @param text - * the Text to add - * @throws PaintException - * if the paint operation failed. - */ - void addText(String text) throws PaintException; + /** + * Adds text node. All the contents of the text are XML-escaped. + * + * @param text + * the Text to add + * @throws PaintException + * if the paint operation failed. + */ + void addText(String text) throws PaintException; - /** - * Adds CDATA node to target UIDL-tree. - * - * @param text - * the Character data to add - * @throws PaintException - * if the paint operation failed. - * @since 3.1 - */ - void addCharacterData(String text) throws PaintException; + /** + * Adds CDATA node to target UIDL-tree. + * + * @param text + * the Character data to add + * @throws PaintException + * if the paint operation failed. + * @since 3.1 + */ + void addCharacterData(String text) throws PaintException; - public void addAttribute(String string, Object[] keys); + public void addAttribute(String string, Object[] keys); } diff --git a/src/com/itmill/toolkit/terminal/Paintable.java b/src/com/itmill/toolkit/terminal/Paintable.java index 29e01e0bf5..3c89923632 100644 --- a/src/com/itmill/toolkit/terminal/Paintable.java +++ b/src/com/itmill/toolkit/terminal/Paintable.java @@ -42,111 +42,112 @@ import java.util.EventObject; */ public interface Paintable extends java.util.EventListener { - /** - *

- * Paints the paintable into a UIDL stream. This method creates the UIDL - * sequence describing it and outputs it to the given UIDL stream. - *

- * - *

- * It is called when the contents of the component should be painted in - * response to the component first being shown or having been altered so - * that its visual representation is changed. - *

- * - * @param target - * the target UIDL stream where the component should paint itself - * to. - * @throws PaintException - * if the paint operation failed. - */ - public void paint(PaintTarget target) throws PaintException; - - /** - * Requests that the paintable should be repainted as soon as possible. - */ - public void requestRepaint(); - - /** - * Repaint request event is thrown when the paintable needs to be repainted. - * This is typically done when the paint method would return - * dissimilar UIDL from the previous call of the method. - */ - public class RepaintRequestEvent extends EventObject { - - /** - * Serial generated by eclipse. - */ - private static final long serialVersionUID = 3256725095530442805L; - - /** - * Constructs a new event. - * - * @param source - * the paintable needing repaint. - */ - public RepaintRequestEvent(Paintable source) { - super(source); - } - - /** - * Gets the paintable needing repainting. - * - * @return Paintable for which the paint method will - * return dissimilar UIDL from the previous call of the method. - */ - public Paintable getPaintable() { - return (Paintable) getSource(); - } - } - - /** - * Listens repaint requests. The repaintRequested method is - * called when the paintable needs to be repainted. This is typically done - * when the paint method would return dissimilar UIDL from - * the previous call of the method. - */ - public interface RepaintRequestListener { - - /** - * Receives repaint request events. - * - * @param event - * the repaint request event specifying the paintable source. - */ - public void repaintRequested(RepaintRequestEvent event); - } - - /** - * Adds repaint request listener. In order to assure that no repaint - * requests are missed, the new repaint listener should paint the paintable - * right after adding itself as listener. - * - * @param listener - * the listener to be added. - */ - public void addListener(RepaintRequestListener listener); - - /** - * Removes repaint request listener. - * - * @param listener - * the listener to be removed. - */ - public void removeListener(RepaintRequestListener listener); - - /** - * Request sending of repaint events on any further visible changes. - * Normally the paintable only send up to one repaint request for listeners - * after paint as the paintable as the paintable assumes that the listeners - * already know about the repaint need. This method resets the assumtion. - * Paint implicitly does the assumtion reset functionality implemented by - * this method. - *

- * This method is normally used only by the terminals to note paintables - * about implicit repaints (painting the component without actually invoking - * paint method). - *

- */ - public void requestRepaintRequests(); + /** + *

+ * Paints the paintable into a UIDL stream. This method creates the UIDL + * sequence describing it and outputs it to the given UIDL stream. + *

+ * + *

+ * It is called when the contents of the component should be painted in + * response to the component first being shown or having been altered so + * that its visual representation is changed. + *

+ * + * @param target + * the target UIDL stream where the component should paint + * itself to. + * @throws PaintException + * if the paint operation failed. + */ + public void paint(PaintTarget target) throws PaintException; + + /** + * Requests that the paintable should be repainted as soon as possible. + */ + public void requestRepaint(); + + /** + * Repaint request event is thrown when the paintable needs to be repainted. + * This is typically done when the paint method would return + * dissimilar UIDL from the previous call of the method. + */ + public class RepaintRequestEvent extends EventObject { + + /** + * Serial generated by eclipse. + */ + private static final long serialVersionUID = 3256725095530442805L; + + /** + * Constructs a new event. + * + * @param source + * the paintable needing repaint. + */ + public RepaintRequestEvent(Paintable source) { + super(source); + } + + /** + * Gets the paintable needing repainting. + * + * @return Paintable for which the paint method will + * return dissimilar UIDL from the previous call of the method. + */ + public Paintable getPaintable() { + return (Paintable) getSource(); + } + } + + /** + * Listens repaint requests. The repaintRequested method is + * called when the paintable needs to be repainted. This is typically done + * when the paint method would return dissimilar UIDL from + * the previous call of the method. + */ + public interface RepaintRequestListener { + + /** + * Receives repaint request events. + * + * @param event + * the repaint request event specifying the paintable + * source. + */ + public void repaintRequested(RepaintRequestEvent event); + } + + /** + * Adds repaint request listener. In order to assure that no repaint + * requests are missed, the new repaint listener should paint the paintable + * right after adding itself as listener. + * + * @param listener + * the listener to be added. + */ + public void addListener(RepaintRequestListener listener); + + /** + * Removes repaint request listener. + * + * @param listener + * the listener to be removed. + */ + public void removeListener(RepaintRequestListener listener); + + /** + * Request sending of repaint events on any further visible changes. + * Normally the paintable only send up to one repaint request for listeners + * after paint as the paintable as the paintable assumes that the listeners + * already know about the repaint need. This method resets the assumtion. + * Paint implicitly does the assumtion reset functionality implemented by + * this method. + *

+ * This method is normally used only by the terminals to note paintables + * about implicit repaints (painting the component without actually invoking + * paint method). + *

+ */ + public void requestRepaintRequests(); } diff --git a/src/com/itmill/toolkit/terminal/ParameterHandler.java b/src/com/itmill/toolkit/terminal/ParameterHandler.java index 1f847ae1c0..8d8ab0ca17 100644 --- a/src/com/itmill/toolkit/terminal/ParameterHandler.java +++ b/src/com/itmill/toolkit/terminal/ParameterHandler.java @@ -50,32 +50,32 @@ import java.util.Map; */ public interface ParameterHandler { - /** - *

- * Handles the given parameters. The parameters are given as inmodifieable - * name to value map. All parameters names are of type: - * {@link java.lang.String}. All the parameter values are arrays of - * strings. - *

- * - * @param parameters - * the Inmodifiable name to value[] mapping. - * - */ - public void handleParameters(Map parameters); + /** + *

+ * Handles the given parameters. The parameters are given as inmodifieable + * name to value map. All parameters names are of type: + * {@link java.lang.String}. All the parameter values are arrays of + * strings. + *

+ * + * @param parameters + * the Inmodifiable name to value[] mapping. + * + */ + public void handleParameters(Map parameters); - /** - * ParameterHandler error event. - */ - public interface ErrorEvent extends Terminal.ErrorEvent { + /** + * ParameterHandler error event. + */ + public interface ErrorEvent extends Terminal.ErrorEvent { - /** - * Gets the source ParameterHandler. - * - * @return the source Parameter Handler. - */ - public ParameterHandler getParameterHandler(); + /** + * Gets the source ParameterHandler. + * + * @return the source Parameter Handler. + */ + public ParameterHandler getParameterHandler(); - } + } } diff --git a/src/com/itmill/toolkit/terminal/Resource.java b/src/com/itmill/toolkit/terminal/Resource.java index 28578ee022..8dc86e2d86 100644 --- a/src/com/itmill/toolkit/terminal/Resource.java +++ b/src/com/itmill/toolkit/terminal/Resource.java @@ -39,10 +39,10 @@ package com.itmill.toolkit.terminal; */ public interface Resource { - /** - * Gets the MIME type of the resource. - * - * @return the MIME type of the resource. - */ - public String getMIMEType(); + /** + * Gets the MIME type of the resource. + * + * @return the MIME type of the resource. + */ + public String getMIMEType(); } diff --git a/src/com/itmill/toolkit/terminal/Scrollable.java b/src/com/itmill/toolkit/terminal/Scrollable.java index de88dbce13..f320a4d2a8 100644 --- a/src/com/itmill/toolkit/terminal/Scrollable.java +++ b/src/com/itmill/toolkit/terminal/Scrollable.java @@ -41,80 +41,80 @@ package com.itmill.toolkit.terminal; */ public interface Scrollable { - /** - * Gets scroll X offset. - * - *

- * Scrolling offset is the number of pixels this scrollable has been - * scrolled to left. - *

- * - * @return Horizontal scrolling position in pixels. - */ - public int getScrollOffsetX(); + /** + * Gets scroll X offset. + * + *

+ * Scrolling offset is the number of pixels this scrollable has been + * scrolled to left. + *

+ * + * @return Horizontal scrolling position in pixels. + */ + public int getScrollOffsetX(); - /** - * Sets scroll X offset. - * - *

- * Scrolling offset is the number of pixels this scrollable has been - * scrolled to left. - *

- * - * @param pixelsScrolledLeft - * the xOffset. - */ - public void setScrollOffsetX(int pixelsScrolledLeft); + /** + * Sets scroll X offset. + * + *

+ * Scrolling offset is the number of pixels this scrollable has been + * scrolled to left. + *

+ * + * @param pixelsScrolledLeft + * the xOffset. + */ + public void setScrollOffsetX(int pixelsScrolledLeft); - /** - * Gets scroll Y offset. - * - *

- * Scrolling offset is the number of pixels this scrollable has been - * scrolled to down. - *

- * - * @return Vertical scrolling position in pixels. - */ - public int getScrollOffsetY(); + /** + * Gets scroll Y offset. + * + *

+ * Scrolling offset is the number of pixels this scrollable has been + * scrolled to down. + *

+ * + * @return Vertical scrolling position in pixels. + */ + public int getScrollOffsetY(); - /** - * Sets scroll Y offset. - * - *

- * Scrolling offset is the number of pixels this scrollable has been - * scrolled to down. - *

- * - * @param pixelsScrolledDown - * the yOffset. - */ - public void setScrollOffsetY(int pixelsScrolledDown); + /** + * Sets scroll Y offset. + * + *

+ * Scrolling offset is the number of pixels this scrollable has been + * scrolled to down. + *

+ * + * @param pixelsScrolledDown + * the yOffset. + */ + public void setScrollOffsetY(int pixelsScrolledDown); - /** - * Is the scrolling enabled. - * - *

- * Enabling scrolling allows the user to scroll the scrollable view - * interactively - *

- * - * @return true if the scrolling is allowed, otherwise - * false. - */ - public boolean isScrollable(); + /** + * Is the scrolling enabled. + * + *

+ * Enabling scrolling allows the user to scroll the scrollable view + * interactively + *

+ * + * @return true if the scrolling is allowed, otherwise + * false. + */ + public boolean isScrollable(); - /** - * Enables or disables scrolling.. - * - *

- * Enabling scrolling allows the user to scroll the scrollable view - * interactively - *

- * - * @param isScrollingEnabled - * true if the scrolling is allowed. - */ - public void setScrollable(boolean isScrollingEnabled); + /** + * Enables or disables scrolling.. + * + *

+ * Enabling scrolling allows the user to scroll the scrollable view + * interactively + *

+ * + * @param isScrollingEnabled + * true if the scrolling is allowed. + */ + public void setScrollable(boolean isScrollingEnabled); } diff --git a/src/com/itmill/toolkit/terminal/Sizeable.java b/src/com/itmill/toolkit/terminal/Sizeable.java index 230440aa50..decacf3fa4 100644 --- a/src/com/itmill/toolkit/terminal/Sizeable.java +++ b/src/com/itmill/toolkit/terminal/Sizeable.java @@ -39,153 +39,153 @@ package com.itmill.toolkit.terminal; */ public interface Sizeable { - /** - * Unit code representing pixels. - */ - public static final int UNITS_PIXELS = 0; - - /** - * Unit code representing points (1/72nd of an inch). - */ - public static final int UNITS_POINTS = 1; - - /** - * Unit code representing picas (12 points). - */ - public static final int UNITS_PICAS = 2; - - /** - * Unit code representing the font-size of the relevant font. - */ - public static final int UNITS_EM = 3; - - /** - * Unit code representing the x-height of the relevant font. - */ - public static final int UNITS_EX = 4; - - /** - * Unit code representing millimetres. - */ - public static final int UNITS_MM = 5; - - /** - * Unit code representing centimetres. - */ - public static final int UNITS_CM = 6; - - /** - * Unit code representing inches. - */ - public static final int UNITS_INCH = 7; - - /** - * Unit code representing in percentage of the containing element defined by - * terminal. - */ - public static final int UNITS_PERCENTAGE = 8; - - /** - * Unit code representing in rows of text. This unit is only applicaple to - * some components can it's meaning is specified by component - * implementation. - */ - public static final int UNITS_ROWS = 9; - - /** - * Textual representations of units symbols. Supported units and their - * symbols are: - *
    - *
  • UNITS_PIXELS: "px"
  • - *
  • UNITS_POINTS: "pt"
  • - *
  • UNITS_PICAS: "pc"
  • - *
  • UNITS_EM: "em"
  • - *
  • UNITS_EX: "ex"
  • - *
  • UNITS_MM: "mm"
  • - *
  • UNITS_CM. "cm"
  • - *
  • UNITS_INCH: "in"
  • - *
  • UNITS_PERCENTAGE: "%"
  • - *
  • UNITS_ROWS: "rows"
  • - *
- * These can be used like Sizeable.UNIT_SYMBOLS[UNITS_PIXELS]. - */ - public static final String[] UNIT_SYMBOLS = { "px", "pt", "pc", "em", "ex", - "mm", "cm", "in", "%", "rows" }; - - /** - * Gets the width of the object. Negative number implies unspecified size - * (terminal is free to set the size). - * - * @return width of the object in units specified by widthUnits property. - */ - public int getWidth(); - - /** - * Sets the width of the object. Negative number implies unspecified size - * (terminal is free to set the size). - * - * @param width - * the width of the object in units specified by widthUnits - * property. - */ - public void setWidth(int width); - - /** - * Gets the height of the object. Negative number implies unspecified size - * (terminal is free to set the size). - * - * @return height of the object in units specified by heightUnits property. - */ - public int getHeight(); - - /** - * Sets the height of the object. Negative number implies unspecified size - * (terminal is free to set the size). - * - * @param height - * the height of the object in units specified by heightUnits - * property. - */ - public void setHeight(int height); - - /** - * Gets the width property units. - * - * @return units used in width property. - */ - public int getWidthUnits(); - - /** - * Sets the width property units. - * - * @param units - * the units used in width property. - */ - public void setWidthUnits(int units); - - /** - * Gets the height property units. - * - * @return units used in height property. - */ - public int getHeightUnits(); - - /** - * Sets the height property units. - * - * @param units - * the units used in height property. - */ - public void setHeightUnits(int units); - - /** - * Sets the size to 100% x 100%. - */ - public void setSizeFull(); - - /** - * Clears any size settings. - */ - public void setSizeUndefined(); + /** + * Unit code representing pixels. + */ + public static final int UNITS_PIXELS = 0; + + /** + * Unit code representing points (1/72nd of an inch). + */ + public static final int UNITS_POINTS = 1; + + /** + * Unit code representing picas (12 points). + */ + public static final int UNITS_PICAS = 2; + + /** + * Unit code representing the font-size of the relevant font. + */ + public static final int UNITS_EM = 3; + + /** + * Unit code representing the x-height of the relevant font. + */ + public static final int UNITS_EX = 4; + + /** + * Unit code representing millimetres. + */ + public static final int UNITS_MM = 5; + + /** + * Unit code representing centimetres. + */ + public static final int UNITS_CM = 6; + + /** + * Unit code representing inches. + */ + public static final int UNITS_INCH = 7; + + /** + * Unit code representing in percentage of the containing element defined by + * terminal. + */ + public static final int UNITS_PERCENTAGE = 8; + + /** + * Unit code representing in rows of text. This unit is only applicaple to + * some components can it's meaning is specified by component + * implementation. + */ + public static final int UNITS_ROWS = 9; + + /** + * Textual representations of units symbols. Supported units and their + * symbols are: + *
    + *
  • UNITS_PIXELS: "px"
  • + *
  • UNITS_POINTS: "pt"
  • + *
  • UNITS_PICAS: "pc"
  • + *
  • UNITS_EM: "em"
  • + *
  • UNITS_EX: "ex"
  • + *
  • UNITS_MM: "mm"
  • + *
  • UNITS_CM. "cm"
  • + *
  • UNITS_INCH: "in"
  • + *
  • UNITS_PERCENTAGE: "%"
  • + *
  • UNITS_ROWS: "rows"
  • + *
+ * These can be used like Sizeable.UNIT_SYMBOLS[UNITS_PIXELS]. + */ + public static final String[] UNIT_SYMBOLS = { "px", "pt", "pc", "em", "ex", + "mm", "cm", "in", "%", "rows" }; + + /** + * Gets the width of the object. Negative number implies unspecified size + * (terminal is free to set the size). + * + * @return width of the object in units specified by widthUnits property. + */ + public int getWidth(); + + /** + * Sets the width of the object. Negative number implies unspecified size + * (terminal is free to set the size). + * + * @param width + * the width of the object in units specified by widthUnits + * property. + */ + public void setWidth(int width); + + /** + * Gets the height of the object. Negative number implies unspecified size + * (terminal is free to set the size). + * + * @return height of the object in units specified by heightUnits property. + */ + public int getHeight(); + + /** + * Sets the height of the object. Negative number implies unspecified size + * (terminal is free to set the size). + * + * @param height + * the height of the object in units specified by heightUnits + * property. + */ + public void setHeight(int height); + + /** + * Gets the width property units. + * + * @return units used in width property. + */ + public int getWidthUnits(); + + /** + * Sets the width property units. + * + * @param units + * the units used in width property. + */ + public void setWidthUnits(int units); + + /** + * Gets the height property units. + * + * @return units used in height property. + */ + public int getHeightUnits(); + + /** + * Sets the height property units. + * + * @param units + * the units used in height property. + */ + public void setHeightUnits(int units); + + /** + * Sets the size to 100% x 100%. + */ + public void setSizeFull(); + + /** + * Clears any size settings. + */ + public void setSizeUndefined(); } diff --git a/src/com/itmill/toolkit/terminal/StreamResource.java b/src/com/itmill/toolkit/terminal/StreamResource.java index d7a467d95a..523741089d 100644 --- a/src/com/itmill/toolkit/terminal/StreamResource.java +++ b/src/com/itmill/toolkit/terminal/StreamResource.java @@ -46,191 +46,193 @@ import com.itmill.toolkit.service.FileTypeResolver; */ public class StreamResource implements ApplicationResource { - /** - * Source stream the downloaded content is fetched from. - */ - private StreamSource streamSource = null; - - /** - * Explicit mime-type. - */ - private String MIMEType = null; - - /** - * Filename. - */ - private String filename; - - /** - * Application. - */ - private Application application; - - /** - * Default buffer size for this stream resource. - */ - private int bufferSize = 0; - - /** - * Default cache time for this stream resource. - */ - private long cacheTime = DEFAULT_CACHETIME; - - /** - * Creates a new stream resource for downloading from stream. - * - * @param streamSource - * the source Stream. - * @param filename - * the name of the file. - * @param application - * the Application object. - */ - public StreamResource(StreamSource streamSource, String filename, - Application application) { - - this.application = application; - setFilename(filename); - setStreamSource(streamSource); - - // Register to application - application.addResource(this); - - } - - /** - * @see com.itmill.toolkit.terminal.Resource#getMIMEType() - */ - public String getMIMEType() { - if (MIMEType != null) - return MIMEType; - return FileTypeResolver.getMIMEType(filename); - } - - /** - * Sets the mime type of the resource. - * - * @param MIMEType - * the MIME type to be set. - */ - public void setMIMEType(String MIMEType) { - this.MIMEType = MIMEType; - } - - /** - * Returns the source for this StreamResource. StreamSource - * is queried when the resource is about to be streamed to the client. - * - * @return Source of the StreamResource. - */ - public StreamSource getStreamSource() { - return streamSource; - } - - /** - * Sets the source for this StreamResource. - * StreamSource is queried when the resource is about to be - * streamed to the client. - * - * @param streamSource - * the source to set. - */ - public void setStreamSource(StreamSource streamSource) { - this.streamSource = streamSource; - } - - /** - * Gets the filename. - * - * @return the filename. - */ - public String getFilename() { - return filename; - } - - /** - * Sets the filename. - * - * @param filename - * the filename to set. - */ - public void setFilename(String filename) { - this.filename = filename; - } - - /** - * @see com.itmill.toolkit.terminal.ApplicationResource#getApplication() - */ - public Application getApplication() { - return application; - } - - /** - * @see com.itmill.toolkit.terminal.ApplicationResource#getStream() - */ - public DownloadStream getStream() { - StreamSource ss = getStreamSource(); - if (ss == null) - return null; - DownloadStream ds = new DownloadStream(ss.getStream(), getMIMEType(), - getFilename()); - ds.setBufferSize(getBufferSize()); - ds.setCacheTime(cacheTime); - return ds; - } - - /** - * Interface implemented by the source of a StreamResource. - * - * @author IT Mill Ltd. - * @version - * @VERSION@ - * @since 3.0 - */ - public interface StreamSource { - - /** - * Returns new input stream that is used for reading the resource. - */ - public InputStream getStream(); - } - - /* documented in superclass */ - public int getBufferSize() { - return bufferSize; - } - - /** - * Sets the size of the download buffer used for this resource. - * - * @param bufferSize - * the size of the buffer in bytes. - */ - public void setBufferSize(int bufferSize) { - this.bufferSize = bufferSize; - } - - /* documented in superclass */ - public long getCacheTime() { - return cacheTime; - } - - /** - * Sets the length of cache expiration time. - * - *

- * This gives the adapter the possibility cache streams sent to the client. - * The caching may be made in adapter or at the client if the client - * supports caching. Zero or negavive value disbales the caching of this - * stream. - *

- * - * @param cacheTime - * the cache time in milliseconds. - * - */ - public void setCacheTime(long cacheTime) { - this.cacheTime = cacheTime; - } + /** + * Source stream the downloaded content is fetched from. + */ + private StreamSource streamSource = null; + + /** + * Explicit mime-type. + */ + private String MIMEType = null; + + /** + * Filename. + */ + private String filename; + + /** + * Application. + */ + private Application application; + + /** + * Default buffer size for this stream resource. + */ + private int bufferSize = 0; + + /** + * Default cache time for this stream resource. + */ + private long cacheTime = DEFAULT_CACHETIME; + + /** + * Creates a new stream resource for downloading from stream. + * + * @param streamSource + * the source Stream. + * @param filename + * the name of the file. + * @param application + * the Application object. + */ + public StreamResource(StreamSource streamSource, String filename, + Application application) { + + this.application = application; + setFilename(filename); + setStreamSource(streamSource); + + // Register to application + application.addResource(this); + + } + + /** + * @see com.itmill.toolkit.terminal.Resource#getMIMEType() + */ + public String getMIMEType() { + if (MIMEType != null) { + return MIMEType; + } + return FileTypeResolver.getMIMEType(filename); + } + + /** + * Sets the mime type of the resource. + * + * @param MIMEType + * the MIME type to be set. + */ + public void setMIMEType(String MIMEType) { + this.MIMEType = MIMEType; + } + + /** + * Returns the source for this StreamResource. StreamSource + * is queried when the resource is about to be streamed to the client. + * + * @return Source of the StreamResource. + */ + public StreamSource getStreamSource() { + return streamSource; + } + + /** + * Sets the source for this StreamResource. + * StreamSource is queried when the resource is about to be + * streamed to the client. + * + * @param streamSource + * the source to set. + */ + public void setStreamSource(StreamSource streamSource) { + this.streamSource = streamSource; + } + + /** + * Gets the filename. + * + * @return the filename. + */ + public String getFilename() { + return filename; + } + + /** + * Sets the filename. + * + * @param filename + * the filename to set. + */ + public void setFilename(String filename) { + this.filename = filename; + } + + /** + * @see com.itmill.toolkit.terminal.ApplicationResource#getApplication() + */ + public Application getApplication() { + return application; + } + + /** + * @see com.itmill.toolkit.terminal.ApplicationResource#getStream() + */ + public DownloadStream getStream() { + StreamSource ss = getStreamSource(); + if (ss == null) { + return null; + } + DownloadStream ds = new DownloadStream(ss.getStream(), getMIMEType(), + getFilename()); + ds.setBufferSize(getBufferSize()); + ds.setCacheTime(cacheTime); + return ds; + } + + /** + * Interface implemented by the source of a StreamResource. + * + * @author IT Mill Ltd. + * @version + * @VERSION@ + * @since 3.0 + */ + public interface StreamSource { + + /** + * Returns new input stream that is used for reading the resource. + */ + public InputStream getStream(); + } + + /* documented in superclass */ + public int getBufferSize() { + return bufferSize; + } + + /** + * Sets the size of the download buffer used for this resource. + * + * @param bufferSize + * the size of the buffer in bytes. + */ + public void setBufferSize(int bufferSize) { + this.bufferSize = bufferSize; + } + + /* documented in superclass */ + public long getCacheTime() { + return cacheTime; + } + + /** + * Sets the length of cache expiration time. + * + *

+ * This gives the adapter the possibility cache streams sent to the client. + * The caching may be made in adapter or at the client if the client + * supports caching. Zero or negavive value disbales the caching of this + * stream. + *

+ * + * @param cacheTime + * the cache time in milliseconds. + * + */ + public void setCacheTime(long cacheTime) { + this.cacheTime = cacheTime; + } } diff --git a/src/com/itmill/toolkit/terminal/SystemError.java b/src/com/itmill/toolkit/terminal/SystemError.java index 90c045c18c..0fbace4337 100644 --- a/src/com/itmill/toolkit/terminal/SystemError.java +++ b/src/com/itmill/toolkit/terminal/SystemError.java @@ -44,107 +44,107 @@ import java.io.StringWriter; */ public class SystemError extends RuntimeException implements ErrorMessage { - /** - * Serial generated by eclipse. - */ - private static final long serialVersionUID = 3256445789512675891L; - - /** - * The cause of the system error. The cause is stored separately as JDK 1.3 - * does not support causes natively. - */ - private Throwable cause = null; - - /** - * Constructor for SystemError with error message specified. - * - * @param message - * the Textual error description. - */ - public SystemError(String message) { - super(message); - } - - /** - * Constructor for SystemError with causing exception and error message. - * - * @param message - * the Textual error description. - * @param cause - * the throwable causing the system error. - */ - public SystemError(String message, Throwable cause) { - super(message); - this.cause = cause; - } - - /** - * Constructor for SystemError with cause. - * - * @param cause - * the throwable causing the system error. - */ - public SystemError(Throwable cause) { - this.cause = cause; - } - - /** - * @see com.itmill.toolkit.terminal.ErrorMessage#getErrorLevel() - */ - public final int getErrorLevel() { - return ErrorMessage.SYSTEMERROR; - } - - /** - * @see com.itmill.toolkit.terminal.Paintable#paint(com.itmill.toolkit.terminal.PaintTarget) - */ - public void paint(PaintTarget target) throws PaintException { - - target.startTag("error"); - target.addAttribute("level", "system"); - - // Paint the error message - String message = getLocalizedMessage(); - if (message != null) { - target.addSection("h2", message); - } - - // Paint the exception - if (cause != null) { - target.addSection("h3", "Exception"); - StringWriter buffer = new StringWriter(); - cause.printStackTrace(new PrintWriter(buffer)); - target.addSection("pre", buffer.toString()); - } - - target.endTag("error"); - - } - - /** - * Gets cause for the error. - * - * @return the cause. - * @see java.lang.Throwable#getCause() - */ - public Throwable getCause() { - return cause; - } - - /* Documented in super interface */ - public void addListener(RepaintRequestListener listener) { - } - - /* Documented in super interface */ - public void removeListener(RepaintRequestListener listener) { - } - - /* Documented in super interface */ - public void requestRepaint() { - } - - /* Documented in super interface */ - public void requestRepaintRequests() { - } + /** + * Serial generated by eclipse. + */ + private static final long serialVersionUID = 3256445789512675891L; + + /** + * The cause of the system error. The cause is stored separately as JDK 1.3 + * does not support causes natively. + */ + private Throwable cause = null; + + /** + * Constructor for SystemError with error message specified. + * + * @param message + * the Textual error description. + */ + public SystemError(String message) { + super(message); + } + + /** + * Constructor for SystemError with causing exception and error message. + * + * @param message + * the Textual error description. + * @param cause + * the throwable causing the system error. + */ + public SystemError(String message, Throwable cause) { + super(message); + this.cause = cause; + } + + /** + * Constructor for SystemError with cause. + * + * @param cause + * the throwable causing the system error. + */ + public SystemError(Throwable cause) { + this.cause = cause; + } + + /** + * @see com.itmill.toolkit.terminal.ErrorMessage#getErrorLevel() + */ + public final int getErrorLevel() { + return ErrorMessage.SYSTEMERROR; + } + + /** + * @see com.itmill.toolkit.terminal.Paintable#paint(com.itmill.toolkit.terminal.PaintTarget) + */ + public void paint(PaintTarget target) throws PaintException { + + target.startTag("error"); + target.addAttribute("level", "system"); + + // Paint the error message + String message = getLocalizedMessage(); + if (message != null) { + target.addSection("h2", message); + } + + // Paint the exception + if (cause != null) { + target.addSection("h3", "Exception"); + StringWriter buffer = new StringWriter(); + cause.printStackTrace(new PrintWriter(buffer)); + target.addSection("pre", buffer.toString()); + } + + target.endTag("error"); + + } + + /** + * Gets cause for the error. + * + * @return the cause. + * @see java.lang.Throwable#getCause() + */ + public Throwable getCause() { + return cause; + } + + /* Documented in super interface */ + public void addListener(RepaintRequestListener listener) { + } + + /* Documented in super interface */ + public void removeListener(RepaintRequestListener listener) { + } + + /* Documented in super interface */ + public void requestRepaint() { + } + + /* Documented in super interface */ + public void requestRepaintRequests() { + } } diff --git a/src/com/itmill/toolkit/terminal/Terminal.java b/src/com/itmill/toolkit/terminal/Terminal.java index e8054d2e88..a31e31c6db 100644 --- a/src/com/itmill/toolkit/terminal/Terminal.java +++ b/src/com/itmill/toolkit/terminal/Terminal.java @@ -38,50 +38,50 @@ package com.itmill.toolkit.terminal; */ public interface Terminal { - /** - * Gets the name of the default theme. - * - * @return the Name of the terminal window. - */ - public String getDefaultTheme(); + /** + * Gets the name of the default theme. + * + * @return the Name of the terminal window. + */ + public String getDefaultTheme(); - /** - * Gets the width of the terminal window in pixels. - * - * @return the Width of the terminal window. - */ - public int getScreenWidth(); + /** + * Gets the width of the terminal window in pixels. + * + * @return the Width of the terminal window. + */ + public int getScreenWidth(); - /** - * Gets the height of the terminal window in pixels. - * - * @return the Height of the terminal window. - */ - public int getScreenHeight(); + /** + * Gets the height of the terminal window in pixels. + * + * @return the Height of the terminal window. + */ + public int getScreenHeight(); - /** - * Terminal error event. - */ - public interface ErrorEvent { + /** + * Terminal error event. + */ + public interface ErrorEvent { - /** - * Gets the contained throwable. - */ - public Throwable getThrowable(); + /** + * Gets the contained throwable. + */ + public Throwable getThrowable(); - } + } - /** - * Terminal error listener interface. - */ - public interface ErrorListener { + /** + * Terminal error listener interface. + */ + public interface ErrorListener { - /** - * Invoked when terminal error occurs. - * - * @param event - * the fired event. - */ - public void terminalError(Terminal.ErrorEvent event); - } + /** + * Invoked when terminal error occurs. + * + * @param event + * the fired event. + */ + public void terminalError(Terminal.ErrorEvent event); + } } diff --git a/src/com/itmill/toolkit/terminal/ThemeResource.java b/src/com/itmill/toolkit/terminal/ThemeResource.java index 566e5b71ab..c8f80ba56a 100644 --- a/src/com/itmill/toolkit/terminal/ThemeResource.java +++ b/src/com/itmill/toolkit/terminal/ThemeResource.java @@ -43,70 +43,73 @@ import com.itmill.toolkit.service.FileTypeResolver; */ public class ThemeResource implements Resource { - /** - * Id of the terminal managed resource. - */ - private String resourceID = null; - - /** - * Creates a resource. - * - * @param resourceId - * the Id of the resource. - */ - public ThemeResource(String resourceId) { - if (resourceId == null) - throw new NullPointerException("Resource ID must not be null"); - if (resourceId.length() == 0) - throw new IllegalArgumentException("Resource ID can not be empty"); - if (resourceId.charAt(0) == '/') - throw new IllegalArgumentException( - "Resource ID must be relative (can not begin with /)"); - - this.resourceID = resourceId; - } - - /** - * Tests if the given object equals this Resource. - * - * @param obj - * the object to be tested for equality. - * @return true if the given object equals this Icon, - * false if not. - * @see java.lang.Object#equals(Object) - */ - public boolean equals(Object obj) { - return obj instanceof ThemeResource - && resourceID.equals(((ThemeResource) obj).resourceID); - } - - /** - * @see java.lang.Object#hashCode() - */ - public int hashCode() { - return resourceID.hashCode(); - } - - /** - * @see java.lang.Object#toString() - */ - public String toString() { - return resourceID.toString(); - } - - /** - * Gets the resource id. - * - * @return the resource id. - */ - public String getResourceId() { - return resourceID; - } - - /** - * @see com.itmill.toolkit.terminal.Resource#getMIMEType() - */ - public String getMIMEType() { - return FileTypeResolver.getMIMEType(getResourceId()); - } + /** + * Id of the terminal managed resource. + */ + private String resourceID = null; + + /** + * Creates a resource. + * + * @param resourceId + * the Id of the resource. + */ + public ThemeResource(String resourceId) { + if (resourceId == null) { + throw new NullPointerException("Resource ID must not be null"); + } + if (resourceId.length() == 0) { + throw new IllegalArgumentException("Resource ID can not be empty"); + } + if (resourceId.charAt(0) == '/') { + throw new IllegalArgumentException( + "Resource ID must be relative (can not begin with /)"); + } + + resourceID = resourceId; + } + + /** + * Tests if the given object equals this Resource. + * + * @param obj + * the object to be tested for equality. + * @return true if the given object equals this Icon, + * false if not. + * @see java.lang.Object#equals(Object) + */ + public boolean equals(Object obj) { + return obj instanceof ThemeResource + && resourceID.equals(((ThemeResource) obj).resourceID); + } + + /** + * @see java.lang.Object#hashCode() + */ + public int hashCode() { + return resourceID.hashCode(); + } + + /** + * @see java.lang.Object#toString() + */ + public String toString() { + return resourceID.toString(); + } + + /** + * Gets the resource id. + * + * @return the resource id. + */ + public String getResourceId() { + return resourceID; + } + + /** + * @see com.itmill.toolkit.terminal.Resource#getMIMEType() + */ + public String getMIMEType() { + return FileTypeResolver.getMIMEType(getResourceId()); + } } diff --git a/src/com/itmill/toolkit/terminal/URIHandler.java b/src/com/itmill/toolkit/terminal/URIHandler.java index 9883606c2a..5b4bf67d58 100644 --- a/src/com/itmill/toolkit/terminal/URIHandler.java +++ b/src/com/itmill/toolkit/terminal/URIHandler.java @@ -45,30 +45,30 @@ import java.net.URL; */ public interface URIHandler { - /** - * Handles a given relative URI. If the URI handling wants to emit a - * downloadable stream it can return download stream object. If no emitting - * stream is necessary, null should be returned instead. - * - * @param context - * the URl. - * @param relativeUri - * the relative uri. - * @return the download stream object. - */ - public DownloadStream handleURI(URL context, String relativeUri); + /** + * Handles a given relative URI. If the URI handling wants to emit a + * downloadable stream it can return download stream object. If no emitting + * stream is necessary, null should be returned instead. + * + * @param context + * the URl. + * @param relativeUri + * the relative uri. + * @return the download stream object. + */ + public DownloadStream handleURI(URL context, String relativeUri); - /** - * URIHandler error event. - */ - public interface ErrorEvent extends Terminal.ErrorEvent { + /** + * URIHandler error event. + */ + public interface ErrorEvent extends Terminal.ErrorEvent { - /** - * Gets the source URIHandler. - * - * @return the URIHandler. - */ - public URIHandler getURIHandler(); + /** + * Gets the source URIHandler. + * + * @return the URIHandler. + */ + public URIHandler getURIHandler(); - } + } } diff --git a/src/com/itmill/toolkit/terminal/UploadStream.java b/src/com/itmill/toolkit/terminal/UploadStream.java index 5a63ac4139..b0a9cf85c9 100644 --- a/src/com/itmill/toolkit/terminal/UploadStream.java +++ b/src/com/itmill/toolkit/terminal/UploadStream.java @@ -42,32 +42,32 @@ import java.io.InputStream; */ public interface UploadStream { - /** - * Gets the name of the stream. - * - * @return the name of the stream. - */ - public String getStreamName(); + /** + * Gets the name of the stream. + * + * @return the name of the stream. + */ + public String getStreamName(); - /** - * Gets the input stream. - * - * @return the Input stream. - */ - public InputStream getStream(); + /** + * Gets the input stream. + * + * @return the Input stream. + */ + public InputStream getStream(); - /** - * Gets the input stream content type. - * - * @return the content type of the input stream. - */ - public String getContentType(); + /** + * Gets the input stream content type. + * + * @return the content type of the input stream. + */ + public String getContentType(); - /** - * Gets stream content name. Stream content name usually differs from the - * actual stream name. It is used to identify the content of the stream. - * - * @return the Name of the stream content. - */ - public String getContentName(); + /** + * Gets stream content name. Stream content name usually differs from the + * actual stream name. It is used to identify the content of the stream. + * + * @return the Name of the stream content. + */ + public String getContentName(); } diff --git a/src/com/itmill/toolkit/terminal/UserError.java b/src/com/itmill/toolkit/terminal/UserError.java index 53b44fded8..6915f07378 100644 --- a/src/com/itmill/toolkit/terminal/UserError.java +++ b/src/com/itmill/toolkit/terminal/UserError.java @@ -39,127 +39,129 @@ package com.itmill.toolkit.terminal; */ public class UserError implements ErrorMessage { - /** - * Content mode, where the error contains only plain text. - */ - public static final int CONTENT_TEXT = 0; - - /** - * Content mode, where the error contains preformatted text. - */ - public static final int CONTENT_PREFORMATTED = 1; - - /** - * Formatted content mode, where the contents is XML restricted to the UIDL - * 1.0 formatting markups. - */ - public static final int CONTENT_UIDL = 2; - - /** - * Content mode. - */ - private int mode = CONTENT_TEXT; - - /** - * Message in content mode. - */ - private String msg; - - /** - * Error level. - */ - private int level = ErrorMessage.ERROR; - - /** - * Creates a textual error message of level ERROR. - * - * @param textErrorMessage - * the text of the error message. - */ - public UserError(String textErrorMessage) { - this.msg = textErrorMessage; - } - - /** - * Creates a error message with level and content mode. - * - * @param message - * the error message. - * @param contentMode - * the content Mode. - * @param errorLevel - * the level of error. - */ - public UserError(String message, int contentMode, int errorLevel) { - - // Check the parameters - if (contentMode < 0 || contentMode > 2) - throw new java.lang.IllegalArgumentException( - "Unsupported content mode: " + contentMode); - - this.msg = message; - this.mode = contentMode; - this.level = errorLevel; - } - - /* Documenten in interface */ - public int getErrorLevel() { - return level; - } - - /* Documenten in interface */ - public void addListener(RepaintRequestListener listener) { - } - - /* Documenten in interface */ - public void removeListener(RepaintRequestListener listener) { - } - - /* Documenten in interface */ - public void requestRepaint() { - } - - /* Documenten in interface */ - public void paint(PaintTarget target) throws PaintException { - - target.startTag("error"); - - // Error level - if (level >= ErrorMessage.SYSTEMERROR) - target.addAttribute("level", "system"); - else if (level >= ErrorMessage.CRITICAL) - target.addAttribute("level", "critical"); - else if (level >= ErrorMessage.ERROR) - target.addAttribute("level", "error"); - else if (level >= ErrorMessage.WARNING) - target.addAttribute("level", "warning"); - else - target.addAttribute("level", "info"); - - // Paint the message - switch (mode) { - case CONTENT_TEXT: - target.addText(msg); - break; - case CONTENT_UIDL: - target.addUIDL(msg); - break; - case CONTENT_PREFORMATTED: - target.startTag("pre"); - target.addText(msg); - target.endTag("pre"); - } - - target.endTag("error"); - } - - /* Documenten in interface */ - public void requestRepaintRequests() { - } - - /* Documented in superclass */ - public String toString() { - return msg; - } + /** + * Content mode, where the error contains only plain text. + */ + public static final int CONTENT_TEXT = 0; + + /** + * Content mode, where the error contains preformatted text. + */ + public static final int CONTENT_PREFORMATTED = 1; + + /** + * Formatted content mode, where the contents is XML restricted to the UIDL + * 1.0 formatting markups. + */ + public static final int CONTENT_UIDL = 2; + + /** + * Content mode. + */ + private int mode = CONTENT_TEXT; + + /** + * Message in content mode. + */ + private String msg; + + /** + * Error level. + */ + private int level = ErrorMessage.ERROR; + + /** + * Creates a textual error message of level ERROR. + * + * @param textErrorMessage + * the text of the error message. + */ + public UserError(String textErrorMessage) { + msg = textErrorMessage; + } + + /** + * Creates a error message with level and content mode. + * + * @param message + * the error message. + * @param contentMode + * the content Mode. + * @param errorLevel + * the level of error. + */ + public UserError(String message, int contentMode, int errorLevel) { + + // Check the parameters + if (contentMode < 0 || contentMode > 2) { + throw new java.lang.IllegalArgumentException( + "Unsupported content mode: " + contentMode); + } + + msg = message; + mode = contentMode; + level = errorLevel; + } + + /* Documenten in interface */ + public int getErrorLevel() { + return level; + } + + /* Documenten in interface */ + public void addListener(RepaintRequestListener listener) { + } + + /* Documenten in interface */ + public void removeListener(RepaintRequestListener listener) { + } + + /* Documenten in interface */ + public void requestRepaint() { + } + + /* Documenten in interface */ + public void paint(PaintTarget target) throws PaintException { + + target.startTag("error"); + + // Error level + if (level >= ErrorMessage.SYSTEMERROR) { + target.addAttribute("level", "system"); + } else if (level >= ErrorMessage.CRITICAL) { + target.addAttribute("level", "critical"); + } else if (level >= ErrorMessage.ERROR) { + target.addAttribute("level", "error"); + } else if (level >= ErrorMessage.WARNING) { + target.addAttribute("level", "warning"); + } else { + target.addAttribute("level", "info"); + } + + // Paint the message + switch (mode) { + case CONTENT_TEXT: + target.addText(msg); + break; + case CONTENT_UIDL: + target.addUIDL(msg); + break; + case CONTENT_PREFORMATTED: + target.startTag("pre"); + target.addText(msg); + target.endTag("pre"); + } + + target.endTag("error"); + } + + /* Documenten in interface */ + public void requestRepaintRequests() { + } + + /* Documented in superclass */ + public String toString() { + return msg; + } } diff --git a/src/com/itmill/toolkit/terminal/VariableOwner.java b/src/com/itmill/toolkit/terminal/VariableOwner.java index b730125d34..93bdb7d780 100644 --- a/src/com/itmill/toolkit/terminal/VariableOwner.java +++ b/src/com/itmill/toolkit/terminal/VariableOwner.java @@ -61,90 +61,93 @@ import java.util.Set; */ public interface VariableOwner { - /** - * Dependencies are not needed anymore as HTML-mode is deprecated in Toolkit 5. - * * - * @return Set of VariableOwners this component directly - * depend on, null if this component does not depend - * on anybody. - * @deprecated - */ - public Set getDirectDependencies(); - - /** - * Called when one or more variables handled by the implementing class are - * changed. - * - * @param source - * the Source of the variable change. This is the origin of the - * event. For example in Web Adapter this is the request. - * @param variables - * the Mapping from variable names to new variable values. - */ - public void changeVariables(Object source, Map variables); - - /** - * Dependencies are not needed anymore as HTML-mode is deprecated in Toolkit 5. - * - * @param depended - * the VariableOwner component who this component - * depends on. - * @deprecated - */ - public void dependsOn(VariableOwner depended); - - /** - * Dependencies are not needed anymore as HTML-mode is deprecated in Toolkit 5. - * - * @param depended - * the component to be removed from this component's dependency - * list. - * @deprecated - */ - public void removeDirectDependency(VariableOwner depended); - - /** - *

- * Tests if the variable owner is enabled or not. The terminal should not - * send any variable changes to disabled variable owners. - *

- * - * @return true if the variable owner is enabled, - * false if not - */ - public boolean isEnabled(); - - /** - *

- * Tests if the variable owner is in immediate mode or not. Being in - * immediate mode means that all variable changes are required to be sent - * back from the terminal immediately when they occur. - *

- * - *

- * Note: VariableOwner does not include a - * set- method for the immediateness property. This is because not all - * VariableOwners wish to offer the functionality. Such VariableOwners are - * never in the immediate mode, thus they always return false - * in {@link #isImmediate()}. - *

- * - * @return true if the component is in immediate mode, - * false if not. - */ - public boolean isImmediate(); - - /** - * VariableOwner error event. - */ - public interface ErrorEvent extends Terminal.ErrorEvent { - - /** - * Gets the source VariableOwner. - * - * @return the variable owner. - */ - public VariableOwner getVariableOwner(); - - } + /** + * Dependencies are not needed anymore as HTML-mode is deprecated in Toolkit + * 5. * + * + * @return Set of VariableOwners this component directly + * depend on, null if this component does not depend + * on anybody. + * @deprecated + */ + public Set getDirectDependencies(); + + /** + * Called when one or more variables handled by the implementing class are + * changed. + * + * @param source + * the Source of the variable change. This is the origin of + * the event. For example in Web Adapter this is the request. + * @param variables + * the Mapping from variable names to new variable values. + */ + public void changeVariables(Object source, Map variables); + + /** + * Dependencies are not needed anymore as HTML-mode is deprecated in Toolkit + * 5. + * + * @param depended + * the VariableOwner component who this + * component depends on. + * @deprecated + */ + public void dependsOn(VariableOwner depended); + + /** + * Dependencies are not needed anymore as HTML-mode is deprecated in Toolkit + * 5. + * + * @param depended + * the component to be removed from this component's + * dependency list. + * @deprecated + */ + public void removeDirectDependency(VariableOwner depended); + + /** + *

+ * Tests if the variable owner is enabled or not. The terminal should not + * send any variable changes to disabled variable owners. + *

+ * + * @return true if the variable owner is enabled, + * false if not + */ + public boolean isEnabled(); + + /** + *

+ * Tests if the variable owner is in immediate mode or not. Being in + * immediate mode means that all variable changes are required to be sent + * back from the terminal immediately when they occur. + *

+ * + *

+ * Note: VariableOwner does not include a + * set- method for the immediateness property. This is because not all + * VariableOwners wish to offer the functionality. Such VariableOwners are + * never in the immediate mode, thus they always return false + * in {@link #isImmediate()}. + *

+ * + * @return true if the component is in immediate mode, + * false if not. + */ + public boolean isImmediate(); + + /** + * VariableOwner error event. + */ + public interface ErrorEvent extends Terminal.ErrorEvent { + + /** + * Gets the source VariableOwner. + * + * @return the variable owner. + */ + public VariableOwner getVariableOwner(); + + } } diff --git a/src/com/itmill/toolkit/terminal/gwt/client/ApplicationConnection.java b/src/com/itmill/toolkit/terminal/gwt/client/ApplicationConnection.java index cce50f4888..035b62efa9 100755 --- a/src/com/itmill/toolkit/terminal/gwt/client/ApplicationConnection.java +++ b/src/com/itmill/toolkit/terminal/gwt/client/ApplicationConnection.java @@ -30,550 +30,552 @@ import com.itmill.toolkit.terminal.gwt.client.ui.IView; */ public class ApplicationConnection { - private String appUri; + private String appUri; - private HashMap resourcesMap = new HashMap(); + private HashMap resourcesMap = new HashMap(); - private static Console console; + private static Console console; - private Vector pendingVariables = new Vector(); - - private HashMap idToPaintable = new HashMap(); - - private HashMap paintableToId = new HashMap(); - - private final WidgetSet widgetSet; - - private ContextMenu contextMenu = null; - - private Timer loadTimer; - private Element loadElement; - - private IView view; - - public ApplicationConnection(WidgetSet widgetSet) { - this.widgetSet = widgetSet; - appUri = getAppUri(); - - if (isDebugMode()) { - console = new DebugConsole(this); - } else { - console = new NullConsole(); - } - - makeUidlRequest("repaintAll=1"); - - // TODO remove hardcoded id name - view = new IView("itmill-ajax-window"); - - } - - public static Console getConsole() { - return console; - } - - private native static boolean isDebugMode() - /*-{ - var uri = $wnd.location; - var re = /debug[^\/]*$/; - return re.test(uri); - }-*/; - - public native String getAppUri() - /*-{ - var u = $wnd.itmill.appUri; - if (u.indexOf("/") != 0 && u.indexOf("http") != 0) { - var b = $wnd.location.href; - var i = b.length-1; - while (b.charAt(i) != "/" && i>0) i--; - b = b.substring(0,i+1); - u = b + u; - } - return u; - }-*/; - - private native String getPathInfo() - /*-{ - return $wnd.itmill.pathInfo; - }-*/; - - private native String getThemeUri() - /*-{ - return $wnd.itmill.themeUri; - }-*/; - - private void makeUidlRequest(String requestData) { - - // place loading indicator - showLoadingIndicator(); - - console.log("Making UIDL Request with params: " + requestData); - String uri = appUri + "/UIDL" + getPathInfo(); - RequestBuilder rb = new RequestBuilder(RequestBuilder.POST, uri); - rb.setHeader("Content-Type", - "application/x-www-form-urlencoded; charset=utf-8"); - try { - rb.sendRequest(requestData, new RequestCallback() { - public void onError(Request request, Throwable exception) { - // TODO Better reporting to user - console.error("Got error"); - } - - public void onResponseReceived(Request request, - Response response) { - handleReceivedJSONMessage(response); - } - - }); - - } catch (RequestException e) { - // TODO Better reporting to user - console.error(e.getMessage()); - } - } - - private void showLoadingIndicator() { - loadTimer = new Timer() { - public void run() { - // show initial throbber - if (loadElement == null) { - loadElement = DOM.createDiv(); - DOM.setStyleAttribute(loadElement, "position", "absolute"); - DOM.appendChild(view.getElement(), loadElement); - } - DOM.setElementProperty(loadElement, "className", - "i-loading-indicator"); - DOM.setStyleAttribute(loadElement, "display", "block"); - // Position - DOM.setStyleAttribute(loadElement, "top", (view - .getAbsoluteTop() + 6) - + "px"); - DOM.setStyleAttribute(loadElement, "left", - (view.getAbsoluteLeft() - + view.getOffsetWidth() - - DOM.getElementPropertyInt(loadElement, - "offsetWidth") - 5) - + "px"); - - // Initialize other timers - Timer delay = new Timer() { - public void run() { - DOM.setElementProperty(loadElement, "className", - "i-loading-indicator-delay"); - } - }; - // Second one kicks in at 1500ms - delay.schedule(1200); - - Timer wait = new Timer() { - public void run() { - DOM.setElementProperty(loadElement, "className", - "i-loading-indicator-wait"); - } - }; - // Third one kicks in at 5000ms - wait.schedule(4700); - } - }; - // First one kicks in at 300ms - loadTimer.schedule(300); - } - - private void hideLoadingIndicator() { - if (loadTimer != null) - loadTimer.cancel(); - if (loadElement != null) - DOM.setStyleAttribute(loadElement, "display", "none"); - } - - private void handleReceivedJSONMessage(Response response) { - hideLoadingIndicator(); - - Date start = new Date(); - String jsonText = response.getText().substring(3) + "}"; - JSONValue json; - try { - json = JSONParser.parse(jsonText); - } catch (com.google.gwt.json.client.JSONException e) { - console.log(e.getMessage() + " - Original JSON-text:"); - console.log(jsonText); - return; - } - // Handle redirect - JSONObject redirect = (JSONObject) ((JSONObject) json).get("redirect"); - if (redirect != null) { - JSONString url = (JSONString) redirect.get("url"); - if (url != null) { - console.log("redirecting to " + url.stringValue()); - redirect(url.stringValue()); - return; - } - } - - // Store resources - JSONObject resources = (JSONObject) ((JSONObject) json) - .get("resources"); - for (Iterator i = resources.keySet().iterator(); i.hasNext();) { - String key = (String) i.next(); - resourcesMap.put(key, ((JSONString) resources.get(key)) - .stringValue()); - } - - // Store locale data - if (((JSONObject) json).containsKey("locales")) { - JSONArray l = (JSONArray) ((JSONObject) json).get("locales"); - for (int i = 0; i < l.size(); i++) { - LocaleService.addLocale((JSONObject) l.get(i)); - } - } - - // Process changes - JSONArray changes = (JSONArray) ((JSONObject) json).get("changes"); - for (int i = 0; i < changes.size(); i++) { - try { - UIDL change = new UIDL((JSONArray) changes.get(i)); - try { - console.dirUIDL(change); - } catch (Exception e) { - console.log(e.getMessage()); - // TODO: dir doesn't work in any browser although it should - // work (works in hosted mode) - // it partially did at some part but now broken. - } - UIDL uidl = change.getChildUIDL(0); - Paintable paintable = getPaintable(uidl.getId()); - if (paintable != null) { - paintable.updateFromUIDL(uidl, this); - } else { - if (!uidl.getTag().equals("window")) { - System.out.println("Received update for " - + uidl.getTag() - + ", but there is no such paintable (" - + uidl.getId() + ") rendered."); - } else { - view.updateFromUIDL(uidl, this); - } - } - } catch (Throwable e) { - e.printStackTrace(); - } - } - - if (((JSONObject) json).containsKey("meta")) { - JSONObject meta = ((JSONObject) json).get("meta").isObject(); - if (meta.containsKey("focus")) { - String focusPid = meta.get("focus").isString().stringValue(); - Paintable toBeFocused = getPaintable(focusPid); - if (toBeFocused instanceof HasFocus) { - HasFocus toBeFocusedWidget = (HasFocus) toBeFocused; - toBeFocusedWidget.setFocus(true); - } - } - } - - long prosessingTime = (new Date().getTime()) - start.getTime(); - console.log(" Processing time was " + String.valueOf(prosessingTime) - + "ms for " + jsonText.length() + " characters of JSON"); - console.log("Referenced paintables: " + idToPaintable.size()); - - } - - // Redirect browser - private static native void redirect(String url) - /*-{ - $wnd.location = url; - }-*/; - - public void registerPaintable(String id, Paintable paintable) { - idToPaintable.put(id, paintable); - paintableToId.put(paintable, id); - } - - public void unregisterPaintable(Paintable p) { - idToPaintable.remove(paintableToId.get(p)); - paintableToId.remove(p); - - if (p instanceof HasWidgets) { - unregisterChildPaintables((HasWidgets) p); - } - } - - public void unregisterChildPaintables(HasWidgets container) { - Iterator it = container.iterator(); - while (it.hasNext()) { - Widget w = (Widget) it.next(); - if (w instanceof Paintable) { - unregisterPaintable((Paintable) w); - } - if (w instanceof HasWidgets) { - unregisterChildPaintables((HasWidgets) w); - } - } - } - - /** - * Returns Paintable element by its id - * - * @param id - * Paintable ID - */ - public Paintable getPaintable(String id) { - return (Paintable) idToPaintable.get(id); - } - - private void addVariableToQueue(String paintableId, String variableName, - String encodedValue, boolean immediate, char type) { - String id = paintableId + "_" + variableName + "_" + type; - for (int i = 0; i < pendingVariables.size(); i += 2) { - if ((pendingVariables.get(i)).equals(id)) { - pendingVariables.remove(i); - pendingVariables.remove(i); - break; - } - } - pendingVariables.add(id); - pendingVariables.add(encodedValue); - if (immediate) { - sendPendingVariableChanges(); - } - } - - public void sendPendingVariableChanges() { - StringBuffer req = new StringBuffer(); - - req.append("changes="); - for (int i = 0; i < pendingVariables.size(); i++) { - if (i > 0) { - req.append("\u0001"); - } - req.append(pendingVariables.get(i)); - } - - pendingVariables.clear(); - makeUidlRequest(req.toString()); - } - - private static native String escapeString(String value) - /*-{ - return encodeURIComponent(value); - }-*/; - - public void updateVariable(String paintableId, String variableName, - String newValue, boolean immediate) { - addVariableToQueue(paintableId, variableName, escapeString(newValue), - immediate, 's'); - } - - public void updateVariable(String paintableId, String variableName, - int newValue, boolean immediate) { - addVariableToQueue(paintableId, variableName, "" + newValue, immediate, - 'i'); - } - - public void updateVariable(String paintableId, String variableName, - long newValue, boolean immediate) { - addVariableToQueue(paintableId, variableName, "" + newValue, immediate, - 'l'); - } - - public void updateVariable(String paintableId, String variableName, - float newValue, boolean immediate) { - addVariableToQueue(paintableId, variableName, "" + newValue, immediate, - 'f'); - } - - public void updateVariable(String paintableId, String variableName, - double newValue, boolean immediate) { - addVariableToQueue(paintableId, variableName, "" + newValue, immediate, - 'd'); - } - - public void updateVariable(String paintableId, String variableName, - boolean newValue, boolean immediate) { - addVariableToQueue(paintableId, variableName, newValue ? "true" - : "false", immediate, 'b'); - } - - public void updateVariable(String paintableId, String variableName, - Object[] values, boolean immediate) { - StringBuffer buf = new StringBuffer(); - for (int i = 0; i < values.length; i++) { - if (i > 0) { - buf.append(","); - } - buf.append(escapeString(values[i].toString())); - } - addVariableToQueue(paintableId, variableName, buf.toString(), - immediate, 'a'); - } - - public static Container getParentLayout(Widget component) { - Widget parent = component.getParent(); - while (parent != null && !(parent instanceof Container)) { - parent = parent.getParent(); - } - if (parent != null && ((Container) parent).hasChildComponent(component)) { - return (Container) parent; - } - return null; - } - - /** - * Update generic component features. - * - *

Selecting correct implementation

- * - *

- * The implementation of a component depends on many properties, including - * styles, component features, etc. Sometimes the user changes those - * properties after the component has been created. Calling this method in - * the beginning of your updateFromUIDL -method automatically replaces your - * component with more appropriate if the requested implementation changes. - *

- * - *

Caption, icon, error messages and description

- * - *

- * Component can delegate management of caption, icon, error messages and - * description to parent layout. This is optional an should be decided by - * component author - *

- * - *

Component visibility and disabling

- * - * This method will manage component visibility automatically and if - * component is an instanceof FocusWidget, also handle component disabling - * when needed. - * - * @param currentWidget - * Current widget that might need replacement - * @param uidl - * UIDL to be painted - * @param manageCaption - * True if you want to delegate caption, icon, description and - * error message management to parent. - * - * @return Returns true iff no further painting is needed by caller - */ - public boolean updateComponent(Widget component, UIDL uidl, - boolean manageCaption) { - - // If the server request that a cached instance should be used, do - // nothing - if (uidl.getBooleanAttribute("cached")) { - return true; - } - - // Visibility - boolean visible = !uidl.getBooleanAttribute("invisible"); - component.setVisible(visible); - if (!visible) { - return true; - } - - // Switch to correct implementation if needed - if (!widgetSet.isCorrectImplementation(component, uidl)) { - Container parent = getParentLayout(component); - if (parent != null) { - Widget w = widgetSet.createWidget(uidl); - parent.replaceChildComponent(component, w); - registerPaintable(uidl.getId(), (Paintable) w); - ((Paintable) w).updateFromUIDL(uidl, this); - return true; - } - } - - // Set captions - // TODO Manage Error messages - if (manageCaption) { - Container parent = getParentLayout(component); - if (parent != null) { - parent.updateCaption((Paintable) component, uidl); - } - } - - // Styles + disabled & readonly - component.setStyleName(component.getStylePrimaryName()); - - // first disabling and read-only status - boolean enabled = true; - if (uidl.hasAttribute("disabled")) { - enabled = !uidl.getBooleanAttribute("disabled"); - } else if (uidl.hasAttribute("readonly")) { - enabled = !uidl.getBooleanAttribute("readonly"); - } - if (component instanceof FocusWidget) { - ((FocusWidget) component).setEnabled(enabled); - } - if (!enabled) { - component.addStyleName("i-disabled"); - } else { - component.removeStyleName("i-disabled"); - } - - // add additional styles as css classes, prefixed with component default - // stylename - if (uidl.hasAttribute("style")) { - String[] styles = uidl.getStringAttribute("style").split(" "); - for (int i = 0; i < styles.length; i++) { - component.addStyleDependentName(styles[i]); - } - } - - return false; - } - - /** - * Get either existing or new widget for given UIDL. - * - * If corresponding paintable has been previously painted, return it. - * Otherwise create and register a new widget from UIDL. Caller must update - * the returned widget from UIDL after it has been connected to parent. - * - * @param uidl - * UIDL to create widget from. - * @return Either existing or new widget corresponding to UIDL. - */ - public Widget getWidget(UIDL uidl) { - String id = uidl.getId(); - Widget w = (Widget) getPaintable(id); - if (w != null) { - return w; - } - w = widgetSet.createWidget(uidl); - registerPaintable(id, (Paintable) w); - return w; - } - - public String getResource(String name) { - return (String) resourcesMap.get(name); - } - - /** - * Singleton method to get instance of app's context menu. - * - * @return IContextMenu object - */ - public ContextMenu getContextMenu() { - if (contextMenu == null) { - contextMenu = new ContextMenu(); - } - return contextMenu; - } - - /** - * Translates custom protocols in UIRL URI's to be recognizable by browser. - * All uri's from UIDL should be routed via this method before giving them - * to browser due URI's in UIDL may contain custom protocols like theme://. - * - * @param toolkitUri - * toolkit URI from uidl - * @return translated URI ready for browser - */ - public String translateToolkitUri(String toolkitUri) { - if (toolkitUri.startsWith("theme")) { - toolkitUri = getThemeUri() + toolkitUri.substring(7); - } - return toolkitUri; - } + private Vector pendingVariables = new Vector(); + + private HashMap idToPaintable = new HashMap(); + + private HashMap paintableToId = new HashMap(); + + private final WidgetSet widgetSet; + + private ContextMenu contextMenu = null; + + private Timer loadTimer; + private Element loadElement; + + private IView view; + + public ApplicationConnection(WidgetSet widgetSet) { + this.widgetSet = widgetSet; + appUri = getAppUri(); + + if (isDebugMode()) { + console = new DebugConsole(this); + } else { + console = new NullConsole(); + } + + makeUidlRequest("repaintAll=1"); + + // TODO remove hardcoded id name + view = new IView("itmill-ajax-window"); + + } + + public static Console getConsole() { + return console; + } + + private native static boolean isDebugMode() + /*-{ + var uri = $wnd.location; + var re = /debug[^\/]*$/; + return re.test(uri); + }-*/; + + public native String getAppUri() + /*-{ + var u = $wnd.itmill.appUri; + if (u.indexOf("/") != 0 && u.indexOf("http") != 0) { + var b = $wnd.location.href; + var i = b.length-1; + while (b.charAt(i) != "/" && i>0) i--; + b = b.substring(0,i+1); + u = b + u; + } + return u; + }-*/; + + private native String getPathInfo() + /*-{ + return $wnd.itmill.pathInfo; + }-*/; + + private native String getThemeUri() + /*-{ + return $wnd.itmill.themeUri; + }-*/; + + private void makeUidlRequest(String requestData) { + + // place loading indicator + showLoadingIndicator(); + + console.log("Making UIDL Request with params: " + requestData); + String uri = appUri + "/UIDL" + getPathInfo(); + RequestBuilder rb = new RequestBuilder(RequestBuilder.POST, uri); + rb.setHeader("Content-Type", + "application/x-www-form-urlencoded; charset=utf-8"); + try { + rb.sendRequest(requestData, new RequestCallback() { + public void onError(Request request, Throwable exception) { + // TODO Better reporting to user + console.error("Got error"); + } + + public void onResponseReceived(Request request, + Response response) { + handleReceivedJSONMessage(response); + } + + }); + + } catch (RequestException e) { + // TODO Better reporting to user + console.error(e.getMessage()); + } + } + + private void showLoadingIndicator() { + loadTimer = new Timer() { + public void run() { + // show initial throbber + if (loadElement == null) { + loadElement = DOM.createDiv(); + DOM.setStyleAttribute(loadElement, "position", "absolute"); + DOM.appendChild(view.getElement(), loadElement); + } + DOM.setElementProperty(loadElement, "className", + "i-loading-indicator"); + DOM.setStyleAttribute(loadElement, "display", "block"); + // Position + DOM.setStyleAttribute(loadElement, "top", (view + .getAbsoluteTop() + 6) + + "px"); + DOM.setStyleAttribute(loadElement, "left", + (view.getAbsoluteLeft() + + view.getOffsetWidth() + - DOM.getElementPropertyInt(loadElement, + "offsetWidth") - 5) + + "px"); + + // Initialize other timers + Timer delay = new Timer() { + public void run() { + DOM.setElementProperty(loadElement, "className", + "i-loading-indicator-delay"); + } + }; + // Second one kicks in at 1500ms + delay.schedule(1200); + + Timer wait = new Timer() { + public void run() { + DOM.setElementProperty(loadElement, "className", + "i-loading-indicator-wait"); + } + }; + // Third one kicks in at 5000ms + wait.schedule(4700); + } + }; + // First one kicks in at 300ms + loadTimer.schedule(300); + } + + private void hideLoadingIndicator() { + if (loadTimer != null) { + loadTimer.cancel(); + } + if (loadElement != null) { + DOM.setStyleAttribute(loadElement, "display", "none"); + } + } + + private void handleReceivedJSONMessage(Response response) { + hideLoadingIndicator(); + + Date start = new Date(); + String jsonText = response.getText().substring(3) + "}"; + JSONValue json; + try { + json = JSONParser.parse(jsonText); + } catch (com.google.gwt.json.client.JSONException e) { + console.log(e.getMessage() + " - Original JSON-text:"); + console.log(jsonText); + return; + } + // Handle redirect + JSONObject redirect = (JSONObject) ((JSONObject) json).get("redirect"); + if (redirect != null) { + JSONString url = (JSONString) redirect.get("url"); + if (url != null) { + console.log("redirecting to " + url.stringValue()); + redirect(url.stringValue()); + return; + } + } + + // Store resources + JSONObject resources = (JSONObject) ((JSONObject) json) + .get("resources"); + for (Iterator i = resources.keySet().iterator(); i.hasNext();) { + String key = (String) i.next(); + resourcesMap.put(key, ((JSONString) resources.get(key)) + .stringValue()); + } + + // Store locale data + if (((JSONObject) json).containsKey("locales")) { + JSONArray l = (JSONArray) ((JSONObject) json).get("locales"); + for (int i = 0; i < l.size(); i++) { + LocaleService.addLocale((JSONObject) l.get(i)); + } + } + + // Process changes + JSONArray changes = (JSONArray) ((JSONObject) json).get("changes"); + for (int i = 0; i < changes.size(); i++) { + try { + UIDL change = new UIDL((JSONArray) changes.get(i)); + try { + console.dirUIDL(change); + } catch (Exception e) { + console.log(e.getMessage()); + // TODO: dir doesn't work in any browser although it should + // work (works in hosted mode) + // it partially did at some part but now broken. + } + UIDL uidl = change.getChildUIDL(0); + Paintable paintable = getPaintable(uidl.getId()); + if (paintable != null) { + paintable.updateFromUIDL(uidl, this); + } else { + if (!uidl.getTag().equals("window")) { + System.out.println("Received update for " + + uidl.getTag() + + ", but there is no such paintable (" + + uidl.getId() + ") rendered."); + } else { + view.updateFromUIDL(uidl, this); + } + } + } catch (Throwable e) { + e.printStackTrace(); + } + } + + if (((JSONObject) json).containsKey("meta")) { + JSONObject meta = ((JSONObject) json).get("meta").isObject(); + if (meta.containsKey("focus")) { + String focusPid = meta.get("focus").isString().stringValue(); + Paintable toBeFocused = getPaintable(focusPid); + if (toBeFocused instanceof HasFocus) { + HasFocus toBeFocusedWidget = (HasFocus) toBeFocused; + toBeFocusedWidget.setFocus(true); + } + } + } + + long prosessingTime = (new Date().getTime()) - start.getTime(); + console.log(" Processing time was " + String.valueOf(prosessingTime) + + "ms for " + jsonText.length() + " characters of JSON"); + console.log("Referenced paintables: " + idToPaintable.size()); + + } + + // Redirect browser + private static native void redirect(String url) + /*-{ + $wnd.location = url; + }-*/; + + public void registerPaintable(String id, Paintable paintable) { + idToPaintable.put(id, paintable); + paintableToId.put(paintable, id); + } + + public void unregisterPaintable(Paintable p) { + idToPaintable.remove(paintableToId.get(p)); + paintableToId.remove(p); + + if (p instanceof HasWidgets) { + unregisterChildPaintables((HasWidgets) p); + } + } + + public void unregisterChildPaintables(HasWidgets container) { + Iterator it = container.iterator(); + while (it.hasNext()) { + Widget w = (Widget) it.next(); + if (w instanceof Paintable) { + unregisterPaintable((Paintable) w); + } + if (w instanceof HasWidgets) { + unregisterChildPaintables((HasWidgets) w); + } + } + } + + /** + * Returns Paintable element by its id + * + * @param id + * Paintable ID + */ + public Paintable getPaintable(String id) { + return (Paintable) idToPaintable.get(id); + } + + private void addVariableToQueue(String paintableId, String variableName, + String encodedValue, boolean immediate, char type) { + String id = paintableId + "_" + variableName + "_" + type; + for (int i = 0; i < pendingVariables.size(); i += 2) { + if ((pendingVariables.get(i)).equals(id)) { + pendingVariables.remove(i); + pendingVariables.remove(i); + break; + } + } + pendingVariables.add(id); + pendingVariables.add(encodedValue); + if (immediate) { + sendPendingVariableChanges(); + } + } + + public void sendPendingVariableChanges() { + StringBuffer req = new StringBuffer(); + + req.append("changes="); + for (int i = 0; i < pendingVariables.size(); i++) { + if (i > 0) { + req.append("\u0001"); + } + req.append(pendingVariables.get(i)); + } + + pendingVariables.clear(); + makeUidlRequest(req.toString()); + } + + private static native String escapeString(String value) + /*-{ + return encodeURIComponent(value); + }-*/; + + public void updateVariable(String paintableId, String variableName, + String newValue, boolean immediate) { + addVariableToQueue(paintableId, variableName, escapeString(newValue), + immediate, 's'); + } + + public void updateVariable(String paintableId, String variableName, + int newValue, boolean immediate) { + addVariableToQueue(paintableId, variableName, "" + newValue, immediate, + 'i'); + } + + public void updateVariable(String paintableId, String variableName, + long newValue, boolean immediate) { + addVariableToQueue(paintableId, variableName, "" + newValue, immediate, + 'l'); + } + + public void updateVariable(String paintableId, String variableName, + float newValue, boolean immediate) { + addVariableToQueue(paintableId, variableName, "" + newValue, immediate, + 'f'); + } + + public void updateVariable(String paintableId, String variableName, + double newValue, boolean immediate) { + addVariableToQueue(paintableId, variableName, "" + newValue, immediate, + 'd'); + } + + public void updateVariable(String paintableId, String variableName, + boolean newValue, boolean immediate) { + addVariableToQueue(paintableId, variableName, newValue ? "true" + : "false", immediate, 'b'); + } + + public void updateVariable(String paintableId, String variableName, + Object[] values, boolean immediate) { + StringBuffer buf = new StringBuffer(); + for (int i = 0; i < values.length; i++) { + if (i > 0) { + buf.append(","); + } + buf.append(escapeString(values[i].toString())); + } + addVariableToQueue(paintableId, variableName, buf.toString(), + immediate, 'a'); + } + + public static Container getParentLayout(Widget component) { + Widget parent = component.getParent(); + while (parent != null && !(parent instanceof Container)) { + parent = parent.getParent(); + } + if (parent != null && ((Container) parent).hasChildComponent(component)) { + return (Container) parent; + } + return null; + } + + /** + * Update generic component features. + * + *

Selecting correct implementation

+ * + *

+ * The implementation of a component depends on many properties, including + * styles, component features, etc. Sometimes the user changes those + * properties after the component has been created. Calling this method in + * the beginning of your updateFromUIDL -method automatically replaces your + * component with more appropriate if the requested implementation changes. + *

+ * + *

Caption, icon, error messages and description

+ * + *

+ * Component can delegate management of caption, icon, error messages and + * description to parent layout. This is optional an should be decided by + * component author + *

+ * + *

Component visibility and disabling

+ * + * This method will manage component visibility automatically and if + * component is an instanceof FocusWidget, also handle component disabling + * when needed. + * + * @param currentWidget + * Current widget that might need replacement + * @param uidl + * UIDL to be painted + * @param manageCaption + * True if you want to delegate caption, icon, description + * and error message management to parent. + * + * @return Returns true iff no further painting is needed by caller + */ + public boolean updateComponent(Widget component, UIDL uidl, + boolean manageCaption) { + + // If the server request that a cached instance should be used, do + // nothing + if (uidl.getBooleanAttribute("cached")) { + return true; + } + + // Visibility + boolean visible = !uidl.getBooleanAttribute("invisible"); + component.setVisible(visible); + if (!visible) { + return true; + } + + // Switch to correct implementation if needed + if (!widgetSet.isCorrectImplementation(component, uidl)) { + Container parent = getParentLayout(component); + if (parent != null) { + Widget w = widgetSet.createWidget(uidl); + parent.replaceChildComponent(component, w); + registerPaintable(uidl.getId(), (Paintable) w); + ((Paintable) w).updateFromUIDL(uidl, this); + return true; + } + } + + // Set captions + // TODO Manage Error messages + if (manageCaption) { + Container parent = getParentLayout(component); + if (parent != null) { + parent.updateCaption((Paintable) component, uidl); + } + } + + // Styles + disabled & readonly + component.setStyleName(component.getStylePrimaryName()); + + // first disabling and read-only status + boolean enabled = true; + if (uidl.hasAttribute("disabled")) { + enabled = !uidl.getBooleanAttribute("disabled"); + } else if (uidl.hasAttribute("readonly")) { + enabled = !uidl.getBooleanAttribute("readonly"); + } + if (component instanceof FocusWidget) { + ((FocusWidget) component).setEnabled(enabled); + } + if (!enabled) { + component.addStyleName("i-disabled"); + } else { + component.removeStyleName("i-disabled"); + } + + // add additional styles as css classes, prefixed with component default + // stylename + if (uidl.hasAttribute("style")) { + String[] styles = uidl.getStringAttribute("style").split(" "); + for (int i = 0; i < styles.length; i++) { + component.addStyleDependentName(styles[i]); + } + } + + return false; + } + + /** + * Get either existing or new widget for given UIDL. + * + * If corresponding paintable has been previously painted, return it. + * Otherwise create and register a new widget from UIDL. Caller must update + * the returned widget from UIDL after it has been connected to parent. + * + * @param uidl + * UIDL to create widget from. + * @return Either existing or new widget corresponding to UIDL. + */ + public Widget getWidget(UIDL uidl) { + String id = uidl.getId(); + Widget w = (Widget) getPaintable(id); + if (w != null) { + return w; + } + w = widgetSet.createWidget(uidl); + registerPaintable(id, (Paintable) w); + return w; + } + + public String getResource(String name) { + return (String) resourcesMap.get(name); + } + + /** + * Singleton method to get instance of app's context menu. + * + * @return IContextMenu object + */ + public ContextMenu getContextMenu() { + if (contextMenu == null) { + contextMenu = new ContextMenu(); + } + return contextMenu; + } + + /** + * Translates custom protocols in UIRL URI's to be recognizable by browser. + * All uri's from UIDL should be routed via this method before giving them + * to browser due URI's in UIDL may contain custom protocols like theme://. + * + * @param toolkitUri + * toolkit URI from uidl + * @return translated URI ready for browser + */ + public String translateToolkitUri(String toolkitUri) { + if (toolkitUri.startsWith("theme")) { + toolkitUri = getThemeUri() + toolkitUri.substring(7); + } + return toolkitUri; + } } diff --git a/src/com/itmill/toolkit/terminal/gwt/client/Console.java b/src/com/itmill/toolkit/terminal/gwt/client/Console.java index 048e6aa925..37c911032d 100644 --- a/src/com/itmill/toolkit/terminal/gwt/client/Console.java +++ b/src/com/itmill/toolkit/terminal/gwt/client/Console.java @@ -2,12 +2,12 @@ package com.itmill.toolkit.terminal.gwt.client; public interface Console { - public abstract void log(String msg); + public abstract void log(String msg); - public abstract void error(String msg); + public abstract void error(String msg); - public abstract void printObject(Object msg); + public abstract void printObject(Object msg); - public abstract void dirUIDL(UIDL u); + public abstract void dirUIDL(UIDL u); } \ No newline at end of file diff --git a/src/com/itmill/toolkit/terminal/gwt/client/Container.java b/src/com/itmill/toolkit/terminal/gwt/client/Container.java index 174e44f516..5e0fe8df31 100644 --- a/src/com/itmill/toolkit/terminal/gwt/client/Container.java +++ b/src/com/itmill/toolkit/terminal/gwt/client/Container.java @@ -4,45 +4,45 @@ import com.google.gwt.user.client.ui.Widget; public interface Container extends Paintable { - /** - * Replace child of this layout with another component. - * - * Each layout must be able to switch children. To to this, one must just - * give references to a current and new child. Note that the Layout is not - * responsible for registering Paintable into ApplicationConnection, but it - * is responsible is for unregistering it. - * - * @param oldComponent - * Child to be replaced - * @param newComponent - * Child that replaces the oldComponent - */ - void replaceChildComponent(Widget oldComponent, Widget newComponent); + /** + * Replace child of this layout with another component. + * + * Each layout must be able to switch children. To to this, one must just + * give references to a current and new child. Note that the Layout is not + * responsible for registering Paintable into ApplicationConnection, but it + * is responsible is for unregistering it. + * + * @param oldComponent + * Child to be replaced + * @param newComponent + * Child that replaces the oldComponent + */ + void replaceChildComponent(Widget oldComponent, Widget newComponent); - /** - * Is a given component child of this layout. - * - * @param component - * Component to test. - * @return true iff component is a child of this layout. - */ - boolean hasChildComponent(Widget component); + /** + * Is a given component child of this layout. + * + * @param component + * Component to test. + * @return true iff component is a child of this layout. + */ + boolean hasChildComponent(Widget component); - /** - * Update child components caption, description and error message. - * - *

- * Each component is responsible for maintaining its caption, description - * and error message. In most cases components doesn't want to do that and - * those elements reside outside of the component. Because of this layouts - * must provide service for it's childen to show those elements for them. - *

- * - * @param component - * Child component for which service is requested. - * @param uidl - * UIDL of the child component. - */ - void updateCaption(Paintable component, UIDL uidl); + /** + * Update child components caption, description and error message. + * + *

+ * Each component is responsible for maintaining its caption, description + * and error message. In most cases components doesn't want to do that and + * those elements reside outside of the component. Because of this layouts + * must provide service for it's childen to show those elements for them. + *

+ * + * @param component + * Child component for which service is requested. + * @param uidl + * UIDL of the child component. + */ + void updateCaption(Paintable component, UIDL uidl); } diff --git a/src/com/itmill/toolkit/terminal/gwt/client/ContainerResizedListener.java b/src/com/itmill/toolkit/terminal/gwt/client/ContainerResizedListener.java index 7248b1d921..22d92355d1 100644 --- a/src/com/itmill/toolkit/terminal/gwt/client/ContainerResizedListener.java +++ b/src/com/itmill/toolkit/terminal/gwt/client/ContainerResizedListener.java @@ -5,12 +5,12 @@ package com.itmill.toolkit.terminal.gwt.client; * relative sizes and who need some additional sizing logic. */ public interface ContainerResizedListener { - /** - * This function is run when container box has been resized. Object - * implementing ContainerResizedListener is responsible to call the same - * function on its ancestors that implement NeedsLayout in case their - * container has resized. runAnchestorsLayout(HasWidgets parent) function - * from Util class may be a good helper for this. - */ - public void iLayout(); + /** + * This function is run when container box has been resized. Object + * implementing ContainerResizedListener is responsible to call the same + * function on its ancestors that implement NeedsLayout in case their + * container has resized. runAnchestorsLayout(HasWidgets parent) function + * from Util class may be a good helper for this. + */ + public void iLayout(); } diff --git a/src/com/itmill/toolkit/terminal/gwt/client/DateLocale.java b/src/com/itmill/toolkit/terminal/gwt/client/DateLocale.java index fec5417a01..7cc4ace944 100644 --- a/src/com/itmill/toolkit/terminal/gwt/client/DateLocale.java +++ b/src/com/itmill/toolkit/terminal/gwt/client/DateLocale.java @@ -1,64 +1,65 @@ package com.itmill.toolkit.terminal.gwt.client; public class DateLocale extends - com.itmill.toolkit.terminal.gwt.client.util.DateLocale { + com.itmill.toolkit.terminal.gwt.client.util.DateLocale { - private static String locale; + private static String locale; - public DateLocale() { - locale = LocaleService.getDefaultLocale(); - } + public DateLocale() { + locale = LocaleService.getDefaultLocale(); + } - public static void setLocale(String l) { - if (LocaleService.getAvailableLocales().contains(locale)) - locale = l; - else - // TODO redirect to console - System.out.println("Tried to use an unloaded locale \"" + locale - + "\". Using default in stead (" + locale + ")"); - } + public static void setLocale(String l) { + if (LocaleService.getAvailableLocales().contains(locale)) { + locale = l; + } else { + // TODO redirect to console + System.out.println("Tried to use an unloaded locale \"" + locale + + "\". Using default in stead (" + locale + ")"); + } + } - public static String getAM() { - try { - return LocaleService.getAmPmStrings(locale)[0]; - } catch (LocaleNotLoadedException e) { - // TODO redirect to console - System.out.println("Tried to use an unloaded locale \"" + locale - + "\"."); - return "AM"; - } - } + public static String getAM() { + try { + return LocaleService.getAmPmStrings(locale)[0]; + } catch (LocaleNotLoadedException e) { + // TODO redirect to console + System.out.println("Tried to use an unloaded locale \"" + locale + + "\"."); + return "AM"; + } + } - public static String getPM() { - try { - return LocaleService.getAmPmStrings(locale)[1]; - } catch (LocaleNotLoadedException e) { - // TODO redirect to console - System.out.println("Tried to use an unloaded locale \"" + locale - + "\"."); - return "PM"; - } - } + public static String getPM() { + try { + return LocaleService.getAmPmStrings(locale)[1]; + } catch (LocaleNotLoadedException e) { + // TODO redirect to console + System.out.println("Tried to use an unloaded locale \"" + locale + + "\"."); + return "PM"; + } + } - public String[] getWEEKDAY_LONG() { - try { - return LocaleService.getDayNames(locale); - } catch (LocaleNotLoadedException e) { - // TODO redirect to console - System.out.println("Tried to use an unloaded locale \"" + locale - + "\"."); - return null; - } - } + public String[] getWEEKDAY_LONG() { + try { + return LocaleService.getDayNames(locale); + } catch (LocaleNotLoadedException e) { + // TODO redirect to console + System.out.println("Tried to use an unloaded locale \"" + locale + + "\"."); + return null; + } + } - public String[] getWEEKDAY_SHORT() { - try { - return LocaleService.getShortDayNames(locale); - } catch (LocaleNotLoadedException e) { - // TODO redirect to console - System.out.println("Tried to use an unloaded locale \"" + locale - + "\"."); - return null; - } - } + public String[] getWEEKDAY_SHORT() { + try { + return LocaleService.getShortDayNames(locale); + } catch (LocaleNotLoadedException e) { + // TODO redirect to console + System.out.println("Tried to use an unloaded locale \"" + locale + + "\"."); + return null; + } + } } diff --git a/src/com/itmill/toolkit/terminal/gwt/client/DateTimeService.java b/src/com/itmill/toolkit/terminal/gwt/client/DateTimeService.java index 9d4b28a555..02d77730f9 100644 --- a/src/com/itmill/toolkit/terminal/gwt/client/DateTimeService.java +++ b/src/com/itmill/toolkit/terminal/gwt/client/DateTimeService.java @@ -2,8 +2,6 @@ package com.itmill.toolkit.terminal.gwt.client; import java.util.Date; -import com.itmill.toolkit.terminal.gwt.client.ui.IDateField; - /** * This class provides date/time parsing services to all components on the * client side. @@ -12,239 +10,242 @@ import com.itmill.toolkit.terminal.gwt.client.ui.IDateField; * */ public class DateTimeService { - public static int RESOLUTION_YEAR = 0; - public static int RESOLUTION_MONTH = 1; - public static int RESOLUTION_DAY = 2; - public static int RESOLUTION_HOUR = 3; - public static int RESOLUTION_MIN = 4; - public static int RESOLUTION_SEC = 5; - public static int RESOLUTION_MSEC = 6; - - private String currentLocale; - - private static int[] maxDaysInMonth = { 31, 28, 31, 30, 31, 30, 31, 31, 30, - 31, 30, 31 }; - - /** - * Creates a new date time service with the application default locale. - */ - public DateTimeService() { - currentLocale = LocaleService.getDefaultLocale(); - } - - /** - * Creates a new date time service with a given locale. - * - * @param locale - * e.g. fi, en etc. - * @throws LocaleNotLoadedException - */ - public DateTimeService(String locale) throws LocaleNotLoadedException { - setLocale(locale); - } - - public void setLocale(String locale) throws LocaleNotLoadedException { - if (LocaleService.getAvailableLocales().contains(locale)) - currentLocale = locale; - else - throw new LocaleNotLoadedException(locale); - } - - public String getLocale() { - return currentLocale; - } - - public String getMonth(int month) { - try { - return LocaleService.getMonthNames(currentLocale)[month]; - } catch (LocaleNotLoadedException e) { - // TODO redirect to console - System.out.println(e + ":" + e.getMessage()); - } - return null; - } - - public String getShortMonth(int month) { - try { - return LocaleService.getShortMonthNames(currentLocale)[month]; - } catch (LocaleNotLoadedException e) { - // TODO redirect to console - System.out.println(e + ":" + e.getMessage()); - } - return null; - } - - public String getDay(int day) { - try { - return LocaleService.getDayNames(currentLocale)[day]; - } catch (LocaleNotLoadedException e) { - // TODO redirect to console - System.out.println(e + ":" + e.getMessage()); - } - return null; - } - - public String getShortDay(int day) { - try { - return LocaleService.getShortDayNames(currentLocale)[day]; - } catch (LocaleNotLoadedException e) { - // TODO redirect to console - System.out.println(e + ":" + e.getMessage()); - } - return null; - } - - public int getFirstDayOfWeek() { - try { - return LocaleService.getFirstDayOfWeek(currentLocale); - } catch (LocaleNotLoadedException e) { - // TODO redirect to console - System.out.println(e + ":" + e.getMessage()); - } - return 0; - } - - public boolean isTwelveHourClock() { - try { - return LocaleService.isTwelveHourClock(currentLocale); - } catch (LocaleNotLoadedException e) { - // TODO redirect to console - System.out.println(e + ":" + e.getMessage()); - } - return false; - } - - public String getClockDelimeter() { - try { - return LocaleService.getClockDelimiter(currentLocale); - } catch (LocaleNotLoadedException e) { - // TODO redirect to console - System.out.println(e + ":" + e.getMessage()); - } - return ":"; - } - - public String[] getAmPmStrings() { - try { - return LocaleService.getAmPmStrings(currentLocale); - } catch (LocaleNotLoadedException e) { - // TODO redirect to console - System.out.println(e + ":" + e.getMessage()); - } - String[] temp = new String[2]; - temp[0] = "AM"; - temp[1] = "PM"; - return temp; - } - - public int getStartWeekDay(Date date) { - Date dateForFirstOfThisMonth = new Date(date.getYear(), - date.getMonth(), 1); - int firstDay; - try { - firstDay = LocaleService.getFirstDayOfWeek(currentLocale); - } catch (LocaleNotLoadedException e) { - firstDay = 0; - // TODO redirect to console - System.out.println(e + ":" + e.getMessage()); - } - int start = dateForFirstOfThisMonth.getDay() - firstDay; - if (start < 0) - start = 6; - return start; - } - - public String getDateFormat() { - try { - return LocaleService.getDateFormat(currentLocale); - } catch (LocaleNotLoadedException e) { - // TODO redirect to console - System.out.println(e + ":" + e.getMessage()); - } - return "M/d/yy"; - } - - public static int getNumberOfDaysInMonth(Date date) { - int month = date.getMonth(); - if (month == 1 && true == isLeapYear(date)) - return 29; - return maxDaysInMonth[month]; - } - - public static boolean isLeapYear(Date date) { - // Instantiate the date for 1st March of that year - Date firstMarch = new Date(date.getYear(), 2, 1); - - // Go back 1 day - long firstMarchTime = firstMarch.getTime(); - long lastDayTimeFeb = firstMarchTime - (24 * 60 * 60 * 1000); // NUM_MILLISECS_A_DAY - - // Instantiate new Date with this time - Date febLastDay = new Date(lastDayTimeFeb); - - // Check for date in this new instance - return (29 == febLastDay.getDate()) ? true : false; - } - - public static boolean isSameDay(Date d1, Date d2) { - return (getDayInt(d1) == getDayInt(d2)); - } - - public static boolean isInRange(Date date, Date rangeStart, Date rangeEnd, - int resolution) { - Date s; - Date e; - if (rangeStart.after(rangeEnd)) { - s = rangeEnd; - e = rangeStart; - } else { - e = rangeEnd; - s = rangeStart; - } - long start = s.getYear() * 10000000000l; - long end = e.getYear() * 10000000000l; - long target = date.getYear() * 10000000000l; - - if (resolution == RESOLUTION_YEAR) { - return (start <= target && end >= target); - } - start += s.getMonth() * 100000000; - end += e.getMonth() * 100000000; - target += date.getMonth() * 100000000; - if (resolution == RESOLUTION_MONTH) { - return (start <= target && end >= target); - } - start += s.getDate() * 1000000; - end += e.getDate() * 1000000; - target += date.getDate() * 1000000; - if (resolution == RESOLUTION_DAY) { - return (start <= target && end >= target); - } - start += s.getHours() * 10000; - end += e.getHours() * 10000; - target += date.getHours() * 10000; - if (resolution == RESOLUTION_HOUR) { - return (start <= target && end >= target); - } - start += s.getMinutes() * 100; - end += e.getMinutes() * 100; - target += date.getMinutes() * 100; - if (resolution == RESOLUTION_MIN) { - return (start <= target && end >= target); - } - start += s.getSeconds(); - end += e.getSeconds(); - target += date.getSeconds(); - return (start <= target && end >= target); - - } - - private static int getDayInt(Date date) { - int y = date.getYear(); - int m = date.getMonth(); - int d = date.getDate(); - - return ((y + 1900) * 10000 + m * 100 + d) * 1000000000; - } + public static int RESOLUTION_YEAR = 0; + public static int RESOLUTION_MONTH = 1; + public static int RESOLUTION_DAY = 2; + public static int RESOLUTION_HOUR = 3; + public static int RESOLUTION_MIN = 4; + public static int RESOLUTION_SEC = 5; + public static int RESOLUTION_MSEC = 6; + + private String currentLocale; + + private static int[] maxDaysInMonth = { 31, 28, 31, 30, 31, 30, 31, 31, 30, + 31, 30, 31 }; + + /** + * Creates a new date time service with the application default locale. + */ + public DateTimeService() { + currentLocale = LocaleService.getDefaultLocale(); + } + + /** + * Creates a new date time service with a given locale. + * + * @param locale + * e.g. fi, en etc. + * @throws LocaleNotLoadedException + */ + public DateTimeService(String locale) throws LocaleNotLoadedException { + setLocale(locale); + } + + public void setLocale(String locale) throws LocaleNotLoadedException { + if (LocaleService.getAvailableLocales().contains(locale)) { + currentLocale = locale; + } else { + throw new LocaleNotLoadedException(locale); + } + } + + public String getLocale() { + return currentLocale; + } + + public String getMonth(int month) { + try { + return LocaleService.getMonthNames(currentLocale)[month]; + } catch (LocaleNotLoadedException e) { + // TODO redirect to console + System.out.println(e + ":" + e.getMessage()); + } + return null; + } + + public String getShortMonth(int month) { + try { + return LocaleService.getShortMonthNames(currentLocale)[month]; + } catch (LocaleNotLoadedException e) { + // TODO redirect to console + System.out.println(e + ":" + e.getMessage()); + } + return null; + } + + public String getDay(int day) { + try { + return LocaleService.getDayNames(currentLocale)[day]; + } catch (LocaleNotLoadedException e) { + // TODO redirect to console + System.out.println(e + ":" + e.getMessage()); + } + return null; + } + + public String getShortDay(int day) { + try { + return LocaleService.getShortDayNames(currentLocale)[day]; + } catch (LocaleNotLoadedException e) { + // TODO redirect to console + System.out.println(e + ":" + e.getMessage()); + } + return null; + } + + public int getFirstDayOfWeek() { + try { + return LocaleService.getFirstDayOfWeek(currentLocale); + } catch (LocaleNotLoadedException e) { + // TODO redirect to console + System.out.println(e + ":" + e.getMessage()); + } + return 0; + } + + public boolean isTwelveHourClock() { + try { + return LocaleService.isTwelveHourClock(currentLocale); + } catch (LocaleNotLoadedException e) { + // TODO redirect to console + System.out.println(e + ":" + e.getMessage()); + } + return false; + } + + public String getClockDelimeter() { + try { + return LocaleService.getClockDelimiter(currentLocale); + } catch (LocaleNotLoadedException e) { + // TODO redirect to console + System.out.println(e + ":" + e.getMessage()); + } + return ":"; + } + + public String[] getAmPmStrings() { + try { + return LocaleService.getAmPmStrings(currentLocale); + } catch (LocaleNotLoadedException e) { + // TODO redirect to console + System.out.println(e + ":" + e.getMessage()); + } + String[] temp = new String[2]; + temp[0] = "AM"; + temp[1] = "PM"; + return temp; + } + + public int getStartWeekDay(Date date) { + Date dateForFirstOfThisMonth = new Date(date.getYear(), + date.getMonth(), 1); + int firstDay; + try { + firstDay = LocaleService.getFirstDayOfWeek(currentLocale); + } catch (LocaleNotLoadedException e) { + firstDay = 0; + // TODO redirect to console + System.out.println(e + ":" + e.getMessage()); + } + int start = dateForFirstOfThisMonth.getDay() - firstDay; + if (start < 0) { + start = 6; + } + return start; + } + + public String getDateFormat() { + try { + return LocaleService.getDateFormat(currentLocale); + } catch (LocaleNotLoadedException e) { + // TODO redirect to console + System.out.println(e + ":" + e.getMessage()); + } + return "M/d/yy"; + } + + public static int getNumberOfDaysInMonth(Date date) { + int month = date.getMonth(); + if (month == 1 && true == isLeapYear(date)) { + return 29; + } + return maxDaysInMonth[month]; + } + + public static boolean isLeapYear(Date date) { + // Instantiate the date for 1st March of that year + Date firstMarch = new Date(date.getYear(), 2, 1); + + // Go back 1 day + long firstMarchTime = firstMarch.getTime(); + long lastDayTimeFeb = firstMarchTime - (24 * 60 * 60 * 1000); // NUM_MILLISECS_A_DAY + + // Instantiate new Date with this time + Date febLastDay = new Date(lastDayTimeFeb); + + // Check for date in this new instance + return (29 == febLastDay.getDate()) ? true : false; + } + + public static boolean isSameDay(Date d1, Date d2) { + return (getDayInt(d1) == getDayInt(d2)); + } + + public static boolean isInRange(Date date, Date rangeStart, Date rangeEnd, + int resolution) { + Date s; + Date e; + if (rangeStart.after(rangeEnd)) { + s = rangeEnd; + e = rangeStart; + } else { + e = rangeEnd; + s = rangeStart; + } + long start = s.getYear() * 10000000000l; + long end = e.getYear() * 10000000000l; + long target = date.getYear() * 10000000000l; + + if (resolution == RESOLUTION_YEAR) { + return (start <= target && end >= target); + } + start += s.getMonth() * 100000000; + end += e.getMonth() * 100000000; + target += date.getMonth() * 100000000; + if (resolution == RESOLUTION_MONTH) { + return (start <= target && end >= target); + } + start += s.getDate() * 1000000; + end += e.getDate() * 1000000; + target += date.getDate() * 1000000; + if (resolution == RESOLUTION_DAY) { + return (start <= target && end >= target); + } + start += s.getHours() * 10000; + end += e.getHours() * 10000; + target += date.getHours() * 10000; + if (resolution == RESOLUTION_HOUR) { + return (start <= target && end >= target); + } + start += s.getMinutes() * 100; + end += e.getMinutes() * 100; + target += date.getMinutes() * 100; + if (resolution == RESOLUTION_MIN) { + return (start <= target && end >= target); + } + start += s.getSeconds(); + end += e.getSeconds(); + target += date.getSeconds(); + return (start <= target && end >= target); + + } + + private static int getDayInt(Date date) { + int y = date.getYear(); + int m = date.getMonth(); + int d = date.getDate(); + + return ((y + 1900) * 10000 + m * 100 + d) * 1000000000; + } } diff --git a/src/com/itmill/toolkit/terminal/gwt/client/DebugConsole.java b/src/com/itmill/toolkit/terminal/gwt/client/DebugConsole.java index 8f6a1c822d..4b9d2b799a 100755 --- a/src/com/itmill/toolkit/terminal/gwt/client/DebugConsole.java +++ b/src/com/itmill/toolkit/terminal/gwt/client/DebugConsole.java @@ -11,69 +11,69 @@ import com.itmill.toolkit.terminal.gwt.client.ui.IWindow; public final class DebugConsole extends IWindow implements Console { - private Panel panel; + private Panel panel; - public DebugConsole(ApplicationConnection client) { - super(); - this.client = client; - panel = new FlowPanel(); - ScrollPanel p = new ScrollPanel(); - p.add(panel); - this.setWidget(p); - this.setCaption("Debug window"); - minimize(); - show(); - } + public DebugConsole(ApplicationConnection client) { + super(); + this.client = client; + panel = new FlowPanel(); + ScrollPanel p = new ScrollPanel(); + p.add(panel); + setWidget(p); + setCaption("Debug window"); + minimize(); + show(); + } - private void minimize() { - // TODO stack to bottom (create window manager of some sort) - setPixelSize(60, 60); - setPopupPosition(Window.getClientWidth() - - (60 + IWindow.BORDER_WIDTH_HORIZONTAL), Window - .getClientHeight() - - (80 + IWindow.BORDER_WIDTH_VERTICAL)); - } + private void minimize() { + // TODO stack to bottom (create window manager of some sort) + setPixelSize(60, 60); + setPopupPosition(Window.getClientWidth() + - (60 + IWindow.BORDER_WIDTH_HORIZONTAL), Window + .getClientHeight() + - (80 + IWindow.BORDER_WIDTH_VERTICAL)); + } - /* - * (non-Javadoc) - * - * @see com.itmill.toolkit.terminal.gwt.client.Console#log(java.lang.String) - */ - public void log(String msg) { - panel.add(new HTML(msg)); - System.out.println(msg); - } + /* + * (non-Javadoc) + * + * @see com.itmill.toolkit.terminal.gwt.client.Console#log(java.lang.String) + */ + public void log(String msg) { + panel.add(new HTML(msg)); + System.out.println(msg); + } - /* - * (non-Javadoc) - * - * @see com.itmill.toolkit.terminal.gwt.client.Console#error(java.lang.String) - */ - public void error(String msg) { - panel.add((new HTML(msg))); - System.out.println(msg); - } + /* + * (non-Javadoc) + * + * @see com.itmill.toolkit.terminal.gwt.client.Console#error(java.lang.String) + */ + public void error(String msg) { + panel.add((new HTML(msg))); + System.out.println(msg); + } - /* - * (non-Javadoc) - * - * @see com.itmill.toolkit.terminal.gwt.client.Console#printObject(java.lang.Object) - */ - public void printObject(Object msg) { - panel.add((new Label(msg.toString()))); - } + /* + * (non-Javadoc) + * + * @see com.itmill.toolkit.terminal.gwt.client.Console#printObject(java.lang.Object) + */ + public void printObject(Object msg) { + panel.add((new Label(msg.toString()))); + } - /* - * (non-Javadoc) - * - * @see com.itmill.toolkit.terminal.gwt.client.Console#dirUIDL(com.itmill.toolkit.terminal.gwt.client.UIDL) - */ - public void dirUIDL(UIDL u) { - panel.add(u.print_r()); - } + /* + * (non-Javadoc) + * + * @see com.itmill.toolkit.terminal.gwt.client.Console#dirUIDL(com.itmill.toolkit.terminal.gwt.client.UIDL) + */ + public void dirUIDL(UIDL u) { + panel.add(u.print_r()); + } - public void setSize(Event event, boolean updateVariables) { - super.setSize(event, false); - } + public void setSize(Event event, boolean updateVariables) { + super.setSize(event, false); + } } diff --git a/src/com/itmill/toolkit/terminal/gwt/client/LocaleNotLoadedException.java b/src/com/itmill/toolkit/terminal/gwt/client/LocaleNotLoadedException.java index 1f1e805d0a..2ff8e09948 100644 --- a/src/com/itmill/toolkit/terminal/gwt/client/LocaleNotLoadedException.java +++ b/src/com/itmill/toolkit/terminal/gwt/client/LocaleNotLoadedException.java @@ -2,12 +2,12 @@ package com.itmill.toolkit.terminal.gwt.client; public class LocaleNotLoadedException extends Exception { - /** - * Serial generated by Eclipse. - */ - private static final long serialVersionUID = 2005227056545210838L; + /** + * Serial generated by Eclipse. + */ + private static final long serialVersionUID = 2005227056545210838L; - public LocaleNotLoadedException(String locale) { - super(locale); - } + public LocaleNotLoadedException(String locale) { + super(locale); + } } diff --git a/src/com/itmill/toolkit/terminal/gwt/client/LocaleService.java b/src/com/itmill/toolkit/terminal/gwt/client/LocaleService.java index 31fe42d167..5a266aed91 100644 --- a/src/com/itmill/toolkit/terminal/gwt/client/LocaleService.java +++ b/src/com/itmill/toolkit/terminal/gwt/client/LocaleService.java @@ -19,163 +19,174 @@ import com.google.gwt.json.client.JSONString; */ public class LocaleService { - private static Map cache = new HashMap(); - private static String defaultLocale; - - public static void addLocale(JSONObject json) { - String key = ((JSONString) json.get("name")).stringValue(); - if (cache.containsKey(key)) - cache.remove(key); - cache.put(key, json); - if (cache.size() == 1) - setDefaultLocale(key); - } - - public static void setDefaultLocale(String locale) { - defaultLocale = locale; - } - - public static String getDefaultLocale() { - return defaultLocale; - } - - public static Set getAvailableLocales() { - return cache.keySet(); - } - - public static String[] getMonthNames(String locale) - throws LocaleNotLoadedException { - if (cache.containsKey(locale)) { - JSONObject l = (JSONObject) cache.get(locale); - JSONArray mn = (JSONArray) l.get("mn"); - String[] temp = new String[12]; - temp[0] = ((JSONString) mn.get(0)).stringValue(); - temp[1] = ((JSONString) mn.get(1)).stringValue(); - temp[2] = ((JSONString) mn.get(2)).stringValue(); - temp[3] = ((JSONString) mn.get(3)).stringValue(); - temp[4] = ((JSONString) mn.get(4)).stringValue(); - temp[5] = ((JSONString) mn.get(5)).stringValue(); - temp[6] = ((JSONString) mn.get(6)).stringValue(); - temp[7] = ((JSONString) mn.get(7)).stringValue(); - temp[8] = ((JSONString) mn.get(8)).stringValue(); - temp[9] = ((JSONString) mn.get(9)).stringValue(); - temp[10] = ((JSONString) mn.get(10)).stringValue(); - temp[11] = ((JSONString) mn.get(11)).stringValue(); - return temp; - } else - throw new LocaleNotLoadedException(locale); - } - - public static String[] getShortMonthNames(String locale) - throws LocaleNotLoadedException { - if (cache.containsKey(locale)) { - JSONObject l = (JSONObject) cache.get(locale); - JSONArray smn = (JSONArray) l.get("smn"); - String[] temp = new String[12]; - temp[0] = ((JSONString) smn.get(0)).stringValue(); - temp[1] = ((JSONString) smn.get(1)).stringValue(); - temp[2] = ((JSONString) smn.get(2)).stringValue(); - temp[3] = ((JSONString) smn.get(3)).stringValue(); - temp[4] = ((JSONString) smn.get(4)).stringValue(); - temp[5] = ((JSONString) smn.get(5)).stringValue(); - temp[6] = ((JSONString) smn.get(6)).stringValue(); - temp[7] = ((JSONString) smn.get(7)).stringValue(); - temp[8] = ((JSONString) smn.get(8)).stringValue(); - temp[9] = ((JSONString) smn.get(9)).stringValue(); - temp[10] = ((JSONString) smn.get(10)).stringValue(); - temp[11] = ((JSONString) smn.get(11)).stringValue(); - return temp; - } else - throw new LocaleNotLoadedException(locale); - } - - public static String[] getDayNames(String locale) - throws LocaleNotLoadedException { - if (cache.containsKey(locale)) { - JSONObject l = (JSONObject) cache.get(locale); - JSONArray dn = (JSONArray) l.get("dn"); - String[] temp = new String[7]; - temp[0] = ((JSONString) dn.get(0)).stringValue(); - temp[1] = ((JSONString) dn.get(1)).stringValue(); - temp[2] = ((JSONString) dn.get(2)).stringValue(); - temp[3] = ((JSONString) dn.get(3)).stringValue(); - temp[4] = ((JSONString) dn.get(4)).stringValue(); - temp[5] = ((JSONString) dn.get(5)).stringValue(); - temp[6] = ((JSONString) dn.get(6)).stringValue(); - return temp; - } else - throw new LocaleNotLoadedException(locale); - } - - public static String[] getShortDayNames(String locale) - throws LocaleNotLoadedException { - if (cache.containsKey(locale)) { - JSONObject l = (JSONObject) cache.get(locale); - JSONArray sdn = (JSONArray) l.get("sdn"); - String[] temp = new String[7]; - temp[0] = ((JSONString) sdn.get(0)).stringValue(); - temp[1] = ((JSONString) sdn.get(1)).stringValue(); - temp[2] = ((JSONString) sdn.get(2)).stringValue(); - temp[3] = ((JSONString) sdn.get(3)).stringValue(); - temp[4] = ((JSONString) sdn.get(4)).stringValue(); - temp[5] = ((JSONString) sdn.get(5)).stringValue(); - temp[6] = ((JSONString) sdn.get(6)).stringValue(); - return temp; - } else - throw new LocaleNotLoadedException(locale); - } - - public static int getFirstDayOfWeek(String locale) - throws LocaleNotLoadedException { - if (cache.containsKey(locale)) { - JSONObject l = (JSONObject) cache.get(locale); - JSONNumber fdow = (JSONNumber) l.get("fdow"); - return (int) fdow.getValue(); - } else - throw new LocaleNotLoadedException(locale); - } - - public static String getDateFormat(String locale) - throws LocaleNotLoadedException { - if (cache.containsKey(locale)) { - JSONObject l = (JSONObject) cache.get(locale); - JSONString df = (JSONString) l.get("df"); - return df.stringValue(); - } else - throw new LocaleNotLoadedException(locale); - } - - public static boolean isTwelveHourClock(String locale) - throws LocaleNotLoadedException { - if (cache.containsKey(locale)) { - JSONObject l = (JSONObject) cache.get(locale); - JSONBoolean thc = (JSONBoolean) l.get("thc"); - return thc.booleanValue(); - } else - throw new LocaleNotLoadedException(locale); - } - - public static String getClockDelimiter(String locale) - throws LocaleNotLoadedException { - if (cache.containsKey(locale)) { - JSONObject l = (JSONObject) cache.get(locale); - JSONString hmd = (JSONString) l.get("hmd"); - return hmd.stringValue(); - } else - throw new LocaleNotLoadedException(locale); - } - - public static String[] getAmPmStrings(String locale) - throws LocaleNotLoadedException { - if (cache.containsKey(locale)) { - JSONObject l = (JSONObject) cache.get(locale); - JSONArray ampm = (JSONArray) l.get("ampm"); - String[] temp = new String[2]; - temp[0] = ((JSONString) ampm.get(0)).stringValue(); - temp[1] = ((JSONString) ampm.get(1)).stringValue(); - return temp; - } else - throw new LocaleNotLoadedException(locale); - } + private static Map cache = new HashMap(); + private static String defaultLocale; + + public static void addLocale(JSONObject json) { + String key = ((JSONString) json.get("name")).stringValue(); + if (cache.containsKey(key)) { + cache.remove(key); + } + cache.put(key, json); + if (cache.size() == 1) { + setDefaultLocale(key); + } + } + + public static void setDefaultLocale(String locale) { + defaultLocale = locale; + } + + public static String getDefaultLocale() { + return defaultLocale; + } + + public static Set getAvailableLocales() { + return cache.keySet(); + } + + public static String[] getMonthNames(String locale) + throws LocaleNotLoadedException { + if (cache.containsKey(locale)) { + JSONObject l = (JSONObject) cache.get(locale); + JSONArray mn = (JSONArray) l.get("mn"); + String[] temp = new String[12]; + temp[0] = ((JSONString) mn.get(0)).stringValue(); + temp[1] = ((JSONString) mn.get(1)).stringValue(); + temp[2] = ((JSONString) mn.get(2)).stringValue(); + temp[3] = ((JSONString) mn.get(3)).stringValue(); + temp[4] = ((JSONString) mn.get(4)).stringValue(); + temp[5] = ((JSONString) mn.get(5)).stringValue(); + temp[6] = ((JSONString) mn.get(6)).stringValue(); + temp[7] = ((JSONString) mn.get(7)).stringValue(); + temp[8] = ((JSONString) mn.get(8)).stringValue(); + temp[9] = ((JSONString) mn.get(9)).stringValue(); + temp[10] = ((JSONString) mn.get(10)).stringValue(); + temp[11] = ((JSONString) mn.get(11)).stringValue(); + return temp; + } else { + throw new LocaleNotLoadedException(locale); + } + } + + public static String[] getShortMonthNames(String locale) + throws LocaleNotLoadedException { + if (cache.containsKey(locale)) { + JSONObject l = (JSONObject) cache.get(locale); + JSONArray smn = (JSONArray) l.get("smn"); + String[] temp = new String[12]; + temp[0] = ((JSONString) smn.get(0)).stringValue(); + temp[1] = ((JSONString) smn.get(1)).stringValue(); + temp[2] = ((JSONString) smn.get(2)).stringValue(); + temp[3] = ((JSONString) smn.get(3)).stringValue(); + temp[4] = ((JSONString) smn.get(4)).stringValue(); + temp[5] = ((JSONString) smn.get(5)).stringValue(); + temp[6] = ((JSONString) smn.get(6)).stringValue(); + temp[7] = ((JSONString) smn.get(7)).stringValue(); + temp[8] = ((JSONString) smn.get(8)).stringValue(); + temp[9] = ((JSONString) smn.get(9)).stringValue(); + temp[10] = ((JSONString) smn.get(10)).stringValue(); + temp[11] = ((JSONString) smn.get(11)).stringValue(); + return temp; + } else { + throw new LocaleNotLoadedException(locale); + } + } + + public static String[] getDayNames(String locale) + throws LocaleNotLoadedException { + if (cache.containsKey(locale)) { + JSONObject l = (JSONObject) cache.get(locale); + JSONArray dn = (JSONArray) l.get("dn"); + String[] temp = new String[7]; + temp[0] = ((JSONString) dn.get(0)).stringValue(); + temp[1] = ((JSONString) dn.get(1)).stringValue(); + temp[2] = ((JSONString) dn.get(2)).stringValue(); + temp[3] = ((JSONString) dn.get(3)).stringValue(); + temp[4] = ((JSONString) dn.get(4)).stringValue(); + temp[5] = ((JSONString) dn.get(5)).stringValue(); + temp[6] = ((JSONString) dn.get(6)).stringValue(); + return temp; + } else { + throw new LocaleNotLoadedException(locale); + } + } + + public static String[] getShortDayNames(String locale) + throws LocaleNotLoadedException { + if (cache.containsKey(locale)) { + JSONObject l = (JSONObject) cache.get(locale); + JSONArray sdn = (JSONArray) l.get("sdn"); + String[] temp = new String[7]; + temp[0] = ((JSONString) sdn.get(0)).stringValue(); + temp[1] = ((JSONString) sdn.get(1)).stringValue(); + temp[2] = ((JSONString) sdn.get(2)).stringValue(); + temp[3] = ((JSONString) sdn.get(3)).stringValue(); + temp[4] = ((JSONString) sdn.get(4)).stringValue(); + temp[5] = ((JSONString) sdn.get(5)).stringValue(); + temp[6] = ((JSONString) sdn.get(6)).stringValue(); + return temp; + } else { + throw new LocaleNotLoadedException(locale); + } + } + + public static int getFirstDayOfWeek(String locale) + throws LocaleNotLoadedException { + if (cache.containsKey(locale)) { + JSONObject l = (JSONObject) cache.get(locale); + JSONNumber fdow = (JSONNumber) l.get("fdow"); + return (int) fdow.getValue(); + } else { + throw new LocaleNotLoadedException(locale); + } + } + + public static String getDateFormat(String locale) + throws LocaleNotLoadedException { + if (cache.containsKey(locale)) { + JSONObject l = (JSONObject) cache.get(locale); + JSONString df = (JSONString) l.get("df"); + return df.stringValue(); + } else { + throw new LocaleNotLoadedException(locale); + } + } + + public static boolean isTwelveHourClock(String locale) + throws LocaleNotLoadedException { + if (cache.containsKey(locale)) { + JSONObject l = (JSONObject) cache.get(locale); + JSONBoolean thc = (JSONBoolean) l.get("thc"); + return thc.booleanValue(); + } else { + throw new LocaleNotLoadedException(locale); + } + } + + public static String getClockDelimiter(String locale) + throws LocaleNotLoadedException { + if (cache.containsKey(locale)) { + JSONObject l = (JSONObject) cache.get(locale); + JSONString hmd = (JSONString) l.get("hmd"); + return hmd.stringValue(); + } else { + throw new LocaleNotLoadedException(locale); + } + } + + public static String[] getAmPmStrings(String locale) + throws LocaleNotLoadedException { + if (cache.containsKey(locale)) { + JSONObject l = (JSONObject) cache.get(locale); + JSONArray ampm = (JSONArray) l.get("ampm"); + String[] temp = new String[2]; + temp[0] = ((JSONString) ampm.get(0)).stringValue(); + temp[1] = ((JSONString) ampm.get(1)).stringValue(); + return temp; + } else { + throw new LocaleNotLoadedException(locale); + } + } } diff --git a/src/com/itmill/toolkit/terminal/gwt/client/NullConsole.java b/src/com/itmill/toolkit/terminal/gwt/client/NullConsole.java index 055251cf45..ec81a7b11f 100644 --- a/src/com/itmill/toolkit/terminal/gwt/client/NullConsole.java +++ b/src/com/itmill/toolkit/terminal/gwt/client/NullConsole.java @@ -7,16 +7,16 @@ package com.itmill.toolkit.terminal.gwt.client; */ public class NullConsole implements Console { - public void dirUIDL(UIDL u) { - } + public void dirUIDL(UIDL u) { + } - public void error(String msg) { - } + public void error(String msg) { + } - public void log(String msg) { - } + public void log(String msg) { + } - public void printObject(Object msg) { - } + public void printObject(Object msg) { + } } diff --git a/src/com/itmill/toolkit/terminal/gwt/client/Paintable.java b/src/com/itmill/toolkit/terminal/gwt/client/Paintable.java index 4f29946569..bfe73243dc 100644 --- a/src/com/itmill/toolkit/terminal/gwt/client/Paintable.java +++ b/src/com/itmill/toolkit/terminal/gwt/client/Paintable.java @@ -2,5 +2,5 @@ package com.itmill.toolkit.terminal.gwt.client; public interface Paintable { - public void updateFromUIDL(UIDL uidl, ApplicationConnection client); + public void updateFromUIDL(UIDL uidl, ApplicationConnection client); } diff --git a/src/com/itmill/toolkit/terminal/gwt/client/StyleConstants.java b/src/com/itmill/toolkit/terminal/gwt/client/StyleConstants.java index c562082e4e..c7a752e5ff 100644 --- a/src/com/itmill/toolkit/terminal/gwt/client/StyleConstants.java +++ b/src/com/itmill/toolkit/terminal/gwt/client/StyleConstants.java @@ -1,10 +1,10 @@ package com.itmill.toolkit.terminal.gwt.client; public class StyleConstants { - - public static final String LAYOUT_MARGIN_TOP = "i-layoutmargin-top"; - public static final String LAYOUT_MARGIN_RIGHT = "i-layoutmargin-right"; - public static final String LAYOUT_MARGIN_BOTTOM = "i-layoutmargin-bottom"; - public static final String LAYOUT_MARGIN_LEFT = "i-layoutmargin-left"; + + public static final String LAYOUT_MARGIN_TOP = "i-layoutmargin-top"; + public static final String LAYOUT_MARGIN_RIGHT = "i-layoutmargin-right"; + public static final String LAYOUT_MARGIN_BOTTOM = "i-layoutmargin-bottom"; + public static final String LAYOUT_MARGIN_LEFT = "i-layoutmargin-left"; } diff --git a/src/com/itmill/toolkit/terminal/gwt/client/UIDL.java b/src/com/itmill/toolkit/terminal/gwt/client/UIDL.java index d03bae840d..14ad0c6a31 100644 --- a/src/com/itmill/toolkit/terminal/gwt/client/UIDL.java +++ b/src/com/itmill/toolkit/terminal/gwt/client/UIDL.java @@ -17,422 +17,450 @@ import com.google.gwt.user.client.ui.TreeListener; public class UIDL { - JSONArray json; - - public UIDL(JSONArray json) { - this.json = json; - } - - public String getId() { - JSONValue val = ((JSONObject) json.get(1)).get("id"); - if (val == null) - return null; - return ((JSONString) val).stringValue(); - } - - public String getTag() { - return ((JSONString) json.get(0)).stringValue(); - } - - public String getStringAttribute(String name) { - JSONValue val = ((JSONObject) json.get(1)).get(name); - if (val == null) - return null; - return ((JSONString) val).stringValue(); - } - - public Set getAttributeNames() { - HashSet attrs = new HashSet(((JSONObject) json.get(1)).keySet()); - attrs.remove("v"); - return attrs; - } - - public int getIntAttribute(String name) { - JSONValue val = ((JSONObject) json.get(1)).get(name); - if (val == null) - return 0; - double num = ((JSONNumber) val).getValue(); - return (int) num; - } - - public long getLongAttribute(String name) { - JSONValue val = ((JSONObject) json.get(1)).get(name); - if (val == null) - return 0; - double num = ((JSONNumber) val).getValue(); - return (long) num; - } - - public float getFloatAttribute(String name) { - JSONValue val = ((JSONObject) json.get(1)).get(name); - if (val == null) - return 0; - double num = ((JSONNumber) val).getValue(); - return (float) num; - } - - public double getDoubleAttribute(String name) { - JSONValue val = ((JSONObject) json.get(1)).get(name); - if (val == null) - return 0; - double num = ((JSONNumber) val).getValue(); - return (double) num; - } - - public boolean getBooleanAttribute(String name) { - JSONValue val = ((JSONObject) json.get(1)).get(name); - if (val == null) - return false; - return ((JSONBoolean) val).booleanValue(); - } - - public String[] getStringArrayAttribute(String name) { - JSONArray a = (JSONArray) ((JSONObject) json.get(1)).get(name); - String[] s = new String[a.size()]; - for (int i = 0; i < a.size(); i++) - s[i] = ((JSONString) a.get(i)).stringValue(); - return s; - } - - public int[] getIntArrayAttribute(String name) { - JSONArray a = (JSONArray) ((JSONObject) json.get(1)).get(name); - int[] s = new int[a.size()]; - for (int i = 0; i < a.size(); i++) - s[i] = Integer.parseInt(((JSONString) a.get(i)).stringValue()); - return s; - } - - public HashSet getStringArrayAttributeAsSet(String string) { - JSONArray a = getArrayVariable(string); - HashSet s = new HashSet(); - for (int i = 0; i < a.size(); i++) - s.add(((JSONString) a.get(i)).stringValue()); - return s; - } - - /** - * Get attributes value as string whateever the type is - * - * @param name - * @return string presentation of attribute - */ - private String getAttribute(String name) { - return json.get(1).isObject().get(name).toString(); - } - - public boolean hasAttribute(String name) { - return ((JSONObject) json.get(1)).get(name) != null; - } - - public UIDL getChildUIDL(int i) { - - JSONValue c = json.get(i + 2); - if (c == null) - return null; - if (c.isArray() != null) - return new UIDL(c.isArray()); - throw new IllegalStateException("Child node " + i - + " is not of type UIDL"); - } - - public String getChildString(int i) { - - JSONValue c = json.get(i + 2); - if (c.isString() != null) - return ((JSONString) c).stringValue(); - throw new IllegalStateException("Child node " + i - + " is not of type String"); - } - - public Iterator getChildIterator() { - - return new Iterator() { - - int index = 2; - - public void remove() { - throw new UnsupportedOperationException(); - } - - public Object next() { - - if (json.size() > index) { - JSONValue c = json.get(index++); - if (c.isString() != null) - return c.isString().stringValue(); - else if (c.isArray() != null) - return new UIDL(c.isArray()); - else if (c.isObject() != null) - return new XML(c.isObject()); - else - throw new IllegalStateException("Illegal child " + c - + " in tag " + getTag() + " at index " + index); - } - return null; - } - - public boolean hasNext() { - return json.size() > index; - } - - }; - } - - public int getNumberOfChildren() { - return json.size() - 2; - } - - public String toString() { - String s = "<" + getTag(); - - for (Iterator i = getAttributeNames().iterator(); i.hasNext();) { - String name = i.next().toString(); - s += " " + name + "="; - JSONValue v = ((JSONObject) json.get(1)).get(name); - if (v.isString() != null) - s += v; - else - s += "\"" + v + "\""; - } - - s += ">\n"; - - Iterator i = getChildIterator(); - while (i.hasNext()) { - Object c = i.next(); - s += c.toString(); - } - - s += "\n"; - - return s; - } - - public String getChildrenAsXML() { - String s = ""; - Iterator i = getChildIterator(); - while (i.hasNext()) { - Object c = i.next(); - s += c.toString(); - } - return s; - } - - public UIDLBrowser print_r() { - return new UIDLBrowser(); - } - - private class UIDLBrowser extends Tree { - public UIDLBrowser() { - - DOM.setStyleAttribute(getElement(), "position", ""); - - final TreeItem root = new TreeItem(getTag()); - addItem(root); - root.addItem(""); - addTreeListener(new TreeListener() { - - public void onTreeItemStateChanged(TreeItem item) { - if (item == root) { - removeItem(root); - UIDLBrowser.this.removeTreeListener(this); - addItem(dir()); - Iterator it = treeItemIterator(); - while (it.hasNext()) - ((TreeItem) it.next()).setState(true); - } - } - - public void onTreeItemSelected(TreeItem item) { - } - - }); - - } - - protected boolean isKeyboardNavigationEnabled(TreeItem currentItem) { - return false; - } - - } - - public TreeItem dir() { - - String nodeName = getTag(); - for (Iterator i = getAttributeNames().iterator(); i.hasNext();) { - String name = i.next().toString(); - String value = getAttribute(name); - nodeName += " " + name + "=" + value; - } - TreeItem item = new TreeItem(nodeName); - - try { - TreeItem tmp = null; - for (Iterator i = getVariableHash().keySet().iterator(); i - .hasNext();) { - String name = i.next().toString(); - String value = ""; - try { - value = getStringVariable(name); - } catch (Exception e) { - try { - JSONArray a = getArrayVariable(name); - value = a.toString(); - } catch (Exception e2) { - try { - int intVal = getIntVariable(name); - value = String.valueOf(intVal); - } catch (Exception e3) { - value = "unknown"; - } - } - } - if (tmp == null) - tmp = new TreeItem("variables"); - tmp.addItem(name + "=" + value); - } - if (tmp != null) - item.addItem(tmp); - } catch (Exception e) { - // Ingonered, no variables - } - - Iterator i = getChildIterator(); - while (i.hasNext()) { - Object child = i.next(); - try { - UIDL c = (UIDL) child; - item.addItem(c.dir()); - - } catch (Exception e) { - item.addItem(child.toString()); - } - } - return item; - } - - private JSONObject getVariableHash() { - JSONObject v = (JSONObject) ((JSONObject) json.get(1)).get("v"); - if (v == null) - throw new IllegalArgumentException("No variables defined in tag."); - return v; - } - - public boolean hasVariable(String name) { - Object v = null; - try { - v = getVariableHash().get(name); - } catch (IllegalArgumentException e) { - } - return v != null; - } - - public String getStringVariable(String name) { - JSONString t = (JSONString) getVariableHash().get(name); - if (t == null) - throw new IllegalArgumentException("No such variable: " + name); - return t.stringValue(); - } - - public int getIntVariable(String name) { - JSONNumber t = (JSONNumber) getVariableHash().get(name); - if (t == null) - throw new IllegalArgumentException("No such variable: " + name); - return (int) t.getValue(); - } - - public long getLongVariable(String name) { - JSONNumber t = (JSONNumber) getVariableHash().get(name); - if (t == null) - throw new IllegalArgumentException("No such variable: " + name); - return (long) t.getValue(); - } - - public float getFloatVariable(String name) { - JSONNumber t = (JSONNumber) getVariableHash().get(name); - if (t == null) - throw new IllegalArgumentException("No such variable: " + name); - return (float) t.getValue(); - } - - public double getDoubleVariable(String name) { - JSONNumber t = (JSONNumber) getVariableHash().get(name); - if (t == null) - throw new IllegalArgumentException("No such variable: " + name); - return (double) t.getValue(); - } - - public boolean getBooleanVariable(String name) { - JSONBoolean t = (JSONBoolean) getVariableHash().get(name); - if (t == null) - throw new IllegalArgumentException("No such variable: " + name); - return t.booleanValue(); - } - - private JSONArray getArrayVariable(String name) { - JSONArray t = (JSONArray) getVariableHash().get(name); - if (t == null) - throw new IllegalArgumentException("No such variable: " + name); - return t; - } - - public String[] getStringArrayVariable(String name) { - JSONArray a = getArrayVariable(name); - String[] s = new String[a.size()]; - for (int i = 0; i < a.size(); i++) - s[i] = ((JSONString) a.get(i)).stringValue(); - return s; - } - - public Set getStringArrayVariableAsSet(String name) { - JSONArray a = getArrayVariable(name); - HashSet s = new HashSet(); - for (int i = 0; i < a.size(); i++) - s.add(((JSONString) a.get(i)).stringValue()); - return s; - } - - public int[] getIntArrayVariable(String name) { - JSONArray a = getArrayVariable(name); - int[] s = new int[a.size()]; - for (int i = 0; i < a.size(); i++) { - JSONValue v = a.get(i); - s[i] = v.isNumber() != null ? (int) ((JSONNumber) v).getValue() - : Integer.parseInt(v.toString()); - } - return s; - } - - public class XML { - JSONObject x; - - private XML(JSONObject x) { - this.x = x; - } - - public String getXMLAsString() { - StringBuffer sb = new StringBuffer(); - for (Iterator it = x.keySet().iterator(); it.hasNext();) { - String tag = (String) it.next(); - sb.append("<"); - sb.append(tag); - sb.append(">"); - sb.append(x.get(tag).isString().stringValue()); - sb.append(""); - } - return sb.toString(); - } - } - - public int getChidlCount() { - return json.size() - 2; - } - - public UIDL getErrors() { - JSONArray a = (JSONArray) ((JSONObject) json.get(1)).get("error"); - return new UIDL(a); - } + JSONArray json; + + public UIDL(JSONArray json) { + this.json = json; + } + + public String getId() { + JSONValue val = ((JSONObject) json.get(1)).get("id"); + if (val == null) { + return null; + } + return ((JSONString) val).stringValue(); + } + + public String getTag() { + return ((JSONString) json.get(0)).stringValue(); + } + + public String getStringAttribute(String name) { + JSONValue val = ((JSONObject) json.get(1)).get(name); + if (val == null) { + return null; + } + return ((JSONString) val).stringValue(); + } + + public Set getAttributeNames() { + HashSet attrs = new HashSet(((JSONObject) json.get(1)).keySet()); + attrs.remove("v"); + return attrs; + } + + public int getIntAttribute(String name) { + JSONValue val = ((JSONObject) json.get(1)).get(name); + if (val == null) { + return 0; + } + double num = ((JSONNumber) val).getValue(); + return (int) num; + } + + public long getLongAttribute(String name) { + JSONValue val = ((JSONObject) json.get(1)).get(name); + if (val == null) { + return 0; + } + double num = ((JSONNumber) val).getValue(); + return (long) num; + } + + public float getFloatAttribute(String name) { + JSONValue val = ((JSONObject) json.get(1)).get(name); + if (val == null) { + return 0; + } + double num = ((JSONNumber) val).getValue(); + return (float) num; + } + + public double getDoubleAttribute(String name) { + JSONValue val = ((JSONObject) json.get(1)).get(name); + if (val == null) { + return 0; + } + double num = ((JSONNumber) val).getValue(); + return num; + } + + public boolean getBooleanAttribute(String name) { + JSONValue val = ((JSONObject) json.get(1)).get(name); + if (val == null) { + return false; + } + return ((JSONBoolean) val).booleanValue(); + } + + public String[] getStringArrayAttribute(String name) { + JSONArray a = (JSONArray) ((JSONObject) json.get(1)).get(name); + String[] s = new String[a.size()]; + for (int i = 0; i < a.size(); i++) { + s[i] = ((JSONString) a.get(i)).stringValue(); + } + return s; + } + + public int[] getIntArrayAttribute(String name) { + JSONArray a = (JSONArray) ((JSONObject) json.get(1)).get(name); + int[] s = new int[a.size()]; + for (int i = 0; i < a.size(); i++) { + s[i] = Integer.parseInt(((JSONString) a.get(i)).stringValue()); + } + return s; + } + + public HashSet getStringArrayAttributeAsSet(String string) { + JSONArray a = getArrayVariable(string); + HashSet s = new HashSet(); + for (int i = 0; i < a.size(); i++) { + s.add(((JSONString) a.get(i)).stringValue()); + } + return s; + } + + /** + * Get attributes value as string whateever the type is + * + * @param name + * @return string presentation of attribute + */ + private String getAttribute(String name) { + return json.get(1).isObject().get(name).toString(); + } + + public boolean hasAttribute(String name) { + return ((JSONObject) json.get(1)).get(name) != null; + } + + public UIDL getChildUIDL(int i) { + + JSONValue c = json.get(i + 2); + if (c == null) { + return null; + } + if (c.isArray() != null) { + return new UIDL(c.isArray()); + } + throw new IllegalStateException("Child node " + i + + " is not of type UIDL"); + } + + public String getChildString(int i) { + + JSONValue c = json.get(i + 2); + if (c.isString() != null) { + return ((JSONString) c).stringValue(); + } + throw new IllegalStateException("Child node " + i + + " is not of type String"); + } + + public Iterator getChildIterator() { + + return new Iterator() { + + int index = 2; + + public void remove() { + throw new UnsupportedOperationException(); + } + + public Object next() { + + if (json.size() > index) { + JSONValue c = json.get(index++); + if (c.isString() != null) { + return c.isString().stringValue(); + } else if (c.isArray() != null) { + return new UIDL(c.isArray()); + } else if (c.isObject() != null) { + return new XML(c.isObject()); + } else { + throw new IllegalStateException("Illegal child " + c + + " in tag " + getTag() + " at index " + index); + } + } + return null; + } + + public boolean hasNext() { + return json.size() > index; + } + + }; + } + + public int getNumberOfChildren() { + return json.size() - 2; + } + + public String toString() { + String s = "<" + getTag(); + + for (Iterator i = getAttributeNames().iterator(); i.hasNext();) { + String name = i.next().toString(); + s += " " + name + "="; + JSONValue v = ((JSONObject) json.get(1)).get(name); + if (v.isString() != null) { + s += v; + } else { + s += "\"" + v + "\""; + } + } + + s += ">\n"; + + Iterator i = getChildIterator(); + while (i.hasNext()) { + Object c = i.next(); + s += c.toString(); + } + + s += "\n"; + + return s; + } + + public String getChildrenAsXML() { + String s = ""; + Iterator i = getChildIterator(); + while (i.hasNext()) { + Object c = i.next(); + s += c.toString(); + } + return s; + } + + public UIDLBrowser print_r() { + return new UIDLBrowser(); + } + + private class UIDLBrowser extends Tree { + public UIDLBrowser() { + + DOM.setStyleAttribute(getElement(), "position", ""); + + final TreeItem root = new TreeItem(getTag()); + addItem(root); + root.addItem(""); + addTreeListener(new TreeListener() { + + public void onTreeItemStateChanged(TreeItem item) { + if (item == root) { + removeItem(root); + UIDLBrowser.this.removeTreeListener(this); + addItem(dir()); + Iterator it = treeItemIterator(); + while (it.hasNext()) { + ((TreeItem) it.next()).setState(true); + } + } + } + + public void onTreeItemSelected(TreeItem item) { + } + + }); + + } + + protected boolean isKeyboardNavigationEnabled(TreeItem currentItem) { + return false; + } + + } + + public TreeItem dir() { + + String nodeName = getTag(); + for (Iterator i = getAttributeNames().iterator(); i.hasNext();) { + String name = i.next().toString(); + String value = getAttribute(name); + nodeName += " " + name + "=" + value; + } + TreeItem item = new TreeItem(nodeName); + + try { + TreeItem tmp = null; + for (Iterator i = getVariableHash().keySet().iterator(); i + .hasNext();) { + String name = i.next().toString(); + String value = ""; + try { + value = getStringVariable(name); + } catch (Exception e) { + try { + JSONArray a = getArrayVariable(name); + value = a.toString(); + } catch (Exception e2) { + try { + int intVal = getIntVariable(name); + value = String.valueOf(intVal); + } catch (Exception e3) { + value = "unknown"; + } + } + } + if (tmp == null) { + tmp = new TreeItem("variables"); + } + tmp.addItem(name + "=" + value); + } + if (tmp != null) { + item.addItem(tmp); + } + } catch (Exception e) { + // Ingonered, no variables + } + + Iterator i = getChildIterator(); + while (i.hasNext()) { + Object child = i.next(); + try { + UIDL c = (UIDL) child; + item.addItem(c.dir()); + + } catch (Exception e) { + item.addItem(child.toString()); + } + } + return item; + } + + private JSONObject getVariableHash() { + JSONObject v = (JSONObject) ((JSONObject) json.get(1)).get("v"); + if (v == null) { + throw new IllegalArgumentException("No variables defined in tag."); + } + return v; + } + + public boolean hasVariable(String name) { + Object v = null; + try { + v = getVariableHash().get(name); + } catch (IllegalArgumentException e) { + } + return v != null; + } + + public String getStringVariable(String name) { + JSONString t = (JSONString) getVariableHash().get(name); + if (t == null) { + throw new IllegalArgumentException("No such variable: " + name); + } + return t.stringValue(); + } + + public int getIntVariable(String name) { + JSONNumber t = (JSONNumber) getVariableHash().get(name); + if (t == null) { + throw new IllegalArgumentException("No such variable: " + name); + } + return (int) t.getValue(); + } + + public long getLongVariable(String name) { + JSONNumber t = (JSONNumber) getVariableHash().get(name); + if (t == null) { + throw new IllegalArgumentException("No such variable: " + name); + } + return (long) t.getValue(); + } + + public float getFloatVariable(String name) { + JSONNumber t = (JSONNumber) getVariableHash().get(name); + if (t == null) { + throw new IllegalArgumentException("No such variable: " + name); + } + return (float) t.getValue(); + } + + public double getDoubleVariable(String name) { + JSONNumber t = (JSONNumber) getVariableHash().get(name); + if (t == null) { + throw new IllegalArgumentException("No such variable: " + name); + } + return t.getValue(); + } + + public boolean getBooleanVariable(String name) { + JSONBoolean t = (JSONBoolean) getVariableHash().get(name); + if (t == null) { + throw new IllegalArgumentException("No such variable: " + name); + } + return t.booleanValue(); + } + + private JSONArray getArrayVariable(String name) { + JSONArray t = (JSONArray) getVariableHash().get(name); + if (t == null) { + throw new IllegalArgumentException("No such variable: " + name); + } + return t; + } + + public String[] getStringArrayVariable(String name) { + JSONArray a = getArrayVariable(name); + String[] s = new String[a.size()]; + for (int i = 0; i < a.size(); i++) { + s[i] = ((JSONString) a.get(i)).stringValue(); + } + return s; + } + + public Set getStringArrayVariableAsSet(String name) { + JSONArray a = getArrayVariable(name); + HashSet s = new HashSet(); + for (int i = 0; i < a.size(); i++) { + s.add(((JSONString) a.get(i)).stringValue()); + } + return s; + } + + public int[] getIntArrayVariable(String name) { + JSONArray a = getArrayVariable(name); + int[] s = new int[a.size()]; + for (int i = 0; i < a.size(); i++) { + JSONValue v = a.get(i); + s[i] = v.isNumber() != null ? (int) ((JSONNumber) v).getValue() + : Integer.parseInt(v.toString()); + } + return s; + } + + public class XML { + JSONObject x; + + private XML(JSONObject x) { + this.x = x; + } + + public String getXMLAsString() { + StringBuffer sb = new StringBuffer(); + for (Iterator it = x.keySet().iterator(); it.hasNext();) { + String tag = (String) it.next(); + sb.append("<"); + sb.append(tag); + sb.append(">"); + sb.append(x.get(tag).isString().stringValue()); + sb.append(""); + } + return sb.toString(); + } + } + + public int getChidlCount() { + return json.size() - 2; + } + + public UIDL getErrors() { + JSONArray a = (JSONArray) ((JSONObject) json.get(1)).get("error"); + return new UIDL(a); + } } diff --git a/src/com/itmill/toolkit/terminal/gwt/client/Util.java b/src/com/itmill/toolkit/terminal/gwt/client/Util.java index e440e28f84..a1fad8258d 100644 --- a/src/com/itmill/toolkit/terminal/gwt/client/Util.java +++ b/src/com/itmill/toolkit/terminal/gwt/client/Util.java @@ -8,74 +8,74 @@ import com.google.gwt.user.client.ui.Widget; public class Util { - /** - * Helper method for debugging purposes. - * - * Stops execution on firefox browsers on a breakpoint. - * - */ - public static native void browserDebugger() /*-{ - if(window.console) - debugger; - }-*/; + /** + * Helper method for debugging purposes. + * + * Stops execution on firefox browsers on a breakpoint. + * + */ + public static native void browserDebugger() /*-{ + if(window.console) + debugger; + }-*/; - /** - * Detects if current browser is IE. - * - * @return true if IE - */ - public static native boolean isIE() /*-{ - var browser=$wnd.navigator.appName; - if (browser=="Microsoft Internet Explorer") { - return true; - } - return false; - }-*/; + /** + * Detects if current browser is IE. + * + * @return true if IE + */ + public static native boolean isIE() /*-{ + var browser=$wnd.navigator.appName; + if (browser=="Microsoft Internet Explorer") { + return true; + } + return false; + }-*/; - /** - * Detects if current browser is IE6. - * - * @return true if IE6 - */ - public static native boolean isIE6() /*-{ - var browser=$wnd.navigator.appName; - if (browser=="Microsoft Internet Explorer") { - var ua = navigator.userAgent; - var re = new RegExp("MSIE ([0-9]{1,}[\.0-9]{0,})"); - if (re.exec(ua) != null) - rv = parseFloat(RegExp.$1); - if(rv == 6) return true; - } - return false; - }-*/; + /** + * Detects if current browser is IE6. + * + * @return true if IE6 + */ + public static native boolean isIE6() /*-{ + var browser=$wnd.navigator.appName; + if (browser=="Microsoft Internet Explorer") { + var ua = navigator.userAgent; + var re = new RegExp("MSIE ([0-9]{1,}[\.0-9]{0,})"); + if (re.exec(ua) != null) + rv = parseFloat(RegExp.$1); + if(rv == 6) return true; + } + return false; + }-*/; - /** - * Nulls oncontextmenu function on given element. We need to manually clear - * context menu events due bad browsers memory leaks, since GWT don't - * support them. - * - * @param el - */ - public native static void removeContextMenuEvent(Element el) /*-{ - el.oncontextmenu = null; - }-*/; + /** + * Nulls oncontextmenu function on given element. We need to manually clear + * context menu events due bad browsers memory leaks, since GWT don't + * support them. + * + * @param el + */ + public native static void removeContextMenuEvent(Element el) /*-{ + el.oncontextmenu = null; + }-*/; - /** - * Traverses recursively ancestors until ContainerResizedListener child - * widget is found. They will delegate it futher if needed. - * - * @param container - */ - public static void runDescendentsLayout(HasWidgets container) { - Iterator childWidgets = container.iterator(); - while (childWidgets.hasNext()) { - Widget child = (Widget) childWidgets.next(); - if (child instanceof ContainerResizedListener) { - ((ContainerResizedListener) child).iLayout(); - } else if (child instanceof HasWidgets) { - HasWidgets childContainer = (HasWidgets) child; - runDescendentsLayout(childContainer); - } - } - } + /** + * Traverses recursively ancestors until ContainerResizedListener child + * widget is found. They will delegate it futher if needed. + * + * @param container + */ + public static void runDescendentsLayout(HasWidgets container) { + Iterator childWidgets = container.iterator(); + while (childWidgets.hasNext()) { + Widget child = (Widget) childWidgets.next(); + if (child instanceof ContainerResizedListener) { + ((ContainerResizedListener) child).iLayout(); + } else if (child instanceof HasWidgets) { + HasWidgets childContainer = (HasWidgets) child; + runDescendentsLayout(childContainer); + } + } + } } diff --git a/src/com/itmill/toolkit/terminal/gwt/client/WidgetSet.java b/src/com/itmill/toolkit/terminal/gwt/client/WidgetSet.java index aaa77a91ab..c975830252 100644 --- a/src/com/itmill/toolkit/terminal/gwt/client/WidgetSet.java +++ b/src/com/itmill/toolkit/terminal/gwt/client/WidgetSet.java @@ -5,25 +5,25 @@ import com.google.gwt.user.client.ui.Widget; public interface WidgetSet extends EntryPoint { - /** - * Create an uninitialized component that best matches given UIDL. - * - * @param uidl - * UIDL to be painted with returned component. - * @return New uninitialized and unregistered component that can paint given - * UIDL. - */ - public Widget createWidget(UIDL uidl); + /** + * Create an uninitialized component that best matches given UIDL. + * + * @param uidl + * UIDL to be painted with returned component. + * @return New uninitialized and unregistered component that can paint given + * UIDL. + */ + public Widget createWidget(UIDL uidl); - /** - * Test if the given component implementation conforms to UIDL. - * - * @param currentWidget - * Current implementation of the component - * @param uidl - * UIDL to test against - * @return true iff createWidget would return a new component of the same - * class than currentWidget - */ - public boolean isCorrectImplementation(Widget currentWidget, UIDL uidl); + /** + * Test if the given component implementation conforms to UIDL. + * + * @param currentWidget + * Current implementation of the component + * @param uidl + * UIDL to test against + * @return true iff createWidget would return a new component of the same + * class than currentWidget + */ + public boolean isCorrectImplementation(Widget currentWidget, UIDL uidl); } diff --git a/src/com/itmill/toolkit/terminal/gwt/client/ui/Action.java b/src/com/itmill/toolkit/terminal/gwt/client/ui/Action.java index dce4342fbe..58d7d679c0 100644 --- a/src/com/itmill/toolkit/terminal/gwt/client/ui/Action.java +++ b/src/com/itmill/toolkit/terminal/gwt/client/ui/Action.java @@ -8,47 +8,47 @@ import com.itmill.toolkit.terminal.gwt.client.ApplicationConnection; */ public abstract class Action implements Command { - protected ActionOwner owner; - - protected String iconUrl = null; - - protected String caption = ""; - - public Action(ActionOwner owner) { - this.owner = owner; - } - - /** - * Executed when action fired - */ - public abstract void execute(); - - public String getHTML() { - StringBuffer sb = new StringBuffer(); - sb.append("
"); - if (getIconUrl() != null) { - sb.append("\"icon\""); - } - sb.append(getCaption()); - sb.append("
"); - return sb.toString(); - } - - public String getCaption() { - return caption; - } - - public void setCaption(String caption) { - this.caption = caption; - } - - public String getIconUrl() { - return iconUrl; - } - - public void setIconUrl(String url) { - iconUrl = url; - } + protected ActionOwner owner; + + protected String iconUrl = null; + + protected String caption = ""; + + public Action(ActionOwner owner) { + this.owner = owner; + } + + /** + * Executed when action fired + */ + public abstract void execute(); + + public String getHTML() { + StringBuffer sb = new StringBuffer(); + sb.append("
"); + if (getIconUrl() != null) { + sb.append("\"icon\""); + } + sb.append(getCaption()); + sb.append("
"); + return sb.toString(); + } + + public String getCaption() { + return caption; + } + + public void setCaption(String caption) { + this.caption = caption; + } + + public String getIconUrl() { + return iconUrl; + } + + public void setIconUrl(String url) { + iconUrl = url; + } } /** @@ -57,12 +57,12 @@ public abstract class Action implements Command { */ interface ActionOwner { - /** - * @return Array of IActions - */ - public Action[] getActions(); + /** + * @return Array of IActions + */ + public Action[] getActions(); - public ApplicationConnection getClient(); + public ApplicationConnection getClient(); - public String getPaintableId(); + public String getPaintableId(); } \ No newline at end of file diff --git a/src/com/itmill/toolkit/terminal/gwt/client/ui/AlignmentInfo.java b/src/com/itmill/toolkit/terminal/gwt/client/ui/AlignmentInfo.java index d2967e1593..0a2f48ab00 100644 --- a/src/com/itmill/toolkit/terminal/gwt/client/ui/AlignmentInfo.java +++ b/src/com/itmill/toolkit/terminal/gwt/client/ui/AlignmentInfo.java @@ -2,71 +2,71 @@ package com.itmill.toolkit.terminal.gwt.client.ui; public class AlignmentInfo { - public static final int ALIGNMENT_LEFT = 1; - public static final int ALIGNMENT_RIGHT = 2; - public static final int ALIGNMENT_TOP = 4; - public static final int ALIGNMENT_BOTTOM = 8; - public static final int ALIGNMENT_HORIZONTAL_CENTER = 16; - public static final int ALIGNMENT_VERTICAL_CENTER = 32; - - private int bitMask; - - public AlignmentInfo(int bitMask) { - this.bitMask = bitMask; - } - - public AlignmentInfo(int horizontal, int vertical) { - setAlignment(horizontal, vertical); - } - - public void setAlignment(int horiz, int vert) { - bitMask = horiz + vert; - } - - public int getBitMask() { - return bitMask; - } - - public boolean isTop() { - return (bitMask & ALIGNMENT_TOP) == ALIGNMENT_TOP; - } - - public boolean isBottom() { - return (bitMask & ALIGNMENT_BOTTOM) == ALIGNMENT_BOTTOM; - } - - public boolean isLeft() { - return (bitMask & ALIGNMENT_LEFT) == ALIGNMENT_LEFT; - } - - public boolean isRight() { - return (bitMask & ALIGNMENT_RIGHT) == ALIGNMENT_RIGHT; - } - - public boolean isVerticalCenter() { - return (bitMask & ALIGNMENT_VERTICAL_CENTER) == ALIGNMENT_VERTICAL_CENTER; - } - - public boolean isHorizontalCenter() { - return (bitMask & ALIGNMENT_HORIZONTAL_CENTER) == ALIGNMENT_HORIZONTAL_CENTER; - } - - public String getVerticalAlignment() { - if (isBottom()) { - return "bottom"; - } else if (isVerticalCenter()) { - return "middle"; - } - return "top"; - } - - public String getHorizontalAlignment() { - if (isRight()) { - return "right"; - } else if (isHorizontalCenter()) { - return "center"; - } - return "left"; - } + public static final int ALIGNMENT_LEFT = 1; + public static final int ALIGNMENT_RIGHT = 2; + public static final int ALIGNMENT_TOP = 4; + public static final int ALIGNMENT_BOTTOM = 8; + public static final int ALIGNMENT_HORIZONTAL_CENTER = 16; + public static final int ALIGNMENT_VERTICAL_CENTER = 32; + + private int bitMask; + + public AlignmentInfo(int bitMask) { + this.bitMask = bitMask; + } + + public AlignmentInfo(int horizontal, int vertical) { + setAlignment(horizontal, vertical); + } + + public void setAlignment(int horiz, int vert) { + bitMask = horiz + vert; + } + + public int getBitMask() { + return bitMask; + } + + public boolean isTop() { + return (bitMask & ALIGNMENT_TOP) == ALIGNMENT_TOP; + } + + public boolean isBottom() { + return (bitMask & ALIGNMENT_BOTTOM) == ALIGNMENT_BOTTOM; + } + + public boolean isLeft() { + return (bitMask & ALIGNMENT_LEFT) == ALIGNMENT_LEFT; + } + + public boolean isRight() { + return (bitMask & ALIGNMENT_RIGHT) == ALIGNMENT_RIGHT; + } + + public boolean isVerticalCenter() { + return (bitMask & ALIGNMENT_VERTICAL_CENTER) == ALIGNMENT_VERTICAL_CENTER; + } + + public boolean isHorizontalCenter() { + return (bitMask & ALIGNMENT_HORIZONTAL_CENTER) == ALIGNMENT_HORIZONTAL_CENTER; + } + + public String getVerticalAlignment() { + if (isBottom()) { + return "bottom"; + } else if (isVerticalCenter()) { + return "middle"; + } + return "top"; + } + + public String getHorizontalAlignment() { + if (isRight()) { + return "right"; + } else if (isHorizontalCenter()) { + return "center"; + } + return "left"; + } } diff --git a/src/com/itmill/toolkit/terminal/gwt/client/ui/CalendarEntry.java b/src/com/itmill/toolkit/terminal/gwt/client/ui/CalendarEntry.java index 075f68cbf6..edf0de98bd 100644 --- a/src/com/itmill/toolkit/terminal/gwt/client/ui/CalendarEntry.java +++ b/src/com/itmill/toolkit/terminal/gwt/client/ui/CalendarEntry.java @@ -5,118 +5,118 @@ import java.util.Date; import com.itmill.toolkit.terminal.gwt.client.DateTimeService; public class CalendarEntry { - private String styleName; - private Date start; - private Date end; - private String title; - private String description; - private boolean notime; - - public CalendarEntry(String styleName, Date start, Date end, String title, - String description, boolean notime) { - this.styleName = styleName; - if (notime) { - Date d = new Date(start.getTime()); - d.setSeconds(0); - d.setMinutes(0); - this.start = d; - if (end != null) { - d = new Date(end.getTime()); - d.setSeconds(0); - d.setMinutes(0); - this.end = d; - } else { - end = start; - } - } else { - this.start = start; - this.end = end; - } - this.title = title; - this.description = description; - this.notime = notime; - } - - public CalendarEntry(String styleName, Date start, Date end, String title, - String description) { - this(styleName, start, end, title, description, false); - } - - public String getStyleName() { - return styleName; - } - - public Date getStart() { - return start; - } - - public void setStart(Date start) { - this.start = start; - } - - public Date getEnd() { - return end; - } - - public void setEnd(Date end) { - this.end = end; - } - - public String getTitle() { - return title; - } - - public void setTitle(String title) { - this.title = title; - } - - public String getDescription() { - return description; - } - - public void setDescription(String description) { - this.description = description; - } - - public boolean isNotime() { - return notime; - } - - public void setNotime(boolean notime) { - this.notime = notime; - } - - public String getStringForDate(Date d) { - // TODO format from DateTimeService - String s = ""; - if (!notime) { - if (!DateTimeService.isSameDay(d, start)) { - s += (start.getYear() + 1900) + "." + (start.getMonth() + 1) - + "." + start.getDate() + " "; - } - int i = start.getHours(); - s += (i < 10 ? "0" : "") + i; - s += ":"; - i = start.getMinutes(); - s += (i < 10 ? "0" : "") + i; - if (!start.equals(end)) { - s += " - "; - if (!DateTimeService.isSameDay(start, end)) { - s += (end.getYear() + 1900) + "." + (end.getMonth() + 1) - + "." + end.getDate() + " "; - } - i = end.getHours(); - s += (i < 10 ? "0" : "") + i; - s += ":"; - i = end.getMinutes(); - s += (i < 10 ? "0" : "") + i; - } - s += " "; - } - if (title!=null) { - s += title; - } - return s; - } + private String styleName; + private Date start; + private Date end; + private String title; + private String description; + private boolean notime; + + public CalendarEntry(String styleName, Date start, Date end, String title, + String description, boolean notime) { + this.styleName = styleName; + if (notime) { + Date d = new Date(start.getTime()); + d.setSeconds(0); + d.setMinutes(0); + this.start = d; + if (end != null) { + d = new Date(end.getTime()); + d.setSeconds(0); + d.setMinutes(0); + this.end = d; + } else { + end = start; + } + } else { + this.start = start; + this.end = end; + } + this.title = title; + this.description = description; + this.notime = notime; + } + + public CalendarEntry(String styleName, Date start, Date end, String title, + String description) { + this(styleName, start, end, title, description, false); + } + + public String getStyleName() { + return styleName; + } + + public Date getStart() { + return start; + } + + public void setStart(Date start) { + this.start = start; + } + + public Date getEnd() { + return end; + } + + public void setEnd(Date end) { + this.end = end; + } + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + public boolean isNotime() { + return notime; + } + + public void setNotime(boolean notime) { + this.notime = notime; + } + + public String getStringForDate(Date d) { + // TODO format from DateTimeService + String s = ""; + if (!notime) { + if (!DateTimeService.isSameDay(d, start)) { + s += (start.getYear() + 1900) + "." + (start.getMonth() + 1) + + "." + start.getDate() + " "; + } + int i = start.getHours(); + s += (i < 10 ? "0" : "") + i; + s += ":"; + i = start.getMinutes(); + s += (i < 10 ? "0" : "") + i; + if (!start.equals(end)) { + s += " - "; + if (!DateTimeService.isSameDay(start, end)) { + s += (end.getYear() + 1900) + "." + (end.getMonth() + 1) + + "." + end.getDate() + " "; + } + i = end.getHours(); + s += (i < 10 ? "0" : "") + i; + s += ":"; + i = end.getMinutes(); + s += (i < 10 ? "0" : "") + i; + } + s += " "; + } + if (title != null) { + s += title; + } + return s; + } } \ No newline at end of file diff --git a/src/com/itmill/toolkit/terminal/gwt/client/ui/CalendarPanel.java b/src/com/itmill/toolkit/terminal/gwt/client/ui/CalendarPanel.java index 0fc60e25dc..216bf95a3a 100644 --- a/src/com/itmill/toolkit/terminal/gwt/client/ui/CalendarPanel.java +++ b/src/com/itmill/toolkit/terminal/gwt/client/ui/CalendarPanel.java @@ -19,413 +19,428 @@ import com.itmill.toolkit.terminal.gwt.client.DateTimeService; import com.itmill.toolkit.terminal.gwt.client.LocaleService; public class CalendarPanel extends FlexTable implements MouseListener, - ClickListener { - - private IDateField datefield; - - private IEventButton prevYear; - - private IEventButton nextYear; - - private IEventButton prevMonth; - - private IEventButton nextMonth; - - private Time time; - - private Date minDate = null; - - private Date maxDate = null; - - private CalendarEntrySource entrySource; - - /* Needed to identify resolution changes */ - private int resolution = IDateField.RESOLUTION_YEAR; - - /* Needed to identify locale changes */ - private String locale = LocaleService.getDefaultLocale(); - - public CalendarPanel(IDateField parent) { - datefield = parent; - setStyleName(datefield.CLASSNAME + "-calendarpanel"); - // buildCalendar(true); - addTableListener(new DateClickListener(this)); - } - - public CalendarPanel(IDateField parent, Date min, Date max) { - datefield = parent; - setStyleName(datefield.CLASSNAME + "-calendarpanel"); - // buildCalendar(true); - addTableListener(new DateClickListener(this)); - } - - private void buildCalendar(boolean forceRedraw) { - boolean needsMonth = datefield.getCurrentResolution() > IDateField.RESOLUTION_YEAR; - boolean needsBody = datefield.getCurrentResolution() >= IDateField.RESOLUTION_DAY; - boolean needsTime = datefield.getCurrentResolution() >= IDateField.RESOLUTION_HOUR; - buildCalendarHeader(forceRedraw, needsMonth); - clearCalendarBody(!needsBody); - if (needsBody) - buildCalendarBody(); - if (needsTime) - buildTime(forceRedraw); - else if (time != null) { - remove(time); - time = null; - } - } - - private void clearCalendarBody(boolean remove) { - if (!remove) { - for (int row = 2; row < 8; row++) { - for (int col = 0; col < 7; col++) { - setHTML(row, col, " "); - } - } - } else if (getRowCount() > 2) { - while (getRowCount() > 2) - removeRow(2); - } - } - - private void buildCalendarHeader(boolean forceRedraw, boolean needsMonth) { - // Can't draw a calendar without a date - if (datefield.getCurrentDate() == null) - datefield.setCurrentDate(new Date()); - - if (forceRedraw) { - if (prevMonth == null) { // Only do once - prevYear = new IEventButton(); - prevYear.setHTML("«"); - prevYear.setStyleName("i-button-prevyear"); - nextYear = new IEventButton(); - nextYear.setHTML("»"); - nextYear.setStyleName("i-button-nextyear"); - prevYear.addMouseListener(this); - nextYear.addMouseListener(this); - prevYear.addClickListener(this); - nextYear.addClickListener(this); - setWidget(0, 0, prevYear); - setWidget(0, 4, nextYear); - - if (needsMonth) { - prevMonth = new IEventButton(); - prevMonth.setHTML("‹"); - prevMonth.setStyleName("i-button-prevmonth"); - nextMonth = new IEventButton(); - nextMonth.setHTML("›"); - nextMonth.setStyleName("i-button-nextmonth"); - prevMonth.addMouseListener(this); - nextMonth.addMouseListener(this); - prevMonth.addClickListener(this); - nextMonth.addClickListener(this); - setWidget(0, 3, nextMonth); - setWidget(0, 1, prevMonth); - } - - getFlexCellFormatter().setColSpan(0, 2, 3); - getRowFormatter().addStyleName(0, - datefield.CLASSNAME + "-calendarpanel-header"); - } else if (!needsMonth) { - // Remove month traverse buttons - prevMonth.removeClickListener(this); - prevMonth.removeMouseListener(this); - nextMonth.removeClickListener(this); - nextMonth.removeMouseListener(this); - remove(prevMonth); - remove(nextMonth); - prevMonth = null; - nextMonth = null; - } - - // Print weekday names - int firstDay = datefield.getDateTimeService().getFirstDayOfWeek(); - for (int i = 0; i < 7; i++) { - int day = i + firstDay; - if (day > 6) - day = 0; - if (datefield.getCurrentResolution() > IDateField.RESOLUTION_MONTH) - setHTML(1, i, "" - + datefield.getDateTimeService().getShortDay(day) - + ""); - else - setHTML(1, i, ""); - } - } - - String monthName = needsMonth ? datefield.getDateTimeService() - .getMonth(datefield.getCurrentDate().getMonth()) : ""; - int year = datefield.getCurrentDate().getYear() + 1900; - setHTML(0, 2, "" + monthName + " " + year - + ""); - } - - private void buildCalendarBody() { - Date date = datefield.getCurrentDate(); - if (date == null) - date = new Date(); - int startWeekDay = datefield.getDateTimeService().getStartWeekDay(date); - int numDays = DateTimeService.getNumberOfDaysInMonth(date); - int dayCount = 0; - Date today = new Date(); - Date curr = new Date(date.getTime()); - for (int row = 2; row < 8; row++) { - for (int col = 0; col < 7; col++) { - if (!(row == 2 && col < startWeekDay)) { - if (dayCount < numDays) { - int selectedDate = ++dayCount; - String title = ""; - if (this.entrySource != null) { - curr.setDate(dayCount); - List entries = this.entrySource.getEntries(curr, - IDateField.RESOLUTION_DAY); - if (entries != null) { - for (Iterator it = entries.iterator(); it - .hasNext();) { - CalendarEntry entry = (CalendarEntry) it - .next(); - title += (title.length() > 0 ? ", " : "") - + entry.getStringForDate(curr); - } - } - } - String baseclass = datefield.CLASSNAME - + "-calendarpanel-day"; - String cssClass = baseclass; - if (!isEnabledDate(curr)) { - cssClass += " " + baseclass + "-disabled"; - } - if (date.getDate() == dayCount) { - cssClass += " " + baseclass + "-selected"; - } - if (today.getDate() == dayCount - && today.getMonth() == date.getMonth() - && today.getYear() == date.getYear()) { - cssClass += " " + baseclass + "-today"; - } - if (title.length() > 0) - cssClass += " " + baseclass + "-entry"; - setHTML(row, col, "" - + selectedDate + ""); - } else { - break; - } - - } - } - } - } - - private void buildTime(boolean forceRedraw) { - if (time == null) { - time = new Time(datefield); - setText(8, 0, ""); // Add new row - getFlexCellFormatter().setColSpan(8, 0, 7); - setWidget(8, 0, time); - } - time.updateTime(forceRedraw); - } - - /** - * - * @param forceRedraw - * Build all from scratch, in case of e.g. locale changes - */ - public void updateCalendar() { - // Locale and resolution changes force a complete redraw - buildCalendar(locale != datefield.getCurrentLocale() - || resolution != datefield.getCurrentResolution()); - if (datefield instanceof ITextualDate) - ((ITextualDate) datefield).buildDate(); - locale = datefield.getCurrentLocale(); - resolution = datefield.getCurrentResolution(); - } - - public void onClick(Widget sender) { - processClickEvent(sender); - } - - private boolean isEnabledDate(Date date) { - if ((this.minDate != null && date.before(this.minDate)) - || (this.maxDate != null && date.after(this.maxDate))) { - return false; - } - return true; - } - - private void processClickEvent(Widget sender) { - if (!datefield.isEnabled() || datefield.isReadonly()) - return; - - if (sender == prevYear) { - datefield.getCurrentDate().setYear( - datefield.getCurrentDate().getYear() - 1); - datefield.getClient().updateVariable(datefield.getId(), "year", - datefield.getCurrentDate().getYear() + 1900, - datefield.isImmediate()); - updateCalendar(); - } else if (sender == nextYear) { - datefield.getCurrentDate().setYear( - datefield.getCurrentDate().getYear() + 1); - datefield.getClient().updateVariable(datefield.getId(), "year", - datefield.getCurrentDate().getYear() + 1900, - datefield.isImmediate()); - updateCalendar(); - } else if (sender == prevMonth) { - datefield.getCurrentDate().setMonth( - datefield.getCurrentDate().getMonth() - 1); - datefield.getClient().updateVariable(datefield.getId(), "month", - datefield.getCurrentDate().getMonth() + 1, - datefield.isImmediate()); - updateCalendar(); - } else if (sender == nextMonth) { - datefield.getCurrentDate().setMonth( - datefield.getCurrentDate().getMonth() + 1); - datefield.getClient().updateVariable(datefield.getId(), "month", - datefield.getCurrentDate().getMonth() + 1, - datefield.isImmediate()); - updateCalendar(); - } - } - - private Timer timer; - - public void onMouseDown(final Widget sender, int x, int y) { - if (sender instanceof IEventButton) { - timer = new Timer() { - public void run() { - processClickEvent(sender); - } - }; - timer.scheduleRepeating(100); - } - } - - public void onMouseEnter(Widget sender) { - } - - public void onMouseLeave(Widget sender) { - if (timer != null) - timer.cancel(); - } - - public void onMouseMove(Widget sender, int x, int y) { - } - - public void onMouseUp(Widget sender, int x, int y) { - if (timer != null) - timer.cancel(); - } - - private class IEventButton extends IButton implements SourcesMouseEvents { - - private MouseListenerCollection mouseListeners; - - public IEventButton() { - super(); - sinkEvents(Event.FOCUSEVENTS | Event.KEYEVENTS | Event.ONCLICK - | Event.MOUSEEVENTS); - } - - public void addMouseListener(MouseListener listener) { - if (mouseListeners == null) { - mouseListeners = new MouseListenerCollection(); - } - mouseListeners.add(listener); - } - - public void removeMouseListener(MouseListener listener) { - if (mouseListeners != null) - mouseListeners.remove(listener); - } - - public void onBrowserEvent(Event event) { - super.onBrowserEvent(event); - switch (DOM.eventGetType(event)) { - case Event.ONMOUSEDOWN: - case Event.ONMOUSEUP: - case Event.ONMOUSEMOVE: - case Event.ONMOUSEOVER: - case Event.ONMOUSEOUT: - if (mouseListeners != null) { - mouseListeners.fireMouseEvent(this, event); - } - break; - } - } - } - - private class DateClickListener implements TableListener { - - private CalendarPanel cal; - - public DateClickListener(CalendarPanel panel) { - cal = panel; - } - - public void onCellClicked(SourcesTableEvents sender, int row, int col) { - if (sender != cal || row < 2 || row > 7 - || !cal.datefield.isEnabled() || cal.datefield.isReadonly()) - return; - - String text = cal.getText(row, col); - if (text.equals(" ")) - return; - - try { - Integer day = new Integer(text); - Date newDate = new Date(cal.datefield.getCurrentDate().getTime()); - newDate.setDate(day.intValue()); - if (!isEnabledDate(newDate)) { - return; - } - cal.datefield.getCurrentDate().setTime(newDate.getTime()); - cal.datefield.getClient().updateVariable(cal.datefield.getId(), - "day", cal.datefield.getCurrentDate().getDate(), - cal.datefield.isImmediate()); - - updateCalendar(); - } catch(NumberFormatException e) { - // Not a number, ignore and stop here - return; - } - } - - } - - public void setLimits(Date min, Date max) { - if (min != null) { - Date d = new Date(min.getTime()); - d.setHours(0); - d.setMinutes(0); - d.setSeconds(1); - this.minDate = d; - } else { - this.minDate = null; - } - if (max != null) { - Date d = new Date(max.getTime()); - d.setHours(24); - d.setMinutes(59); - d.setSeconds(59); - this.maxDate = d; - } else { - this.maxDate = null; - } - } - - public void setCalendarEntrySource(CalendarEntrySource entrySource) { - this.entrySource = entrySource; - } - - public CalendarEntrySource getCalendarEntrySource() { - return this.entrySource; - } - - public interface CalendarEntrySource { - public List getEntries(Date date, int resolution); - } + ClickListener { + + private IDateField datefield; + + private IEventButton prevYear; + + private IEventButton nextYear; + + private IEventButton prevMonth; + + private IEventButton nextMonth; + + private Time time; + + private Date minDate = null; + + private Date maxDate = null; + + private CalendarEntrySource entrySource; + + /* Needed to identify resolution changes */ + private int resolution = IDateField.RESOLUTION_YEAR; + + /* Needed to identify locale changes */ + private String locale = LocaleService.getDefaultLocale(); + + public CalendarPanel(IDateField parent) { + datefield = parent; + setStyleName(IDateField.CLASSNAME + "-calendarpanel"); + // buildCalendar(true); + addTableListener(new DateClickListener(this)); + } + + public CalendarPanel(IDateField parent, Date min, Date max) { + datefield = parent; + setStyleName(IDateField.CLASSNAME + "-calendarpanel"); + // buildCalendar(true); + addTableListener(new DateClickListener(this)); + } + + private void buildCalendar(boolean forceRedraw) { + boolean needsMonth = datefield.getCurrentResolution() > IDateField.RESOLUTION_YEAR; + boolean needsBody = datefield.getCurrentResolution() >= IDateField.RESOLUTION_DAY; + boolean needsTime = datefield.getCurrentResolution() >= IDateField.RESOLUTION_HOUR; + buildCalendarHeader(forceRedraw, needsMonth); + clearCalendarBody(!needsBody); + if (needsBody) { + buildCalendarBody(); + } + if (needsTime) { + buildTime(forceRedraw); + } else if (time != null) { + remove(time); + time = null; + } + } + + private void clearCalendarBody(boolean remove) { + if (!remove) { + for (int row = 2; row < 8; row++) { + for (int col = 0; col < 7; col++) { + setHTML(row, col, " "); + } + } + } else if (getRowCount() > 2) { + while (getRowCount() > 2) { + removeRow(2); + } + } + } + + private void buildCalendarHeader(boolean forceRedraw, boolean needsMonth) { + // Can't draw a calendar without a date + if (datefield.getCurrentDate() == null) { + datefield.setCurrentDate(new Date()); + } + + if (forceRedraw) { + if (prevMonth == null) { // Only do once + prevYear = new IEventButton(); + prevYear.setHTML("«"); + prevYear.setStyleName("i-button-prevyear"); + nextYear = new IEventButton(); + nextYear.setHTML("»"); + nextYear.setStyleName("i-button-nextyear"); + prevYear.addMouseListener(this); + nextYear.addMouseListener(this); + prevYear.addClickListener(this); + nextYear.addClickListener(this); + setWidget(0, 0, prevYear); + setWidget(0, 4, nextYear); + + if (needsMonth) { + prevMonth = new IEventButton(); + prevMonth.setHTML("‹"); + prevMonth.setStyleName("i-button-prevmonth"); + nextMonth = new IEventButton(); + nextMonth.setHTML("›"); + nextMonth.setStyleName("i-button-nextmonth"); + prevMonth.addMouseListener(this); + nextMonth.addMouseListener(this); + prevMonth.addClickListener(this); + nextMonth.addClickListener(this); + setWidget(0, 3, nextMonth); + setWidget(0, 1, prevMonth); + } + + getFlexCellFormatter().setColSpan(0, 2, 3); + getRowFormatter().addStyleName(0, + IDateField.CLASSNAME + "-calendarpanel-header"); + } else if (!needsMonth) { + // Remove month traverse buttons + prevMonth.removeClickListener(this); + prevMonth.removeMouseListener(this); + nextMonth.removeClickListener(this); + nextMonth.removeMouseListener(this); + remove(prevMonth); + remove(nextMonth); + prevMonth = null; + nextMonth = null; + } + + // Print weekday names + int firstDay = datefield.getDateTimeService().getFirstDayOfWeek(); + for (int i = 0; i < 7; i++) { + int day = i + firstDay; + if (day > 6) { + day = 0; + } + if (datefield.getCurrentResolution() > IDateField.RESOLUTION_MONTH) { + setHTML(1, i, "" + + datefield.getDateTimeService().getShortDay(day) + + ""); + } else { + setHTML(1, i, ""); + } + } + } + + String monthName = needsMonth ? datefield.getDateTimeService() + .getMonth(datefield.getCurrentDate().getMonth()) : ""; + int year = datefield.getCurrentDate().getYear() + 1900; + setHTML(0, 2, "" + monthName + " " + year + + ""); + } + + private void buildCalendarBody() { + Date date = datefield.getCurrentDate(); + if (date == null) { + date = new Date(); + } + int startWeekDay = datefield.getDateTimeService().getStartWeekDay(date); + int numDays = DateTimeService.getNumberOfDaysInMonth(date); + int dayCount = 0; + Date today = new Date(); + Date curr = new Date(date.getTime()); + for (int row = 2; row < 8; row++) { + for (int col = 0; col < 7; col++) { + if (!(row == 2 && col < startWeekDay)) { + if (dayCount < numDays) { + int selectedDate = ++dayCount; + String title = ""; + if (entrySource != null) { + curr.setDate(dayCount); + List entries = entrySource.getEntries(curr, + IDateField.RESOLUTION_DAY); + if (entries != null) { + for (Iterator it = entries.iterator(); it + .hasNext();) { + CalendarEntry entry = (CalendarEntry) it + .next(); + title += (title.length() > 0 ? ", " : "") + + entry.getStringForDate(curr); + } + } + } + String baseclass = IDateField.CLASSNAME + + "-calendarpanel-day"; + String cssClass = baseclass; + if (!isEnabledDate(curr)) { + cssClass += " " + baseclass + "-disabled"; + } + if (date.getDate() == dayCount) { + cssClass += " " + baseclass + "-selected"; + } + if (today.getDate() == dayCount + && today.getMonth() == date.getMonth() + && today.getYear() == date.getYear()) { + cssClass += " " + baseclass + "-today"; + } + if (title.length() > 0) { + cssClass += " " + baseclass + "-entry"; + } + setHTML(row, col, "" + + selectedDate + ""); + } else { + break; + } + + } + } + } + } + + private void buildTime(boolean forceRedraw) { + if (time == null) { + time = new Time(datefield); + setText(8, 0, ""); // Add new row + getFlexCellFormatter().setColSpan(8, 0, 7); + setWidget(8, 0, time); + } + time.updateTime(forceRedraw); + } + + /** + * + * @param forceRedraw + * Build all from scratch, in case of e.g. locale changes + */ + public void updateCalendar() { + // Locale and resolution changes force a complete redraw + buildCalendar(locale != datefield.getCurrentLocale() + || resolution != datefield.getCurrentResolution()); + if (datefield instanceof ITextualDate) { + ((ITextualDate) datefield).buildDate(); + } + locale = datefield.getCurrentLocale(); + resolution = datefield.getCurrentResolution(); + } + + public void onClick(Widget sender) { + processClickEvent(sender); + } + + private boolean isEnabledDate(Date date) { + if ((minDate != null && date.before(minDate)) + || (maxDate != null && date.after(maxDate))) { + return false; + } + return true; + } + + private void processClickEvent(Widget sender) { + if (!datefield.isEnabled() || datefield.isReadonly()) { + return; + } + + if (sender == prevYear) { + datefield.getCurrentDate().setYear( + datefield.getCurrentDate().getYear() - 1); + datefield.getClient().updateVariable(datefield.getId(), "year", + datefield.getCurrentDate().getYear() + 1900, + datefield.isImmediate()); + updateCalendar(); + } else if (sender == nextYear) { + datefield.getCurrentDate().setYear( + datefield.getCurrentDate().getYear() + 1); + datefield.getClient().updateVariable(datefield.getId(), "year", + datefield.getCurrentDate().getYear() + 1900, + datefield.isImmediate()); + updateCalendar(); + } else if (sender == prevMonth) { + datefield.getCurrentDate().setMonth( + datefield.getCurrentDate().getMonth() - 1); + datefield.getClient().updateVariable(datefield.getId(), "month", + datefield.getCurrentDate().getMonth() + 1, + datefield.isImmediate()); + updateCalendar(); + } else if (sender == nextMonth) { + datefield.getCurrentDate().setMonth( + datefield.getCurrentDate().getMonth() + 1); + datefield.getClient().updateVariable(datefield.getId(), "month", + datefield.getCurrentDate().getMonth() + 1, + datefield.isImmediate()); + updateCalendar(); + } + } + + private Timer timer; + + public void onMouseDown(final Widget sender, int x, int y) { + if (sender instanceof IEventButton) { + timer = new Timer() { + public void run() { + processClickEvent(sender); + } + }; + timer.scheduleRepeating(100); + } + } + + public void onMouseEnter(Widget sender) { + } + + public void onMouseLeave(Widget sender) { + if (timer != null) { + timer.cancel(); + } + } + + public void onMouseMove(Widget sender, int x, int y) { + } + + public void onMouseUp(Widget sender, int x, int y) { + if (timer != null) { + timer.cancel(); + } + } + + private class IEventButton extends IButton implements SourcesMouseEvents { + + private MouseListenerCollection mouseListeners; + + public IEventButton() { + super(); + sinkEvents(Event.FOCUSEVENTS | Event.KEYEVENTS | Event.ONCLICK + | Event.MOUSEEVENTS); + } + + public void addMouseListener(MouseListener listener) { + if (mouseListeners == null) { + mouseListeners = new MouseListenerCollection(); + } + mouseListeners.add(listener); + } + + public void removeMouseListener(MouseListener listener) { + if (mouseListeners != null) { + mouseListeners.remove(listener); + } + } + + public void onBrowserEvent(Event event) { + super.onBrowserEvent(event); + switch (DOM.eventGetType(event)) { + case Event.ONMOUSEDOWN: + case Event.ONMOUSEUP: + case Event.ONMOUSEMOVE: + case Event.ONMOUSEOVER: + case Event.ONMOUSEOUT: + if (mouseListeners != null) { + mouseListeners.fireMouseEvent(this, event); + } + break; + } + } + } + + private class DateClickListener implements TableListener { + + private CalendarPanel cal; + + public DateClickListener(CalendarPanel panel) { + cal = panel; + } + + public void onCellClicked(SourcesTableEvents sender, int row, int col) { + if (sender != cal || row < 2 || row > 7 + || !cal.datefield.isEnabled() || cal.datefield.isReadonly()) { + return; + } + + String text = cal.getText(row, col); + if (text.equals(" ")) { + return; + } + + try { + Integer day = new Integer(text); + Date newDate = new Date(cal.datefield.getCurrentDate() + .getTime()); + newDate.setDate(day.intValue()); + if (!isEnabledDate(newDate)) { + return; + } + cal.datefield.getCurrentDate().setTime(newDate.getTime()); + cal.datefield.getClient().updateVariable(cal.datefield.getId(), + "day", cal.datefield.getCurrentDate().getDate(), + cal.datefield.isImmediate()); + + updateCalendar(); + } catch (NumberFormatException e) { + // Not a number, ignore and stop here + return; + } + } + + } + + public void setLimits(Date min, Date max) { + if (min != null) { + Date d = new Date(min.getTime()); + d.setHours(0); + d.setMinutes(0); + d.setSeconds(1); + minDate = d; + } else { + minDate = null; + } + if (max != null) { + Date d = new Date(max.getTime()); + d.setHours(24); + d.setMinutes(59); + d.setSeconds(59); + maxDate = d; + } else { + maxDate = null; + } + } + + public void setCalendarEntrySource(CalendarEntrySource entrySource) { + this.entrySource = entrySource; + } + + public CalendarEntrySource getCalendarEntrySource() { + return entrySource; + } + + public interface CalendarEntrySource { + public List getEntries(Date date, int resolution); + } } diff --git a/src/com/itmill/toolkit/terminal/gwt/client/ui/ICheckBox.java b/src/com/itmill/toolkit/terminal/gwt/client/ui/ICheckBox.java index 50e1b76e6d..8d80561231 100644 --- a/src/com/itmill/toolkit/terminal/gwt/client/ui/ICheckBox.java +++ b/src/com/itmill/toolkit/terminal/gwt/client/ui/ICheckBox.java @@ -11,91 +11,93 @@ import com.itmill.toolkit.terminal.gwt.client.Paintable; import com.itmill.toolkit.terminal.gwt.client.UIDL; public class ICheckBox extends com.google.gwt.user.client.ui.CheckBox implements - Paintable { - - public static final String CLASSNAME = "i-checkbox"; - - String id; - - boolean immediate; - - ApplicationConnection client; - - private Element errorIndicatorElement; - - private ErrorMessage errorMessage; - - public ICheckBox() { - setStyleName(CLASSNAME); - addClickListener(new ClickListener() { - - public void onClick(Widget sender) { - if (id == null || client == null) - return; - client.updateVariable(id, "state", isChecked(), immediate); - } - - }); - - } - - public void updateFromUIDL(UIDL uidl, ApplicationConnection client) { - // Save details - this.client = client; - id = uidl.getId(); - - // Ensure correct implementation - if (client.updateComponent(this, uidl, false)) - return; - - if (uidl.hasAttribute("error")) { - UIDL errorUidl = uidl.getErrors(); - - if (errorIndicatorElement == null) { - errorIndicatorElement = DOM.createDiv(); - DOM.sinkEvents(errorIndicatorElement, Event.MOUSEEVENTS); - DOM.setElementProperty(errorIndicatorElement, "className", - "i-errorindicator"); - DOM.appendChild(getElement(), errorIndicatorElement); - } - if (errorMessage == null) - errorMessage = new ErrorMessage(); - errorMessage.updateFromUIDL(errorUidl); - - } else if (errorIndicatorElement != null) { - DOM.setStyleAttribute(errorIndicatorElement, "display", "none"); - } - - if(uidl.hasAttribute("description")) { - setTitle(uidl.getStringAttribute("description")); - } - - - // Set text - setText(uidl.getStringAttribute("caption")); - setChecked(uidl.getBooleanVariable("state")); - immediate = uidl.getBooleanAttribute("immediate"); - } - - public void onBrowserEvent(Event event) { - super.onBrowserEvent(event); - Element target = DOM.eventGetTarget(event); - if (errorIndicatorElement != null - && DOM.compare(target, errorIndicatorElement)) { - switch (DOM.eventGetType(event)) { - case Event.ONMOUSEOVER: - errorMessage.showAt(errorIndicatorElement); - break; - case Event.ONMOUSEOUT: - errorMessage.hide(); - break; - case Event.ONCLICK: - ApplicationConnection.getConsole().log( - DOM.getInnerHTML(errorMessage.getElement())); - default: - break; - } - } - - } + Paintable { + + public static final String CLASSNAME = "i-checkbox"; + + String id; + + boolean immediate; + + ApplicationConnection client; + + private Element errorIndicatorElement; + + private ErrorMessage errorMessage; + + public ICheckBox() { + setStyleName(CLASSNAME); + addClickListener(new ClickListener() { + + public void onClick(Widget sender) { + if (id == null || client == null) { + return; + } + client.updateVariable(id, "state", isChecked(), immediate); + } + + }); + + } + + public void updateFromUIDL(UIDL uidl, ApplicationConnection client) { + // Save details + this.client = client; + id = uidl.getId(); + + // Ensure correct implementation + if (client.updateComponent(this, uidl, false)) { + return; + } + + if (uidl.hasAttribute("error")) { + UIDL errorUidl = uidl.getErrors(); + + if (errorIndicatorElement == null) { + errorIndicatorElement = DOM.createDiv(); + DOM.sinkEvents(errorIndicatorElement, Event.MOUSEEVENTS); + DOM.setElementProperty(errorIndicatorElement, "className", + "i-errorindicator"); + DOM.appendChild(getElement(), errorIndicatorElement); + } + if (errorMessage == null) { + errorMessage = new ErrorMessage(); + } + errorMessage.updateFromUIDL(errorUidl); + + } else if (errorIndicatorElement != null) { + DOM.setStyleAttribute(errorIndicatorElement, "display", "none"); + } + + if (uidl.hasAttribute("description")) { + setTitle(uidl.getStringAttribute("description")); + } + + // Set text + setText(uidl.getStringAttribute("caption")); + setChecked(uidl.getBooleanVariable("state")); + immediate = uidl.getBooleanAttribute("immediate"); + } + + public void onBrowserEvent(Event event) { + super.onBrowserEvent(event); + Element target = DOM.eventGetTarget(event); + if (errorIndicatorElement != null + && DOM.compare(target, errorIndicatorElement)) { + switch (DOM.eventGetType(event)) { + case Event.ONMOUSEOVER: + errorMessage.showAt(errorIndicatorElement); + break; + case Event.ONMOUSEOUT: + errorMessage.hide(); + break; + case Event.ONCLICK: + ApplicationConnection.getConsole().log( + DOM.getInnerHTML(errorMessage.getElement())); + default: + break; + } + } + + } } diff --git a/src/com/itmill/toolkit/terminal/gwt/client/ui/ICustomComponent.java b/src/com/itmill/toolkit/terminal/gwt/client/ui/ICustomComponent.java index e75adb340d..73deb42e18 100644 --- a/src/com/itmill/toolkit/terminal/gwt/client/ui/ICustomComponent.java +++ b/src/com/itmill/toolkit/terminal/gwt/client/ui/ICustomComponent.java @@ -8,28 +8,28 @@ import com.itmill.toolkit.terminal.gwt.client.UIDL; public class ICustomComponent extends SimplePanel implements Paintable { - private static final String CLASSNAME = "i-customcomponent"; - - public ICustomComponent() { - super(); - setStyleName(CLASSNAME); - } - - public void updateFromUIDL(UIDL uidl, ApplicationConnection client) { - - UIDL child = uidl.getChildUIDL(0); - if (child != null) { - Paintable p = (Paintable) client.getWidget(child); - if (p != getWidget()) { - if (getWidget() != null) { - client.unregisterPaintable((Paintable) getWidget()); - clear(); - } - setWidget((Widget) p); - } - p.updateFromUIDL(child, client); - } - - } + private static final String CLASSNAME = "i-customcomponent"; + + public ICustomComponent() { + super(); + setStyleName(CLASSNAME); + } + + public void updateFromUIDL(UIDL uidl, ApplicationConnection client) { + + UIDL child = uidl.getChildUIDL(0); + if (child != null) { + Paintable p = (Paintable) client.getWidget(child); + if (p != getWidget()) { + if (getWidget() != null) { + client.unregisterPaintable((Paintable) getWidget()); + clear(); + } + setWidget((Widget) p); + } + p.updateFromUIDL(child, client); + } + + } } diff --git a/src/com/itmill/toolkit/terminal/gwt/client/ui/ICustomLayout.java b/src/com/itmill/toolkit/terminal/gwt/client/ui/ICustomLayout.java index 7b8264b8eb..38637e6bed 100644 --- a/src/com/itmill/toolkit/terminal/gwt/client/ui/ICustomLayout.java +++ b/src/com/itmill/toolkit/terminal/gwt/client/ui/ICustomLayout.java @@ -23,425 +23,425 @@ import com.itmill.toolkit.terminal.gwt.client.Util; * */ public class ICustomLayout extends ComplexPanel implements Paintable, - Container, ContainerResizedListener { - - public static final String CLASSNAME = "i-customlayout"; - - /** Location-name to containing element in DOM map */ - private HashMap locationToElement = new HashMap(); - - /** Location-name to contained widget map */ - private HashMap locationToWidget = new HashMap(); - - /** Widget to captionwrapper map */ - private HashMap widgetToCaptionWrapper = new HashMap(); - - /** Currently rendered style */ - String currentTemplate; - - /** Unexecuted scripts loaded from the template */ - private String scripts = ""; - - /** Paintable ID of this paintable */ - private String pid; - - private ApplicationConnection client; - - public ICustomLayout() { - setElement(DOM.createDiv()); - // Clear any unwanted styling - DOM.setStyleAttribute(getElement(), "border", "none"); - DOM.setStyleAttribute(getElement(), "margin", "0"); - DOM.setStyleAttribute(getElement(), "padding", "0"); - DOM.setStyleAttribute(getElement(), "overflow", "hidden"); - setStyleName(CLASSNAME); - } - - /** - * Sets widget to given location. - * - * If location already contains a widget it will be removed. - * - * @param widget - * Widget to be set into location. - * @param location - * location name where widget will be added - * - * @throws IllegalArgumentException - * if no such location is found in the layout. - */ - public void setWidget(Widget widget, String location) { - - if (widget == null) { - return; - } - - // If no given location is found in the layout, and exception is throws - Element elem = (Element) locationToElement.get(location); - if (elem == null && hasTemplate()) { - throw new IllegalArgumentException("No location " + location - + " found"); - } - - // Get previous widget - Widget previous = (Widget) locationToWidget.get(location); - // NOP if given widget already exists in this location - if (previous == widget) { - return; - } - remove(previous); - - // if template is missing add element in order - if (!hasTemplate()) { - elem = getElement(); - } - - // Add widget to location - super.add(widget, elem); - locationToWidget.put(location, widget); - } - - /** Update the layout from UIDL */ - public void updateFromUIDL(UIDL uidl, ApplicationConnection client) { - this.client = client; - // Client manages general cases - if (client.updateComponent(this, uidl, false)) { - return; - } - - // Update PID - pid = uidl.getId(); - if (!hasTemplate()) { - // Update HTML template only once - initializeHTML(uidl, client); - } - - // Set size - if (uidl.hasAttribute("width")) { - setWidth(uidl.getStringAttribute("width")); - } else { - setWidth("100%"); - } - if (uidl.hasAttribute("height")) { - setHeight(uidl.getStringAttribute("height")); - } else { - setHeight("100%"); - } - - // Evaluate scripts - eval(scripts); - scripts = null; - - // For all contained widgets - for (Iterator i = uidl.getChildIterator(); i.hasNext();) { - UIDL uidlForChild = (UIDL) i.next(); - if (uidlForChild.getTag().equals("location")) { - String location = uidlForChild.getStringAttribute("name"); - Widget child = client.getWidget(uidlForChild.getChildUIDL(0)); - try { - setWidget(child, location); - ((Paintable) child).updateFromUIDL(uidlForChild - .getChildUIDL(0), client); - } catch (IllegalArgumentException e) { - // If no location is found, this component is not visible - } - } - } - - iLayout(); - } - - /** Initialize HTML-layout. */ - private void initializeHTML(UIDL uidl, ApplicationConnection client) { - - String newTemplate = uidl.getStringAttribute("template"); - - // Get the HTML-template from client - String template = client - .getResource("layouts/" + newTemplate + ".html"); - if (template == null) { - template = "Layout file layouts/" - + newTemplate - + ".html is missing. Components will be drawn for debug purposes."; - } else { - currentTemplate = newTemplate; - } - - // Connect body of the template to DOM - template = extractBodyAndScriptsFromTemplate(template); - DOM.setInnerHTML(getElement(), template); - - // Remap locations to elements - locationToElement.clear(); - scanForLocations(getElement()); - - // Remap image srcs in layout - Widget parent = getParent(); - while (parent != null && !(parent instanceof IView)) { - parent = parent.getParent(); - } - if (parent != null && ((IView) parent).getTheme() != null) { - String prefix; - if (uriEndsWithSlash()) { - prefix = "../ITMILL/themes/"; - } else { - prefix = "ITMILL/themes/"; - } - prefixImgSrcs(getElement(), prefix + ((IView) parent).getTheme() - + "/layouts/"); - } else { - throw (new IllegalStateException( - "Could not find IView; maybe updateFromUIDL() was called before attaching the widget?")); - } - - publishResizedFunction(DOM.getFirstChild(getElement())); - - } - - private native boolean uriEndsWithSlash() /*-{ - var path = $wnd.location.pathname; - if(path.charAt(path.length - 1) == "/") - return true; - return false; - }-*/; - - private boolean hasTemplate() { - if (currentTemplate == null) { - return false; - } else { - return true; - } - } - - /** Collect locations from template */ - private void scanForLocations(Element elem) { - - String location = getLocation(elem); - if (location != null) { - locationToElement.put(location, elem); - DOM.setInnerHTML(elem, ""); - } else { - int len = DOM.getChildCount(elem); - for (int i = 0; i < len; i++) { - scanForLocations(DOM.getChild(elem, i)); - } - } - } - - /** Get the location attribute for given element */ - private static native String getLocation(Element elem) /*-{ - return elem.getAttribute("location"); - }-*/; - - /** Evaluate given script in browser document */ - private static native void eval(String script) /*-{ - try { - if (script != null) - eval("{ var document = $doc; var window = $wnd; "+ script + "}"); - } catch (e) { - } - }-*/; - - /** Prefix all img tag srcs with given prefix. */ - private static native void prefixImgSrcs(Element e, String srcPrefix) /*-{ - try { - var divs = e.getElementsByTagName("img"); - var base = "" + $doc.location; - var l = base.length-1; - while (l >= 0 && base.charAt(l) != "/") l--; - base = base.substring(0,l+1); - for (var i = 0; i < divs.length; i++) { - var div = divs[i]; - var src = div.getAttribute("src"); - if (src.indexOf(base) == 0) div.setAttribute("src",base + srcPrefix + src.substring(base.length)); - else if (src.indexOf("http") != 0) div.setAttribute("src",srcPrefix + src); - } - } catch (e) { alert(e + " " + srcPrefix);} - }-*/; - - /** - * Extract body part and script tags from raw html-template. - * - * Saves contents of all script-tags to private property: scripts. Returns - * contents of the body part for the html without script-tags. Also replaces - * all _UID_ tags with an unique id-string. - * - * @param html - * Original HTML-template received from server - * @return html that is used to create the HTMLPanel. - */ - private String extractBodyAndScriptsFromTemplate(String html) { - - // Replace UID:s - html = html.replaceAll("_UID_", pid + "__"); - - // Exctract script-tags - scripts = ""; - int endOfPrevScript = 0; - int nextPosToCheck = 0; - String lc = html.toLowerCase(); - String res = ""; - int scriptStart = lc.indexOf(" 0) { - res += html.substring(endOfPrevScript, scriptStart); - scriptStart = lc.indexOf(">", scriptStart); - int j = lc.indexOf("", scriptStart); - scripts += html.substring(scriptStart + 1, j) + ";"; - nextPosToCheck = endOfPrevScript = j + "".length(); - scriptStart = lc.indexOf("", startOfBody) + 1; - int endOfBody = lc.indexOf("", startOfBody); - if (endOfBody > startOfBody) { - res = html.substring(startOfBody, endOfBody); - } else { - res = html.substring(startOfBody); - } - } - - return res; - } - - /** Replace child components */ - public void replaceChildComponent(Widget from, Widget to) { - String location = getLocation(from); - if (location == null) { - throw new IllegalArgumentException(); - } - setWidget(to, location); - } - - /** Does this layout contain given child */ - public boolean hasChildComponent(Widget component) { - return locationToWidget.containsValue(component); - } - - /** Update caption for given widget */ - public void updateCaption(Paintable component, UIDL uidl) { - CaptionWrapper wrapper = (CaptionWrapper) widgetToCaptionWrapper - .get(component); - if (Caption.isNeeded(uidl)) { - if (wrapper == null) { - String loc = getLocation((Widget) component); - super.remove((Widget) component); - wrapper = new CaptionWrapper(component, client); - super.add(wrapper, (Element) locationToElement.get(loc)); - widgetToCaptionWrapper.put(component, wrapper); - } - wrapper.updateCaption(uidl); - } else { - if (wrapper != null) { - String loc = getLocation((Widget) component); - super.remove(wrapper); - super.add((Widget) wrapper.getPaintable(), - (Element) locationToElement.get(loc)); - widgetToCaptionWrapper.remove(component); - } - } - } - - /** Get the location of an widget */ - public String getLocation(Widget w) { - for (Iterator i = locationToWidget.keySet().iterator(); i.hasNext();) { - String location = (String) i.next(); - if (locationToWidget.get(location) == w) { - return location; - } - } - return null; - } - - /** Removes given widget from the layout */ - public boolean remove(Widget w) { - client.unregisterPaintable((Paintable) w); - String location = getLocation(w); - if (location != null) { - locationToWidget.remove(location); - } - CaptionWrapper cw = (CaptionWrapper) widgetToCaptionWrapper.get(w); - if (cw != null) { - widgetToCaptionWrapper.remove(w); - return super.remove(cw); - } else if (w != null) { - return super.remove(w); - } - return false; - } - - /** Adding widget without specifying location is not supported */ - public void add(Widget w) { - throw new UnsupportedOperationException(); - } - - /** Clear all widgets from the layout */ - public void clear() { - super.clear(); - locationToWidget.clear(); - widgetToCaptionWrapper.clear(); - } - - public void iLayout() { - if (!iLayoutJS(DOM.getFirstChild(getElement()))) { - Util.runDescendentsLayout(this); - } - } - - /** - * This method is published to JS side with the same name into first DOM - * node of custom layout. This way if one implements some resizeable - * containers in custom layout he/she can notify children after resize. - */ - public void notifyChildrenOfSizeChange() { - Util.runDescendentsLayout(this); - } - - public void onDetach() { - detachResizedFunction(DOM.getFirstChild(getElement())); - } - - private native void detachResizedFunction(Element element) - /*-{ - element.notifyChildrenOfSizeChange = null; - }-*/; - - private native void publishResizedFunction(Element element) - /*-{ - var self = this; - element.notifyChildrenOfSizeChange = function() { - self.@com.itmill.toolkit.terminal.gwt.client.ui.ICustomLayout::notifyChildrenOfSizeChange()(); - }; - }-*/; - - /** - * In custom layout one may want to run layout functions made with - * JavaScript. This function tests if one exists (with name "iLayoutJS" in - * layouts first DOM node) and runs if it. Return value is used to determine - * is children needs to be notified of size changes. - * - * @param el - * @return true if layout function was run and it returned true. - */ - private native boolean iLayoutJS(Element el) - /*-{ - if(el && el.iLayoutJS) { - try { - el.iLayoutJS(); - return true; - } catch (e) { - return false; - } - } else { - return false; - } - }-*/; + Container, ContainerResizedListener { + + public static final String CLASSNAME = "i-customlayout"; + + /** Location-name to containing element in DOM map */ + private HashMap locationToElement = new HashMap(); + + /** Location-name to contained widget map */ + private HashMap locationToWidget = new HashMap(); + + /** Widget to captionwrapper map */ + private HashMap widgetToCaptionWrapper = new HashMap(); + + /** Currently rendered style */ + String currentTemplate; + + /** Unexecuted scripts loaded from the template */ + private String scripts = ""; + + /** Paintable ID of this paintable */ + private String pid; + + private ApplicationConnection client; + + public ICustomLayout() { + setElement(DOM.createDiv()); + // Clear any unwanted styling + DOM.setStyleAttribute(getElement(), "border", "none"); + DOM.setStyleAttribute(getElement(), "margin", "0"); + DOM.setStyleAttribute(getElement(), "padding", "0"); + DOM.setStyleAttribute(getElement(), "overflow", "hidden"); + setStyleName(CLASSNAME); + } + + /** + * Sets widget to given location. + * + * If location already contains a widget it will be removed. + * + * @param widget + * Widget to be set into location. + * @param location + * location name where widget will be added + * + * @throws IllegalArgumentException + * if no such location is found in the layout. + */ + public void setWidget(Widget widget, String location) { + + if (widget == null) { + return; + } + + // If no given location is found in the layout, and exception is throws + Element elem = (Element) locationToElement.get(location); + if (elem == null && hasTemplate()) { + throw new IllegalArgumentException("No location " + location + + " found"); + } + + // Get previous widget + Widget previous = (Widget) locationToWidget.get(location); + // NOP if given widget already exists in this location + if (previous == widget) { + return; + } + remove(previous); + + // if template is missing add element in order + if (!hasTemplate()) { + elem = getElement(); + } + + // Add widget to location + super.add(widget, elem); + locationToWidget.put(location, widget); + } + + /** Update the layout from UIDL */ + public void updateFromUIDL(UIDL uidl, ApplicationConnection client) { + this.client = client; + // Client manages general cases + if (client.updateComponent(this, uidl, false)) { + return; + } + + // Update PID + pid = uidl.getId(); + if (!hasTemplate()) { + // Update HTML template only once + initializeHTML(uidl, client); + } + + // Set size + if (uidl.hasAttribute("width")) { + setWidth(uidl.getStringAttribute("width")); + } else { + setWidth("100%"); + } + if (uidl.hasAttribute("height")) { + setHeight(uidl.getStringAttribute("height")); + } else { + setHeight("100%"); + } + + // Evaluate scripts + eval(scripts); + scripts = null; + + // For all contained widgets + for (Iterator i = uidl.getChildIterator(); i.hasNext();) { + UIDL uidlForChild = (UIDL) i.next(); + if (uidlForChild.getTag().equals("location")) { + String location = uidlForChild.getStringAttribute("name"); + Widget child = client.getWidget(uidlForChild.getChildUIDL(0)); + try { + setWidget(child, location); + ((Paintable) child).updateFromUIDL(uidlForChild + .getChildUIDL(0), client); + } catch (IllegalArgumentException e) { + // If no location is found, this component is not visible + } + } + } + + iLayout(); + } + + /** Initialize HTML-layout. */ + private void initializeHTML(UIDL uidl, ApplicationConnection client) { + + String newTemplate = uidl.getStringAttribute("template"); + + // Get the HTML-template from client + String template = client + .getResource("layouts/" + newTemplate + ".html"); + if (template == null) { + template = "Layout file layouts/" + + newTemplate + + ".html is missing. Components will be drawn for debug purposes."; + } else { + currentTemplate = newTemplate; + } + + // Connect body of the template to DOM + template = extractBodyAndScriptsFromTemplate(template); + DOM.setInnerHTML(getElement(), template); + + // Remap locations to elements + locationToElement.clear(); + scanForLocations(getElement()); + + // Remap image srcs in layout + Widget parent = getParent(); + while (parent != null && !(parent instanceof IView)) { + parent = parent.getParent(); + } + if (parent != null && ((IView) parent).getTheme() != null) { + String prefix; + if (uriEndsWithSlash()) { + prefix = "../ITMILL/themes/"; + } else { + prefix = "ITMILL/themes/"; + } + prefixImgSrcs(getElement(), prefix + ((IView) parent).getTheme() + + "/layouts/"); + } else { + throw (new IllegalStateException( + "Could not find IView; maybe updateFromUIDL() was called before attaching the widget?")); + } + + publishResizedFunction(DOM.getFirstChild(getElement())); + + } + + private native boolean uriEndsWithSlash() /*-{ + var path = $wnd.location.pathname; + if(path.charAt(path.length - 1) == "/") + return true; + return false; + }-*/; + + private boolean hasTemplate() { + if (currentTemplate == null) { + return false; + } else { + return true; + } + } + + /** Collect locations from template */ + private void scanForLocations(Element elem) { + + String location = getLocation(elem); + if (location != null) { + locationToElement.put(location, elem); + DOM.setInnerHTML(elem, ""); + } else { + int len = DOM.getChildCount(elem); + for (int i = 0; i < len; i++) { + scanForLocations(DOM.getChild(elem, i)); + } + } + } + + /** Get the location attribute for given element */ + private static native String getLocation(Element elem) /*-{ + return elem.getAttribute("location"); + }-*/; + + /** Evaluate given script in browser document */ + private static native void eval(String script) /*-{ + try { + if (script != null) + eval("{ var document = $doc; var window = $wnd; "+ script + "}"); + } catch (e) { + } + }-*/; + + /** Prefix all img tag srcs with given prefix. */ + private static native void prefixImgSrcs(Element e, String srcPrefix) /*-{ + try { + var divs = e.getElementsByTagName("img"); + var base = "" + $doc.location; + var l = base.length-1; + while (l >= 0 && base.charAt(l) != "/") l--; + base = base.substring(0,l+1); + for (var i = 0; i < divs.length; i++) { + var div = divs[i]; + var src = div.getAttribute("src"); + if (src.indexOf(base) == 0) div.setAttribute("src",base + srcPrefix + src.substring(base.length)); + else if (src.indexOf("http") != 0) div.setAttribute("src",srcPrefix + src); + } + } catch (e) { alert(e + " " + srcPrefix);} + }-*/; + + /** + * Extract body part and script tags from raw html-template. + * + * Saves contents of all script-tags to private property: scripts. Returns + * contents of the body part for the html without script-tags. Also replaces + * all _UID_ tags with an unique id-string. + * + * @param html + * Original HTML-template received from server + * @return html that is used to create the HTMLPanel. + */ + private String extractBodyAndScriptsFromTemplate(String html) { + + // Replace UID:s + html = html.replaceAll("_UID_", pid + "__"); + + // Exctract script-tags + scripts = ""; + int endOfPrevScript = 0; + int nextPosToCheck = 0; + String lc = html.toLowerCase(); + String res = ""; + int scriptStart = lc.indexOf(" 0) { + res += html.substring(endOfPrevScript, scriptStart); + scriptStart = lc.indexOf(">", scriptStart); + int j = lc.indexOf("", scriptStart); + scripts += html.substring(scriptStart + 1, j) + ";"; + nextPosToCheck = endOfPrevScript = j + "".length(); + scriptStart = lc.indexOf("", startOfBody) + 1; + int endOfBody = lc.indexOf("", startOfBody); + if (endOfBody > startOfBody) { + res = html.substring(startOfBody, endOfBody); + } else { + res = html.substring(startOfBody); + } + } + + return res; + } + + /** Replace child components */ + public void replaceChildComponent(Widget from, Widget to) { + String location = getLocation(from); + if (location == null) { + throw new IllegalArgumentException(); + } + setWidget(to, location); + } + + /** Does this layout contain given child */ + public boolean hasChildComponent(Widget component) { + return locationToWidget.containsValue(component); + } + + /** Update caption for given widget */ + public void updateCaption(Paintable component, UIDL uidl) { + CaptionWrapper wrapper = (CaptionWrapper) widgetToCaptionWrapper + .get(component); + if (Caption.isNeeded(uidl)) { + if (wrapper == null) { + String loc = getLocation((Widget) component); + super.remove((Widget) component); + wrapper = new CaptionWrapper(component, client); + super.add(wrapper, (Element) locationToElement.get(loc)); + widgetToCaptionWrapper.put(component, wrapper); + } + wrapper.updateCaption(uidl); + } else { + if (wrapper != null) { + String loc = getLocation((Widget) component); + super.remove(wrapper); + super.add((Widget) wrapper.getPaintable(), + (Element) locationToElement.get(loc)); + widgetToCaptionWrapper.remove(component); + } + } + } + + /** Get the location of an widget */ + public String getLocation(Widget w) { + for (Iterator i = locationToWidget.keySet().iterator(); i.hasNext();) { + String location = (String) i.next(); + if (locationToWidget.get(location) == w) { + return location; + } + } + return null; + } + + /** Removes given widget from the layout */ + public boolean remove(Widget w) { + client.unregisterPaintable((Paintable) w); + String location = getLocation(w); + if (location != null) { + locationToWidget.remove(location); + } + CaptionWrapper cw = (CaptionWrapper) widgetToCaptionWrapper.get(w); + if (cw != null) { + widgetToCaptionWrapper.remove(w); + return super.remove(cw); + } else if (w != null) { + return super.remove(w); + } + return false; + } + + /** Adding widget without specifying location is not supported */ + public void add(Widget w) { + throw new UnsupportedOperationException(); + } + + /** Clear all widgets from the layout */ + public void clear() { + super.clear(); + locationToWidget.clear(); + widgetToCaptionWrapper.clear(); + } + + public void iLayout() { + if (!iLayoutJS(DOM.getFirstChild(getElement()))) { + Util.runDescendentsLayout(this); + } + } + + /** + * This method is published to JS side with the same name into first DOM + * node of custom layout. This way if one implements some resizeable + * containers in custom layout he/she can notify children after resize. + */ + public void notifyChildrenOfSizeChange() { + Util.runDescendentsLayout(this); + } + + public void onDetach() { + detachResizedFunction(DOM.getFirstChild(getElement())); + } + + private native void detachResizedFunction(Element element) + /*-{ + element.notifyChildrenOfSizeChange = null; + }-*/; + + private native void publishResizedFunction(Element element) + /*-{ + var self = this; + element.notifyChildrenOfSizeChange = function() { + self.@com.itmill.toolkit.terminal.gwt.client.ui.ICustomLayout::notifyChildrenOfSizeChange()(); + }; + }-*/; + + /** + * In custom layout one may want to run layout functions made with + * JavaScript. This function tests if one exists (with name "iLayoutJS" in + * layouts first DOM node) and runs if it. Return value is used to determine + * is children needs to be notified of size changes. + * + * @param el + * @return true if layout function was run and it returned true. + */ + private native boolean iLayoutJS(Element el) + /*-{ + if(el && el.iLayoutJS) { + try { + el.iLayoutJS(); + return true; + } catch (e) { + return false; + } + } else { + return false; + } + }-*/; } diff --git a/src/com/itmill/toolkit/terminal/gwt/client/ui/IDateField.java b/src/com/itmill/toolkit/terminal/gwt/client/ui/IDateField.java index 53859ddf6e..b039ab22f7 100644 --- a/src/com/itmill/toolkit/terminal/gwt/client/ui/IDateField.java +++ b/src/com/itmill/toolkit/terminal/gwt/client/ui/IDateField.java @@ -11,181 +11,184 @@ import com.itmill.toolkit.terminal.gwt.client.UIDL; public class IDateField extends FlowPanel implements Paintable { - public static final String CLASSNAME = "i-datefield"; - - protected String id; - - protected ApplicationConnection client; - - protected boolean immediate; - - public static int RESOLUTION_YEAR = 0; - public static int RESOLUTION_MONTH = 1; - public static int RESOLUTION_DAY = 2; - public static int RESOLUTION_HOUR = 3; - public static int RESOLUTION_MIN = 4; - public static int RESOLUTION_SEC = 5; - public static int RESOLUTION_MSEC = 6; - - protected int currentResolution = RESOLUTION_YEAR; - - protected String currentLocale; - - protected boolean readonly; - - protected boolean enabled; - - protected Date date = null; - - protected DateTimeService dts; - - public IDateField() { - setStyleName(CLASSNAME); - dts = new DateTimeService(); - } - - public void updateFromUIDL(UIDL uidl, ApplicationConnection client) { - // Ensure correct implementation and let layout manage caption - if (client.updateComponent(this, uidl, true)) - return; - - // Save details - this.client = client; - this.id = uidl.getId(); - this.immediate = uidl.getBooleanAttribute("immediate"); - - readonly = uidl.getBooleanAttribute("readonly"); - enabled = !uidl.getBooleanAttribute("disabled"); - - if (uidl.hasAttribute("locale")) { - String locale = uidl.getStringAttribute("locale"); - try { - dts.setLocale(locale); - currentLocale = locale; - } catch (LocaleNotLoadedException e) { - currentLocale = dts.getLocale(); - // TODO redirect this to console - System.out.println("Tried to use an unloaded locale \"" - + locale + "\". Using default locale (" + currentLocale - + ")."); - } - } - - int newResolution; - if (uidl.hasVariable("msec")) - newResolution = RESOLUTION_MSEC; - else if (uidl.hasVariable("sec")) - newResolution = RESOLUTION_SEC; - else if (uidl.hasVariable("min")) - newResolution = RESOLUTION_MIN; - else if (uidl.hasVariable("hour")) - newResolution = RESOLUTION_HOUR; - else if (uidl.hasVariable("day")) - newResolution = RESOLUTION_DAY; - else if (uidl.hasVariable("month")) - newResolution = RESOLUTION_MONTH; - else - newResolution = RESOLUTION_YEAR; - - currentResolution = newResolution; - - int year = uidl.getIntVariable("year"); - int month = (currentResolution >= RESOLUTION_MONTH) ? uidl - .getIntVariable("month") : -1; - int day = (currentResolution >= RESOLUTION_DAY) ? uidl - .getIntVariable("day") : -1; - int hour = (currentResolution >= RESOLUTION_HOUR) ? uidl - .getIntVariable("hour") : -1; - int min = (currentResolution >= RESOLUTION_MIN) ? uidl - .getIntVariable("min") : -1; - int sec = (currentResolution >= RESOLUTION_SEC) ? uidl - .getIntVariable("sec") : -1; - int msec = (currentResolution >= RESOLUTION_MSEC) ? uidl - .getIntVariable("msec") : -1; - - // Construct new date for this datefield (only if not null) - if (year > -1) - date = new Date((long) getTime(year, month, day, hour, min, sec, - msec)); - - } - - /* - * We need this redundant native function because Java's Date object doesn't - * have a setMilliseconds method. - */ - private static native double getTime(int y, int m, int d, int h, int mi, - int s, int ms) /*-{ - try { - var date = new Date(); - if(y && y >= 0) date.setFullYear(y); - if(m && m >= 1) date.setMonth(m-1); - if(d && d >= 0) date.setDate(d); - if(h && h >= 0) date.setHours(h); - if(mi && mi >= 0) date.setMinutes(mi); - if(s && s >= 0) date.setSeconds(s); - if(ms && ms >= 0) date.setMilliseconds(ms); - return date.getTime(); - } catch (e) { - // TODO print some error message on the console - //console.log(e); - return (new Date()).getTime(); - } - }-*/; - - public int getMilliseconds() { - return (int) (date.getTime() - date.getTime() / 1000 * 1000); - } - - public void setMilliseconds(int ms) { - date.setTime(date.getTime() / 1000 * 1000 + ms); - } - - public int getCurrentResolution() { - return currentResolution; - } - - public void setCurrentResolution(int currentResolution) { - this.currentResolution = currentResolution; - } - - public String getCurrentLocale() { - return currentLocale; - } - - public void setCurrentLocale(String currentLocale) { - this.currentLocale = currentLocale; - } - - public Date getCurrentDate() { - return date; - } - - public void setCurrentDate(Date date) { - this.date = date; - } - - public boolean isImmediate() { - return immediate; - } - - public boolean isReadonly() { - return readonly; - } - - public boolean isEnabled() { - return enabled; - } - - public DateTimeService getDateTimeService() { - return dts; - } - - public String getId() { - return id; - } - - public ApplicationConnection getClient() { - return client; - } + public static final String CLASSNAME = "i-datefield"; + + protected String id; + + protected ApplicationConnection client; + + protected boolean immediate; + + public static int RESOLUTION_YEAR = 0; + public static int RESOLUTION_MONTH = 1; + public static int RESOLUTION_DAY = 2; + public static int RESOLUTION_HOUR = 3; + public static int RESOLUTION_MIN = 4; + public static int RESOLUTION_SEC = 5; + public static int RESOLUTION_MSEC = 6; + + protected int currentResolution = RESOLUTION_YEAR; + + protected String currentLocale; + + protected boolean readonly; + + protected boolean enabled; + + protected Date date = null; + + protected DateTimeService dts; + + public IDateField() { + setStyleName(CLASSNAME); + dts = new DateTimeService(); + } + + public void updateFromUIDL(UIDL uidl, ApplicationConnection client) { + // Ensure correct implementation and let layout manage caption + if (client.updateComponent(this, uidl, true)) { + return; + } + + // Save details + this.client = client; + id = uidl.getId(); + immediate = uidl.getBooleanAttribute("immediate"); + + readonly = uidl.getBooleanAttribute("readonly"); + enabled = !uidl.getBooleanAttribute("disabled"); + + if (uidl.hasAttribute("locale")) { + String locale = uidl.getStringAttribute("locale"); + try { + dts.setLocale(locale); + currentLocale = locale; + } catch (LocaleNotLoadedException e) { + currentLocale = dts.getLocale(); + // TODO redirect this to console + System.out.println("Tried to use an unloaded locale \"" + + locale + "\". Using default locale (" + currentLocale + + ")."); + } + } + + int newResolution; + if (uidl.hasVariable("msec")) { + newResolution = RESOLUTION_MSEC; + } else if (uidl.hasVariable("sec")) { + newResolution = RESOLUTION_SEC; + } else if (uidl.hasVariable("min")) { + newResolution = RESOLUTION_MIN; + } else if (uidl.hasVariable("hour")) { + newResolution = RESOLUTION_HOUR; + } else if (uidl.hasVariable("day")) { + newResolution = RESOLUTION_DAY; + } else if (uidl.hasVariable("month")) { + newResolution = RESOLUTION_MONTH; + } else { + newResolution = RESOLUTION_YEAR; + } + + currentResolution = newResolution; + + int year = uidl.getIntVariable("year"); + int month = (currentResolution >= RESOLUTION_MONTH) ? uidl + .getIntVariable("month") : -1; + int day = (currentResolution >= RESOLUTION_DAY) ? uidl + .getIntVariable("day") : -1; + int hour = (currentResolution >= RESOLUTION_HOUR) ? uidl + .getIntVariable("hour") : -1; + int min = (currentResolution >= RESOLUTION_MIN) ? uidl + .getIntVariable("min") : -1; + int sec = (currentResolution >= RESOLUTION_SEC) ? uidl + .getIntVariable("sec") : -1; + int msec = (currentResolution >= RESOLUTION_MSEC) ? uidl + .getIntVariable("msec") : -1; + + // Construct new date for this datefield (only if not null) + if (year > -1) { + date = new Date((long) getTime(year, month, day, hour, min, sec, + msec)); + } + + } + + /* + * We need this redundant native function because Java's Date object doesn't + * have a setMilliseconds method. + */ + private static native double getTime(int y, int m, int d, int h, int mi, + int s, int ms) /*-{ + try { + var date = new Date(); + if(y && y >= 0) date.setFullYear(y); + if(m && m >= 1) date.setMonth(m-1); + if(d && d >= 0) date.setDate(d); + if(h && h >= 0) date.setHours(h); + if(mi && mi >= 0) date.setMinutes(mi); + if(s && s >= 0) date.setSeconds(s); + if(ms && ms >= 0) date.setMilliseconds(ms); + return date.getTime(); + } catch (e) { + // TODO print some error message on the console + //console.log(e); + return (new Date()).getTime(); + } + }-*/; + + public int getMilliseconds() { + return (int) (date.getTime() - date.getTime() / 1000 * 1000); + } + + public void setMilliseconds(int ms) { + date.setTime(date.getTime() / 1000 * 1000 + ms); + } + + public int getCurrentResolution() { + return currentResolution; + } + + public void setCurrentResolution(int currentResolution) { + this.currentResolution = currentResolution; + } + + public String getCurrentLocale() { + return currentLocale; + } + + public void setCurrentLocale(String currentLocale) { + this.currentLocale = currentLocale; + } + + public Date getCurrentDate() { + return date; + } + + public void setCurrentDate(Date date) { + this.date = date; + } + + public boolean isImmediate() { + return immediate; + } + + public boolean isReadonly() { + return readonly; + } + + public boolean isEnabled() { + return enabled; + } + + public DateTimeService getDateTimeService() { + return dts; + } + + public String getId() { + return id; + } + + public ApplicationConnection getClient() { + return client; + } } diff --git a/src/com/itmill/toolkit/terminal/gwt/client/ui/IDateFieldCalendar.java b/src/com/itmill/toolkit/terminal/gwt/client/ui/IDateFieldCalendar.java index 2d5540298d..80d4bfde63 100644 --- a/src/com/itmill/toolkit/terminal/gwt/client/ui/IDateFieldCalendar.java +++ b/src/com/itmill/toolkit/terminal/gwt/client/ui/IDateFieldCalendar.java @@ -5,17 +5,17 @@ import com.itmill.toolkit.terminal.gwt.client.UIDL; public class IDateFieldCalendar extends IDateField { - private CalendarPanel date; + private CalendarPanel date; - public IDateFieldCalendar() { - super(); - date = new CalendarPanel(this); - add(date); - } + public IDateFieldCalendar() { + super(); + date = new CalendarPanel(this); + add(date); + } - public void updateFromUIDL(UIDL uidl, ApplicationConnection client) { - super.updateFromUIDL(uidl, client); - date.updateCalendar(); - } + public void updateFromUIDL(UIDL uidl, ApplicationConnection client) { + super.updateFromUIDL(uidl, client); + date.updateCalendar(); + } } diff --git a/src/com/itmill/toolkit/terminal/gwt/client/ui/IExpandLayout.java b/src/com/itmill/toolkit/terminal/gwt/client/ui/IExpandLayout.java index fb0ee43b67..a13fa413d7 100644 --- a/src/com/itmill/toolkit/terminal/gwt/client/ui/IExpandLayout.java +++ b/src/com/itmill/toolkit/terminal/gwt/client/ui/IExpandLayout.java @@ -18,184 +18,190 @@ import com.itmill.toolkit.terminal.gwt.client.Util; * @author IT Mill Ltd */ public class IExpandLayout extends IOrderedLayout implements - ContainerResizedListener { - public static final String CLASSNAME = "i-expandlayout"; - - private Widget expandedWidget; - private UIDL expandedWidgetUidl; - - public IExpandLayout() { - super(IOrderedLayout.ORIENTATION_VERTICAL); - setStyleName(CLASSNAME); - } - - public void updateFromUIDL(UIDL uidl, ApplicationConnection client) { - - this.client = client; - - // Ensure correct implementation - if (client.updateComponent(this, uidl, false)) - return; - - // Set size - if (uidl.hasAttribute("width")) { - setWidth(uidl.getStringAttribute("width")); - DOM.setStyleAttribute(DOM.getFirstChild(DOM - .getFirstChild(getElement())), "width", "100%"); - } else { - setWidth(""); - DOM.setStyleAttribute(DOM.getFirstChild(DOM - .getFirstChild(getElement())), "width", ""); - } - if (uidl.hasAttribute("height")) { - setHeight(uidl.getStringAttribute("height")); - DOM.setStyleAttribute(margin, "height", "100%"); - DOM.setStyleAttribute(DOM.getFirstChild(DOM - .getFirstChild(getElement())), "height", "100%"); - } else { - setHeight(""); - DOM.setStyleAttribute(margin, "height", ""); - DOM.setStyleAttribute(DOM.getFirstChild(DOM - .getFirstChild(getElement())), "height", ""); - } - - ArrayList uidlWidgets = new ArrayList(); - for (Iterator it = uidl.getChildIterator(); it.hasNext();) { - UIDL cellUidl = (UIDL) it.next(); - Widget child = client.getWidget(cellUidl.getChildUIDL(0)); - uidlWidgets.add(child); - if (cellUidl.hasAttribute("expanded")) { - expandedWidget = child; - expandedWidgetUidl = cellUidl.getChildUIDL(0); - } - } - - ArrayList oldWidgets = getPaintables(); - - Iterator oldIt = oldWidgets.iterator(); - Iterator newIt = uidlWidgets.iterator(); - Iterator newUidl = uidl.getChildIterator(); - - Widget oldChild = null; - while (newIt.hasNext()) { - Widget child = (Widget) newIt.next(); - UIDL childUidl = ((UIDL) newUidl.next()).getChildUIDL(0); - if (oldChild == null && oldIt.hasNext()) { - // search for next old Paintable which still exists in layout - // and delete others - while (oldIt.hasNext()) { - oldChild = (Widget) oldIt.next(); - // now oldChild is an instance of Paintable - if (uidlWidgets.contains(oldChild)) - break; - else { - removePaintable((Paintable) oldChild); - oldChild = null; - } - } - } - if (oldChild == null) { - // we are adding components to layout - add(child); - } else if (child == oldChild) { - // child already attached and updated - oldChild = null; - } else if (hasChildComponent(child)) { - // current child has been moved, re-insert before current - // oldChild - // TODO this might be optimized by moving only container element - // to correct position - removeCaption(child); - int index = getWidgetIndex(oldChild); - if (componentToCaption.containsKey(oldChild)) - index--; - remove(child); - this.insert(child, index); - } else { - // insert new child before old one - int index = getWidgetIndex(oldChild); - insert(child, index); - } - if (child != expandedWidget) - ((Paintable) child).updateFromUIDL(childUidl, client); - } - // remove possibly remaining old Paintable object which were not updated - while (oldIt.hasNext()) { - oldChild = (Widget) oldIt.next(); - Paintable p = (Paintable) oldChild; - if (!uidlWidgets.contains(p)) - removePaintable(p); - } - - // Modify layout margins - handleMargins(uidl); - - if (uidlWidgets.size() == 0) - return; - - iLayout(); - - /* - * Expanded widget is updated after layout function so it has its - * container fixed at the moment of updateFromUIDL. - */ - ((Paintable) expandedWidget).updateFromUIDL(expandedWidgetUidl, client); - - // Set component alignments - handleAlignments(uidl); - - } - - public void iLayout() { - if (expandedWidget == null) { - return; - } - // Clear expanded elements height so we get the available height right - Element expandedElement = DOM.getParent(expandedWidget.getElement()); - DOM.setStyleAttribute(expandedElement, "height", ""); - DOM.setStyleAttribute(DOM.getParent(expandedElement), "height", ""); - // Get available height - int availableHeight = getOffsetHeight(); - // Clear TABLE height temporarily, so we get used space right - Element table = DOM.getFirstChild(margin); - String height = DOM.getStyleAttribute(table, "height"); - DOM.setStyleAttribute(table, "height", ""); - - // take expanded element temporarely out of flow to make container - // minimum sized - String originalPositioning = DOM.getStyleAttribute(expandedWidget - .getElement(), "position"); - DOM.setStyleAttribute(expandedWidget.getElement(), "position", - "absolute"); - - // add temp element to make some measurements - Element meter = createWidgetWrappper(); - DOM.setStyleAttribute(meter, "overflow", "hidden"); - DOM.setStyleAttribute(meter, "height", "0"); - DOM.appendChild(childContainer, meter); - int usedSpace = DOM.getElementPropertyInt(meter, "offsetTop") - - DOM.getElementPropertyInt(DOM.getFirstChild(childContainer), - "offsetTop"); - - int freeSpace = availableHeight - usedSpace; - - if (freeSpace < 0) - freeSpace = 0; - - DOM.setStyleAttribute(expandedElement, "height", freeSpace + "px"); - DOM.setStyleAttribute(DOM.getParent(expandedElement), "height", - freeSpace + "px"); - // Component margins will bleed if overflow is not hidden - // DOM.setStyleAttribute(expandedElement, "overflow", "hidden"); - - DOM.setStyleAttribute(expandedWidget.getElement(), "position", - originalPositioning); - - DOM.removeChild(childContainer, meter); - DOM.setStyleAttribute(table, "height", height); - - // TODO save previous size and only propagate if really changed - Util.runDescendentsLayout(this); - } + ContainerResizedListener { + public static final String CLASSNAME = "i-expandlayout"; + + private Widget expandedWidget; + private UIDL expandedWidgetUidl; + + public IExpandLayout() { + super(IOrderedLayout.ORIENTATION_VERTICAL); + setStyleName(CLASSNAME); + } + + public void updateFromUIDL(UIDL uidl, ApplicationConnection client) { + + this.client = client; + + // Ensure correct implementation + if (client.updateComponent(this, uidl, false)) { + return; + } + + // Set size + if (uidl.hasAttribute("width")) { + setWidth(uidl.getStringAttribute("width")); + DOM.setStyleAttribute(DOM.getFirstChild(DOM + .getFirstChild(getElement())), "width", "100%"); + } else { + setWidth(""); + DOM.setStyleAttribute(DOM.getFirstChild(DOM + .getFirstChild(getElement())), "width", ""); + } + if (uidl.hasAttribute("height")) { + setHeight(uidl.getStringAttribute("height")); + DOM.setStyleAttribute(margin, "height", "100%"); + DOM.setStyleAttribute(DOM.getFirstChild(DOM + .getFirstChild(getElement())), "height", "100%"); + } else { + setHeight(""); + DOM.setStyleAttribute(margin, "height", ""); + DOM.setStyleAttribute(DOM.getFirstChild(DOM + .getFirstChild(getElement())), "height", ""); + } + + ArrayList uidlWidgets = new ArrayList(); + for (Iterator it = uidl.getChildIterator(); it.hasNext();) { + UIDL cellUidl = (UIDL) it.next(); + Widget child = client.getWidget(cellUidl.getChildUIDL(0)); + uidlWidgets.add(child); + if (cellUidl.hasAttribute("expanded")) { + expandedWidget = child; + expandedWidgetUidl = cellUidl.getChildUIDL(0); + } + } + + ArrayList oldWidgets = getPaintables(); + + Iterator oldIt = oldWidgets.iterator(); + Iterator newIt = uidlWidgets.iterator(); + Iterator newUidl = uidl.getChildIterator(); + + Widget oldChild = null; + while (newIt.hasNext()) { + Widget child = (Widget) newIt.next(); + UIDL childUidl = ((UIDL) newUidl.next()).getChildUIDL(0); + if (oldChild == null && oldIt.hasNext()) { + // search for next old Paintable which still exists in layout + // and delete others + while (oldIt.hasNext()) { + oldChild = (Widget) oldIt.next(); + // now oldChild is an instance of Paintable + if (uidlWidgets.contains(oldChild)) { + break; + } else { + removePaintable((Paintable) oldChild); + oldChild = null; + } + } + } + if (oldChild == null) { + // we are adding components to layout + add(child); + } else if (child == oldChild) { + // child already attached and updated + oldChild = null; + } else if (hasChildComponent(child)) { + // current child has been moved, re-insert before current + // oldChild + // TODO this might be optimized by moving only container element + // to correct position + removeCaption(child); + int index = getWidgetIndex(oldChild); + if (componentToCaption.containsKey(oldChild)) { + index--; + } + remove(child); + this.insert(child, index); + } else { + // insert new child before old one + int index = getWidgetIndex(oldChild); + insert(child, index); + } + if (child != expandedWidget) { + ((Paintable) child).updateFromUIDL(childUidl, client); + } + } + // remove possibly remaining old Paintable object which were not updated + while (oldIt.hasNext()) { + oldChild = (Widget) oldIt.next(); + Paintable p = (Paintable) oldChild; + if (!uidlWidgets.contains(p)) { + removePaintable(p); + } + } + + // Modify layout margins + handleMargins(uidl); + + if (uidlWidgets.size() == 0) { + return; + } + + iLayout(); + + /* + * Expanded widget is updated after layout function so it has its + * container fixed at the moment of updateFromUIDL. + */ + ((Paintable) expandedWidget).updateFromUIDL(expandedWidgetUidl, client); + + // Set component alignments + handleAlignments(uidl); + + } + + public void iLayout() { + if (expandedWidget == null) { + return; + } + // Clear expanded elements height so we get the available height right + Element expandedElement = DOM.getParent(expandedWidget.getElement()); + DOM.setStyleAttribute(expandedElement, "height", ""); + DOM.setStyleAttribute(DOM.getParent(expandedElement), "height", ""); + // Get available height + int availableHeight = getOffsetHeight(); + // Clear TABLE height temporarily, so we get used space right + Element table = DOM.getFirstChild(margin); + String height = DOM.getStyleAttribute(table, "height"); + DOM.setStyleAttribute(table, "height", ""); + + // take expanded element temporarely out of flow to make container + // minimum sized + String originalPositioning = DOM.getStyleAttribute(expandedWidget + .getElement(), "position"); + DOM.setStyleAttribute(expandedWidget.getElement(), "position", + "absolute"); + + // add temp element to make some measurements + Element meter = createWidgetWrappper(); + DOM.setStyleAttribute(meter, "overflow", "hidden"); + DOM.setStyleAttribute(meter, "height", "0"); + DOM.appendChild(childContainer, meter); + int usedSpace = DOM.getElementPropertyInt(meter, "offsetTop") + - DOM.getElementPropertyInt(DOM.getFirstChild(childContainer), + "offsetTop"); + + int freeSpace = availableHeight - usedSpace; + + if (freeSpace < 0) { + freeSpace = 0; + } + + DOM.setStyleAttribute(expandedElement, "height", freeSpace + "px"); + DOM.setStyleAttribute(DOM.getParent(expandedElement), "height", + freeSpace + "px"); + // Component margins will bleed if overflow is not hidden + // DOM.setStyleAttribute(expandedElement, "overflow", "hidden"); + + DOM.setStyleAttribute(expandedWidget.getElement(), "position", + originalPositioning); + + DOM.removeChild(childContainer, meter); + DOM.setStyleAttribute(table, "height", height); + + // TODO save previous size and only propagate if really changed + Util.runDescendentsLayout(this); + } } diff --git a/src/com/itmill/toolkit/terminal/gwt/client/ui/IFilterSelect.java b/src/com/itmill/toolkit/terminal/gwt/client/ui/IFilterSelect.java index 5432ed21b1..2f458123ca 100644 --- a/src/com/itmill/toolkit/terminal/gwt/client/ui/IFilterSelect.java +++ b/src/com/itmill/toolkit/terminal/gwt/client/ui/IFilterSelect.java @@ -659,25 +659,25 @@ public class IFilterSelect extends Composite implements Paintable, * Calculate minumum width for FilterSelect textarea */ private native int minWidth(String captions) /*-{ - if(!captions || captions.length <= 0) - return 0; - captions = captions.split("|"); - var d = $wnd.document.createElement("div"); - var html = ""; - for(var i=0; i < captions.length; i++) { - html += "
" + captions[i] + "
"; - // TODO apply same CSS classname as in suggestionmenu - } - d.style.position = "absolute"; - d.style.top = "0"; - d.style.left = "0"; - d.style.visibility = "hidden"; - d.innerHTML = html; - $wnd.document.body.appendChild(d); - var w = d.offsetWidth; - $wnd.document.body.removeChild(d); - return w; - }-*/; + if(!captions || captions.length <= 0) + return 0; + captions = captions.split("|"); + var d = $wnd.document.createElement("div"); + var html = ""; + for(var i=0; i < captions.length; i++) { + html += "
" + captions[i] + "
"; + // TODO apply same CSS classname as in suggestionmenu + } + d.style.position = "absolute"; + d.style.top = "0"; + d.style.left = "0"; + d.style.visibility = "hidden"; + d.innerHTML = html; + $wnd.document.body.appendChild(d); + var w = d.offsetWidth; + $wnd.document.body.removeChild(d); + return w; + }-*/; public void onFocus(Widget sender) { // NOP diff --git a/src/com/itmill/toolkit/terminal/gwt/client/ui/IForm.java b/src/com/itmill/toolkit/terminal/gwt/client/ui/IForm.java index 753947b43a..df883927fb 100644 --- a/src/com/itmill/toolkit/terminal/gwt/client/ui/IForm.java +++ b/src/com/itmill/toolkit/terminal/gwt/client/ui/IForm.java @@ -9,28 +9,29 @@ import com.itmill.toolkit.terminal.gwt.client.UIDL; public class IForm extends SimplePanel implements Paintable { - public static final String CLASSNAME = "i-form"; - - private Container lo; - - private ApplicationConnection client; - - public IForm() { - super(); - setStyleName(CLASSNAME); - } - - public void updateFromUIDL(UIDL uidl, ApplicationConnection client) { - this.client = client; - - if(client.updateComponent(this, uidl, true)) - return; - - UIDL layoutUidl = uidl.getChildUIDL(0); - if (lo == null) { - lo = (Container) client.getWidget(layoutUidl); - setWidget((Widget) lo); - } - lo.updateFromUIDL(layoutUidl, client); - } + public static final String CLASSNAME = "i-form"; + + private Container lo; + + private ApplicationConnection client; + + public IForm() { + super(); + setStyleName(CLASSNAME); + } + + public void updateFromUIDL(UIDL uidl, ApplicationConnection client) { + this.client = client; + + if (client.updateComponent(this, uidl, true)) { + return; + } + + UIDL layoutUidl = uidl.getChildUIDL(0); + if (lo == null) { + lo = (Container) client.getWidget(layoutUidl); + setWidget((Widget) lo); + } + lo.updateFromUIDL(layoutUidl, client); + } } diff --git a/src/com/itmill/toolkit/terminal/gwt/client/ui/ILabel.java b/src/com/itmill/toolkit/terminal/gwt/client/ui/ILabel.java index a3721acabb..588e6f21a6 100644 --- a/src/com/itmill/toolkit/terminal/gwt/client/ui/ILabel.java +++ b/src/com/itmill/toolkit/terminal/gwt/client/ui/ILabel.java @@ -7,38 +7,39 @@ import com.itmill.toolkit.terminal.gwt.client.UIDL; public class ILabel extends HTML implements Paintable { - public static final String CLASSNAME = "i-label"; - - public ILabel() { - super(); - setStyleName(CLASSNAME); - } - - public ILabel(String text) { - super(text); - setStyleName(CLASSNAME); - } - - public void updateFromUIDL(UIDL uidl, ApplicationConnection client) { - - if (client.updateComponent(this, uidl, true)) - return; - - String mode = uidl.getStringAttribute("mode"); - if (mode == null || "text".equals(mode)) - setText(uidl.getChildString(0)); - else if ("pre".equals(mode)) { - setHTML(uidl.getChildrenAsXML()); - } else if ("uidl".equals(mode)) { - setHTML(uidl.getChildrenAsXML()); - } else if ("xhtml".equals(mode)) { - setHTML(uidl.getChildUIDL(0).getChildUIDL(0).getChildString(0)); - } else if ("xml".equals(mode)) { - setHTML(uidl.getChildUIDL(0).getChildString(0)); - } else if ("raw".equals(mode)) { - setHTML(uidl.getChildUIDL(0).getChildString(0)); - } else { - setText(""); - } - } + public static final String CLASSNAME = "i-label"; + + public ILabel() { + super(); + setStyleName(CLASSNAME); + } + + public ILabel(String text) { + super(text); + setStyleName(CLASSNAME); + } + + public void updateFromUIDL(UIDL uidl, ApplicationConnection client) { + + if (client.updateComponent(this, uidl, true)) { + return; + } + + String mode = uidl.getStringAttribute("mode"); + if (mode == null || "text".equals(mode)) { + setText(uidl.getChildString(0)); + } else if ("pre".equals(mode)) { + setHTML(uidl.getChildrenAsXML()); + } else if ("uidl".equals(mode)) { + setHTML(uidl.getChildrenAsXML()); + } else if ("xhtml".equals(mode)) { + setHTML(uidl.getChildUIDL(0).getChildUIDL(0).getChildString(0)); + } else if ("xml".equals(mode)) { + setHTML(uidl.getChildUIDL(0).getChildString(0)); + } else if ("raw".equals(mode)) { + setHTML(uidl.getChildUIDL(0).getChildString(0)); + } else { + setText(""); + } + } } diff --git a/src/com/itmill/toolkit/terminal/gwt/client/ui/IOrderedLayoutHorizontal.java b/src/com/itmill/toolkit/terminal/gwt/client/ui/IOrderedLayoutHorizontal.java index d323d171b7..34979948cc 100644 --- a/src/com/itmill/toolkit/terminal/gwt/client/ui/IOrderedLayoutHorizontal.java +++ b/src/com/itmill/toolkit/terminal/gwt/client/ui/IOrderedLayoutHorizontal.java @@ -2,7 +2,7 @@ package com.itmill.toolkit.terminal.gwt.client.ui; public class IOrderedLayoutHorizontal extends IOrderedLayout { - public IOrderedLayoutHorizontal() { - super(ORIENTATION_HORIZONTAL); - } + public IOrderedLayoutHorizontal() { + super(ORIENTATION_HORIZONTAL); + } } diff --git a/src/com/itmill/toolkit/terminal/gwt/client/ui/IOrderedLayoutVertical.java b/src/com/itmill/toolkit/terminal/gwt/client/ui/IOrderedLayoutVertical.java index 10de874f65..6f73b32830 100644 --- a/src/com/itmill/toolkit/terminal/gwt/client/ui/IOrderedLayoutVertical.java +++ b/src/com/itmill/toolkit/terminal/gwt/client/ui/IOrderedLayoutVertical.java @@ -2,7 +2,7 @@ package com.itmill.toolkit.terminal.gwt.client.ui; public class IOrderedLayoutVertical extends IOrderedLayout { - public IOrderedLayoutVertical() { - super(ORIENTATION_VERTICAL); - } + public IOrderedLayoutVertical() { + super(ORIENTATION_VERTICAL); + } } diff --git a/src/com/itmill/toolkit/terminal/gwt/client/ui/IPanel.java b/src/com/itmill/toolkit/terminal/gwt/client/ui/IPanel.java index 31c2586aa0..4e8190684b 100644 --- a/src/com/itmill/toolkit/terminal/gwt/client/ui/IPanel.java +++ b/src/com/itmill/toolkit/terminal/gwt/client/ui/IPanel.java @@ -11,142 +11,149 @@ import com.itmill.toolkit.terminal.gwt.client.UIDL; import com.itmill.toolkit.terminal.gwt.client.Util; public class IPanel extends SimplePanel implements Paintable, - ContainerResizedListener { - - public static final String CLASSNAME = "i-panel"; - - ApplicationConnection client; - - String id; - - private Element captionNode = DOM.createDiv(); - - private Element bottomDecoration = DOM.createDiv(); - - private Element contentNode = DOM.createDiv(); - - private String height; - - private Widget layout; - - public IPanel() { - super(); - DOM.appendChild(getElement(), captionNode); - DOM.appendChild(getElement(), contentNode); - DOM.appendChild(getElement(), bottomDecoration); - setStyleName(CLASSNAME); - DOM - .setElementProperty(captionNode, "className", CLASSNAME - + "-caption"); - DOM - .setElementProperty(contentNode, "className", CLASSNAME - + "-content"); - DOM.setElementProperty(bottomDecoration, "className", CLASSNAME - + "-deco"); - } - - protected Element getContainerElement() { - return contentNode; - } - - public void updateFromUIDL(UIDL uidl, ApplicationConnection client) { - // Ensure correct implementation - if (client.updateComponent(this, uidl, false)) - return; - - this.client = client; - this.id = uidl.getId(); - - // Panel size. Height needs to be saved for later use - String w = uidl.hasVariable("width") ? uidl.getStringVariable("width") - : null; - height = uidl.hasVariable("height") ? uidl.getStringVariable("height") - : null; - setWidth(w != null ? w : ""); - - // Handle caption displaying - boolean hasCaption = false; - if (uidl.hasAttribute("caption") - && !uidl.getStringAttribute("caption").equals("")) { - DOM.setInnerText(captionNode, uidl.getStringAttribute("caption")); - hasCaption = true; - } else { - DOM.setInnerText(captionNode, ""); - DOM.setElementProperty(captionNode, "className", CLASSNAME - + "-nocaption"); - } - - // Add proper stylenames for all elements - if (uidl.hasAttribute("style")) { - String[] styles = uidl.getStringAttribute("style").split(" "); - String captionBaseClass = CLASSNAME - + (hasCaption ? "-caption" : "-nocaption"); - String contentBaseClass = CLASSNAME + "-content"; - String decoBaseClass = CLASSNAME + "-deco"; - String captionClass = captionBaseClass; - String contentClass = contentBaseClass; - String decoClass = decoBaseClass; - for (int i = 0; i < styles.length; i++) { - captionClass += " " + captionBaseClass + "-" + styles[i]; - contentClass += " " + contentBaseClass + "-" + styles[i]; - decoClass += " " + decoBaseClass + "-" + styles[i]; - } - DOM.setElementProperty(captionNode, "className", captionClass); - DOM.setElementProperty(contentNode, "className", contentClass); - DOM.setElementProperty(bottomDecoration, "className", decoClass); - } - - // Height adjustment - iLayout(); - - // Render content - UIDL layoutUidl = uidl.getChildUIDL(0); - Widget newLayout = client.getWidget(layoutUidl); - if(newLayout != layout) { - if(layout != null) - client.unregisterPaintable((Paintable) layout); - setWidget(newLayout); - layout = newLayout; - } - ((Paintable) layout).updateFromUIDL(layoutUidl, client); - - } - - public void iLayout() { - if (height != null && height != "") { - // need to fix containers height properly - DOM.setStyleAttribute(getElement(), "height", height); - DOM.setStyleAttribute(contentNode, "overflow", "hidden"); - boolean hasChildren = getWidget() != null; - Element contentEl = null; - String origPositioning = null; - if (hasChildren) { - // remove children temporary form normal flow to detect proper - // size - contentEl = getWidget().getElement(); - origPositioning = DOM.getStyleAttribute(contentEl, "position"); - DOM.setStyleAttribute(contentEl, "position", "absolute"); - } - DOM.setStyleAttribute(contentNode, "height", ""); - int availableH = DOM.getElementPropertyInt(getElement(), "clientHeight"); - - int usedH = DOM.getElementPropertyInt(bottomDecoration, - "offsetTop") - DOM.getElementPropertyInt(getElement(), "offsetTop") + DOM.getElementPropertyInt(bottomDecoration, - "offsetHeight"); - - int contentH = availableH - usedH; - if (contentH < 0) - contentH = 0; - DOM.setStyleAttribute(contentNode, "height", contentH + "px"); - if (hasChildren) { - ApplicationConnection.getConsole().log("positioning:" + origPositioning); - DOM.setStyleAttribute(contentEl, "position", origPositioning); - } - DOM.setStyleAttribute(contentNode, "overflow", "auto"); - } else { - DOM.setStyleAttribute(contentNode, "height", ""); - } - Util.runDescendentsLayout(this); - } + ContainerResizedListener { + + public static final String CLASSNAME = "i-panel"; + + ApplicationConnection client; + + String id; + + private Element captionNode = DOM.createDiv(); + + private Element bottomDecoration = DOM.createDiv(); + + private Element contentNode = DOM.createDiv(); + + private String height; + + private Widget layout; + + public IPanel() { + super(); + DOM.appendChild(getElement(), captionNode); + DOM.appendChild(getElement(), contentNode); + DOM.appendChild(getElement(), bottomDecoration); + setStyleName(CLASSNAME); + DOM + .setElementProperty(captionNode, "className", CLASSNAME + + "-caption"); + DOM + .setElementProperty(contentNode, "className", CLASSNAME + + "-content"); + DOM.setElementProperty(bottomDecoration, "className", CLASSNAME + + "-deco"); + } + + protected Element getContainerElement() { + return contentNode; + } + + public void updateFromUIDL(UIDL uidl, ApplicationConnection client) { + // Ensure correct implementation + if (client.updateComponent(this, uidl, false)) { + return; + } + + this.client = client; + id = uidl.getId(); + + // Panel size. Height needs to be saved for later use + String w = uidl.hasVariable("width") ? uidl.getStringVariable("width") + : null; + height = uidl.hasVariable("height") ? uidl.getStringVariable("height") + : null; + setWidth(w != null ? w : ""); + + // Handle caption displaying + boolean hasCaption = false; + if (uidl.hasAttribute("caption") + && !uidl.getStringAttribute("caption").equals("")) { + DOM.setInnerText(captionNode, uidl.getStringAttribute("caption")); + hasCaption = true; + } else { + DOM.setInnerText(captionNode, ""); + DOM.setElementProperty(captionNode, "className", CLASSNAME + + "-nocaption"); + } + + // Add proper stylenames for all elements + if (uidl.hasAttribute("style")) { + String[] styles = uidl.getStringAttribute("style").split(" "); + String captionBaseClass = CLASSNAME + + (hasCaption ? "-caption" : "-nocaption"); + String contentBaseClass = CLASSNAME + "-content"; + String decoBaseClass = CLASSNAME + "-deco"; + String captionClass = captionBaseClass; + String contentClass = contentBaseClass; + String decoClass = decoBaseClass; + for (int i = 0; i < styles.length; i++) { + captionClass += " " + captionBaseClass + "-" + styles[i]; + contentClass += " " + contentBaseClass + "-" + styles[i]; + decoClass += " " + decoBaseClass + "-" + styles[i]; + } + DOM.setElementProperty(captionNode, "className", captionClass); + DOM.setElementProperty(contentNode, "className", contentClass); + DOM.setElementProperty(bottomDecoration, "className", decoClass); + } + + // Height adjustment + iLayout(); + + // Render content + UIDL layoutUidl = uidl.getChildUIDL(0); + Widget newLayout = client.getWidget(layoutUidl); + if (newLayout != layout) { + if (layout != null) { + client.unregisterPaintable((Paintable) layout); + } + setWidget(newLayout); + layout = newLayout; + } + ((Paintable) layout).updateFromUIDL(layoutUidl, client); + + } + + public void iLayout() { + if (height != null && height != "") { + // need to fix containers height properly + DOM.setStyleAttribute(getElement(), "height", height); + DOM.setStyleAttribute(contentNode, "overflow", "hidden"); + boolean hasChildren = getWidget() != null; + Element contentEl = null; + String origPositioning = null; + if (hasChildren) { + // remove children temporary form normal flow to detect proper + // size + contentEl = getWidget().getElement(); + origPositioning = DOM.getStyleAttribute(contentEl, "position"); + DOM.setStyleAttribute(contentEl, "position", "absolute"); + } + DOM.setStyleAttribute(contentNode, "height", ""); + int availableH = DOM.getElementPropertyInt(getElement(), + "clientHeight"); + + int usedH = DOM + .getElementPropertyInt(bottomDecoration, "offsetTop") + - DOM.getElementPropertyInt(getElement(), "offsetTop") + + DOM.getElementPropertyInt(bottomDecoration, + "offsetHeight"); + + int contentH = availableH - usedH; + if (contentH < 0) { + contentH = 0; + } + DOM.setStyleAttribute(contentNode, "height", contentH + "px"); + if (hasChildren) { + ApplicationConnection.getConsole().log( + "positioning:" + origPositioning); + DOM.setStyleAttribute(contentEl, "position", origPositioning); + } + DOM.setStyleAttribute(contentNode, "overflow", "auto"); + } else { + DOM.setStyleAttribute(contentNode, "height", ""); + } + Util.runDescendentsLayout(this); + } } diff --git a/src/com/itmill/toolkit/terminal/gwt/client/ui/IPasswordField.java b/src/com/itmill/toolkit/terminal/gwt/client/ui/IPasswordField.java index 1dd3043f32..c5576f7090 100644 --- a/src/com/itmill/toolkit/terminal/gwt/client/ui/IPasswordField.java +++ b/src/com/itmill/toolkit/terminal/gwt/client/ui/IPasswordField.java @@ -10,8 +10,8 @@ import com.google.gwt.user.client.DOM; */ public class IPasswordField extends ITextField { - public IPasswordField() { - super(DOM.createInputPassword()); - } + public IPasswordField() { + super(DOM.createInputPassword()); + } } diff --git a/src/com/itmill/toolkit/terminal/gwt/client/ui/IProgressIndicator.java b/src/com/itmill/toolkit/terminal/gwt/client/ui/IProgressIndicator.java index 7d22df4379..d77b792750 100644 --- a/src/com/itmill/toolkit/terminal/gwt/client/ui/IProgressIndicator.java +++ b/src/com/itmill/toolkit/terminal/gwt/client/ui/IProgressIndicator.java @@ -10,48 +10,50 @@ import com.itmill.toolkit.terminal.gwt.client.UIDL; public class IProgressIndicator extends Widget implements Paintable { - private static final String CLASSNAME = "i-progressindicator"; - Element wrapper = DOM.createDiv(); - Element indicator = DOM.createDiv(); - private ApplicationConnection client; - private Poller poller; - - public IProgressIndicator() { - setElement(wrapper); - setStyleName(CLASSNAME); - DOM.appendChild(wrapper, indicator); - poller = new Poller(); - } - - public void updateFromUIDL(UIDL uidl, ApplicationConnection client) { - if (client.updateComponent(this, uidl, true)) - return; - - poller.cancel(); - this.client = client; - if (client.updateComponent(this, uidl, true)) - return; - boolean indeterminate = uidl.getBooleanAttribute("indeterminate"); - - if (indeterminate) { - // TODO put up some image or something - } else { - try { - float f = Float.parseFloat(uidl.getStringAttribute("state")); - int size = Math.round(100 * f); - DOM.setStyleAttribute(indicator, "width", size + "%"); - } catch (Exception e) { - } - } - poller.scheduleRepeating(uidl.getIntAttribute("pollinginterval")); - } - - class Poller extends Timer { - - public void run() { - client.sendPendingVariableChanges(); - } - - } + private static final String CLASSNAME = "i-progressindicator"; + Element wrapper = DOM.createDiv(); + Element indicator = DOM.createDiv(); + private ApplicationConnection client; + private Poller poller; + + public IProgressIndicator() { + setElement(wrapper); + setStyleName(CLASSNAME); + DOM.appendChild(wrapper, indicator); + poller = new Poller(); + } + + public void updateFromUIDL(UIDL uidl, ApplicationConnection client) { + if (client.updateComponent(this, uidl, true)) { + return; + } + + poller.cancel(); + this.client = client; + if (client.updateComponent(this, uidl, true)) { + return; + } + boolean indeterminate = uidl.getBooleanAttribute("indeterminate"); + + if (indeterminate) { + // TODO put up some image or something + } else { + try { + float f = Float.parseFloat(uidl.getStringAttribute("state")); + int size = Math.round(100 * f); + DOM.setStyleAttribute(indicator, "width", size + "%"); + } catch (Exception e) { + } + } + poller.scheduleRepeating(uidl.getIntAttribute("pollinginterval")); + } + + class Poller extends Timer { + + public void run() { + client.sendPendingVariableChanges(); + } + + } } diff --git a/src/com/itmill/toolkit/terminal/gwt/client/ui/ISlider.java b/src/com/itmill/toolkit/terminal/gwt/client/ui/ISlider.java index 9f090518c9..38f932ed8b 100644 --- a/src/com/itmill/toolkit/terminal/gwt/client/ui/ISlider.java +++ b/src/com/itmill/toolkit/terminal/gwt/client/ui/ISlider.java @@ -14,441 +14,473 @@ import com.itmill.toolkit.terminal.gwt.client.UIDL; import com.itmill.toolkit.terminal.gwt.client.Util; public class ISlider extends Widget implements Paintable, - ContainerResizedListener { + ContainerResizedListener { - public static final String CLASSNAME = "i-slider"; - - /** - * Minimum size (width or height, depending on orientation) of the slider - * base. - */ - private static final int MIN_SIZE = 50; - - ApplicationConnection client; - - String id; - - private boolean immediate; - private boolean disabled; - private boolean readonly; - private boolean scrollbarStyle; - - private int handleSize; - private double min; - private double max; - private int resolution; - private Double value; - private boolean vertical; - private int size = -1; - private boolean arrows; - - /* DOM element for slider's base */ - private Element base; - - /* DOM element for slider's handle */ - private Element handle; - - /* DOM element for decrement arrow */ - private Element smaller; - - /* DOM element for increment arrow */ - private Element bigger; - - /* Temporary dragging/animation variables */ - private boolean dragging = false; - private Timer anim; - - public ISlider() { - super(); - - setElement(DOM.createDiv()); - base = DOM.createDiv(); - handle = DOM.createDiv(); - smaller = DOM.createDiv(); - bigger = DOM.createDiv(); - - setStyleName(CLASSNAME); - DOM.setElementProperty(base, "className", CLASSNAME + "-base"); - DOM.setElementProperty(handle, "className", CLASSNAME + "-handle"); - DOM.setElementProperty(smaller, "className", CLASSNAME + "-smaller"); - DOM.setElementProperty(bigger, "className", CLASSNAME + "-bigger"); - - DOM.appendChild(getElement(), bigger); - DOM.appendChild(getElement(), smaller); - DOM.appendChild(getElement(), base); - DOM.appendChild(base, handle); - - // Hide initially - DOM.setStyleAttribute(smaller, "display", "none"); - DOM.setStyleAttribute(bigger, "display", "none"); - DOM.setStyleAttribute(handle, "visibility", "hidden"); - - DOM.sinkEvents(getElement(), Event.MOUSEEVENTS | Event.ONMOUSEWHEEL); - DOM.sinkEvents(base, Event.ONCLICK); - DOM.sinkEvents(handle, Event.MOUSEEVENTS); - DOM.sinkEvents(smaller, Event.ONMOUSEDOWN | Event.ONMOUSEUP - | Event.ONMOUSEOUT); - DOM.sinkEvents(bigger, Event.ONMOUSEDOWN | Event.ONMOUSEUP - | Event.ONMOUSEOUT); - } - - public void updateFromUIDL(UIDL uidl, ApplicationConnection client) { - - this.client = client; - this.id = uidl.getId(); - - // Ensure correct implementation (handle own caption) - if (client.updateComponent(this, uidl, false)) - return; - - immediate = uidl.getBooleanAttribute("immediate"); - disabled = uidl.getBooleanAttribute("disabled"); - readonly = uidl.getBooleanAttribute("readonly"); - - vertical = uidl.hasAttribute("vertical"); - arrows = uidl.hasAttribute("arrows"); - - String style = ""; - if (uidl.hasAttribute("style")) - style = uidl.getStringAttribute("style"); - - scrollbarStyle = style.indexOf("scrollbar") > -1; - - if (arrows) { - DOM.setStyleAttribute(smaller, "display", "block"); - DOM.setStyleAttribute(bigger, "display", "block"); - } - - if (vertical) - addStyleName(CLASSNAME + "-vertical"); - else - removeStyleName(CLASSNAME + "-vertical"); - - min = uidl.getDoubleAttribute("min"); - max = uidl.getDoubleAttribute("max"); - resolution = uidl.getIntAttribute("resolution"); - value = new Double(uidl.getDoubleVariable("value")); - - handleSize = uidl.getIntAttribute("hsize"); - - if (uidl.hasAttribute("size")) - size = uidl.getIntAttribute("size"); - - buildBase(); - - if (!vertical) { - // Draw handle with a delay to allow base to gain maximum width - DeferredCommand.addCommand(new Command() { - public void execute() { - buildHandle(); - setValue(value, false, false); - } - }); - } else { - buildHandle(); - setValue(value, false, false); - } - } - - private void buildBase() { - final String styleAttribute = vertical ? "height" : "width"; - final String domProperty = vertical ? "offsetHeight" : "offsetWidth"; - - if (size == -1) { - Element p = DOM.getParent(getElement()); - if (DOM.getElementPropertyInt(p, domProperty) > 50) { - if (vertical) - setHeight(); - else - DOM.setStyleAttribute(base, styleAttribute, ""); - } else { - // Set minimum size and adjust after all components have - // (supposedly) been drawn completely. - DOM.setStyleAttribute(base, styleAttribute, MIN_SIZE + "px"); - DeferredCommand.addCommand(new Command() { - public void execute() { - Element p = DOM.getParent(getElement()); - if (DOM.getElementPropertyInt(p, domProperty) > (MIN_SIZE + 5)) { - if (vertical) { - setHeight(); - } else - DOM.setStyleAttribute(base, styleAttribute, ""); - // Ensure correct position - setValue(value, false, false); - } - } - }); - } - } else - DOM.setStyleAttribute(base, styleAttribute, size + "px"); - - // TODO attach listeners for focusing and arrow keys - } - - private void buildHandle() { - String styleAttribute = vertical ? "height" : "width"; - String handleAttribute = vertical ? "marginTop" : "marginLeft"; - String domProperty = vertical ? "offsetHeight" : "offsetWidth"; - - DOM.setStyleAttribute(handle, handleAttribute, "0"); - - if (scrollbarStyle) { - // Only stretch the handle if scrollbar style is set. - int s = (int) (Double.parseDouble(DOM.getElementProperty(base, - domProperty)) / 100 * handleSize); - if (handleSize == -1) { - int baseS = Integer.parseInt(DOM.getElementProperty(base, - domProperty)); - double range = (max - min) * (resolution + 1) * 3; - s = (int) (baseS - range); - } - if (s < 3) - s = 3; - DOM.setStyleAttribute(handle, styleAttribute, s + "px"); - } else - DOM.setStyleAttribute(handle, styleAttribute, ""); - - // Restore visibility - DOM.setStyleAttribute(handle, "visibility", "visible"); - - } - - private void setValue(Double value, boolean animate, boolean updateToServer) { - if (value.doubleValue() < min) - value = new Double(min); - else if (value.doubleValue() > max) - value = new Double(max); - - // Update handle position - final String styleAttribute = vertical ? "marginTop" : "marginLeft"; - String domProperty = vertical ? "offsetHeight" : "offsetWidth"; - int handleSize = Integer.parseInt(DOM.getElementProperty(handle, - domProperty)); - int baseSize = Integer.parseInt(DOM.getElementProperty(base, - domProperty)); - int range = baseSize - handleSize; - double v = value.doubleValue(); - double valueRange = max - min; - double p = 0; - if (valueRange > 0) - p = range * ((v - min) / valueRange); - if (p < 0) - p = 0; - if (vertical) - // IE6 rounding behaves a little unstable, reduce one pixel so the - // containing element (base) won't expand without limits - p = range - p - (Util.isIE6() ? 1 : 0); - final double pos = p; - - int current = DOM.getIntStyleAttribute(handle, styleAttribute); - - if ((int) (Math.round(pos)) != current && animate) { - if (anim != null) - anim.cancel(); - anim = new Timer() { - private int current; - private int goal = (int) Math.round(pos); - private int dir = 0; - - public void run() { - current = DOM.getIntStyleAttribute(handle, styleAttribute); - - // Determine direction - if (dir == 0) - dir = (goal - current) / Math.abs(goal - current); - - if ((dir > 0 && current >= goal) - || (dir < 0 && current <= goal)) { - this.cancel(); - return; - } - int increment = (goal - current) / 2; - DOM.setStyleAttribute(handle, styleAttribute, - (current + increment) + "px"); - } - }; - anim.scheduleRepeating(50); - } else - DOM.setStyleAttribute(handle, styleAttribute, ((int) pos) + "px"); - - // Round value to resolution - if (resolution > 0) { - v = (int) (v * (double) Math.pow(10, resolution)); - v = v / (double) Math.pow(10, resolution); - } else - v = Math.round(v); - - // TODO give more detailed info when dragging and do roundup - DOM.setElementAttribute(handle, "title", "" + v); - - // Update value - this.value = new Double(v); - - if (updateToServer) - client.updateVariable(id, "value", this.value.doubleValue(), immediate); - } - - public void onBrowserEvent(Event event) { - if (disabled || readonly) - return; - Element targ = DOM.eventGetTarget(event); - - if (DOM.eventGetType(event) == Event.ONMOUSEWHEEL) { - processMouseWheelEvent(event); - } else if (dragging || DOM.compare(targ, handle)) - processHandleEvent(event); - else if (DOM.compare(targ, smaller)) - decreaseValue(event, true); - else if (DOM.compare(targ, bigger)) - increaseValue(event, true); - else - processBaseEvent(event); - } - - private void processMouseWheelEvent(Event event) { - int dir = DOM.eventGetMouseWheelVelocityY(event); - if (dir < 0) - increaseValue(event, false); - else - decreaseValue(event, false); - DOM.eventPreventDefault(event); - DOM.eventCancelBubble(event, true); - } - - private void processHandleEvent(Event event) { - switch (DOM.eventGetType(event)) { - case Event.ONMOUSEDOWN: - if (!disabled && !readonly) { - if (anim != null) - anim.cancel(); - dragging = true; - DOM.setCapture(getElement()); - DOM.eventPreventDefault(event); // prevent selecting text - DOM.eventCancelBubble(event, true); - } - break; - case Event.ONMOUSEMOVE: - if (dragging) { - // DOM.setCapture(getElement()); - setValueByEvent(event, false, false); - } - break; - case Event.ONMOUSEUP: - dragging = false; - DOM.releaseCapture(getElement()); - setValueByEvent(event, true, true); - break; - default: - break; - } - } - - private void processBaseEvent(Event event) { - if (DOM.eventGetType(event) == Event.ONMOUSEDOWN) { - if (!disabled && !readonly && !dragging) { - setValueByEvent(event, true, true); - DOM.eventCancelBubble(event, true); - } - } else if (DOM.eventGetType(event) == Event.ONMOUSEDOWN && dragging) { - dragging = false; - DOM.releaseCapture(getElement()); - setValueByEvent(event, true, true); - } - } - - private void decreaseValue(Event event, boolean animate) { - setValue(new Double(value.doubleValue() - Math.pow(10, -resolution)), - false, true); - if (DOM.eventGetType(event) == Event.ONMOUSEDOWN && animate) { - if (anim != null) - anim.cancel(); - anim = new Timer() { - public void run() { - if (value.doubleValue() - Math.pow(10, -resolution) > min) - setValue(new Double(value.doubleValue() - - Math.pow(10, -resolution)), false, true); - } - }; - anim.scheduleRepeating(100); - DOM.eventCancelBubble(event, true); - } else if (anim != null) - anim.cancel(); - } - - private void increaseValue(Event event, boolean animate) { - setValue(new Double(value.doubleValue() + Math.pow(10, -resolution)), - false, true); - if (DOM.eventGetType(event) == Event.ONMOUSEDOWN && animate) { - if (anim != null) - anim.cancel(); - anim = new Timer() { - public void run() { - if (value.doubleValue() - Math.pow(10, -resolution) < max) - setValue(new Double(value.doubleValue() - + Math.pow(10, -resolution)), false, true); - } - }; - anim.scheduleRepeating(100); - DOM.eventCancelBubble(event, true); - } else if (anim != null) - anim.cancel(); - } - - private void setValueByEvent(Event event, boolean animate, boolean roundup) { - double v = min; // Fallback to min - - int coord = vertical ? DOM.eventGetClientY(event) : DOM - .eventGetClientX(event); - String domProperty = vertical ? "offsetHeight" : "offsetWidth"; - - double handleSize = Integer.parseInt(DOM.getElementProperty(handle, - domProperty)); - double baseSize = Integer.parseInt(DOM.getElementProperty(base, - domProperty)); - double baseOffset = vertical ? DOM.getAbsoluteTop(base) - handleSize - / 2 : DOM.getAbsoluteLeft(base) + handleSize / 2; - - if (vertical) - v = ((baseSize - (coord - baseOffset)) / (baseSize - handleSize)) - * (max - min) + min; - else - v = ((coord - baseOffset) / (baseSize - handleSize)) * (max - min) - + min; - - if (v < min) - v = min; - else if (v > max) - v = max; - - setValue(new Double(v), animate, roundup); - } - - public void iLayout() { - if (vertical) { - setHeight(); - } - // Update handle position - setValue(value, false, false); - } - - private void setHeight() { - if (size == -1) { - // Calculate decoration size - DOM.setStyleAttribute(base, "height", "0"); - DOM.setStyleAttribute(base, "overflow", "hidden"); - int decoHeight = DOM.getElementPropertyInt(getElement(), - "offsetHeight"); - // Get available space size - int availableHeight = DOM.getElementPropertyInt(DOM - .getParent(getElement()), "offsetHeight"); - int h = availableHeight - decoHeight; - if (h < MIN_SIZE) - h = MIN_SIZE; - DOM.setStyleAttribute(base, "height", h + "px"); - } else { - DOM.setStyleAttribute(base, "height", size + "px"); - } - DOM.setStyleAttribute(base, "overflow", ""); - } + public static final String CLASSNAME = "i-slider"; + + /** + * Minimum size (width or height, depending on orientation) of the slider + * base. + */ + private static final int MIN_SIZE = 50; + + ApplicationConnection client; + + String id; + + private boolean immediate; + private boolean disabled; + private boolean readonly; + private boolean scrollbarStyle; + + private int handleSize; + private double min; + private double max; + private int resolution; + private Double value; + private boolean vertical; + private int size = -1; + private boolean arrows; + + /* DOM element for slider's base */ + private Element base; + + /* DOM element for slider's handle */ + private Element handle; + + /* DOM element for decrement arrow */ + private Element smaller; + + /* DOM element for increment arrow */ + private Element bigger; + + /* Temporary dragging/animation variables */ + private boolean dragging = false; + private Timer anim; + + public ISlider() { + super(); + + setElement(DOM.createDiv()); + base = DOM.createDiv(); + handle = DOM.createDiv(); + smaller = DOM.createDiv(); + bigger = DOM.createDiv(); + + setStyleName(CLASSNAME); + DOM.setElementProperty(base, "className", CLASSNAME + "-base"); + DOM.setElementProperty(handle, "className", CLASSNAME + "-handle"); + DOM.setElementProperty(smaller, "className", CLASSNAME + "-smaller"); + DOM.setElementProperty(bigger, "className", CLASSNAME + "-bigger"); + + DOM.appendChild(getElement(), bigger); + DOM.appendChild(getElement(), smaller); + DOM.appendChild(getElement(), base); + DOM.appendChild(base, handle); + + // Hide initially + DOM.setStyleAttribute(smaller, "display", "none"); + DOM.setStyleAttribute(bigger, "display", "none"); + DOM.setStyleAttribute(handle, "visibility", "hidden"); + + DOM.sinkEvents(getElement(), Event.MOUSEEVENTS | Event.ONMOUSEWHEEL); + DOM.sinkEvents(base, Event.ONCLICK); + DOM.sinkEvents(handle, Event.MOUSEEVENTS); + DOM.sinkEvents(smaller, Event.ONMOUSEDOWN | Event.ONMOUSEUP + | Event.ONMOUSEOUT); + DOM.sinkEvents(bigger, Event.ONMOUSEDOWN | Event.ONMOUSEUP + | Event.ONMOUSEOUT); + } + + public void updateFromUIDL(UIDL uidl, ApplicationConnection client) { + + this.client = client; + id = uidl.getId(); + + // Ensure correct implementation (handle own caption) + if (client.updateComponent(this, uidl, false)) { + return; + } + + immediate = uidl.getBooleanAttribute("immediate"); + disabled = uidl.getBooleanAttribute("disabled"); + readonly = uidl.getBooleanAttribute("readonly"); + + vertical = uidl.hasAttribute("vertical"); + arrows = uidl.hasAttribute("arrows"); + + String style = ""; + if (uidl.hasAttribute("style")) { + style = uidl.getStringAttribute("style"); + } + + scrollbarStyle = style.indexOf("scrollbar") > -1; + + if (arrows) { + DOM.setStyleAttribute(smaller, "display", "block"); + DOM.setStyleAttribute(bigger, "display", "block"); + } + + if (vertical) { + addStyleName(CLASSNAME + "-vertical"); + } else { + removeStyleName(CLASSNAME + "-vertical"); + } + + min = uidl.getDoubleAttribute("min"); + max = uidl.getDoubleAttribute("max"); + resolution = uidl.getIntAttribute("resolution"); + value = new Double(uidl.getDoubleVariable("value")); + + handleSize = uidl.getIntAttribute("hsize"); + + if (uidl.hasAttribute("size")) { + size = uidl.getIntAttribute("size"); + } + + buildBase(); + + if (!vertical) { + // Draw handle with a delay to allow base to gain maximum width + DeferredCommand.addCommand(new Command() { + public void execute() { + buildHandle(); + setValue(value, false, false); + } + }); + } else { + buildHandle(); + setValue(value, false, false); + } + } + + private void buildBase() { + final String styleAttribute = vertical ? "height" : "width"; + final String domProperty = vertical ? "offsetHeight" : "offsetWidth"; + + if (size == -1) { + Element p = DOM.getParent(getElement()); + if (DOM.getElementPropertyInt(p, domProperty) > 50) { + if (vertical) { + setHeight(); + } else { + DOM.setStyleAttribute(base, styleAttribute, ""); + } + } else { + // Set minimum size and adjust after all components have + // (supposedly) been drawn completely. + DOM.setStyleAttribute(base, styleAttribute, MIN_SIZE + "px"); + DeferredCommand.addCommand(new Command() { + public void execute() { + Element p = DOM.getParent(getElement()); + if (DOM.getElementPropertyInt(p, domProperty) > (MIN_SIZE + 5)) { + if (vertical) { + setHeight(); + } else { + DOM.setStyleAttribute(base, styleAttribute, ""); + } + // Ensure correct position + setValue(value, false, false); + } + } + }); + } + } else { + DOM.setStyleAttribute(base, styleAttribute, size + "px"); + } + + // TODO attach listeners for focusing and arrow keys + } + + private void buildHandle() { + String styleAttribute = vertical ? "height" : "width"; + String handleAttribute = vertical ? "marginTop" : "marginLeft"; + String domProperty = vertical ? "offsetHeight" : "offsetWidth"; + + DOM.setStyleAttribute(handle, handleAttribute, "0"); + + if (scrollbarStyle) { + // Only stretch the handle if scrollbar style is set. + int s = (int) (Double.parseDouble(DOM.getElementProperty(base, + domProperty)) / 100 * handleSize); + if (handleSize == -1) { + int baseS = Integer.parseInt(DOM.getElementProperty(base, + domProperty)); + double range = (max - min) * (resolution + 1) * 3; + s = (int) (baseS - range); + } + if (s < 3) { + s = 3; + } + DOM.setStyleAttribute(handle, styleAttribute, s + "px"); + } else { + DOM.setStyleAttribute(handle, styleAttribute, ""); + } + + // Restore visibility + DOM.setStyleAttribute(handle, "visibility", "visible"); + + } + + private void setValue(Double value, boolean animate, boolean updateToServer) { + if (value.doubleValue() < min) { + value = new Double(min); + } else if (value.doubleValue() > max) { + value = new Double(max); + } + + // Update handle position + final String styleAttribute = vertical ? "marginTop" : "marginLeft"; + String domProperty = vertical ? "offsetHeight" : "offsetWidth"; + int handleSize = Integer.parseInt(DOM.getElementProperty(handle, + domProperty)); + int baseSize = Integer.parseInt(DOM.getElementProperty(base, + domProperty)); + int range = baseSize - handleSize; + double v = value.doubleValue(); + double valueRange = max - min; + double p = 0; + if (valueRange > 0) { + p = range * ((v - min) / valueRange); + } + if (p < 0) { + p = 0; + } + if (vertical) { + // IE6 rounding behaves a little unstable, reduce one pixel so the + // containing element (base) won't expand without limits + p = range - p - (Util.isIE6() ? 1 : 0); + } + final double pos = p; + + int current = DOM.getIntStyleAttribute(handle, styleAttribute); + + if ((int) (Math.round(pos)) != current && animate) { + if (anim != null) { + anim.cancel(); + } + anim = new Timer() { + private int current; + private int goal = (int) Math.round(pos); + private int dir = 0; + + public void run() { + current = DOM.getIntStyleAttribute(handle, styleAttribute); + + // Determine direction + if (dir == 0) { + dir = (goal - current) / Math.abs(goal - current); + } + + if ((dir > 0 && current >= goal) + || (dir < 0 && current <= goal)) { + cancel(); + return; + } + int increment = (goal - current) / 2; + DOM.setStyleAttribute(handle, styleAttribute, + (current + increment) + "px"); + } + }; + anim.scheduleRepeating(50); + } else { + DOM.setStyleAttribute(handle, styleAttribute, ((int) pos) + "px"); + } + + // Round value to resolution + if (resolution > 0) { + v = (int) (v * Math.pow(10, resolution)); + v = v / Math.pow(10, resolution); + } else { + v = Math.round(v); + } + + // TODO give more detailed info when dragging and do roundup + DOM.setElementAttribute(handle, "title", "" + v); + + // Update value + this.value = new Double(v); + + if (updateToServer) { + client.updateVariable(id, "value", this.value.doubleValue(), + immediate); + } + } + + public void onBrowserEvent(Event event) { + if (disabled || readonly) { + return; + } + Element targ = DOM.eventGetTarget(event); + + if (DOM.eventGetType(event) == Event.ONMOUSEWHEEL) { + processMouseWheelEvent(event); + } else if (dragging || DOM.compare(targ, handle)) { + processHandleEvent(event); + } else if (DOM.compare(targ, smaller)) { + decreaseValue(event, true); + } else if (DOM.compare(targ, bigger)) { + increaseValue(event, true); + } else { + processBaseEvent(event); + } + } + + private void processMouseWheelEvent(Event event) { + int dir = DOM.eventGetMouseWheelVelocityY(event); + if (dir < 0) { + increaseValue(event, false); + } else { + decreaseValue(event, false); + } + DOM.eventPreventDefault(event); + DOM.eventCancelBubble(event, true); + } + + private void processHandleEvent(Event event) { + switch (DOM.eventGetType(event)) { + case Event.ONMOUSEDOWN: + if (!disabled && !readonly) { + if (anim != null) { + anim.cancel(); + } + dragging = true; + DOM.setCapture(getElement()); + DOM.eventPreventDefault(event); // prevent selecting text + DOM.eventCancelBubble(event, true); + } + break; + case Event.ONMOUSEMOVE: + if (dragging) { + // DOM.setCapture(getElement()); + setValueByEvent(event, false, false); + } + break; + case Event.ONMOUSEUP: + dragging = false; + DOM.releaseCapture(getElement()); + setValueByEvent(event, true, true); + break; + default: + break; + } + } + + private void processBaseEvent(Event event) { + if (DOM.eventGetType(event) == Event.ONMOUSEDOWN) { + if (!disabled && !readonly && !dragging) { + setValueByEvent(event, true, true); + DOM.eventCancelBubble(event, true); + } + } else if (DOM.eventGetType(event) == Event.ONMOUSEDOWN && dragging) { + dragging = false; + DOM.releaseCapture(getElement()); + setValueByEvent(event, true, true); + } + } + + private void decreaseValue(Event event, boolean animate) { + setValue(new Double(value.doubleValue() - Math.pow(10, -resolution)), + false, true); + if (DOM.eventGetType(event) == Event.ONMOUSEDOWN && animate) { + if (anim != null) { + anim.cancel(); + } + anim = new Timer() { + public void run() { + if (value.doubleValue() - Math.pow(10, -resolution) > min) { + setValue(new Double(value.doubleValue() + - Math.pow(10, -resolution)), false, true); + } + } + }; + anim.scheduleRepeating(100); + DOM.eventCancelBubble(event, true); + } else if (anim != null) { + anim.cancel(); + } + } + + private void increaseValue(Event event, boolean animate) { + setValue(new Double(value.doubleValue() + Math.pow(10, -resolution)), + false, true); + if (DOM.eventGetType(event) == Event.ONMOUSEDOWN && animate) { + if (anim != null) { + anim.cancel(); + } + anim = new Timer() { + public void run() { + if (value.doubleValue() - Math.pow(10, -resolution) < max) { + setValue(new Double(value.doubleValue() + + Math.pow(10, -resolution)), false, true); + } + } + }; + anim.scheduleRepeating(100); + DOM.eventCancelBubble(event, true); + } else if (anim != null) { + anim.cancel(); + } + } + + private void setValueByEvent(Event event, boolean animate, boolean roundup) { + double v = min; // Fallback to min + + int coord = vertical ? DOM.eventGetClientY(event) : DOM + .eventGetClientX(event); + String domProperty = vertical ? "offsetHeight" : "offsetWidth"; + + double handleSize = Integer.parseInt(DOM.getElementProperty(handle, + domProperty)); + double baseSize = Integer.parseInt(DOM.getElementProperty(base, + domProperty)); + double baseOffset = vertical ? DOM.getAbsoluteTop(base) - handleSize + / 2 : DOM.getAbsoluteLeft(base) + handleSize / 2; + + if (vertical) { + v = ((baseSize - (coord - baseOffset)) / (baseSize - handleSize)) + * (max - min) + min; + } else { + v = ((coord - baseOffset) / (baseSize - handleSize)) * (max - min) + + min; + } + + if (v < min) { + v = min; + } else if (v > max) { + v = max; + } + + setValue(new Double(v), animate, roundup); + } + + public void iLayout() { + if (vertical) { + setHeight(); + } + // Update handle position + setValue(value, false, false); + } + + private void setHeight() { + if (size == -1) { + // Calculate decoration size + DOM.setStyleAttribute(base, "height", "0"); + DOM.setStyleAttribute(base, "overflow", "hidden"); + int decoHeight = DOM.getElementPropertyInt(getElement(), + "offsetHeight"); + // Get available space size + int availableHeight = DOM.getElementPropertyInt(DOM + .getParent(getElement()), "offsetHeight"); + int h = availableHeight - decoHeight; + if (h < MIN_SIZE) { + h = MIN_SIZE; + } + DOM.setStyleAttribute(base, "height", h + "px"); + } else { + DOM.setStyleAttribute(base, "height", size + "px"); + } + DOM.setStyleAttribute(base, "overflow", ""); + } } diff --git a/src/com/itmill/toolkit/terminal/gwt/client/ui/ISplitPanel.java b/src/com/itmill/toolkit/terminal/gwt/client/ui/ISplitPanel.java index 1e6a043d10..00eb3f932b 100644 --- a/src/com/itmill/toolkit/terminal/gwt/client/ui/ISplitPanel.java +++ b/src/com/itmill/toolkit/terminal/gwt/client/ui/ISplitPanel.java @@ -12,334 +12,348 @@ import com.itmill.toolkit.terminal.gwt.client.UIDL; import com.itmill.toolkit.terminal.gwt.client.Util; public class ISplitPanel extends ComplexPanel implements Paintable, - ContainerResizedListener { - public static final String CLASSNAME = "i-splitpanel"; + ContainerResizedListener { + public static final String CLASSNAME = "i-splitpanel"; - public static final int ORIENTATION_HORIZONTAL = 0; + public static final int ORIENTATION_HORIZONTAL = 0; - public static final int ORIENTATION_VERTICAL = 1; + public static final int ORIENTATION_VERTICAL = 1; - private static final int MIN_SIZE = 30; + private static final int MIN_SIZE = 30; - private int orientation = ORIENTATION_HORIZONTAL; + private int orientation = ORIENTATION_HORIZONTAL; - private Widget firstChild; - - private Widget secondChild; - - private Element wrapper = DOM.createDiv(); - - private Element firstContainer = DOM.createDiv(); - - private Element secondContainer = DOM.createDiv(); - - private Element splitter = DOM.createDiv(); - - private boolean resizing; - - private int origX; - - private int origY; - - private int origMouseX; - - private int origMouseY; - - public ISplitPanel() { - this(ORIENTATION_HORIZONTAL); - } - - public ISplitPanel(int orientation) { - setElement(DOM.createDiv()); - switch (orientation) { - case ORIENTATION_HORIZONTAL: - setStyleName(CLASSNAME + "-horizontal"); - break; - case ORIENTATION_VERTICAL: - default: - setStyleName(CLASSNAME + "-vertical"); - break; - } - // size below will be overridden in update from uidl, initial size - // needed to keep IE alive - setWidth(MIN_SIZE + "px"); - setHeight(MIN_SIZE + "px"); - constructDom(); - setOrientation(orientation); - DOM.sinkEvents(splitter, (Event.MOUSEEVENTS)); - DOM.sinkEvents(getElement(), (Event.MOUSEEVENTS)); - } - - protected void constructDom() { - DOM.appendChild(splitter, DOM.createDiv()); // for styling - DOM.appendChild(getElement(), wrapper); - DOM.setStyleAttribute(wrapper, "position", "relative"); - DOM.setStyleAttribute(wrapper, "width", "100%"); - DOM.setStyleAttribute(wrapper, "height", "100%"); - - DOM.appendChild(wrapper, splitter); - DOM.appendChild(wrapper, secondContainer); - DOM.appendChild(wrapper, firstContainer); - - DOM.setStyleAttribute(splitter, "position", "absolute"); - DOM.setStyleAttribute(secondContainer, "position", "absolute"); - - DOM.setStyleAttribute(firstContainer, "overflow", "auto"); - DOM.setStyleAttribute(secondContainer, "overflow", "auto"); - - } - - private void setOrientation(int orientation) { - this.orientation = orientation; - if (orientation == ORIENTATION_HORIZONTAL) { - DOM.setStyleAttribute(splitter, "height", "100%"); - DOM.setStyleAttribute(firstContainer, "height", "100%"); - DOM.setStyleAttribute(secondContainer, "height", "100%"); - DOM.setElementProperty(splitter, "className", CLASSNAME - + "-hsplitter"); - } else { - DOM.setStyleAttribute(splitter, "width", "100%"); - DOM.setStyleAttribute(firstContainer, "width", "100%"); - DOM.setStyleAttribute(secondContainer, "width", "100%"); - DOM.setElementProperty(splitter, "className", CLASSNAME - + "-vsplitter"); - } - } - - public void updateFromUIDL(UIDL uidl, ApplicationConnection client) { - if (client.updateComponent(this, uidl, true)) - return; - - setWidth(uidl.getStringAttribute("width")); - setHeight(uidl.getStringAttribute("height")); - - setSplitPosition(uidl.getStringAttribute("position")); - - Paintable newFirstChild = (Paintable) client.getWidget(uidl - .getChildUIDL(0)); - Paintable newSecondChild = (Paintable) client.getWidget(uidl - .getChildUIDL(1)); - if (firstChild != newFirstChild) { - if (firstChild != null) - client.unregisterPaintable((Paintable) firstChild); - setFirstWidget((Widget) newFirstChild); - } - if (secondChild != newSecondChild) { - if (secondChild != null) - client.unregisterPaintable((Paintable) secondChild); - setSecondWidget((Widget) newSecondChild); - } - newFirstChild.updateFromUIDL(uidl.getChildUIDL(0), client); - newSecondChild.updateFromUIDL(uidl.getChildUIDL(1), client); - } - - private void setSplitPosition(String pos) { - if (orientation == ORIENTATION_HORIZONTAL) { - DOM.setStyleAttribute(splitter, "left", pos); - } else { - DOM.setStyleAttribute(splitter, "top", pos); - } - iLayout(); - } - - /* - * Calculates absolutely positioned container places/sizes (non-Javadoc) - * - * @see com.itmill.toolkit.terminal.gwt.client.NeedsLayout#layout() - */ - public void iLayout() { - if (!isAttached()) { - return; - } - int wholeSize; - int pixelPosition; - - switch (orientation) { - case ORIENTATION_HORIZONTAL: - wholeSize = DOM.getElementPropertyInt(wrapper, "clientWidth"); - pixelPosition = DOM.getElementPropertyInt(splitter, "offsetLeft"); - - // reposition splitter in case it is out of box - if (pixelPosition > 0 - && pixelPosition + getSplitterSize() > wholeSize) { - pixelPosition = wholeSize - getSplitterSize(); - if (pixelPosition < 0) - pixelPosition = 0; - setSplitPosition(pixelPosition + "px"); - return; - } - - DOM - .setStyleAttribute(firstContainer, "width", pixelPosition - + "px"); - int secondContainerWidth = (wholeSize - pixelPosition - getSplitterSize()); - if (secondContainerWidth < 0) - secondContainerWidth = 0; - DOM.setStyleAttribute(secondContainer, "width", - secondContainerWidth + "px"); - DOM.setStyleAttribute(secondContainer, "left", - (pixelPosition + getSplitterSize()) + "px"); - - break; - case ORIENTATION_VERTICAL: - wholeSize = DOM.getElementPropertyInt(wrapper, "clientHeight"); - pixelPosition = DOM.getElementPropertyInt(splitter, "offsetTop"); - - // reposition splitter in case it is out of box - if (pixelPosition > 0 - && pixelPosition + getSplitterSize() > wholeSize) { - pixelPosition = wholeSize - getSplitterSize(); - if (pixelPosition < 0) - pixelPosition = 0; - setSplitPosition(pixelPosition + "px"); - return; - } - - DOM.setStyleAttribute(firstContainer, "height", pixelPosition - + "px"); - int secondContainerHeight = (wholeSize - pixelPosition - getSplitterSize()); - if (secondContainerHeight < 0) - secondContainerHeight = 0; - DOM.setStyleAttribute(secondContainer, "height", - secondContainerHeight + "px"); - DOM.setStyleAttribute(secondContainer, "top", - (pixelPosition + getSplitterSize()) + "px"); - break; - default: - ApplicationConnection.getConsole().log("???"); - - break; - } - - Util.runDescendentsLayout(this); - } - - private void setFirstWidget(Widget w) { - if (firstChild != null) { - firstChild.removeFromParent(); - } - super.add(w, firstContainer); - firstChild = w; - } - - private void setSecondWidget(Widget w) { - if (secondChild != null) { - secondChild.removeFromParent(); - } - super.add(w, secondContainer); - secondChild = w; - } - - public void setHeight(String height) { - super.setHeight(height); - // give sane height - getOffsetHeight(); // shake IE - if (getOffsetHeight() < MIN_SIZE) - super.setHeight(MIN_SIZE + "px"); - } - - public void setWidth(String width) { - super.setWidth(width); - // give sane width - getOffsetWidth(); // shake IE - if (getOffsetWidth() < MIN_SIZE) - super.setWidth(MIN_SIZE + "px"); - } - - public void onBrowserEvent(Event event) { - switch (DOM.eventGetType(event)) { - case Event.ONMOUSEMOVE: - if (resizing) { - onMouseMove(event); - } - break; - case Event.ONMOUSEDOWN: - onMouseDown(event); - break; - case Event.ONMOUSEUP: - if (resizing) - onMouseUp(event); - break; - case Event.ONCLICK: - resizing = false; - break; - } - } - - public void onMouseDown(Event event) { - Element trg = DOM.eventGetTarget(event); - if (DOM.compare(trg, splitter) - || DOM.compare(trg, DOM.getChild(splitter, 0))) { - resizing = true; - DOM.setCapture(getElement()); - origX = DOM.getElementPropertyInt(splitter, "offsetLeft"); - origY = DOM.getElementPropertyInt(splitter, "offsetTop"); - origMouseX = DOM.eventGetClientX(event); - origMouseY = DOM.eventGetClientY(event); - DOM.eventCancelBubble(event, true); - DOM.eventPreventDefault(event); - } - } - - public void onMouseMove(Event event) { - switch (orientation) { - case ORIENTATION_HORIZONTAL: - int x = DOM.eventGetClientX(event); - onHorizontalMouseMove(x); - break; - case ORIENTATION_VERTICAL: - default: - int y = DOM.eventGetClientY(event); - onVerticalMouseMove(y); - break; - } - iLayout(); - } - - private void onHorizontalMouseMove(int x) { - int newX = origX + x - origMouseX; - if (newX < 0) - newX = 0; - if (newX + getSplitterSize() > getOffsetWidth()) - newX = getOffsetWidth() - getSplitterSize(); - DOM.setStyleAttribute(splitter, "left", newX + "px"); - } - - private void onVerticalMouseMove(int y) { - int newY = origY + y - origMouseY; - if (newY < 0) - newY = 0; - - if (newY + getSplitterSize() > getOffsetHeight()) - newY = getOffsetHeight() - getSplitterSize(); - DOM.setStyleAttribute(splitter, "top", newY + "px"); - } - - public void onMouseUp(Event event) { - DOM.releaseCapture(getElement()); - resizing = false; - onMouseMove(event); - } - - private static int splitterSize = -1; - - private int getSplitterSize() { - if (splitterSize < 0) { - if (isAttached()) { - switch (orientation) { - case ORIENTATION_HORIZONTAL: - splitterSize = DOM.getElementPropertyInt(splitter, - "offsetWidth"); - break; - - default: - splitterSize = DOM.getElementPropertyInt(splitter, - "offsetHeight"); - break; - } - } - } - return splitterSize; - } + private Widget firstChild; + + private Widget secondChild; + + private Element wrapper = DOM.createDiv(); + + private Element firstContainer = DOM.createDiv(); + + private Element secondContainer = DOM.createDiv(); + + private Element splitter = DOM.createDiv(); + + private boolean resizing; + + private int origX; + + private int origY; + + private int origMouseX; + + private int origMouseY; + + public ISplitPanel() { + this(ORIENTATION_HORIZONTAL); + } + + public ISplitPanel(int orientation) { + setElement(DOM.createDiv()); + switch (orientation) { + case ORIENTATION_HORIZONTAL: + setStyleName(CLASSNAME + "-horizontal"); + break; + case ORIENTATION_VERTICAL: + default: + setStyleName(CLASSNAME + "-vertical"); + break; + } + // size below will be overridden in update from uidl, initial size + // needed to keep IE alive + setWidth(MIN_SIZE + "px"); + setHeight(MIN_SIZE + "px"); + constructDom(); + setOrientation(orientation); + DOM.sinkEvents(splitter, (Event.MOUSEEVENTS)); + DOM.sinkEvents(getElement(), (Event.MOUSEEVENTS)); + } + + protected void constructDom() { + DOM.appendChild(splitter, DOM.createDiv()); // for styling + DOM.appendChild(getElement(), wrapper); + DOM.setStyleAttribute(wrapper, "position", "relative"); + DOM.setStyleAttribute(wrapper, "width", "100%"); + DOM.setStyleAttribute(wrapper, "height", "100%"); + + DOM.appendChild(wrapper, splitter); + DOM.appendChild(wrapper, secondContainer); + DOM.appendChild(wrapper, firstContainer); + + DOM.setStyleAttribute(splitter, "position", "absolute"); + DOM.setStyleAttribute(secondContainer, "position", "absolute"); + + DOM.setStyleAttribute(firstContainer, "overflow", "auto"); + DOM.setStyleAttribute(secondContainer, "overflow", "auto"); + + } + + private void setOrientation(int orientation) { + this.orientation = orientation; + if (orientation == ORIENTATION_HORIZONTAL) { + DOM.setStyleAttribute(splitter, "height", "100%"); + DOM.setStyleAttribute(firstContainer, "height", "100%"); + DOM.setStyleAttribute(secondContainer, "height", "100%"); + DOM.setElementProperty(splitter, "className", CLASSNAME + + "-hsplitter"); + } else { + DOM.setStyleAttribute(splitter, "width", "100%"); + DOM.setStyleAttribute(firstContainer, "width", "100%"); + DOM.setStyleAttribute(secondContainer, "width", "100%"); + DOM.setElementProperty(splitter, "className", CLASSNAME + + "-vsplitter"); + } + } + + public void updateFromUIDL(UIDL uidl, ApplicationConnection client) { + if (client.updateComponent(this, uidl, true)) { + return; + } + + setWidth(uidl.getStringAttribute("width")); + setHeight(uidl.getStringAttribute("height")); + + setSplitPosition(uidl.getStringAttribute("position")); + + Paintable newFirstChild = (Paintable) client.getWidget(uidl + .getChildUIDL(0)); + Paintable newSecondChild = (Paintable) client.getWidget(uidl + .getChildUIDL(1)); + if (firstChild != newFirstChild) { + if (firstChild != null) { + client.unregisterPaintable((Paintable) firstChild); + } + setFirstWidget((Widget) newFirstChild); + } + if (secondChild != newSecondChild) { + if (secondChild != null) { + client.unregisterPaintable((Paintable) secondChild); + } + setSecondWidget((Widget) newSecondChild); + } + newFirstChild.updateFromUIDL(uidl.getChildUIDL(0), client); + newSecondChild.updateFromUIDL(uidl.getChildUIDL(1), client); + } + + private void setSplitPosition(String pos) { + if (orientation == ORIENTATION_HORIZONTAL) { + DOM.setStyleAttribute(splitter, "left", pos); + } else { + DOM.setStyleAttribute(splitter, "top", pos); + } + iLayout(); + } + + /* + * Calculates absolutely positioned container places/sizes (non-Javadoc) + * + * @see com.itmill.toolkit.terminal.gwt.client.NeedsLayout#layout() + */ + public void iLayout() { + if (!isAttached()) { + return; + } + int wholeSize; + int pixelPosition; + + switch (orientation) { + case ORIENTATION_HORIZONTAL: + wholeSize = DOM.getElementPropertyInt(wrapper, "clientWidth"); + pixelPosition = DOM.getElementPropertyInt(splitter, "offsetLeft"); + + // reposition splitter in case it is out of box + if (pixelPosition > 0 + && pixelPosition + getSplitterSize() > wholeSize) { + pixelPosition = wholeSize - getSplitterSize(); + if (pixelPosition < 0) { + pixelPosition = 0; + } + setSplitPosition(pixelPosition + "px"); + return; + } + + DOM + .setStyleAttribute(firstContainer, "width", pixelPosition + + "px"); + int secondContainerWidth = (wholeSize - pixelPosition - getSplitterSize()); + if (secondContainerWidth < 0) { + secondContainerWidth = 0; + } + DOM.setStyleAttribute(secondContainer, "width", + secondContainerWidth + "px"); + DOM.setStyleAttribute(secondContainer, "left", + (pixelPosition + getSplitterSize()) + "px"); + + break; + case ORIENTATION_VERTICAL: + wholeSize = DOM.getElementPropertyInt(wrapper, "clientHeight"); + pixelPosition = DOM.getElementPropertyInt(splitter, "offsetTop"); + + // reposition splitter in case it is out of box + if (pixelPosition > 0 + && pixelPosition + getSplitterSize() > wholeSize) { + pixelPosition = wholeSize - getSplitterSize(); + if (pixelPosition < 0) { + pixelPosition = 0; + } + setSplitPosition(pixelPosition + "px"); + return; + } + + DOM.setStyleAttribute(firstContainer, "height", pixelPosition + + "px"); + int secondContainerHeight = (wholeSize - pixelPosition - getSplitterSize()); + if (secondContainerHeight < 0) { + secondContainerHeight = 0; + } + DOM.setStyleAttribute(secondContainer, "height", + secondContainerHeight + "px"); + DOM.setStyleAttribute(secondContainer, "top", + (pixelPosition + getSplitterSize()) + "px"); + break; + default: + ApplicationConnection.getConsole().log("???"); + + break; + } + + Util.runDescendentsLayout(this); + } + + private void setFirstWidget(Widget w) { + if (firstChild != null) { + firstChild.removeFromParent(); + } + super.add(w, firstContainer); + firstChild = w; + } + + private void setSecondWidget(Widget w) { + if (secondChild != null) { + secondChild.removeFromParent(); + } + super.add(w, secondContainer); + secondChild = w; + } + + public void setHeight(String height) { + super.setHeight(height); + // give sane height + getOffsetHeight(); // shake IE + if (getOffsetHeight() < MIN_SIZE) { + super.setHeight(MIN_SIZE + "px"); + } + } + + public void setWidth(String width) { + super.setWidth(width); + // give sane width + getOffsetWidth(); // shake IE + if (getOffsetWidth() < MIN_SIZE) { + super.setWidth(MIN_SIZE + "px"); + } + } + + public void onBrowserEvent(Event event) { + switch (DOM.eventGetType(event)) { + case Event.ONMOUSEMOVE: + if (resizing) { + onMouseMove(event); + } + break; + case Event.ONMOUSEDOWN: + onMouseDown(event); + break; + case Event.ONMOUSEUP: + if (resizing) { + onMouseUp(event); + } + break; + case Event.ONCLICK: + resizing = false; + break; + } + } + + public void onMouseDown(Event event) { + Element trg = DOM.eventGetTarget(event); + if (DOM.compare(trg, splitter) + || DOM.compare(trg, DOM.getChild(splitter, 0))) { + resizing = true; + DOM.setCapture(getElement()); + origX = DOM.getElementPropertyInt(splitter, "offsetLeft"); + origY = DOM.getElementPropertyInt(splitter, "offsetTop"); + origMouseX = DOM.eventGetClientX(event); + origMouseY = DOM.eventGetClientY(event); + DOM.eventCancelBubble(event, true); + DOM.eventPreventDefault(event); + } + } + + public void onMouseMove(Event event) { + switch (orientation) { + case ORIENTATION_HORIZONTAL: + int x = DOM.eventGetClientX(event); + onHorizontalMouseMove(x); + break; + case ORIENTATION_VERTICAL: + default: + int y = DOM.eventGetClientY(event); + onVerticalMouseMove(y); + break; + } + iLayout(); + } + + private void onHorizontalMouseMove(int x) { + int newX = origX + x - origMouseX; + if (newX < 0) { + newX = 0; + } + if (newX + getSplitterSize() > getOffsetWidth()) { + newX = getOffsetWidth() - getSplitterSize(); + } + DOM.setStyleAttribute(splitter, "left", newX + "px"); + } + + private void onVerticalMouseMove(int y) { + int newY = origY + y - origMouseY; + if (newY < 0) { + newY = 0; + } + + if (newY + getSplitterSize() > getOffsetHeight()) { + newY = getOffsetHeight() - getSplitterSize(); + } + DOM.setStyleAttribute(splitter, "top", newY + "px"); + } + + public void onMouseUp(Event event) { + DOM.releaseCapture(getElement()); + resizing = false; + onMouseMove(event); + } + + private static int splitterSize = -1; + + private int getSplitterSize() { + if (splitterSize < 0) { + if (isAttached()) { + switch (orientation) { + case ORIENTATION_HORIZONTAL: + splitterSize = DOM.getElementPropertyInt(splitter, + "offsetWidth"); + break; + + default: + splitterSize = DOM.getElementPropertyInt(splitter, + "offsetHeight"); + break; + } + } + } + return splitterSize; + } } diff --git a/src/com/itmill/toolkit/terminal/gwt/client/ui/ISplitPanelHorizontal.java b/src/com/itmill/toolkit/terminal/gwt/client/ui/ISplitPanelHorizontal.java index f476f23dbb..77f08a2564 100644 --- a/src/com/itmill/toolkit/terminal/gwt/client/ui/ISplitPanelHorizontal.java +++ b/src/com/itmill/toolkit/terminal/gwt/client/ui/ISplitPanelHorizontal.java @@ -2,7 +2,7 @@ package com.itmill.toolkit.terminal.gwt.client.ui; public class ISplitPanelHorizontal extends ISplitPanel { - public ISplitPanelHorizontal() { - super(ISplitPanel.ORIENTATION_HORIZONTAL); - } + public ISplitPanelHorizontal() { + super(ISplitPanel.ORIENTATION_HORIZONTAL); + } } diff --git a/src/com/itmill/toolkit/terminal/gwt/client/ui/ISplitPanelVertical.java b/src/com/itmill/toolkit/terminal/gwt/client/ui/ISplitPanelVertical.java index 9fd7bc5a2c..cdcd8d0c65 100644 --- a/src/com/itmill/toolkit/terminal/gwt/client/ui/ISplitPanelVertical.java +++ b/src/com/itmill/toolkit/terminal/gwt/client/ui/ISplitPanelVertical.java @@ -2,7 +2,7 @@ package com.itmill.toolkit.terminal.gwt.client.ui; public class ISplitPanelVertical extends ISplitPanel { - public ISplitPanelVertical() { - super(ISplitPanel.ORIENTATION_VERTICAL); - } + public ISplitPanelVertical() { + super(ISplitPanel.ORIENTATION_VERTICAL); + } } diff --git a/src/com/itmill/toolkit/terminal/gwt/client/ui/ITablePaging.java b/src/com/itmill/toolkit/terminal/gwt/client/ui/ITablePaging.java index 731d1cc2e4..d10b62ba43 100644 --- a/src/com/itmill/toolkit/terminal/gwt/client/ui/ITablePaging.java +++ b/src/com/itmill/toolkit/terminal/gwt/client/ui/ITablePaging.java @@ -28,397 +28,408 @@ import com.itmill.toolkit.terminal.gwt.client.UIDL; * style table which will be much lighter than IScrollTable is. */ public class ITablePaging extends Composite implements Table, Paintable, - ClickListener { + ClickListener { - private Grid tBody = new Grid(); - private Button nextPage = new Button(">"); - private Button prevPage = new Button("<"); - private Button firstPage = new Button("<<"); - private Button lastPage = new Button(">>"); + private Grid tBody = new Grid(); + private Button nextPage = new Button(">"); + private Button prevPage = new Button("<"); + private Button firstPage = new Button("<<"); + private Button lastPage = new Button(">>"); - private int pageLength = 15; + private int pageLength = 15; - private boolean rowHeaders = false; + private boolean rowHeaders = false; + + private Map columnOrder = new HashMap(); - private Map columnOrder = new HashMap(); + private ApplicationConnection client; + private String id; - private ApplicationConnection client; - private String id; + private boolean immediate = false; - private boolean immediate = false; - - private int selectMode = Table.SELECT_MODE_NONE; - - private Vector selectedRowKeys = new Vector(); - - private int totalRows; - - private HashMap columnWidths = new HashMap(); - - private HashMap visibleColumns = new HashMap(); - - private int rows; - - private int firstRow; - private boolean sortAscending = true; - private HorizontalPanel pager; - - public HashMap rowKeysToTableRows = new HashMap(); - - public ITablePaging() { - - tBody.setStyleName("itable-tbody"); - - VerticalPanel panel = new VerticalPanel(); - - pager = new HorizontalPanel(); - pager.add(firstPage); - firstPage.addClickListener(this); - pager.add(prevPage); - prevPage.addClickListener(this); - pager.add(nextPage); - nextPage.addClickListener(this); - pager.add(lastPage); - lastPage.addClickListener(this); - - panel.add(pager); - panel.add(tBody); - - initWidget(panel); - } - - public void updateFromUIDL(UIDL uidl, ApplicationConnection client) { - if (client.updateComponent(this, uidl, true)) - return; - - this.client = client; - this.id = uidl.getStringAttribute("id"); - this.immediate = uidl.getBooleanAttribute("immediate"); - this.totalRows = uidl.getIntAttribute("totalrows"); - this.pageLength = uidl.getIntAttribute("pagelength"); - this.firstRow = uidl.getIntAttribute("firstrow"); - this.rows = uidl.getIntAttribute("rows"); - - if (uidl.hasAttribute("selectmode")) { - if (uidl.getStringAttribute("selectmode").equals("multi")) - selectMode = Table.SELECT_MODE_MULTI; - else - selectMode = Table.SELECT_MODE_SINGLE; - - if (uidl.hasAttribute("selected")) { - Set selectedKeys = uidl.getStringArrayVariableAsSet("selected"); - selectedRowKeys.clear(); - for (Iterator it = selectedKeys.iterator(); it.hasNext();) - selectedRowKeys.add((String) it.next()); - } - } - - if (uidl.hasVariable("sortascending")) - this.sortAscending = uidl.getBooleanVariable("sortascending"); - - if (uidl.hasAttribute("rowheaders")) - rowHeaders = true; - - UIDL rowData = null; - UIDL visibleColumns = null; - for (Iterator it = uidl.getChildIterator(); it.hasNext();) { - UIDL c = (UIDL) it.next(); - if (c.getTag().equals("rows")) - rowData = c; - else if (c.getTag().equals("actions")) - updateActionMap(c); - else if (c.getTag().equals("visiblecolumns")) - visibleColumns = c; - } - tBody.resize(rows + 1, uidl.getIntAttribute("cols") - + (rowHeaders ? 1 : 0)); - updateHeader(visibleColumns); - updateBody(rowData); - - updatePager(); - } - - private void updateHeader(UIDL c) { - Iterator it = c.getChildIterator(); - visibleColumns.clear(); - int colIndex = (rowHeaders ? 1 : 0); - while (it.hasNext()) { - UIDL col = (UIDL) it.next(); - String cid = col.getStringAttribute("cid"); - if (!col.hasAttribute("collapsed")) { - tBody.setWidget(0, colIndex, new HeaderCell(cid, col - .getStringAttribute("caption"))); - - } - colIndex++; - } - } - - private void updateActionMap(UIDL c) { - // TODO Auto-generated method stub - - } - - /** - * Updates row data from uidl. UpdateFromUIDL delegates updating tBody to - * this method. - * - * Updates may be to different part of tBody, depending on update type. It - * can be initial row data, scroll up, scroll down... - * - * @param uidl - * which contains row data - */ - private void updateBody(UIDL uidl) { - Iterator it = uidl.getChildIterator(); - - int curRowIndex = 1; - while (it.hasNext()) { - UIDL rowUidl = (UIDL) it.next(); - TableRow row = new TableRow(curRowIndex, String.valueOf(rowUidl - .getIntAttribute("key")), rowUidl.hasAttribute("selected")); - int colIndex = 0; - if (rowHeaders) { - tBody.setWidget(curRowIndex, colIndex, new BodyCell(row, - rowUidl.getStringAttribute("caption"))); - colIndex++; - } - Iterator cells = rowUidl.getChildIterator(); - while (cells.hasNext()) { - Object cell = cells.next(); - if (cell instanceof String) { - tBody.setWidget(curRowIndex, colIndex, new BodyCell(row, - (String) cell)); - } else { - Widget cellContent = client.getWidget((UIDL) cell); - BodyCell bodyCell = new BodyCell(row); - bodyCell.setWidget(cellContent); - tBody.setWidget(curRowIndex, colIndex, bodyCell); - } - colIndex++; - } - curRowIndex++; - } - } - - private void updatePager() { - if (pageLength == 0) { - pager.setVisible(false); - return; - } - if (isFirstPage()) { - firstPage.setEnabled(false); - prevPage.setEnabled(false); - } else { - firstPage.setEnabled(true); - prevPage.setEnabled(true); - } - if (hasNextPage()) { - nextPage.setEnabled(true); - lastPage.setEnabled(true); - } else { - nextPage.setEnabled(false); - lastPage.setEnabled(false); - - } - } - - private boolean hasNextPage() { - if (firstRow + rows + 1 > totalRows) - return false; - return true; - } - - private boolean isFirstPage() { - if (firstRow == 0) - return true; - return false; - } - - public void onClick(Widget sender) { - if (sender instanceof Button) { - if (sender == firstPage) - client.updateVariable(this.id, "firstvisible", 0, true); - else if (sender == nextPage) - client.updateVariable(this.id, "firstvisible", firstRow - + pageLength, true); - else if (sender == prevPage) { - int newFirst = firstRow - pageLength; - if (newFirst < 0) - newFirst = 0; - client.updateVariable(this.id, "firstvisible", newFirst, true); - } else if (sender == lastPage) { - client.updateVariable(this.id, "firstvisible", totalRows - - pageLength, true); - } - } - if (sender instanceof HeaderCell) { - HeaderCell hCell = (HeaderCell) sender; - client.updateVariable(this.id, "sortcolumn", hCell.getCid(), false); - client.updateVariable(this.id, "sortascending", - (sortAscending ? false : true), true); - } - } - - private class HeaderCell extends HTML { - - private String cid; - - public String getCid() { - return cid; - } - - public void setCid(String pid) { - this.cid = pid; - } - - HeaderCell(String pid, String caption) { - super(); - this.cid = pid; - addClickListener(ITablePaging.this); - setText(caption); - // TODO remove debug color - DOM.setStyleAttribute(getElement(), "color", "brown"); - DOM.setStyleAttribute(getElement(), "font-weight", "bold"); - } - } - - /** - * Abstraction of table cell content. In needs to know on which row it is in - * case of context click. - * - * @author mattitahvonen - */ - public class BodyCell extends SimplePanel { - private TableRow row; - - public BodyCell(TableRow row) { - super(); - this.sinkEvents(Event.BUTTON_LEFT | Event.BUTTON_RIGHT); - this.row = row; - } - - public BodyCell(TableRow row2, String textContent) { - super(); - this.sinkEvents(Event.BUTTON_LEFT | Event.BUTTON_RIGHT); - this.row = row2; - setWidget(new Label(textContent)); - } - - public void onBrowserEvent(Event event) { - System.out.println("CEll event: " + event.toString()); - switch (DOM.eventGetType(event)) { - case Event.BUTTON_RIGHT: - row.showContextMenu(event); - Window.alert("context menu un-implemented"); - DOM.eventCancelBubble(event, true); - break; - case Event.BUTTON_LEFT: - if (ITablePaging.this.selectMode > Table.SELECT_MODE_NONE) - row.toggleSelected(); - break; - default: - break; - } - super.onBrowserEvent(event); - } - } - - private class TableRow { - - private String key; - private int rowIndex; - private boolean selected = false; - - public TableRow(int rowIndex, String rowKey, boolean selected) { - ITablePaging.this.rowKeysToTableRows.put(rowKey, this); - this.rowIndex = rowIndex; - this.key = rowKey; - setSelected(selected); - } - - /** - * This method is used to set row status. Does not change value on - * server. - * - * @param selected - */ - public void setSelected(boolean sel) { - this.selected = sel; - if (selected) { - selectedRowKeys.add(key); - DOM.setStyleAttribute(ITablePaging.this.tBody.getRowFormatter() - .getElement(rowIndex), "background", "yellow"); - - } else { - selectedRowKeys.remove(key); - DOM.setStyleAttribute(ITablePaging.this.tBody.getRowFormatter() - .getElement(rowIndex), "background", "transparent"); - } - } - - public void setContextMenuOptions(HashMap options) { - - } - - /** - * Toggles rows select state. Also updates state to server according to - * tables immediate flag. - * - */ - public void toggleSelected() { - if (selected) { - setSelected(false); - } else { - if (ITablePaging.this.selectMode == Table.SELECT_MODE_SINGLE) { - ITablePaging.this.deselectAll(); - } - setSelected(true); - } - client.updateVariable(id, "selected", selectedRowKeys.toArray(), - immediate); - } - - /** - * Shows context menu for this row. - * - * @param event - * Event which triggered context menu. Correct place for - * context menu can be determined with it. - */ - public void showContextMenu(Event event) { - System.out.println("TODO: Show context menu"); - } - } - - public void deselectAll() { - Object[] keys = selectedRowKeys.toArray(); - for (int i = 0; i < keys.length; i++) { - TableRow tableRow = (TableRow) rowKeysToTableRows.get(keys[i]); - if (tableRow != null) - tableRow.setSelected(false); - } - // still ensure all selects are removed from - selectedRowKeys.clear(); - } - - public void add(Widget w) { - // TODO Auto-generated method stub - - } - - public void clear() { - // TODO Auto-generated method stub - - } - - public Iterator iterator() { - // TODO Auto-generated method stub - return null; - } - - public boolean remove(Widget w) { - // TODO Auto-generated method stub - return false; - } + private int selectMode = Table.SELECT_MODE_NONE; + + private Vector selectedRowKeys = new Vector(); + + private int totalRows; + + private HashMap columnWidths = new HashMap(); + + private HashMap visibleColumns = new HashMap(); + + private int rows; + + private int firstRow; + private boolean sortAscending = true; + private HorizontalPanel pager; + + public HashMap rowKeysToTableRows = new HashMap(); + + public ITablePaging() { + + tBody.setStyleName("itable-tbody"); + + VerticalPanel panel = new VerticalPanel(); + + pager = new HorizontalPanel(); + pager.add(firstPage); + firstPage.addClickListener(this); + pager.add(prevPage); + prevPage.addClickListener(this); + pager.add(nextPage); + nextPage.addClickListener(this); + pager.add(lastPage); + lastPage.addClickListener(this); + + panel.add(pager); + panel.add(tBody); + + initWidget(panel); + } + + public void updateFromUIDL(UIDL uidl, ApplicationConnection client) { + if (client.updateComponent(this, uidl, true)) { + return; + } + + this.client = client; + id = uidl.getStringAttribute("id"); + immediate = uidl.getBooleanAttribute("immediate"); + totalRows = uidl.getIntAttribute("totalrows"); + pageLength = uidl.getIntAttribute("pagelength"); + firstRow = uidl.getIntAttribute("firstrow"); + rows = uidl.getIntAttribute("rows"); + + if (uidl.hasAttribute("selectmode")) { + if (uidl.getStringAttribute("selectmode").equals("multi")) { + selectMode = Table.SELECT_MODE_MULTI; + } else { + selectMode = Table.SELECT_MODE_SINGLE; + } + + if (uidl.hasAttribute("selected")) { + Set selectedKeys = uidl.getStringArrayVariableAsSet("selected"); + selectedRowKeys.clear(); + for (Iterator it = selectedKeys.iterator(); it.hasNext();) { + selectedRowKeys.add(it.next()); + } + } + } + + if (uidl.hasVariable("sortascending")) { + sortAscending = uidl.getBooleanVariable("sortascending"); + } + + if (uidl.hasAttribute("rowheaders")) { + rowHeaders = true; + } + + UIDL rowData = null; + UIDL visibleColumns = null; + for (Iterator it = uidl.getChildIterator(); it.hasNext();) { + UIDL c = (UIDL) it.next(); + if (c.getTag().equals("rows")) { + rowData = c; + } else if (c.getTag().equals("actions")) { + updateActionMap(c); + } else if (c.getTag().equals("visiblecolumns")) { + visibleColumns = c; + } + } + tBody.resize(rows + 1, uidl.getIntAttribute("cols") + + (rowHeaders ? 1 : 0)); + updateHeader(visibleColumns); + updateBody(rowData); + + updatePager(); + } + + private void updateHeader(UIDL c) { + Iterator it = c.getChildIterator(); + visibleColumns.clear(); + int colIndex = (rowHeaders ? 1 : 0); + while (it.hasNext()) { + UIDL col = (UIDL) it.next(); + String cid = col.getStringAttribute("cid"); + if (!col.hasAttribute("collapsed")) { + tBody.setWidget(0, colIndex, new HeaderCell(cid, col + .getStringAttribute("caption"))); + + } + colIndex++; + } + } + + private void updateActionMap(UIDL c) { + // TODO Auto-generated method stub + + } + + /** + * Updates row data from uidl. UpdateFromUIDL delegates updating tBody to + * this method. + * + * Updates may be to different part of tBody, depending on update type. It + * can be initial row data, scroll up, scroll down... + * + * @param uidl + * which contains row data + */ + private void updateBody(UIDL uidl) { + Iterator it = uidl.getChildIterator(); + + int curRowIndex = 1; + while (it.hasNext()) { + UIDL rowUidl = (UIDL) it.next(); + TableRow row = new TableRow(curRowIndex, String.valueOf(rowUidl + .getIntAttribute("key")), rowUidl.hasAttribute("selected")); + int colIndex = 0; + if (rowHeaders) { + tBody.setWidget(curRowIndex, colIndex, new BodyCell(row, + rowUidl.getStringAttribute("caption"))); + colIndex++; + } + Iterator cells = rowUidl.getChildIterator(); + while (cells.hasNext()) { + Object cell = cells.next(); + if (cell instanceof String) { + tBody.setWidget(curRowIndex, colIndex, new BodyCell(row, + (String) cell)); + } else { + Widget cellContent = client.getWidget((UIDL) cell); + BodyCell bodyCell = new BodyCell(row); + bodyCell.setWidget(cellContent); + tBody.setWidget(curRowIndex, colIndex, bodyCell); + } + colIndex++; + } + curRowIndex++; + } + } + + private void updatePager() { + if (pageLength == 0) { + pager.setVisible(false); + return; + } + if (isFirstPage()) { + firstPage.setEnabled(false); + prevPage.setEnabled(false); + } else { + firstPage.setEnabled(true); + prevPage.setEnabled(true); + } + if (hasNextPage()) { + nextPage.setEnabled(true); + lastPage.setEnabled(true); + } else { + nextPage.setEnabled(false); + lastPage.setEnabled(false); + + } + } + + private boolean hasNextPage() { + if (firstRow + rows + 1 > totalRows) { + return false; + } + return true; + } + + private boolean isFirstPage() { + if (firstRow == 0) { + return true; + } + return false; + } + + public void onClick(Widget sender) { + if (sender instanceof Button) { + if (sender == firstPage) { + client.updateVariable(id, "firstvisible", 0, true); + } else if (sender == nextPage) { + client.updateVariable(id, "firstvisible", + firstRow + pageLength, true); + } else if (sender == prevPage) { + int newFirst = firstRow - pageLength; + if (newFirst < 0) { + newFirst = 0; + } + client.updateVariable(id, "firstvisible", newFirst, true); + } else if (sender == lastPage) { + client.updateVariable(id, "firstvisible", totalRows + - pageLength, true); + } + } + if (sender instanceof HeaderCell) { + HeaderCell hCell = (HeaderCell) sender; + client.updateVariable(id, "sortcolumn", hCell.getCid(), false); + client.updateVariable(id, "sortascending", (sortAscending ? false + : true), true); + } + } + + private class HeaderCell extends HTML { + + private String cid; + + public String getCid() { + return cid; + } + + public void setCid(String pid) { + cid = pid; + } + + HeaderCell(String pid, String caption) { + super(); + cid = pid; + addClickListener(ITablePaging.this); + setText(caption); + // TODO remove debug color + DOM.setStyleAttribute(getElement(), "color", "brown"); + DOM.setStyleAttribute(getElement(), "font-weight", "bold"); + } + } + + /** + * Abstraction of table cell content. In needs to know on which row it is in + * case of context click. + * + * @author mattitahvonen + */ + public class BodyCell extends SimplePanel { + private TableRow row; + + public BodyCell(TableRow row) { + super(); + sinkEvents(Event.BUTTON_LEFT | Event.BUTTON_RIGHT); + this.row = row; + } + + public BodyCell(TableRow row2, String textContent) { + super(); + sinkEvents(Event.BUTTON_LEFT | Event.BUTTON_RIGHT); + row = row2; + setWidget(new Label(textContent)); + } + + public void onBrowserEvent(Event event) { + System.out.println("CEll event: " + event.toString()); + switch (DOM.eventGetType(event)) { + case Event.BUTTON_RIGHT: + row.showContextMenu(event); + Window.alert("context menu un-implemented"); + DOM.eventCancelBubble(event, true); + break; + case Event.BUTTON_LEFT: + if (selectMode > Table.SELECT_MODE_NONE) { + row.toggleSelected(); + } + break; + default: + break; + } + super.onBrowserEvent(event); + } + } + + private class TableRow { + + private String key; + private int rowIndex; + private boolean selected = false; + + public TableRow(int rowIndex, String rowKey, boolean selected) { + rowKeysToTableRows.put(rowKey, this); + this.rowIndex = rowIndex; + key = rowKey; + setSelected(selected); + } + + /** + * This method is used to set row status. Does not change value on + * server. + * + * @param selected + */ + public void setSelected(boolean sel) { + selected = sel; + if (selected) { + selectedRowKeys.add(key); + DOM.setStyleAttribute(tBody.getRowFormatter().getElement( + rowIndex), "background", "yellow"); + + } else { + selectedRowKeys.remove(key); + DOM.setStyleAttribute(tBody.getRowFormatter().getElement( + rowIndex), "background", "transparent"); + } + } + + public void setContextMenuOptions(HashMap options) { + + } + + /** + * Toggles rows select state. Also updates state to server according to + * tables immediate flag. + * + */ + public void toggleSelected() { + if (selected) { + setSelected(false); + } else { + if (selectMode == Table.SELECT_MODE_SINGLE) { + deselectAll(); + } + setSelected(true); + } + client.updateVariable(id, "selected", selectedRowKeys.toArray(), + immediate); + } + + /** + * Shows context menu for this row. + * + * @param event + * Event which triggered context menu. Correct place for + * context menu can be determined with it. + */ + public void showContextMenu(Event event) { + System.out.println("TODO: Show context menu"); + } + } + + public void deselectAll() { + Object[] keys = selectedRowKeys.toArray(); + for (int i = 0; i < keys.length; i++) { + TableRow tableRow = (TableRow) rowKeysToTableRows.get(keys[i]); + if (tableRow != null) { + tableRow.setSelected(false); + } + } + // still ensure all selects are removed from + selectedRowKeys.clear(); + } + + public void add(Widget w) { + // TODO Auto-generated method stub + + } + + public void clear() { + // TODO Auto-generated method stub + + } + + public Iterator iterator() { + // TODO Auto-generated method stub + return null; + } + + public boolean remove(Widget w) { + // TODO Auto-generated method stub + return false; + } } diff --git a/src/com/itmill/toolkit/terminal/gwt/client/ui/ITabsheet.java b/src/com/itmill/toolkit/terminal/gwt/client/ui/ITabsheet.java index 83387d3564..d1d1eb6ee4 100644 --- a/src/com/itmill/toolkit/terminal/gwt/client/ui/ITabsheet.java +++ b/src/com/itmill/toolkit/terminal/gwt/client/ui/ITabsheet.java @@ -19,219 +19,216 @@ import com.itmill.toolkit.terminal.gwt.client.UIDL; import com.itmill.toolkit.terminal.gwt.client.Util; public class ITabsheet extends FlowPanel implements Paintable, - ContainerResizedListener { + ContainerResizedListener { - public static final String CLASSNAME = "i-tabsheet"; - - String id; + public static final String CLASSNAME = "i-tabsheet"; - ApplicationConnection client; - - ArrayList tabKeys = new ArrayList(); - - ArrayList captions = new ArrayList(); - - int activeTabIndex = 0; - - private final TabBar tb; - - private final ITabsheetPanel tp; - - private final Element deco; - - private final TabListener tl = new TabListener() { - - public void onTabSelected(SourcesTabEvents sender, final int tabIndex) { - if (ITabsheet.this.client != null - && ITabsheet.this.activeTabIndex != tabIndex) { - addStyleDependentName("loading"); - // run updating variables in deferred command to bypass some FF - // optimization issues - DeferredCommand.addCommand(new Command() { - public void execute() { - ITabsheet.this.client.updateVariable(ITabsheet.this.id, - "selected", "" - + ITabsheet.this.tabKeys.get(tabIndex), - true); - } - }); - } - } - - public boolean onBeforeTabSelected(SourcesTabEvents sender, int tabIndex) { - return true; - } - - }; - - private String height; - - public ITabsheet() { - setStyleName(CLASSNAME); - - this.tb = new TabBar(); - this.tp = new ITabsheetPanel(); - this.deco = DOM.createDiv(); - - this.tp.setStyleName(CLASSNAME + "-content"); - addStyleDependentName("loading"); // Indicate initial progress - this.tb.setStyleName(CLASSNAME + "-tabs"); - DOM.setElementProperty(this.deco, "className", CLASSNAME + "-deco"); - - add(this.tb); - add(this.tp); - DOM.appendChild(getElement(), this.deco); - - this.tb.addTabListener(this.tl); - - clearTabs(); - } - - public void updateFromUIDL(UIDL uidl, ApplicationConnection client) { - this.client = client; - this.id = uidl.getId(); - - if (client.updateComponent(this, uidl, false)) { - return; - } - - // Add proper stylenames for all elements - if (uidl.hasAttribute("style")) { - String[] styles = uidl.getStringAttribute("style").split(" "); - String decoBaseClass = CLASSNAME + "-deco"; - String decoClass = decoBaseClass; - for (int i = 0; i < styles.length; i++) { - this.tb.addStyleDependentName(styles[i]); - this.tp.addStyleDependentName(styles[i]); - decoClass += " " + decoBaseClass + "-" + styles[i]; - } - DOM.setElementProperty(this.deco, "className", decoClass); - } - - // Adjust width and height - String h = uidl.hasAttribute("height") ? uidl - .getStringAttribute("height") : null; - String w = uidl.hasAttribute("width") ? uidl - .getStringAttribute("width") : null; - setWidth(w != null ? w : "auto"); - - // Height calculations - if (h != null) { - if (!h.equals(height)) { - setHeight(h); - } - } else { - this.height = null; - this.tp.setHeight(""); - } - - // Render content - UIDL tabs = uidl.getChildUIDL(0); - boolean keepCurrentTabs = this.tabKeys.size() == tabs - .getNumberOfChildren(); - for (int i = 0; keepCurrentTabs && i < this.tabKeys.size(); i++) { - keepCurrentTabs = this.tabKeys.get(i).equals( - tabs.getChildUIDL(i).getStringAttribute("key")) - && this.captions.get(i).equals( - tabs.getChildUIDL(i).getStringAttribute("caption")); - } - if (keepCurrentTabs) { - int index = 0; - for (Iterator it = tabs.getChildIterator(); it.hasNext();) { - UIDL tab = (UIDL) it.next(); - if (tab.getBooleanAttribute("selected")) { - this.activeTabIndex = index; - renderContent(tab.getChildUIDL(0)); - } - index++; - } - } else { - this.tabKeys.clear(); - this.captions.clear(); - clearTabs(); - - int index = 0; - for (Iterator it = tabs.getChildIterator(); it.hasNext();) { - UIDL tab = (UIDL) it.next(); - String key = tab.getStringAttribute("key"); - String caption = tab.getStringAttribute("caption"); - if (caption == null) { - caption = " "; - } - - this.captions.add(caption); - this.tabKeys.add(key); - - // Add new tab (additional SPAN-element for loading indication) - this.tb.insertTab("" + caption + "", true, this.tb - .getTabCount()); - - // Add placeholder content - this.tp.add(new ILabel("")); - - if (tab.getBooleanAttribute("selected")) { - this.activeTabIndex = index; - renderContent(tab.getChildUIDL(0)); - } - index++; - } - } - - // Open selected tab - this.tb.selectTab(this.activeTabIndex); - - } - - private void renderContent(final UIDL contentUIDL) { - DeferredCommand.addCommand(new Command() { - public void execute() { - Widget content = ITabsheet.this.client.getWidget(contentUIDL); - ITabsheet.this.tp.remove(ITabsheet.this.activeTabIndex); - ITabsheet.this.tp - .insert(content, ITabsheet.this.activeTabIndex); - ITabsheet.this.tp.showWidget(ITabsheet.this.activeTabIndex); - ((Paintable) content).updateFromUIDL(contentUIDL, - ITabsheet.this.client); - removeStyleDependentName("loading"); - ITabsheet.this.iLayout(); - } - }); - - } - - private void clearTabs() { - int i = this.tb.getTabCount(); - while (i > 0) { - this.tb.removeTab(--i); - } - this.tp.clear(); - - // Get rid of unnecessary 100% cell heights in TabBar (really ugly hack) - Element tr = DOM.getChild(DOM.getChild(this.tb.getElement(), 0), 0); - Element rest = DOM.getChild( - DOM.getChild(tr, DOM.getChildCount(tr) - 1), 0); - DOM.removeElementAttribute(rest, "style"); - } - - public void setHeight(String height) { - this.height = height; - iLayout(); - } - - public void iLayout() { - if (this.height != null) { - // Make content zero height - this.tp.setHeight("0"); - DOM.setStyleAttribute(this.tp.getElement(), "overflow", "hidden"); - // First, calculate needed pixel height - super.setHeight(this.height); - int neededHeight = getOffsetHeight(); - super.setHeight(""); - // Then calculate the size the content area needs to be - int pixelHeight = getOffsetHeight(); - this.tp.setHeight(neededHeight - pixelHeight + "px"); - DOM.setStyleAttribute(this.tp.getElement(), "overflow", ""); - } - Util.runDescendentsLayout(this); - } + String id; + + ApplicationConnection client; + + ArrayList tabKeys = new ArrayList(); + + ArrayList captions = new ArrayList(); + + int activeTabIndex = 0; + + private final TabBar tb; + + private final ITabsheetPanel tp; + + private final Element deco; + + private final TabListener tl = new TabListener() { + + public void onTabSelected(SourcesTabEvents sender, final int tabIndex) { + if (client != null && activeTabIndex != tabIndex) { + addStyleDependentName("loading"); + // run updating variables in deferred command to + // bypass some FF + // optimization issues + DeferredCommand.addCommand(new Command() { + public void execute() { + client.updateVariable(id, "selected", "" + + tabKeys.get(tabIndex), true); + } + }); + } + } + + public boolean onBeforeTabSelected(SourcesTabEvents sender, int tabIndex) { + return true; + } + + }; + + private String height; + + public ITabsheet() { + setStyleName(CLASSNAME); + + tb = new TabBar(); + tp = new ITabsheetPanel(); + deco = DOM.createDiv(); + + tp.setStyleName(CLASSNAME + "-content"); + addStyleDependentName("loading"); // Indicate initial progress + tb.setStyleName(CLASSNAME + "-tabs"); + DOM.setElementProperty(deco, "className", CLASSNAME + "-deco"); + + add(tb); + add(tp); + DOM.appendChild(getElement(), deco); + + tb.addTabListener(tl); + + clearTabs(); + } + + public void updateFromUIDL(UIDL uidl, ApplicationConnection client) { + this.client = client; + id = uidl.getId(); + + if (client.updateComponent(this, uidl, false)) { + return; + } + + // Add proper stylenames for all elements + if (uidl.hasAttribute("style")) { + String[] styles = uidl.getStringAttribute("style").split(" "); + String decoBaseClass = CLASSNAME + "-deco"; + String decoClass = decoBaseClass; + for (int i = 0; i < styles.length; i++) { + tb.addStyleDependentName(styles[i]); + tp.addStyleDependentName(styles[i]); + decoClass += " " + decoBaseClass + "-" + styles[i]; + } + DOM.setElementProperty(deco, "className", decoClass); + } + + // Adjust width and height + String h = uidl.hasAttribute("height") ? uidl + .getStringAttribute("height") : null; + String w = uidl.hasAttribute("width") ? uidl + .getStringAttribute("width") : null; + setWidth(w != null ? w : "auto"); + + // Height calculations + if (h != null) { + if (!h.equals(height)) { + setHeight(h); + } + } else { + height = null; + tp.setHeight(""); + } + + // Render content + UIDL tabs = uidl.getChildUIDL(0); + boolean keepCurrentTabs = tabKeys.size() == tabs.getNumberOfChildren(); + for (int i = 0; keepCurrentTabs && i < tabKeys.size(); i++) { + keepCurrentTabs = tabKeys.get(i).equals( + tabs.getChildUIDL(i).getStringAttribute("key")) + && captions.get(i).equals( + tabs.getChildUIDL(i).getStringAttribute("caption")); + } + if (keepCurrentTabs) { + int index = 0; + for (Iterator it = tabs.getChildIterator(); it.hasNext();) { + UIDL tab = (UIDL) it.next(); + if (tab.getBooleanAttribute("selected")) { + activeTabIndex = index; + renderContent(tab.getChildUIDL(0)); + } + index++; + } + } else { + tabKeys.clear(); + captions.clear(); + clearTabs(); + + int index = 0; + for (Iterator it = tabs.getChildIterator(); it.hasNext();) { + UIDL tab = (UIDL) it.next(); + String key = tab.getStringAttribute("key"); + String caption = tab.getStringAttribute("caption"); + if (caption == null) { + caption = " "; + } + + captions.add(caption); + tabKeys.add(key); + + // Add new tab (additional SPAN-element for + // loading indication) + tb.insertTab("" + caption + "", true, tb + .getTabCount()); + + // Add placeholder content + tp.add(new ILabel("")); + + if (tab.getBooleanAttribute("selected")) { + activeTabIndex = index; + renderContent(tab.getChildUIDL(0)); + } + index++; + } + } + + // Open selected tab + tb.selectTab(activeTabIndex); + + } + + private void renderContent(final UIDL contentUIDL) { + DeferredCommand.addCommand(new Command() { + public void execute() { + Widget content = client.getWidget(contentUIDL); + tp.remove(activeTabIndex); + tp.insert(content, activeTabIndex); + tp.showWidget(activeTabIndex); + ((Paintable) content).updateFromUIDL(contentUIDL, client); + removeStyleDependentName("loading"); + ITabsheet.this.iLayout(); + } + }); + + } + + private void clearTabs() { + int i = tb.getTabCount(); + while (i > 0) { + tb.removeTab(--i); + } + tp.clear(); + + // Get rid of unnecessary 100% cell heights in TabBar (really + // ugly hack) + Element tr = DOM.getChild(DOM.getChild(tb.getElement(), 0), 0); + Element rest = DOM.getChild( + DOM.getChild(tr, DOM.getChildCount(tr) - 1), 0); + DOM.removeElementAttribute(rest, "style"); + } + + public void setHeight(String height) { + this.height = height; + iLayout(); + } + + public void iLayout() { + if (height != null) { + // Make content zero height + tp.setHeight("0"); + DOM.setStyleAttribute(tp.getElement(), "overflow", "hidden"); + // First, calculate needed pixel height + super.setHeight(height); + int neededHeight = getOffsetHeight(); + super.setHeight(""); + // Then calculate the size the content area needs to be + int pixelHeight = getOffsetHeight(); + tp.setHeight(neededHeight - pixelHeight + "px"); + DOM.setStyleAttribute(tp.getElement(), "overflow", ""); + } + Util.runDescendentsLayout(this); + } } diff --git a/src/com/itmill/toolkit/terminal/gwt/client/ui/ITabsheetPanel.java b/src/com/itmill/toolkit/terminal/gwt/client/ui/ITabsheetPanel.java index 4c37633e82..e1f8ce3b7a 100644 --- a/src/com/itmill/toolkit/terminal/gwt/client/ui/ITabsheetPanel.java +++ b/src/com/itmill/toolkit/terminal/gwt/client/ui/ITabsheetPanel.java @@ -15,92 +15,92 @@ import com.google.gwt.user.client.ui.Widget; */ public class ITabsheetPanel extends ComplexPanel { - private Widget visibleWidget; + private Widget visibleWidget; - /** - * Creates an empty tabsheet panel. - */ - public ITabsheetPanel() { - setElement(DOM.createDiv()); - } + /** + * Creates an empty tabsheet panel. + */ + public ITabsheetPanel() { + setElement(DOM.createDiv()); + } - /** - * Adds the specified widget to the deck. - * - * @param w - * the widget to be added - */ - public void add(Widget w) { - super.add(w, getElement()); - initChildWidget(w); - } + /** + * Adds the specified widget to the deck. + * + * @param w + * the widget to be added + */ + public void add(Widget w) { + super.add(w, getElement()); + initChildWidget(w); + } - /** - * Gets the index of the currently-visible widget. - * - * @return the visible widget's index - */ - public int getVisibleWidget() { - return getWidgetIndex(visibleWidget); - } + /** + * Gets the index of the currently-visible widget. + * + * @return the visible widget's index + */ + public int getVisibleWidget() { + return getWidgetIndex(visibleWidget); + } - /** - * Inserts a widget before the specified index. - * - * @param w - * the widget to be inserted - * @param beforeIndex - * the index before which it will be inserted - * @throws IndexOutOfBoundsException - * if beforeIndex is out of range - */ - public void insert(Widget w, int beforeIndex) { - super.insert(w, getElement(), beforeIndex, true); - initChildWidget(w); - } + /** + * Inserts a widget before the specified index. + * + * @param w + * the widget to be inserted + * @param beforeIndex + * the index before which it will be inserted + * @throws IndexOutOfBoundsException + * if beforeIndex is out of range + */ + public void insert(Widget w, int beforeIndex) { + super.insert(w, getElement(), beforeIndex, true); + initChildWidget(w); + } - public boolean remove(Widget w) { - boolean removed = super.remove(w); - if (removed) { - resetChildWidget(w); + public boolean remove(Widget w) { + boolean removed = super.remove(w); + if (removed) { + resetChildWidget(w); - if (visibleWidget == w) { - visibleWidget = null; - } - } - return removed; - } + if (visibleWidget == w) { + visibleWidget = null; + } + } + return removed; + } - /** - * Shows the widget at the specified index. This causes the currently- - * visible widget to be hidden. - * - * @param index - * the index of the widget to be shown - */ - public void showWidget(int index) { - checkIndexBoundsForAccess(index); + /** + * Shows the widget at the specified index. This causes the currently- + * visible widget to be hidden. + * + * @param index + * the index of the widget to be shown + */ + public void showWidget(int index) { + checkIndexBoundsForAccess(index); - if (visibleWidget != null) { - visibleWidget.setVisible(false); - } - visibleWidget = getWidget(index); - visibleWidget.setVisible(true); - } + if (visibleWidget != null) { + visibleWidget.setVisible(false); + } + visibleWidget = getWidget(index); + visibleWidget.setVisible(true); + } - /** - * Make the widget invisible, and set its width and height to full. - */ - private void initChildWidget(Widget w) { - w.setVisible(false); - } + /** + * Make the widget invisible, and set its width and height to full. + */ + private void initChildWidget(Widget w) { + w.setVisible(false); + } - /** - * Make the widget visible, and clear the widget's width and height - * attributes. This is done so that any changes to the visibility, height, - * or width of the widget that were done by the panel are undone. - */ - private void resetChildWidget(Widget w) { - w.setVisible(true); - } + /** + * Make the widget visible, and clear the widget's width and height + * attributes. This is done so that any changes to the visibility, height, + * or width of the widget that were done by the panel are undone. + */ + private void resetChildWidget(Widget w) { + w.setVisible(true); + } } diff --git a/src/com/itmill/toolkit/terminal/gwt/client/ui/ITextField.java b/src/com/itmill/toolkit/terminal/gwt/client/ui/ITextField.java index cd3c548e0e..7b1ed75f27 100644 --- a/src/com/itmill/toolkit/terminal/gwt/client/ui/ITextField.java +++ b/src/com/itmill/toolkit/terminal/gwt/client/ui/ITextField.java @@ -17,90 +17,93 @@ import com.itmill.toolkit.terminal.gwt.client.UIDL; * */ public class ITextField extends TextBoxBase implements Paintable, - ChangeListener, FocusListener { - - /** - * The input node CSS classname. - */ - public static final String CLASSNAME = "i-textfield"; - - /** - * This CSS classname is added to the input node on hover. - */ - public static final String CLASSNAME_FOCUS = "i-textfield-focus"; - - protected String id; - - protected ApplicationConnection client; - - private boolean immediate = false; - - public ITextField() { - this(DOM.createInputText()); - } - - protected ITextField(Element node) { - super(node); - setStyleName(CLASSNAME); - addChangeListener(this); - addFocusListener(this); - } - - public void updateFromUIDL(UIDL uidl, ApplicationConnection client) { - this.client = client; - id = uidl.getId(); - - if (client.updateComponent(this, uidl, true)) - return; - - immediate = uidl.getBooleanAttribute("immediate"); - - if (uidl.hasAttribute("cols")) - setColumns(new Integer(uidl.getStringAttribute("cols")).intValue()); - - setText(uidl.getStringVariable("text")); - - } - - public void onChange(Widget sender) { - if (client != null && id != null) - client.updateVariable(id, "text", getText(), immediate); - } - - public void onFocus(Widget sender) { - addStyleName(CLASSNAME_FOCUS); - } - - public void onLostFocus(Widget sender) { - removeStyleName(CLASSNAME_FOCUS); - } - - public void setColumns(int columns) { - setColumns(getElement(), columns); - } - - public void setRows(int rows) { - setRows(getElement(), rows); - } - - private native void setColumns(Element e, int c) /*-{ - try { - switch(e.tagName.toLowerCase()) { - case "input": - e.size = c; - break; - case "textarea": - e.cols = c; - break; - default:; - } - } catch (e) {} - }-*/; - - private native void setRows(Element e, int r) /*-{ - try { - if(e.tagName.toLowerCase() == "textarea") - e.rows = r; - } catch (e) {} - }-*/; + ChangeListener, FocusListener { + + /** + * The input node CSS classname. + */ + public static final String CLASSNAME = "i-textfield"; + + /** + * This CSS classname is added to the input node on hover. + */ + public static final String CLASSNAME_FOCUS = "i-textfield-focus"; + + protected String id; + + protected ApplicationConnection client; + + private boolean immediate = false; + + public ITextField() { + this(DOM.createInputText()); + } + + protected ITextField(Element node) { + super(node); + setStyleName(CLASSNAME); + addChangeListener(this); + addFocusListener(this); + } + + public void updateFromUIDL(UIDL uidl, ApplicationConnection client) { + this.client = client; + id = uidl.getId(); + + if (client.updateComponent(this, uidl, true)) { + return; + } + + immediate = uidl.getBooleanAttribute("immediate"); + + if (uidl.hasAttribute("cols")) { + setColumns(new Integer(uidl.getStringAttribute("cols")).intValue()); + } + + setText(uidl.getStringVariable("text")); + + } + + public void onChange(Widget sender) { + if (client != null && id != null) { + client.updateVariable(id, "text", getText(), immediate); + } + } + + public void onFocus(Widget sender) { + addStyleName(CLASSNAME_FOCUS); + } + + public void onLostFocus(Widget sender) { + removeStyleName(CLASSNAME_FOCUS); + } + + public void setColumns(int columns) { + setColumns(getElement(), columns); + } + + public void setRows(int rows) { + setRows(getElement(), rows); + } + + private native void setColumns(Element e, int c) /*-{ + try { + switch(e.tagName.toLowerCase()) { + case "input": + e.size = c; + break; + case "textarea": + e.cols = c; + break; + default:; + } + } catch (e) {} + }-*/; + + private native void setRows(Element e, int r) /*-{ + try { + if(e.tagName.toLowerCase() == "textarea") + e.rows = r; + } catch (e) {} + }-*/; } diff --git a/src/com/itmill/toolkit/terminal/gwt/client/ui/ITextualDate.java b/src/com/itmill/toolkit/terminal/gwt/client/ui/ITextualDate.java index 889f74ba98..e5ed1bccbe 100644 --- a/src/com/itmill/toolkit/terminal/gwt/client/ui/ITextualDate.java +++ b/src/com/itmill/toolkit/terminal/gwt/client/ui/ITextualDate.java @@ -10,204 +10,231 @@ import com.itmill.toolkit.terminal.gwt.client.UIDL; import com.itmill.toolkit.terminal.gwt.client.util.SimpleDateFormat; public class ITextualDate extends IDateField implements Paintable, - ChangeListener { - - private ITextField text; - - private SimpleDateFormat format; - - private DateLocale dl; - - public ITextualDate() { - super(); - text = new ITextField(); - text.addChangeListener(this); - add(text); - } - - public void updateFromUIDL(UIDL uidl, ApplicationConnection client) { - super.updateFromUIDL(uidl, client); - buildDate(); - } - - public void buildDate() { - dl = new DateLocale(); - DateLocale.setLocale(currentLocale); - - DateLocale.SUPPORTED_DF_TOKENS = DateLocale.TOKENS_RESOLUTION_YEAR; - if (currentResolution == IDateField.RESOLUTION_MONTH) - DateLocale.SUPPORTED_DF_TOKENS = DateLocale.TOKENS_RESOLUTION_MONTH; - else if (currentResolution >= IDateField.RESOLUTION_DAY) - DateLocale.SUPPORTED_DF_TOKENS = DateLocale.TOKENS_RESOLUTION_DAY; - - format = new SimpleDateFormat(cleanFormat(dts.getDateFormat())); - format.setLocale(dl); - - // Size the textfield a bit smaller if no clock time is needed - if (currentResolution <= IDateField.RESOLUTION_DAY) - text.setColumns(12); - - // Create the initial text for the textfield - String dateText = ""; - if (date != null) { - dateText = format.format(date); - - if (currentResolution >= IDateField.RESOLUTION_HOUR) { - DateLocale.SUPPORTED_DF_TOKENS = DateLocale.TOKENS_RESOLUTION_ALL; - int h = date.getHours(); - if (h > 11 && dts.isTwelveHourClock()) - h -= 12; - int m = currentResolution > IDateField.RESOLUTION_HOUR ? date - .getMinutes() : 0; - dateText += " " + (h < 10 ? "0" + h : "" + h) - + dts.getClockDelimeter() + (m < 10 ? "0" + m : "" + m); - } - if (currentResolution >= IDateField.RESOLUTION_SEC) { - int s = date.getSeconds(); - dateText += dts.getClockDelimeter() - + (s < 10 ? "0" + s : "" + s); - } - if (currentResolution == IDateField.RESOLUTION_MSEC) { - int ms = getMilliseconds(); - String text = "" + ms; - if (ms < 10) - text = "00" + text; - else if (ms < 100) - text = "0" + text; - dateText += "." + text; - } - if (currentResolution >= IDateField.RESOLUTION_HOUR - && dts.isTwelveHourClock()) - dateText += " " - + (date.getHours() < 12 ? dts.getAmPmStrings()[0] : dts - .getAmPmStrings()[1]); - } - - text.setText(dateText); - text.setEnabled(enabled && !readonly); - - if (readonly) - text.addStyleName("i-readonly"); - else - text.removeStyleName("i-readonly"); - } - - public void onChange(Widget sender) { - if (sender == text) { - if (!text.getText().equals("")) { - DateLocale.SUPPORTED_DF_TOKENS = DateLocale.TOKENS_RESOLUTION_ALL; - if (currentResolution == IDateField.RESOLUTION_YEAR) - DateLocale.SUPPORTED_DF_TOKENS = DateLocale.TOKENS_RESOLUTION_YEAR; - else if (currentResolution == IDateField.RESOLUTION_MONTH) - DateLocale.SUPPORTED_DF_TOKENS = DateLocale.TOKENS_RESOLUTION_MONTH; - else if (currentResolution == IDateField.RESOLUTION_DAY) - DateLocale.SUPPORTED_DF_TOKENS = DateLocale.TOKENS_RESOLUTION_DAY; - - String f = cleanFormat(dts.getDateFormat()); - - if (currentResolution >= IDateField.RESOLUTION_HOUR) - f += " " - + (dts.isTwelveHourClock() ? DateLocale.TOKEN_HOUR_12 - + DateLocale.TOKEN_HOUR_12 - : DateLocale.TOKEN_HOUR_24 - + DateLocale.TOKEN_HOUR_24) - + dts.getClockDelimeter() + DateLocale.TOKEN_MINUTE - + DateLocale.TOKEN_MINUTE; - if (currentResolution >= IDateField.RESOLUTION_SEC) - f += dts.getClockDelimeter() + DateLocale.TOKEN_SECOND - + DateLocale.TOKEN_SECOND; - if (currentResolution == IDateField.RESOLUTION_MSEC) - f += "." + DateLocale.TOKEN_MILLISECOND - + DateLocale.TOKEN_MILLISECOND - + DateLocale.TOKEN_MILLISECOND; - if (currentResolution >= IDateField.RESOLUTION_HOUR - && dts.isTwelveHourClock()) - f += " " + DateLocale.TOKEN_AM_PM; - - format = new SimpleDateFormat(f); - DateLocale.setLocale(currentLocale); - format.setLocale(dl); - - try { - date = format.parse(text.getText()); - } catch (Exception e) { - ApplicationConnection.getConsole().log(e.getMessage()); - text.addStyleName(ITextField.CLASSNAME + "-error"); - Timer t = new Timer() { - public void run() { - text.removeStyleName(ITextField.CLASSNAME - + "-error"); - } - }; - t.schedule(2000); - return; - } - - } else - date = null; - - // Update variables - // (only the smallest defining resolution needs to be immediate) - client.updateVariable(id, "year", - date != null ? date.getYear() + 1900 : -1, - currentResolution == IDateField.RESOLUTION_YEAR - && immediate); - if (currentResolution >= IDateField.RESOLUTION_MONTH) - client.updateVariable(id, "month", date != null ? date - .getMonth() + 1 : -1, - currentResolution == IDateField.RESOLUTION_MONTH - && immediate); - if (currentResolution >= IDateField.RESOLUTION_DAY) - client.updateVariable(id, "day", date != null ? date.getDate() - : -1, currentResolution == IDateField.RESOLUTION_DAY - && immediate); - if (currentResolution >= IDateField.RESOLUTION_HOUR) - client.updateVariable(id, "hour", date != null ? date - .getHours() : -1, - currentResolution == IDateField.RESOLUTION_HOUR - && immediate); - if (currentResolution >= IDateField.RESOLUTION_MIN) - client.updateVariable(id, "min", date != null ? date - .getMinutes() : -1, - currentResolution == IDateField.RESOLUTION_MIN - && immediate); - if (currentResolution >= IDateField.RESOLUTION_SEC) - client.updateVariable(id, "sec", date != null ? date - .getSeconds() : -1, - currentResolution == IDateField.RESOLUTION_SEC - && immediate); - if (currentResolution == IDateField.RESOLUTION_MSEC) - client.updateVariable(id, "msec", - date != null ? getMilliseconds() : -1, immediate); - - buildDate(); - } - } - - private String cleanFormat(String format) { - // Remove unnecessary d & M if resolution is too low - if (currentResolution < IDateField.RESOLUTION_DAY) - format = format.replaceAll("d", ""); - if (currentResolution < IDateField.RESOLUTION_MONTH) - format = format.replaceAll("M", ""); - - // Remove unsupported patterns - // TODO support for 'G', era designator (used at least in Japan) - format = format.replaceAll("[GzZwWkK]", ""); - - // Remove extra delimiters ('/' and '.') - while (format.startsWith("/") || format.startsWith(".") - || format.startsWith("-")) - format = format.substring(1); - while (format.endsWith("/") || format.endsWith(".") - || format.endsWith("-")) - format = format.substring(0, format.length() - 1); - - // Remove duplicate delimiters - format = format.replaceAll("//", "/"); - format = format.replaceAll("\\.\\.", "."); - format = format.replaceAll("--", "-"); - - return format.trim(); - } + ChangeListener { + + private ITextField text; + + private SimpleDateFormat format; + + private DateLocale dl; + + public ITextualDate() { + super(); + text = new ITextField(); + text.addChangeListener(this); + add(text); + } + + public void updateFromUIDL(UIDL uidl, ApplicationConnection client) { + super.updateFromUIDL(uidl, client); + buildDate(); + } + + public void buildDate() { + dl = new DateLocale(); + DateLocale.setLocale(currentLocale); + + com.itmill.toolkit.terminal.gwt.client.util.DateLocale.SUPPORTED_DF_TOKENS = com.itmill.toolkit.terminal.gwt.client.util.DateLocale.TOKENS_RESOLUTION_YEAR; + if (currentResolution == IDateField.RESOLUTION_MONTH) { + com.itmill.toolkit.terminal.gwt.client.util.DateLocale.SUPPORTED_DF_TOKENS = com.itmill.toolkit.terminal.gwt.client.util.DateLocale.TOKENS_RESOLUTION_MONTH; + } else if (currentResolution >= IDateField.RESOLUTION_DAY) { + com.itmill.toolkit.terminal.gwt.client.util.DateLocale.SUPPORTED_DF_TOKENS = com.itmill.toolkit.terminal.gwt.client.util.DateLocale.TOKENS_RESOLUTION_DAY; + } + + format = new SimpleDateFormat(cleanFormat(dts.getDateFormat())); + format.setLocale(dl); + + // Size the textfield a bit smaller if no clock time is needed + if (currentResolution <= IDateField.RESOLUTION_DAY) { + text.setColumns(12); + } + + // Create the initial text for the textfield + String dateText = ""; + if (date != null) { + dateText = format.format(date); + + if (currentResolution >= IDateField.RESOLUTION_HOUR) { + com.itmill.toolkit.terminal.gwt.client.util.DateLocale.SUPPORTED_DF_TOKENS = com.itmill.toolkit.terminal.gwt.client.util.DateLocale.TOKENS_RESOLUTION_ALL; + int h = date.getHours(); + if (h > 11 && dts.isTwelveHourClock()) { + h -= 12; + } + int m = currentResolution > IDateField.RESOLUTION_HOUR ? date + .getMinutes() : 0; + dateText += " " + (h < 10 ? "0" + h : "" + h) + + dts.getClockDelimeter() + (m < 10 ? "0" + m : "" + m); + } + if (currentResolution >= IDateField.RESOLUTION_SEC) { + int s = date.getSeconds(); + dateText += dts.getClockDelimeter() + + (s < 10 ? "0" + s : "" + s); + } + if (currentResolution == IDateField.RESOLUTION_MSEC) { + int ms = getMilliseconds(); + String text = "" + ms; + if (ms < 10) { + text = "00" + text; + } else if (ms < 100) { + text = "0" + text; + } + dateText += "." + text; + } + if (currentResolution >= IDateField.RESOLUTION_HOUR + && dts.isTwelveHourClock()) { + dateText += " " + + (date.getHours() < 12 ? dts.getAmPmStrings()[0] : dts + .getAmPmStrings()[1]); + } + } + + text.setText(dateText); + text.setEnabled(enabled && !readonly); + + if (readonly) { + text.addStyleName("i-readonly"); + } else { + text.removeStyleName("i-readonly"); + } + } + + public void onChange(Widget sender) { + if (sender == text) { + if (!text.getText().equals("")) { + com.itmill.toolkit.terminal.gwt.client.util.DateLocale.SUPPORTED_DF_TOKENS = com.itmill.toolkit.terminal.gwt.client.util.DateLocale.TOKENS_RESOLUTION_ALL; + if (currentResolution == IDateField.RESOLUTION_YEAR) { + com.itmill.toolkit.terminal.gwt.client.util.DateLocale.SUPPORTED_DF_TOKENS = com.itmill.toolkit.terminal.gwt.client.util.DateLocale.TOKENS_RESOLUTION_YEAR; + } else if (currentResolution == IDateField.RESOLUTION_MONTH) { + com.itmill.toolkit.terminal.gwt.client.util.DateLocale.SUPPORTED_DF_TOKENS = com.itmill.toolkit.terminal.gwt.client.util.DateLocale.TOKENS_RESOLUTION_MONTH; + } else if (currentResolution == IDateField.RESOLUTION_DAY) { + com.itmill.toolkit.terminal.gwt.client.util.DateLocale.SUPPORTED_DF_TOKENS = com.itmill.toolkit.terminal.gwt.client.util.DateLocale.TOKENS_RESOLUTION_DAY; + } + + String f = cleanFormat(dts.getDateFormat()); + + if (currentResolution >= IDateField.RESOLUTION_HOUR) { + f += " " + + (dts.isTwelveHourClock() ? com.itmill.toolkit.terminal.gwt.client.util.DateLocale.TOKEN_HOUR_12 + + com.itmill.toolkit.terminal.gwt.client.util.DateLocale.TOKEN_HOUR_12 + : com.itmill.toolkit.terminal.gwt.client.util.DateLocale.TOKEN_HOUR_24 + + com.itmill.toolkit.terminal.gwt.client.util.DateLocale.TOKEN_HOUR_24) + + dts.getClockDelimeter() + + com.itmill.toolkit.terminal.gwt.client.util.DateLocale.TOKEN_MINUTE + + com.itmill.toolkit.terminal.gwt.client.util.DateLocale.TOKEN_MINUTE; + } + if (currentResolution >= IDateField.RESOLUTION_SEC) { + f += dts.getClockDelimeter() + + com.itmill.toolkit.terminal.gwt.client.util.DateLocale.TOKEN_SECOND + + com.itmill.toolkit.terminal.gwt.client.util.DateLocale.TOKEN_SECOND; + } + if (currentResolution == IDateField.RESOLUTION_MSEC) { + f += "." + + com.itmill.toolkit.terminal.gwt.client.util.DateLocale.TOKEN_MILLISECOND + + com.itmill.toolkit.terminal.gwt.client.util.DateLocale.TOKEN_MILLISECOND + + com.itmill.toolkit.terminal.gwt.client.util.DateLocale.TOKEN_MILLISECOND; + } + if (currentResolution >= IDateField.RESOLUTION_HOUR + && dts.isTwelveHourClock()) { + f += " " + + com.itmill.toolkit.terminal.gwt.client.util.DateLocale.TOKEN_AM_PM; + } + + format = new SimpleDateFormat(f); + DateLocale.setLocale(currentLocale); + format.setLocale(dl); + + try { + date = format.parse(text.getText()); + } catch (Exception e) { + ApplicationConnection.getConsole().log(e.getMessage()); + text.addStyleName(ITextField.CLASSNAME + "-error"); + Timer t = new Timer() { + public void run() { + text.removeStyleName(ITextField.CLASSNAME + + "-error"); + } + }; + t.schedule(2000); + return; + } + + } else { + date = null; + } + + // Update variables + // (only the smallest defining resolution needs to be + // immediate) + client.updateVariable(id, "year", + date != null ? date.getYear() + 1900 : -1, + currentResolution == IDateField.RESOLUTION_YEAR + && immediate); + if (currentResolution >= IDateField.RESOLUTION_MONTH) { + client.updateVariable(id, "month", date != null ? date + .getMonth() + 1 : -1, + currentResolution == IDateField.RESOLUTION_MONTH + && immediate); + } + if (currentResolution >= IDateField.RESOLUTION_DAY) { + client.updateVariable(id, "day", date != null ? date.getDate() + : -1, currentResolution == IDateField.RESOLUTION_DAY + && immediate); + } + if (currentResolution >= IDateField.RESOLUTION_HOUR) { + client.updateVariable(id, "hour", date != null ? date + .getHours() : -1, + currentResolution == IDateField.RESOLUTION_HOUR + && immediate); + } + if (currentResolution >= IDateField.RESOLUTION_MIN) { + client.updateVariable(id, "min", date != null ? date + .getMinutes() : -1, + currentResolution == IDateField.RESOLUTION_MIN + && immediate); + } + if (currentResolution >= IDateField.RESOLUTION_SEC) { + client.updateVariable(id, "sec", date != null ? date + .getSeconds() : -1, + currentResolution == IDateField.RESOLUTION_SEC + && immediate); + } + if (currentResolution == IDateField.RESOLUTION_MSEC) { + client.updateVariable(id, "msec", + date != null ? getMilliseconds() : -1, immediate); + } + + buildDate(); + } + } + + private String cleanFormat(String format) { + // Remove unnecessary d & M if resolution is too low + if (currentResolution < IDateField.RESOLUTION_DAY) { + format = format.replaceAll("d", ""); + } + if (currentResolution < IDateField.RESOLUTION_MONTH) { + format = format.replaceAll("M", ""); + } + + // Remove unsupported patterns + // TODO support for 'G', era designator (used at least in Japan) + format = format.replaceAll("[GzZwWkK]", ""); + + // Remove extra delimiters ('/' and '.') + while (format.startsWith("/") || format.startsWith(".") + || format.startsWith("-")) { + format = format.substring(1); + } + while (format.endsWith("/") || format.endsWith(".") + || format.endsWith("-")) { + format = format.substring(0, format.length() - 1); + } + + // Remove duplicate delimiters + format = format.replaceAll("//", "/"); + format = format.replaceAll("\\.\\.", "."); + format = format.replaceAll("--", "-"); + + return format.trim(); + } } diff --git a/src/com/itmill/toolkit/terminal/gwt/client/ui/IUnknownComponent.java b/src/com/itmill/toolkit/terminal/gwt/client/ui/IUnknownComponent.java index 5785489a3a..73d8be8a18 100644 --- a/src/com/itmill/toolkit/terminal/gwt/client/ui/IUnknownComponent.java +++ b/src/com/itmill/toolkit/terminal/gwt/client/ui/IUnknownComponent.java @@ -9,27 +9,28 @@ import com.itmill.toolkit.terminal.gwt.client.UIDL; public class IUnknownComponent extends Composite implements Paintable { - com.google.gwt.user.client.ui.Label caption = new com.google.gwt.user.client.ui.Label();; - Tree uidlTree = new Tree(); + com.google.gwt.user.client.ui.Label caption = new com.google.gwt.user.client.ui.Label();; + Tree uidlTree = new Tree(); - public IUnknownComponent() { - VerticalPanel panel = new VerticalPanel(); - panel.add(caption); - panel.add(uidlTree); - initWidget(panel); - setStyleName("itmill-unknown"); - caption.setStyleName("itmill-unknown-caption"); - } + public IUnknownComponent() { + VerticalPanel panel = new VerticalPanel(); + panel.add(caption); + panel.add(uidlTree); + initWidget(panel); + setStyleName("itmill-unknown"); + caption.setStyleName("itmill-unknown-caption"); + } - public void updateFromUIDL(UIDL uidl, ApplicationConnection client) { - if (client.updateComponent(this, uidl, false)) - return; - setCaption("Client faced an unknown component type. Unrendered UIDL:"); - uidlTree.clear(); - uidlTree.addItem(uidl.dir()); - } + public void updateFromUIDL(UIDL uidl, ApplicationConnection client) { + if (client.updateComponent(this, uidl, false)) { + return; + } + setCaption("Client faced an unknown component type. Unrendered UIDL:"); + uidlTree.clear(); + uidlTree.addItem(uidl.dir()); + } - public void setCaption(String c) { - caption.setText(c); - } + public void setCaption(String c) { + caption.setText(c); + } } diff --git a/src/com/itmill/toolkit/terminal/gwt/client/ui/IUpload.java b/src/com/itmill/toolkit/terminal/gwt/client/ui/IUpload.java index 477b03298f..5eacb2b558 100644 --- a/src/com/itmill/toolkit/terminal/gwt/client/ui/IUpload.java +++ b/src/com/itmill/toolkit/terminal/gwt/client/ui/IUpload.java @@ -16,113 +16,116 @@ import com.itmill.toolkit.terminal.gwt.client.Paintable; import com.itmill.toolkit.terminal.gwt.client.UIDL; public class IUpload extends FormPanel implements Paintable, ClickListener, - FormHandler { - - /** - * FileUpload component that opens native OS dialog to select file. - */ - FileUpload fu = new FileUpload(); - - Panel panel = new FlowPanel(); - - ApplicationConnection client; - - private String paintableId; - - /** - * Button that initiates uploading - */ - private Button b; - - /** - * When expecting big files, programmer may initiate some UI changes when - * uploading the file starts. Bit after submitting file we'll visit the - * server to check possible changes. - */ - private Timer t; - - /** - * some browsers tries to send form twice if submit is called in button - * click handler, some don't submit at all without it, so we need to track - * if form is already being submitted - */ - private boolean submitted = false; - - public IUpload() { - super(); - setEncoding(FormPanel.ENCODING_MULTIPART); - setMethod(FormPanel.METHOD_POST); - - setWidget(panel); - panel.add(fu); - // TODO - b = new Button("Click to Upload"); - b.addClickListener(this); - panel.add(b); - - addFormHandler(this); - } - - public void updateFromUIDL(UIDL uidl, ApplicationConnection client) { - if (client.updateComponent(this, uidl, false)) - return; - this.client = client; - this.paintableId = uidl.getId(); - setAction(client.getAppUri()); - - if (uidl.hasAttribute("caption")) - b.setText(uidl.getStringAttribute("caption")); - fu.setName(paintableId + "_file"); - - } - - public void onClick(Widget sender) { - this.submit(); - } - - public void onSubmit(FormSubmitEvent event) { - if (fu.getFilename().length() == 0 || submitted) { - event.setCancelled(true); - ApplicationConnection.getConsole().log( - "Submit cancelled (no file or already submitted)"); - return; - } - submitted = true; - ApplicationConnection.getConsole().log("Submitted form"); - - disableUpload(); - - /* - * visit server after upload to see possible changes from UploadStarted - * event - */ - t = new Timer() { - public void run() { - client.sendPendingVariableChanges(); - } - }; - t.schedule(800); - } - - protected void disableUpload() { - b.setEnabled(false); - fu.setVisible(false); - } - - protected void enableUploaod() { - b.setEnabled(true); - fu.setVisible(true); - } - - public void onSubmitComplete(FormSubmitCompleteEvent event) { - if (client != null) { - if (t != null) - t.cancel(); - ApplicationConnection.getConsole().log("Submit complete"); - client.sendPendingVariableChanges(); - } - submitted = false; - enableUploaod(); - } + FormHandler { + + /** + * FileUpload component that opens native OS dialog to select file. + */ + FileUpload fu = new FileUpload(); + + Panel panel = new FlowPanel(); + + ApplicationConnection client; + + private String paintableId; + + /** + * Button that initiates uploading + */ + private Button b; + + /** + * When expecting big files, programmer may initiate some UI changes when + * uploading the file starts. Bit after submitting file we'll visit the + * server to check possible changes. + */ + private Timer t; + + /** + * some browsers tries to send form twice if submit is called in button + * click handler, some don't submit at all without it, so we need to track + * if form is already being submitted + */ + private boolean submitted = false; + + public IUpload() { + super(); + setEncoding(FormPanel.ENCODING_MULTIPART); + setMethod(FormPanel.METHOD_POST); + + setWidget(panel); + panel.add(fu); + // TODO + b = new Button("Click to Upload"); + b.addClickListener(this); + panel.add(b); + + addFormHandler(this); + } + + public void updateFromUIDL(UIDL uidl, ApplicationConnection client) { + if (client.updateComponent(this, uidl, false)) { + return; + } + this.client = client; + paintableId = uidl.getId(); + setAction(client.getAppUri()); + + if (uidl.hasAttribute("caption")) { + b.setText(uidl.getStringAttribute("caption")); + } + fu.setName(paintableId + "_file"); + + } + + public void onClick(Widget sender) { + submit(); + } + + public void onSubmit(FormSubmitEvent event) { + if (fu.getFilename().length() == 0 || submitted) { + event.setCancelled(true); + ApplicationConnection.getConsole().log( + "Submit cancelled (no file or already submitted)"); + return; + } + submitted = true; + ApplicationConnection.getConsole().log("Submitted form"); + + disableUpload(); + + /* + * visit server after upload to see possible changes from UploadStarted + * event + */ + t = new Timer() { + public void run() { + client.sendPendingVariableChanges(); + } + }; + t.schedule(800); + } + + protected void disableUpload() { + b.setEnabled(false); + fu.setVisible(false); + } + + protected void enableUploaod() { + b.setEnabled(true); + fu.setVisible(true); + } + + public void onSubmitComplete(FormSubmitCompleteEvent event) { + if (client != null) { + if (t != null) { + t.cancel(); + } + ApplicationConnection.getConsole().log("Submit complete"); + client.sendPendingVariableChanges(); + } + submitted = false; + enableUploaod(); + } } diff --git a/src/com/itmill/toolkit/terminal/gwt/client/ui/IView.java b/src/com/itmill/toolkit/terminal/gwt/client/ui/IView.java index fc2fcf0a2d..afb29709ed 100644 --- a/src/com/itmill/toolkit/terminal/gwt/client/ui/IView.java +++ b/src/com/itmill/toolkit/terminal/gwt/client/ui/IView.java @@ -20,149 +20,149 @@ import com.itmill.toolkit.terminal.gwt.client.Util; * */ public class IView extends SimplePanel implements Paintable, - WindowResizeListener { - - private static final String CLASSNAME = "i-view"; - - private String theme; - - private Paintable layout; - - private final HashSet subWindows = new HashSet(); - - private String id; - - private ShortcutActionHandler actionHandler; - - public IView(String elementId) { - super(); - setStyleName(CLASSNAME); - DOM.sinkEvents(getElement(), Event.ONKEYDOWN); - - RootPanel.get(elementId).add(this); - - Window.addWindowResizeListener(this); - } - - public String getTheme() { - return theme; - } - - public void updateFromUIDL(UIDL uidl, ApplicationConnection client) { - - this.id = uidl.getId(); - - // Some attributes to note - theme = uidl.getStringAttribute("theme"); - com.google.gwt.user.client.Window.setTitle(uidl - .getStringAttribute("caption")); - - // Process children - int childIndex = 0; - - // Open URL:s - while (childIndex < uidl.getChidlCount() - && "open".equals(uidl.getChildUIDL(childIndex).getTag())) { - UIDL open = uidl.getChildUIDL(childIndex); - String url = open.getStringAttribute("src"); - String target = open.getStringAttribute("name"); - if (target == null) { - goTo(url); - } else { - // TODO width & height - Window.open(url, target != null ? target : null, ""); - } - childIndex++; - } - - // Draw this application level window - UIDL childUidl = uidl.getChildUIDL(childIndex); - Paintable lo = (Paintable) client.getWidget(childUidl); - - if (layout != null) { - if (layout != lo) { - // remove old - client.unregisterPaintable(layout); - // add new - setWidget((Widget) lo); - layout = lo; - } - } else { - setWidget((Widget) lo); - layout = lo; - } - layout.updateFromUIDL(childUidl, client); - - // Update subwindows - HashSet removedSubWindows = new HashSet(subWindows); - - // Open new windows - while ((childUidl = uidl.getChildUIDL(childIndex++)) != null) { - if ("window".equals(childUidl.getTag())) { - Widget w = client.getWidget(childUidl); - if (subWindows.contains(w)) { - removedSubWindows.remove(w); - } else { - subWindows.add(w); - } - ((Paintable) w).updateFromUIDL(childUidl, client); - } else if ("actions".equals(childUidl.getTag())) { - if (actionHandler == null) { - actionHandler = new ShortcutActionHandler(id, client); - } - actionHandler.updateActionMap(childUidl); - } else if (childUidl.getTag().equals("notifications")) { - for (Iterator it = childUidl.getChildIterator(); it.hasNext();) { - UIDL notification = (UIDL) it.next(); - String html = ""; - if (notification.hasAttribute("caption")) { - html += "

" - + notification.getStringAttribute("caption") - + "

"; - } - if (notification.hasAttribute("message")) { - html += "

" - + notification.getStringAttribute("message") - + "

"; - } - - String style = notification.hasAttribute("style") ? notification - .getStringAttribute("style") - : null; - int position = notification.getIntAttribute("position"); - int delay = notification.getIntAttribute("delay"); - new Notification(delay).show(html, position, style); - } - } - } - - // Close old windows - for (Iterator rem = removedSubWindows.iterator(); rem.hasNext();) { - IWindow w = (IWindow) rem.next(); - client.unregisterPaintable(w); - subWindows.remove(w); - RootPanel.get().remove(w); - } - } - - public void onBrowserEvent(Event event) { - super.onBrowserEvent(event); - if (DOM.eventGetType(event) == Event.ONKEYDOWN && actionHandler != null) { - int modifiers = KeyboardListenerCollection - .getKeyboardModifiers(event); - actionHandler.handleKeyboardEvent( - (char) DOM.eventGetKeyCode(event), modifiers); - return; - } - } - - public void onWindowResized(int width, int height) { - Util.runDescendentsLayout(this); - } - - public native static void goTo(String url) - /*-{ - $wnd.location = url; - }-*/; + WindowResizeListener { + + private static final String CLASSNAME = "i-view"; + + private String theme; + + private Paintable layout; + + private final HashSet subWindows = new HashSet(); + + private String id; + + private ShortcutActionHandler actionHandler; + + public IView(String elementId) { + super(); + setStyleName(CLASSNAME); + DOM.sinkEvents(getElement(), Event.ONKEYDOWN); + + RootPanel.get(elementId).add(this); + + Window.addWindowResizeListener(this); + } + + public String getTheme() { + return theme; + } + + public void updateFromUIDL(UIDL uidl, ApplicationConnection client) { + + id = uidl.getId(); + + // Some attributes to note + theme = uidl.getStringAttribute("theme"); + com.google.gwt.user.client.Window.setTitle(uidl + .getStringAttribute("caption")); + + // Process children + int childIndex = 0; + + // Open URL:s + while (childIndex < uidl.getChidlCount() + && "open".equals(uidl.getChildUIDL(childIndex).getTag())) { + UIDL open = uidl.getChildUIDL(childIndex); + String url = open.getStringAttribute("src"); + String target = open.getStringAttribute("name"); + if (target == null) { + goTo(url); + } else { + // TODO width & height + Window.open(url, target != null ? target : null, ""); + } + childIndex++; + } + + // Draw this application level window + UIDL childUidl = uidl.getChildUIDL(childIndex); + Paintable lo = (Paintable) client.getWidget(childUidl); + + if (layout != null) { + if (layout != lo) { + // remove old + client.unregisterPaintable(layout); + // add new + setWidget((Widget) lo); + layout = lo; + } + } else { + setWidget((Widget) lo); + layout = lo; + } + layout.updateFromUIDL(childUidl, client); + + // Update subwindows + HashSet removedSubWindows = new HashSet(subWindows); + + // Open new windows + while ((childUidl = uidl.getChildUIDL(childIndex++)) != null) { + if ("window".equals(childUidl.getTag())) { + Widget w = client.getWidget(childUidl); + if (subWindows.contains(w)) { + removedSubWindows.remove(w); + } else { + subWindows.add(w); + } + ((Paintable) w).updateFromUIDL(childUidl, client); + } else if ("actions".equals(childUidl.getTag())) { + if (actionHandler == null) { + actionHandler = new ShortcutActionHandler(id, client); + } + actionHandler.updateActionMap(childUidl); + } else if (childUidl.getTag().equals("notifications")) { + for (Iterator it = childUidl.getChildIterator(); it.hasNext();) { + UIDL notification = (UIDL) it.next(); + String html = ""; + if (notification.hasAttribute("caption")) { + html += "

" + + notification.getStringAttribute("caption") + + "

"; + } + if (notification.hasAttribute("message")) { + html += "

" + + notification.getStringAttribute("message") + + "

"; + } + + String style = notification.hasAttribute("style") ? notification + .getStringAttribute("style") + : null; + int position = notification.getIntAttribute("position"); + int delay = notification.getIntAttribute("delay"); + new Notification(delay).show(html, position, style); + } + } + } + + // Close old windows + for (Iterator rem = removedSubWindows.iterator(); rem.hasNext();) { + IWindow w = (IWindow) rem.next(); + client.unregisterPaintable(w); + subWindows.remove(w); + RootPanel.get().remove(w); + } + } + + public void onBrowserEvent(Event event) { + super.onBrowserEvent(event); + if (DOM.eventGetType(event) == Event.ONKEYDOWN && actionHandler != null) { + int modifiers = KeyboardListenerCollection + .getKeyboardModifiers(event); + actionHandler.handleKeyboardEvent( + (char) DOM.eventGetKeyCode(event), modifiers); + return; + } + } + + public void onWindowResized(int width, int height) { + Util.runDescendentsLayout(this); + } + + public native static void goTo(String url) + /*-{ + $wnd.location = url; + }-*/; } diff --git a/src/com/itmill/toolkit/terminal/gwt/client/ui/IWindow.java b/src/com/itmill/toolkit/terminal/gwt/client/ui/IWindow.java index d0bb7e40b7..dbefb37e70 100644 --- a/src/com/itmill/toolkit/terminal/gwt/client/ui/IWindow.java +++ b/src/com/itmill/toolkit/terminal/gwt/client/ui/IWindow.java @@ -26,398 +26,398 @@ import com.itmill.toolkit.terminal.gwt.client.Util; */ public class IWindow extends PopupPanel implements Paintable, ScrollListener { - private static final int DEFAULT_HEIGHT = 300; + private static final int DEFAULT_HEIGHT = 300; - private static final int DEFAULT_WIDTH = 400; + private static final int DEFAULT_WIDTH = 400; - private static final int MIN_HEIGHT = 60; + private static final int MIN_HEIGHT = 60; - private static final int MIN_WIDTH = 80; + private static final int MIN_WIDTH = 80; - private static Vector windowOrder = new Vector(); + private static Vector windowOrder = new Vector(); - public static final String CLASSNAME = "i-window"; + public static final String CLASSNAME = "i-window"; - /** pixels used by inner borders and paddings horizontally */ - protected static final int BORDER_WIDTH_HORIZONTAL = 41; + /** pixels used by inner borders and paddings horizontally */ + protected static final int BORDER_WIDTH_HORIZONTAL = 41; - /** pixels used by headers, footers, inner borders and paddings vertically */ - protected static final int BORDER_WIDTH_VERTICAL = 58; + /** pixels used by headers, footers, inner borders and paddings vertically */ + protected static final int BORDER_WIDTH_VERTICAL = 58; - private static final int STACKING_OFFSET_PIXELS = 15; + private static final int STACKING_OFFSET_PIXELS = 15; - private static final int Z_INDEX_BASE = 10000; + private static final int Z_INDEX_BASE = 10000; - private Paintable layout; + private Paintable layout; - private Element contents; + private Element contents; - private Element header; + private Element header; - private Element footer; + private Element footer; - private Element resizeBox; + private Element resizeBox; - private final ScrollPanel contentPanel = new ScrollPanel(); + private final ScrollPanel contentPanel = new ScrollPanel(); - private boolean dragging; + private boolean dragging; - private int startX; + private int startX; - private int startY; + private int startY; - private int origX; + private int origX; - private int origY; + private int origY; - private boolean resizing; + private boolean resizing; - private int origW; + private int origW; - private int origH; + private int origH; - private Element closeBox; + private Element closeBox; - protected ApplicationConnection client; + protected ApplicationConnection client; - private String id; + private String id; - ShortcutActionHandler shortcutHandler; + ShortcutActionHandler shortcutHandler; - /** Last known width read from UIDL or updated to application connection */ - private int uidlWidth = -1; + /** Last known width read from UIDL or updated to application connection */ + private int uidlWidth = -1; - /** Last known height read from UIDL or updated to application connection */ - private int uidlHeight = -1; + /** Last known height read from UIDL or updated to application connection */ + private int uidlHeight = -1; - /** Last known positionx read from UIDL or updated to application connection */ - private int uidlPositionX = -1; + /** Last known positionx read from UIDL or updated to application connection */ + private int uidlPositionX = -1; - /** Last known positiony read from UIDL or updated to application connection */ - private int uidlPositionY = -1; + /** Last known positiony read from UIDL or updated to application connection */ + private int uidlPositionY = -1; - public IWindow() { - super(); - int order = windowOrder.size(); - setWindowOrder(order); - windowOrder.add(this); - setStyleName(CLASSNAME); - constructDOM(); - setPopupPosition(order * STACKING_OFFSET_PIXELS, order - * STACKING_OFFSET_PIXELS); - contentPanel.addScrollListener(this); - } + public IWindow() { + super(); + int order = windowOrder.size(); + setWindowOrder(order); + windowOrder.add(this); + setStyleName(CLASSNAME); + constructDOM(); + setPopupPosition(order * STACKING_OFFSET_PIXELS, order + * STACKING_OFFSET_PIXELS); + contentPanel.addScrollListener(this); + } - private void bringToFront() { - int curIndex = windowOrder.indexOf(this); - if (curIndex + 1 < windowOrder.size()) { - windowOrder.remove(this); - windowOrder.add(this); - for (; curIndex < windowOrder.size(); curIndex++) { - ((IWindow) windowOrder.get(curIndex)).setWindowOrder(curIndex); - } - } - } + private void bringToFront() { + int curIndex = windowOrder.indexOf(this); + if (curIndex + 1 < windowOrder.size()) { + windowOrder.remove(this); + windowOrder.add(this); + for (; curIndex < windowOrder.size(); curIndex++) { + ((IWindow) windowOrder.get(curIndex)).setWindowOrder(curIndex); + } + } + } - /** - * Returns true if window is the topmost window - * - * @return - */ - private boolean isActive() { - return windowOrder.lastElement().equals(this); - } + /** + * Returns true if window is the topmost window + * + * @return + */ + private boolean isActive() { + return windowOrder.lastElement().equals(this); + } - public void setWindowOrder(int order) { - DOM.setStyleAttribute(getElement(), "zIndex", "" - + (order + Z_INDEX_BASE)); - } - - protected void constructDOM() { - Element outerHeader = DOM.createDiv(); - DOM.setElementProperty(outerHeader, "className", CLASSNAME - + "-outerheader"); - header = DOM.createDiv(); - DOM.setElementProperty(header, "className", CLASSNAME + "-header"); - contents = DOM.createDiv(); - DOM.setElementProperty(contents, "className", CLASSNAME + "-contents"); - footer = DOM.createDiv(); - DOM.setElementProperty(footer, "className", CLASSNAME + "-footer"); - resizeBox = DOM.createDiv(); - DOM - .setElementProperty(resizeBox, "className", CLASSNAME - + "-resizebox"); - closeBox = DOM.createDiv(); - DOM.setElementProperty(closeBox, "className", CLASSNAME + "-closebox"); - DOM.appendChild(footer, resizeBox); - - DOM.sinkEvents(header, Event.MOUSEEVENTS); - DOM.sinkEvents(resizeBox, Event.MOUSEEVENTS); - DOM.sinkEvents(closeBox, Event.ONCLICK); - DOM.sinkEvents(contents, Event.ONCLICK); - - Element wrapper = DOM.createDiv(); - DOM.setElementProperty(wrapper, "className", CLASSNAME + "-wrap"); - Element wrapper2 = DOM.createDiv(); - DOM.setElementProperty(wrapper2, "className", CLASSNAME + "-wrap2"); - - DOM.sinkEvents(wrapper, Event.ONKEYDOWN); - - DOM.appendChild(wrapper2, closeBox); - DOM.appendChild(wrapper2, outerHeader); - DOM.appendChild(outerHeader, header); - DOM.appendChild(wrapper2, contents); - DOM.appendChild(wrapper2, footer); - DOM.appendChild(wrapper, wrapper2); - DOM.appendChild(getElement(), wrapper); - setWidget(contentPanel); - - // set default size - setWidth(DEFAULT_WIDTH + "px"); - setHeight(DEFAULT_HEIGHT + "px"); - } - - public void updateFromUIDL(UIDL uidl, ApplicationConnection client) { - this.id = uidl.getId(); - this.client = client; - - if (uidl.hasAttribute("invisible")) { - this.hide(); - return; - } - - if (client.updateComponent(this, uidl, false)) { - return; - } - - // Initialize the width from UIDL - if (uidl.hasVariable("width")) { - String width = uidl.getStringVariable("width"); - setWidth(width); - } - if (uidl.hasVariable("height")) { - String height = uidl.getStringVariable("height"); - setHeight(height); - } - - contentPanel.setScrollPosition(uidl.getIntVariable("scrolltop")); - contentPanel.setHorizontalScrollPosition(uidl - .getIntVariable("scrollleft")); - - // Initialize the position form UIDL - try { - int positionx = uidl.getIntVariable("positionx"); - int positiony = uidl.getIntVariable("positiony"); - if (positionx >= 0 && positiony >= 0) { - setPopupPosition(positionx, positiony); - } - } catch (IllegalArgumentException e) { - // Silently ignored as positionx and positiony are not required - // parameters - } - - if (!isAttached()) { - show(); - } - - if (uidl.hasAttribute("caption")) { - setCaption(uidl.getStringAttribute("caption")); - } - - UIDL childUidl = uidl.getChildUIDL(0); - if ("open".equals(childUidl.getTag())) { - // TODO render different resources (theme:// etc?) - // TODO this should be a while-loop for multiple opens - if (!childUidl.hasAttribute("name")) { - Frame frame = new Frame(); - DOM.setStyleAttribute(frame.getElement(), "width", "100%"); - DOM.setStyleAttribute(frame.getElement(), "height", "100%"); - DOM.setStyleAttribute(frame.getElement(), "border", "0px"); - frame.setUrl(childUidl.getStringAttribute("src")); - contentPanel.setWidget(frame); - } else { - String target = childUidl.getStringAttribute("name"); - Window.open(childUidl.getStringAttribute("src"), target, ""); - } - } else { - Paintable lo = (Paintable) client.getWidget(childUidl); - if (layout != null) { - if (layout != lo) { - // remove old - client.unregisterPaintable(layout); - contentPanel.remove((Widget) layout); - // add new - contentPanel.setWidget((Widget) lo); - layout = lo; - } - } else { - contentPanel.setWidget((Widget) lo); - } - lo.updateFromUIDL(childUidl, client); - } - - // we may have actions - if (uidl.getChidlCount() > 1) { - childUidl = uidl.getChildUIDL(1); - if (childUidl.getTag().equals("actions")) { - if (shortcutHandler == null) { - shortcutHandler = new ShortcutActionHandler(id, client); - } - shortcutHandler.updateActionMap(childUidl); - } - - } - - } - - public void setPopupPosition(int left, int top) { - super.setPopupPosition(left, top); - if (left != uidlPositionX && client != null) { - client.updateVariable(id, "positionx", left, false); - uidlPositionX = left; - } - if (top != uidlPositionY && client != null) { - client.updateVariable(id, "positiony", top, false); - uidlPositionY = top; - } - } - - public void setCaption(String c) { - DOM.setInnerText(header, c); - } - - protected Element getContainerElement() { - return contents; - } - - public void onBrowserEvent(Event event) { - int type = DOM.eventGetType(event); - if (type == Event.ONKEYDOWN && shortcutHandler != null) { - int modifiers = KeyboardListenerCollection - .getKeyboardModifiers(event); - shortcutHandler.handleKeyboardEvent((char) DOM - .eventGetKeyCode(event), modifiers); - return; - } - - if (!isActive()) { - bringToFront(); - } - Element target = DOM.eventGetTarget(event); - if (dragging || DOM.compare(header, target)) { - onHeaderEvent(event); - DOM.eventCancelBubble(event, true); - } else if (resizing || DOM.compare(resizeBox, target)) { - onResizeEvent(event); - DOM.eventCancelBubble(event, true); - } else if (DOM.compare(target, closeBox) && type == Event.ONCLICK) { - onCloseClick(); - DOM.eventCancelBubble(event, true); - } - } - - private void onCloseClick() { - client.updateVariable(id, "close", true, true); - } - - private void onResizeEvent(Event event) { - switch (DOM.eventGetType(event)) { - case Event.ONMOUSEDOWN: - resizing = true; - startX = DOM.eventGetScreenX(event); - startY = DOM.eventGetScreenY(event); - origW = DOM.getIntStyleAttribute(getElement(), "width") - - BORDER_WIDTH_HORIZONTAL; - origH = getWidget().getOffsetHeight(); - DOM.eventPreventDefault(event); - DOM.addEventPreview(this); - break; - case Event.ONMOUSEUP: - resizing = false; - DOM.removeEventPreview(this); - setSize(event, true); - break; - case Event.ONMOUSEMOVE: - if (resizing) { - setSize(event, false); - DOM.eventPreventDefault(event); - } - break; - default: - DOM.eventPreventDefault(event); - break; - } - } - - public void setSize(Event event, boolean updateVariables) { - int w = DOM.eventGetScreenX(event) - startX + origW; - if (w < MIN_WIDTH) { - w = MIN_WIDTH; - } - int h = DOM.eventGetScreenY(event) - startY + origH; - if (h < MIN_HEIGHT) { - h = MIN_HEIGHT; - } - setWidth(w + "px"); - setHeight(h + "px"); - if (updateVariables) { - // sending width back always as pixels, no need for unit - client.updateVariable(id, "width", w, false); - client.updateVariable(id, "height", h, false); - } - // Update child widget dimensions - Util.runDescendentsLayout(this); - } - - public void setWidth(String width) { - DOM.setStyleAttribute(getElement(), "width", (Integer.parseInt(width - .substring(0, width.length() - 2)) + BORDER_WIDTH_HORIZONTAL) - + "px"); - } - - private void onHeaderEvent(Event event) { - switch (DOM.eventGetType(event)) { - case Event.ONMOUSEDOWN: - dragging = true; - startX = DOM.eventGetScreenX(event); - startY = DOM.eventGetScreenY(event); - origX = DOM.getAbsoluteLeft(getElement()); - origY = DOM.getAbsoluteTop(getElement()); - DOM.eventPreventDefault(event); - DOM.addEventPreview(this); - break; - case Event.ONMOUSEUP: - dragging = false; - DOM.removeEventPreview(this); - break; - case Event.ONMOUSEMOVE: - if (dragging) { - int x = DOM.eventGetScreenX(event) - startX + origX; - int y = DOM.eventGetScreenY(event) - startY + origY; - this.setPopupPosition(x, y); - DOM.eventPreventDefault(event); - } - break; - default: - break; - } - } - - public boolean onEventPreview(Event event) { - if (dragging) { - onHeaderEvent(event); - return false; - } else if (resizing) { - onResizeEvent(event); - return false; - } - // TODO return false when modal - return true; - } - - public void onScroll(Widget widget, int scrollLeft, int scrollTop) { - client.updateVariable(id, "scrolltop", scrollTop, false); - client.updateVariable(id, "scrollleft", scrollLeft, false); - } + public void setWindowOrder(int order) { + DOM.setStyleAttribute(getElement(), "zIndex", "" + + (order + Z_INDEX_BASE)); + } + + protected void constructDOM() { + Element outerHeader = DOM.createDiv(); + DOM.setElementProperty(outerHeader, "className", CLASSNAME + + "-outerheader"); + header = DOM.createDiv(); + DOM.setElementProperty(header, "className", CLASSNAME + "-header"); + contents = DOM.createDiv(); + DOM.setElementProperty(contents, "className", CLASSNAME + "-contents"); + footer = DOM.createDiv(); + DOM.setElementProperty(footer, "className", CLASSNAME + "-footer"); + resizeBox = DOM.createDiv(); + DOM + .setElementProperty(resizeBox, "className", CLASSNAME + + "-resizebox"); + closeBox = DOM.createDiv(); + DOM.setElementProperty(closeBox, "className", CLASSNAME + "-closebox"); + DOM.appendChild(footer, resizeBox); + + DOM.sinkEvents(header, Event.MOUSEEVENTS); + DOM.sinkEvents(resizeBox, Event.MOUSEEVENTS); + DOM.sinkEvents(closeBox, Event.ONCLICK); + DOM.sinkEvents(contents, Event.ONCLICK); + + Element wrapper = DOM.createDiv(); + DOM.setElementProperty(wrapper, "className", CLASSNAME + "-wrap"); + Element wrapper2 = DOM.createDiv(); + DOM.setElementProperty(wrapper2, "className", CLASSNAME + "-wrap2"); + + DOM.sinkEvents(wrapper, Event.ONKEYDOWN); + + DOM.appendChild(wrapper2, closeBox); + DOM.appendChild(wrapper2, outerHeader); + DOM.appendChild(outerHeader, header); + DOM.appendChild(wrapper2, contents); + DOM.appendChild(wrapper2, footer); + DOM.appendChild(wrapper, wrapper2); + DOM.appendChild(getElement(), wrapper); + setWidget(contentPanel); + + // set default size + setWidth(DEFAULT_WIDTH + "px"); + setHeight(DEFAULT_HEIGHT + "px"); + } + + public void updateFromUIDL(UIDL uidl, ApplicationConnection client) { + id = uidl.getId(); + this.client = client; + + if (uidl.hasAttribute("invisible")) { + this.hide(); + return; + } + + if (client.updateComponent(this, uidl, false)) { + return; + } + + // Initialize the width from UIDL + if (uidl.hasVariable("width")) { + String width = uidl.getStringVariable("width"); + setWidth(width); + } + if (uidl.hasVariable("height")) { + String height = uidl.getStringVariable("height"); + setHeight(height); + } + + contentPanel.setScrollPosition(uidl.getIntVariable("scrolltop")); + contentPanel.setHorizontalScrollPosition(uidl + .getIntVariable("scrollleft")); + + // Initialize the position form UIDL + try { + int positionx = uidl.getIntVariable("positionx"); + int positiony = uidl.getIntVariable("positiony"); + if (positionx >= 0 && positiony >= 0) { + setPopupPosition(positionx, positiony); + } + } catch (IllegalArgumentException e) { + // Silently ignored as positionx and positiony are not required + // parameters + } + + if (!isAttached()) { + show(); + } + + if (uidl.hasAttribute("caption")) { + setCaption(uidl.getStringAttribute("caption")); + } + + UIDL childUidl = uidl.getChildUIDL(0); + if ("open".equals(childUidl.getTag())) { + // TODO render different resources (theme:// etc?) + // TODO this should be a while-loop for multiple opens + if (!childUidl.hasAttribute("name")) { + Frame frame = new Frame(); + DOM.setStyleAttribute(frame.getElement(), "width", "100%"); + DOM.setStyleAttribute(frame.getElement(), "height", "100%"); + DOM.setStyleAttribute(frame.getElement(), "border", "0px"); + frame.setUrl(childUidl.getStringAttribute("src")); + contentPanel.setWidget(frame); + } else { + String target = childUidl.getStringAttribute("name"); + Window.open(childUidl.getStringAttribute("src"), target, ""); + } + } else { + Paintable lo = (Paintable) client.getWidget(childUidl); + if (layout != null) { + if (layout != lo) { + // remove old + client.unregisterPaintable(layout); + contentPanel.remove((Widget) layout); + // add new + contentPanel.setWidget((Widget) lo); + layout = lo; + } + } else { + contentPanel.setWidget((Widget) lo); + } + lo.updateFromUIDL(childUidl, client); + } + + // we may have actions + if (uidl.getChidlCount() > 1) { + childUidl = uidl.getChildUIDL(1); + if (childUidl.getTag().equals("actions")) { + if (shortcutHandler == null) { + shortcutHandler = new ShortcutActionHandler(id, client); + } + shortcutHandler.updateActionMap(childUidl); + } + + } + + } + + public void setPopupPosition(int left, int top) { + super.setPopupPosition(left, top); + if (left != uidlPositionX && client != null) { + client.updateVariable(id, "positionx", left, false); + uidlPositionX = left; + } + if (top != uidlPositionY && client != null) { + client.updateVariable(id, "positiony", top, false); + uidlPositionY = top; + } + } + + public void setCaption(String c) { + DOM.setInnerText(header, c); + } + + protected Element getContainerElement() { + return contents; + } + + public void onBrowserEvent(Event event) { + int type = DOM.eventGetType(event); + if (type == Event.ONKEYDOWN && shortcutHandler != null) { + int modifiers = KeyboardListenerCollection + .getKeyboardModifiers(event); + shortcutHandler.handleKeyboardEvent((char) DOM + .eventGetKeyCode(event), modifiers); + return; + } + + if (!isActive()) { + bringToFront(); + } + Element target = DOM.eventGetTarget(event); + if (dragging || DOM.compare(header, target)) { + onHeaderEvent(event); + DOM.eventCancelBubble(event, true); + } else if (resizing || DOM.compare(resizeBox, target)) { + onResizeEvent(event); + DOM.eventCancelBubble(event, true); + } else if (DOM.compare(target, closeBox) && type == Event.ONCLICK) { + onCloseClick(); + DOM.eventCancelBubble(event, true); + } + } + + private void onCloseClick() { + client.updateVariable(id, "close", true, true); + } + + private void onResizeEvent(Event event) { + switch (DOM.eventGetType(event)) { + case Event.ONMOUSEDOWN: + resizing = true; + startX = DOM.eventGetScreenX(event); + startY = DOM.eventGetScreenY(event); + origW = DOM.getIntStyleAttribute(getElement(), "width") + - BORDER_WIDTH_HORIZONTAL; + origH = getWidget().getOffsetHeight(); + DOM.eventPreventDefault(event); + DOM.addEventPreview(this); + break; + case Event.ONMOUSEUP: + resizing = false; + DOM.removeEventPreview(this); + setSize(event, true); + break; + case Event.ONMOUSEMOVE: + if (resizing) { + setSize(event, false); + DOM.eventPreventDefault(event); + } + break; + default: + DOM.eventPreventDefault(event); + break; + } + } + + public void setSize(Event event, boolean updateVariables) { + int w = DOM.eventGetScreenX(event) - startX + origW; + if (w < MIN_WIDTH) { + w = MIN_WIDTH; + } + int h = DOM.eventGetScreenY(event) - startY + origH; + if (h < MIN_HEIGHT) { + h = MIN_HEIGHT; + } + setWidth(w + "px"); + setHeight(h + "px"); + if (updateVariables) { + // sending width back always as pixels, no need for unit + client.updateVariable(id, "width", w, false); + client.updateVariable(id, "height", h, false); + } + // Update child widget dimensions + Util.runDescendentsLayout(this); + } + + public void setWidth(String width) { + DOM.setStyleAttribute(getElement(), "width", (Integer.parseInt(width + .substring(0, width.length() - 2)) + BORDER_WIDTH_HORIZONTAL) + + "px"); + } + + private void onHeaderEvent(Event event) { + switch (DOM.eventGetType(event)) { + case Event.ONMOUSEDOWN: + dragging = true; + startX = DOM.eventGetScreenX(event); + startY = DOM.eventGetScreenY(event); + origX = DOM.getAbsoluteLeft(getElement()); + origY = DOM.getAbsoluteTop(getElement()); + DOM.eventPreventDefault(event); + DOM.addEventPreview(this); + break; + case Event.ONMOUSEUP: + dragging = false; + DOM.removeEventPreview(this); + break; + case Event.ONMOUSEMOVE: + if (dragging) { + int x = DOM.eventGetScreenX(event) - startX + origX; + int y = DOM.eventGetScreenY(event) - startY + origY; + setPopupPosition(x, y); + DOM.eventPreventDefault(event); + } + break; + default: + break; + } + } + + public boolean onEventPreview(Event event) { + if (dragging) { + onHeaderEvent(event); + return false; + } else if (resizing) { + onResizeEvent(event); + return false; + } + // TODO return false when modal + return true; + } + + public void onScroll(Widget widget, int scrollLeft, int scrollTop) { + client.updateVariable(id, "scrolltop", scrollTop, false); + client.updateVariable(id, "scrollleft", scrollLeft, false); + } } diff --git a/src/com/itmill/toolkit/terminal/gwt/client/ui/MarginInfo.java b/src/com/itmill/toolkit/terminal/gwt/client/ui/MarginInfo.java index e1aa952743..038954d4f2 100644 --- a/src/com/itmill/toolkit/terminal/gwt/client/ui/MarginInfo.java +++ b/src/com/itmill/toolkit/terminal/gwt/client/ui/MarginInfo.java @@ -2,53 +2,54 @@ package com.itmill.toolkit.terminal.gwt.client.ui; public class MarginInfo { - private static final int TOP = 1; - private static final int RIGHT = 2; - private static final int BOTTOM = 4; - private static final int LEFT = 8; - - - private int bitMask; - - public MarginInfo(int bitMask) { - this.bitMask = bitMask; - } - - public MarginInfo(boolean top, boolean right, boolean bottom, boolean left) { - setMargins(top,right,bottom,left); - } - - public void setMargins(boolean top, boolean right, boolean bottom, boolean left) { - bitMask = top ? TOP : 0; - bitMask += right ? RIGHT : 0; - bitMask += bottom ? BOTTOM : 0; - bitMask += left ? LEFT : 0; - } - - public boolean hasLeft() { - return (bitMask & LEFT) == LEFT; - } - - public boolean hasRight() { - return (bitMask & RIGHT) == RIGHT; - } - - public boolean hasTop() { - return (bitMask & TOP) == TOP; - } - public boolean hasBottom() { - return (bitMask & BOTTOM) == BOTTOM; - } - - public int getBitMask() { - return bitMask; - } - - public void setMargins(boolean enabled) { - if(enabled) { - bitMask = TOP + RIGHT + BOTTOM + LEFT; - } else { - bitMask = 0; - } - } + private static final int TOP = 1; + private static final int RIGHT = 2; + private static final int BOTTOM = 4; + private static final int LEFT = 8; + + private int bitMask; + + public MarginInfo(int bitMask) { + this.bitMask = bitMask; + } + + public MarginInfo(boolean top, boolean right, boolean bottom, boolean left) { + setMargins(top, right, bottom, left); + } + + public void setMargins(boolean top, boolean right, boolean bottom, + boolean left) { + bitMask = top ? TOP : 0; + bitMask += right ? RIGHT : 0; + bitMask += bottom ? BOTTOM : 0; + bitMask += left ? LEFT : 0; + } + + public boolean hasLeft() { + return (bitMask & LEFT) == LEFT; + } + + public boolean hasRight() { + return (bitMask & RIGHT) == RIGHT; + } + + public boolean hasTop() { + return (bitMask & TOP) == TOP; + } + + public boolean hasBottom() { + return (bitMask & BOTTOM) == BOTTOM; + } + + public int getBitMask() { + return bitMask; + } + + public void setMargins(boolean enabled) { + if (enabled) { + bitMask = TOP + RIGHT + BOTTOM + LEFT; + } else { + bitMask = 0; + } + } } diff --git a/src/com/itmill/toolkit/terminal/gwt/client/ui/MenuItem.java b/src/com/itmill/toolkit/terminal/gwt/client/ui/MenuItem.java index 295c17e41e..6767864a6e 100644 --- a/src/com/itmill/toolkit/terminal/gwt/client/ui/MenuItem.java +++ b/src/com/itmill/toolkit/terminal/gwt/client/ui/MenuItem.java @@ -17,7 +17,6 @@ package com.itmill.toolkit.terminal.gwt.client.ui; */ //COPIED HERE DUE package privates in GWT - import com.google.gwt.user.client.Command; import com.google.gwt.user.client.DOM; import com.google.gwt.user.client.ui.HasHTML; @@ -31,153 +30,153 @@ import com.google.gwt.user.client.ui.UIObject; */ public class MenuItem extends UIObject implements HasHTML { - private static final String DEPENDENT_STYLENAME_SELECTED_ITEM = "selected"; - - private Command command; - private MenuBar parentMenu, subMenu; - - /** - * Constructs a new menu item that fires a command when it is selected. - * - * @param text - * the item's text - * @param cmd - * the command to be fired when it is selected - */ - public MenuItem(String text, Command cmd) { - this(text, false); - setCommand(cmd); - } - - /** - * Constructs a new menu item that fires a command when it is selected. - * - * @param text - * the item's text - * @param asHTML - * true to treat the specified text as html - * @param cmd - * the command to be fired when it is selected - */ - public MenuItem(String text, boolean asHTML, Command cmd) { - this(text, asHTML); - setCommand(cmd); - } - - /** - * Constructs a new menu item that cascades to a sub-menu when it is - * selected. - * - * @param text - * the item's text - * @param subMenu - * the sub-menu to be displayed when it is selected - */ - public MenuItem(String text, MenuBar subMenu) { - this(text, false); - setSubMenu(subMenu); - } - - /** - * Constructs a new menu item that cascades to a sub-menu when it is - * selected. - * - * @param text - * the item's text - * @param asHTML - * true to treat the specified text as html - * @param subMenu - * the sub-menu to be displayed when it is selected - */ - public MenuItem(String text, boolean asHTML, MenuBar subMenu) { - this(text, asHTML); - setSubMenu(subMenu); - } - - MenuItem(String text, boolean asHTML) { - setElement(DOM.createTD()); - setSelectionStyle(false); - - if (asHTML) { - setHTML(text); - } else { - setText(text); - } - setStyleName("gwt-MenuItem"); - } - - /** - * Gets the command associated with this item. - * - * @return this item's command, or null if none exists - */ - public Command getCommand() { - return command; - } - - public String getHTML() { - return DOM.getInnerHTML(getElement()); - } - - /** - * Gets the menu that contains this item. - * - * @return the parent menu, or null if none exists. - */ - public MenuBar getParentMenu() { - return parentMenu; - } - - /** - * Gets the sub-menu associated with this item. - * - * @return this item's sub-menu, or null if none exists - */ - public MenuBar getSubMenu() { - return subMenu; - } - - public String getText() { - return DOM.getInnerText(getElement()); - } - - /** - * Sets the command associated with this item. - * - * @param cmd - * the command to be associated with this item - */ - public void setCommand(Command cmd) { - command = cmd; - } - - public void setHTML(String html) { - DOM.setInnerHTML(getElement(), html); - } - - /** - * Sets the sub-menu associated with this item. - * - * @param subMenu - * this item's new sub-menu - */ - public void setSubMenu(MenuBar subMenu) { - this.subMenu = subMenu; - } - - public void setText(String text) { - DOM.setInnerText(getElement(), text); - } - - void setParentMenu(MenuBar parentMenu) { - this.parentMenu = parentMenu; - } - - void setSelectionStyle(boolean selected) { - if (selected) { - addStyleDependentName(DEPENDENT_STYLENAME_SELECTED_ITEM); - } else { - removeStyleDependentName(DEPENDENT_STYLENAME_SELECTED_ITEM); - } - } + private static final String DEPENDENT_STYLENAME_SELECTED_ITEM = "selected"; + + private Command command; + private MenuBar parentMenu, subMenu; + + /** + * Constructs a new menu item that fires a command when it is selected. + * + * @param text + * the item's text + * @param cmd + * the command to be fired when it is selected + */ + public MenuItem(String text, Command cmd) { + this(text, false); + setCommand(cmd); + } + + /** + * Constructs a new menu item that fires a command when it is selected. + * + * @param text + * the item's text + * @param asHTML + * true to treat the specified text as html + * @param cmd + * the command to be fired when it is selected + */ + public MenuItem(String text, boolean asHTML, Command cmd) { + this(text, asHTML); + setCommand(cmd); + } + + /** + * Constructs a new menu item that cascades to a sub-menu when it is + * selected. + * + * @param text + * the item's text + * @param subMenu + * the sub-menu to be displayed when it is selected + */ + public MenuItem(String text, MenuBar subMenu) { + this(text, false); + setSubMenu(subMenu); + } + + /** + * Constructs a new menu item that cascades to a sub-menu when it is + * selected. + * + * @param text + * the item's text + * @param asHTML + * true to treat the specified text as html + * @param subMenu + * the sub-menu to be displayed when it is selected + */ + public MenuItem(String text, boolean asHTML, MenuBar subMenu) { + this(text, asHTML); + setSubMenu(subMenu); + } + + MenuItem(String text, boolean asHTML) { + setElement(DOM.createTD()); + setSelectionStyle(false); + + if (asHTML) { + setHTML(text); + } else { + setText(text); + } + setStyleName("gwt-MenuItem"); + } + + /** + * Gets the command associated with this item. + * + * @return this item's command, or null if none exists + */ + public Command getCommand() { + return command; + } + + public String getHTML() { + return DOM.getInnerHTML(getElement()); + } + + /** + * Gets the menu that contains this item. + * + * @return the parent menu, or null if none exists. + */ + public MenuBar getParentMenu() { + return parentMenu; + } + + /** + * Gets the sub-menu associated with this item. + * + * @return this item's sub-menu, or null if none exists + */ + public MenuBar getSubMenu() { + return subMenu; + } + + public String getText() { + return DOM.getInnerText(getElement()); + } + + /** + * Sets the command associated with this item. + * + * @param cmd + * the command to be associated with this item + */ + public void setCommand(Command cmd) { + command = cmd; + } + + public void setHTML(String html) { + DOM.setInnerHTML(getElement(), html); + } + + /** + * Sets the sub-menu associated with this item. + * + * @param subMenu + * this item's new sub-menu + */ + public void setSubMenu(MenuBar subMenu) { + this.subMenu = subMenu; + } + + public void setText(String text) { + DOM.setInnerText(getElement(), text); + } + + void setParentMenu(MenuBar parentMenu) { + this.parentMenu = parentMenu; + } + + void setSelectionStyle(boolean selected) { + if (selected) { + addStyleDependentName(DEPENDENT_STYLENAME_SELECTED_ITEM); + } else { + removeStyleDependentName(DEPENDENT_STYLENAME_SELECTED_ITEM); + } + } } diff --git a/src/com/itmill/toolkit/terminal/gwt/client/ui/ShortcutActionHandler.java b/src/com/itmill/toolkit/terminal/gwt/client/ui/ShortcutActionHandler.java index 08fcf40662..1cc99be0f0 100644 --- a/src/com/itmill/toolkit/terminal/gwt/client/ui/ShortcutActionHandler.java +++ b/src/com/itmill/toolkit/terminal/gwt/client/ui/ShortcutActionHandler.java @@ -15,147 +15,148 @@ import com.itmill.toolkit.terminal.gwt.client.UIDL; * @author IT Mill ltd */ public class ShortcutActionHandler { - private ArrayList actions = new ArrayList(); - private ApplicationConnection client; - private String paintableId; - - private ShortcutActionHandler() { - } - - /** - * - * @param pid - * Paintable id - * @param c - * reference to application connections - */ - public ShortcutActionHandler(String pid, ApplicationConnection c) { - paintableId = pid; - client = c; - } - - /** - * Updates list of actions this handler listens to. - * - * @param c - * UIDL snippet containing actions - */ - public void updateActionMap(UIDL c) { - actions.clear(); - Iterator it = c.getChildIterator(); - while (it.hasNext()) { - UIDL action = (UIDL) it.next(); - - int[] modifiers = null; - if (action.hasAttribute("mk")) - modifiers = action.getIntArrayAttribute("mk"); - - ShortcutKeyCombination kc = new ShortcutKeyCombination(action - .getIntAttribute("kc"), modifiers); - String key = action.getStringAttribute("key"); - String caption = action.getStringAttribute("caption"); - actions.add(new ShortcutAction(key, kc, caption)); - } - } - - /** - * This method compares given key code and modifier keys to internal list of - * actions. If matching action is found it is fired. - * - * @param keyCode - * character typed - * @param modifiers - * modifier keys (bitmask like in {@link KeyboardListener}) - */ - public void handleKeyboardEvent(char keyCode, int modifiers) { - ShortcutKeyCombination kc = new ShortcutKeyCombination(keyCode, - modifiers); - Iterator it = actions.iterator(); - while (it.hasNext()) { - ShortcutAction a = (ShortcutAction) it.next(); - if (a.getShortcutCombination().equals(kc)) { - client.updateVariable(paintableId, "action", a.getKey(), true); - break; - } - } - } + private ArrayList actions = new ArrayList(); + private ApplicationConnection client; + private String paintableId; + + private ShortcutActionHandler() { + } + + /** + * + * @param pid + * Paintable id + * @param c + * reference to application connections + */ + public ShortcutActionHandler(String pid, ApplicationConnection c) { + paintableId = pid; + client = c; + } + + /** + * Updates list of actions this handler listens to. + * + * @param c + * UIDL snippet containing actions + */ + public void updateActionMap(UIDL c) { + actions.clear(); + Iterator it = c.getChildIterator(); + while (it.hasNext()) { + UIDL action = (UIDL) it.next(); + + int[] modifiers = null; + if (action.hasAttribute("mk")) { + modifiers = action.getIntArrayAttribute("mk"); + } + + ShortcutKeyCombination kc = new ShortcutKeyCombination(action + .getIntAttribute("kc"), modifiers); + String key = action.getStringAttribute("key"); + String caption = action.getStringAttribute("caption"); + actions.add(new ShortcutAction(key, kc, caption)); + } + } + + /** + * This method compares given key code and modifier keys to internal list of + * actions. If matching action is found it is fired. + * + * @param keyCode + * character typed + * @param modifiers + * modifier keys (bitmask like in {@link KeyboardListener}) + */ + public void handleKeyboardEvent(char keyCode, int modifiers) { + ShortcutKeyCombination kc = new ShortcutKeyCombination(keyCode, + modifiers); + Iterator it = actions.iterator(); + while (it.hasNext()) { + ShortcutAction a = (ShortcutAction) it.next(); + if (a.getShortcutCombination().equals(kc)) { + client.updateVariable(paintableId, "action", a.getKey(), true); + break; + } + } + } } class ShortcutKeyCombination { - public static final int SHIFT = 16; - public static final int CTRL = 17; - public static final int ALT = 18; - - char keyCode = 0; - private int modifiersMask; - - public ShortcutKeyCombination() { - } - - ShortcutKeyCombination(char kc, int modifierMask) { - keyCode = kc; - this.modifiersMask = modifierMask; - } - - ShortcutKeyCombination(int kc, int[] modifiers) { - keyCode = (char) kc; - keyCode = Character.toUpperCase(keyCode); - - this.modifiersMask = 0; - if (modifiers != null) { - for (int i = 0; i < modifiers.length; i++) { - switch (modifiers[i]) { - case ALT: - modifiersMask = modifiersMask - | KeyboardListener.MODIFIER_ALT; - break; - case CTRL: - modifiersMask = modifiersMask - | KeyboardListener.MODIFIER_CTRL; - break; - case SHIFT: - modifiersMask = modifiersMask - | KeyboardListener.MODIFIER_SHIFT; - break; - default: - break; - } - } - } - } - - public boolean equals(ShortcutKeyCombination other) { - if (this.keyCode == other.keyCode - && this.modifiersMask == other.modifiersMask) - return true; - return false; - } + public static final int SHIFT = 16; + public static final int CTRL = 17; + public static final int ALT = 18; + + char keyCode = 0; + private int modifiersMask; + + public ShortcutKeyCombination() { + } + + ShortcutKeyCombination(char kc, int modifierMask) { + keyCode = kc; + modifiersMask = modifierMask; + } + + ShortcutKeyCombination(int kc, int[] modifiers) { + keyCode = (char) kc; + keyCode = Character.toUpperCase(keyCode); + + modifiersMask = 0; + if (modifiers != null) { + for (int i = 0; i < modifiers.length; i++) { + switch (modifiers[i]) { + case ALT: + modifiersMask = modifiersMask + | KeyboardListener.MODIFIER_ALT; + break; + case CTRL: + modifiersMask = modifiersMask + | KeyboardListener.MODIFIER_CTRL; + break; + case SHIFT: + modifiersMask = modifiersMask + | KeyboardListener.MODIFIER_SHIFT; + break; + default: + break; + } + } + } + } + + public boolean equals(ShortcutKeyCombination other) { + if (keyCode == other.keyCode && modifiersMask == other.modifiersMask) { + return true; + } + return false; + } } class ShortcutAction { - private ShortcutKeyCombination sc; - private String caption; - private String key; + private ShortcutKeyCombination sc; + private String caption; + private String key; - public ShortcutAction(String key, ShortcutKeyCombination sc, String caption) { - this.sc = sc; - this.key = key; - this.caption = caption; - } + public ShortcutAction(String key, ShortcutKeyCombination sc, String caption) { + this.sc = sc; + this.key = key; + this.caption = caption; + } - public ShortcutKeyCombination getShortcutCombination() { - return sc; - } + public ShortcutKeyCombination getShortcutCombination() { + return sc; + } - public String getCaption() { - return caption; - } + public String getCaption() { + return caption; + } - public String getKey() { - return key; - } + public String getKey() { + return key; + } } diff --git a/src/com/itmill/toolkit/terminal/gwt/client/ui/Table.java b/src/com/itmill/toolkit/terminal/gwt/client/ui/Table.java index 22268d598e..eb955137f0 100644 --- a/src/com/itmill/toolkit/terminal/gwt/client/ui/Table.java +++ b/src/com/itmill/toolkit/terminal/gwt/client/ui/Table.java @@ -4,8 +4,8 @@ import com.google.gwt.user.client.ui.HasWidgets; import com.itmill.toolkit.terminal.gwt.client.Paintable; public interface Table extends Paintable, HasWidgets { - final int SELECT_MODE_NONE = 0; - final int SELECT_MODE_SINGLE = 1; - final int SELECT_MODE_MULTI = 2; + final int SELECT_MODE_NONE = 0; + final int SELECT_MODE_SINGLE = 1; + final int SELECT_MODE_MULTI = 2; } diff --git a/src/com/itmill/toolkit/terminal/gwt/client/ui/Time.java b/src/com/itmill/toolkit/terminal/gwt/client/ui/Time.java index 3c853a0208..0ff537c542 100644 --- a/src/com/itmill/toolkit/terminal/gwt/client/ui/Time.java +++ b/src/com/itmill/toolkit/terminal/gwt/client/ui/Time.java @@ -7,243 +7,267 @@ import com.google.gwt.user.client.ui.Widget; public class Time extends FlowPanel implements ChangeListener { - private IDateField datefield; - - private ListBox hours; - - private ListBox mins; - - private ListBox sec; - - private ListBox msec; - - private ListBox ampm; - - private int resolution = IDateField.RESOLUTION_HOUR; - - private boolean readonly; - - public Time(IDateField parent) { - super(); - datefield = parent; - setStyleName(IDateField.CLASSNAME + "-time"); - } - - private void buildTime(boolean redraw) { - boolean thc = datefield.getDateTimeService().isTwelveHourClock(); - if (redraw) { - clear(); - int numHours = thc ? 12 : 24; - hours = new ListBox(); - hours.setStyleName(INativeSelect.CLASSNAME); - for (int i = 0; i < numHours; i++) - hours.addItem((i < 10) ? "0" + i : "" + i); - hours.addChangeListener(this); - if (thc) { - ampm = new ListBox(); - ampm.setStyleName(INativeSelect.CLASSNAME); - String[] ampmText = datefield.getDateTimeService() - .getAmPmStrings(); - ampm.addItem(ampmText[0]); - ampm.addItem(ampmText[1]); - ampm.addChangeListener(this); - } - - if (datefield.getCurrentResolution() >= IDateField.RESOLUTION_MIN) { - mins = new ListBox(); - mins.setStyleName(INativeSelect.CLASSNAME); - for (int i = 0; i < 60; i++) - mins.addItem((i < 10) ? "0" + i : "" + i); - mins.addChangeListener(this); - } - if (datefield.getCurrentResolution() >= IDateField.RESOLUTION_SEC) { - sec = new ListBox(); - sec.setStyleName(INativeSelect.CLASSNAME); - for (int i = 0; i < 60; i++) - sec.addItem((i < 10) ? "0" + i : "" + i); - sec.addChangeListener(this); - } - if (datefield.getCurrentResolution() == IDateField.RESOLUTION_MSEC) { - msec = new ListBox(); - msec.setStyleName(INativeSelect.CLASSNAME); - for (int i = 0; i < 1000; i++) { - if (i < 10) - msec.addItem("00" + i); - else if (i < 100) - msec.addItem("0" + i); - else - msec.addItem("" + i); - } - msec.addChangeListener(this); - } - - String delimiter = datefield.getDateTimeService() - .getClockDelimeter(); - boolean ro = datefield.isReadonly(); - - if (ro) { - int h = 0; - if (datefield.getCurrentDate() != null) - h = datefield.getCurrentDate().getHours(); - if (thc) - h -= h < 12 ? 0 : 12; - add(new ILabel(h < 10 ? "0" + h : "" + h)); - } else - add(hours); - - if (datefield.getCurrentResolution() >= IDateField.RESOLUTION_MIN) { - add(new ILabel(delimiter)); - if (ro) { - int m = mins.getSelectedIndex(); - add(new ILabel(m < 10 ? "0" + m : "" + m)); - } else - add(mins); - } - if (datefield.getCurrentResolution() >= IDateField.RESOLUTION_SEC) { - add(new ILabel(delimiter)); - if (ro) { - int s = sec.getSelectedIndex(); - add(new ILabel(s < 10 ? "0" + s : "" + s)); - } else - add(sec); - } - if (datefield.getCurrentResolution() == IDateField.RESOLUTION_MSEC) { - add(new ILabel(".")); - if (ro) { - int m = datefield.getMilliseconds(); - String ms = m < 100 ? "0" + m : "" + m; - add(new ILabel(m < 10 ? "0" + ms : ms)); - } else - add(msec); - } - if (datefield.getCurrentResolution() == IDateField.RESOLUTION_HOUR) { - add(new ILabel(delimiter + "00")); // o'clock - } - if (thc) { - add(new ILabel(" ")); - if (ro) - add(new ILabel(ampm.getItemText(datefield.getCurrentDate() - .getHours() < 12 ? 0 : 1))); - else - add(ampm); - } - - if (ro) - return; - } - - // Update times - if (thc) { - int h = datefield.getCurrentDate().getHours(); - ampm.setSelectedIndex(h < 12 ? 0 : 1); - h -= ampm.getSelectedIndex() * 12; - hours.setSelectedIndex(h); - } else - hours.setSelectedIndex(datefield.getCurrentDate().getHours()); - if (datefield.getCurrentResolution() >= IDateField.RESOLUTION_MIN) - mins.setSelectedIndex(datefield.getCurrentDate().getMinutes()); - if (datefield.getCurrentResolution() >= IDateField.RESOLUTION_SEC) - sec.setSelectedIndex(datefield.getCurrentDate().getSeconds()); - if (datefield.getCurrentResolution() == IDateField.RESOLUTION_MSEC) - msec.setSelectedIndex(datefield.getMilliseconds()); - if (thc) - ampm - .setSelectedIndex(datefield.getCurrentDate().getHours() < 12 ? 0 - : 1); - - if (datefield.isReadonly() && !redraw) { - // Do complete redraw when in read-only status - clear(); - String delimiter = datefield.getDateTimeService() - .getClockDelimeter(); - - int h = datefield.getCurrentDate().getHours(); - if (thc) - h -= h < 12 ? 0 : 12; - add(new ILabel(h < 10 ? "0" + h : "" + h)); - - if (datefield.getCurrentResolution() >= IDateField.RESOLUTION_MIN) { - add(new ILabel(delimiter)); - int m = mins.getSelectedIndex(); - add(new ILabel(m < 10 ? "0" + m : "" + m)); - } - if (datefield.getCurrentResolution() >= IDateField.RESOLUTION_SEC) { - add(new ILabel(delimiter)); - int s = sec.getSelectedIndex(); - add(new ILabel(s < 10 ? "0" + s : "" + s)); - } - if (datefield.getCurrentResolution() == IDateField.RESOLUTION_MSEC) { - add(new ILabel(".")); - int m = datefield.getMilliseconds(); - String ms = m < 100 ? "0" + m : "" + m; - add(new ILabel(m < 10 ? "0" + ms : ms)); - } - if (datefield.getCurrentResolution() == IDateField.RESOLUTION_HOUR) { - add(new ILabel(delimiter + "00")); // o'clock - } - if (thc) { - add(new ILabel(" ")); - add(new ILabel(ampm.getItemText(datefield.getCurrentDate() - .getHours() < 12 ? 0 : 1))); - } - } - - boolean enabled = datefield.isEnabled(); - hours.setEnabled(enabled); - if (mins != null) - mins.setEnabled(enabled); - if (sec != null) - sec.setEnabled(enabled); - if (msec != null) - msec.setEnabled(enabled); - if (ampm != null) - ampm.setEnabled(enabled); - - } - - public void updateTime(boolean redraw) { - buildTime(redraw || resolution != datefield.getCurrentResolution() - || readonly != datefield.isReadonly()); - if (datefield instanceof ITextualDate) - ((ITextualDate) datefield).buildDate(); - resolution = datefield.getCurrentResolution(); - readonly = datefield.isReadonly(); - } - - public void onChange(Widget sender) { - if (sender == hours) { - int h = hours.getSelectedIndex(); - if (datefield.getDateTimeService().isTwelveHourClock()) - h = h + ampm.getSelectedIndex() * 12; - datefield.getCurrentDate().setHours(h); - datefield.getClient().updateVariable(datefield.getId(), "hour", h, - datefield.isImmediate()); - updateTime(false); - } else if (sender == mins) { - int m = mins.getSelectedIndex(); - datefield.getCurrentDate().setMinutes(m); - datefield.getClient().updateVariable(datefield.getId(), "min", m, - datefield.isImmediate()); - updateTime(false); - } else if (sender == sec) { - int s = sec.getSelectedIndex(); - datefield.getCurrentDate().setSeconds(s); - datefield.getClient().updateVariable(datefield.getId(), "sec", s, - datefield.isImmediate()); - updateTime(false); - } else if (sender == msec) { - int ms = msec.getSelectedIndex(); - datefield.setMilliseconds(ms); - datefield.getClient().updateVariable(datefield.getId(), "msec", ms, - datefield.isImmediate()); - updateTime(false); - } else if (sender == ampm) { - int h = hours.getSelectedIndex() + ampm.getSelectedIndex() * 12; - datefield.getCurrentDate().setHours(h); - datefield.getClient().updateVariable(datefield.getId(), "hour", h, - datefield.isImmediate()); - updateTime(false); - } - } + private IDateField datefield; + + private ListBox hours; + + private ListBox mins; + + private ListBox sec; + + private ListBox msec; + + private ListBox ampm; + + private int resolution = IDateField.RESOLUTION_HOUR; + + private boolean readonly; + + public Time(IDateField parent) { + super(); + datefield = parent; + setStyleName(IDateField.CLASSNAME + "-time"); + } + + private void buildTime(boolean redraw) { + boolean thc = datefield.getDateTimeService().isTwelveHourClock(); + if (redraw) { + clear(); + int numHours = thc ? 12 : 24; + hours = new ListBox(); + hours.setStyleName(INativeSelect.CLASSNAME); + for (int i = 0; i < numHours; i++) { + hours.addItem((i < 10) ? "0" + i : "" + i); + } + hours.addChangeListener(this); + if (thc) { + ampm = new ListBox(); + ampm.setStyleName(INativeSelect.CLASSNAME); + String[] ampmText = datefield.getDateTimeService() + .getAmPmStrings(); + ampm.addItem(ampmText[0]); + ampm.addItem(ampmText[1]); + ampm.addChangeListener(this); + } + + if (datefield.getCurrentResolution() >= IDateField.RESOLUTION_MIN) { + mins = new ListBox(); + mins.setStyleName(INativeSelect.CLASSNAME); + for (int i = 0; i < 60; i++) { + mins.addItem((i < 10) ? "0" + i : "" + i); + } + mins.addChangeListener(this); + } + if (datefield.getCurrentResolution() >= IDateField.RESOLUTION_SEC) { + sec = new ListBox(); + sec.setStyleName(INativeSelect.CLASSNAME); + for (int i = 0; i < 60; i++) { + sec.addItem((i < 10) ? "0" + i : "" + i); + } + sec.addChangeListener(this); + } + if (datefield.getCurrentResolution() == IDateField.RESOLUTION_MSEC) { + msec = new ListBox(); + msec.setStyleName(INativeSelect.CLASSNAME); + for (int i = 0; i < 1000; i++) { + if (i < 10) { + msec.addItem("00" + i); + } else if (i < 100) { + msec.addItem("0" + i); + } else { + msec.addItem("" + i); + } + } + msec.addChangeListener(this); + } + + String delimiter = datefield.getDateTimeService() + .getClockDelimeter(); + boolean ro = datefield.isReadonly(); + + if (ro) { + int h = 0; + if (datefield.getCurrentDate() != null) { + h = datefield.getCurrentDate().getHours(); + } + if (thc) { + h -= h < 12 ? 0 : 12; + } + add(new ILabel(h < 10 ? "0" + h : "" + h)); + } else { + add(hours); + } + + if (datefield.getCurrentResolution() >= IDateField.RESOLUTION_MIN) { + add(new ILabel(delimiter)); + if (ro) { + int m = mins.getSelectedIndex(); + add(new ILabel(m < 10 ? "0" + m : "" + m)); + } else { + add(mins); + } + } + if (datefield.getCurrentResolution() >= IDateField.RESOLUTION_SEC) { + add(new ILabel(delimiter)); + if (ro) { + int s = sec.getSelectedIndex(); + add(new ILabel(s < 10 ? "0" + s : "" + s)); + } else { + add(sec); + } + } + if (datefield.getCurrentResolution() == IDateField.RESOLUTION_MSEC) { + add(new ILabel(".")); + if (ro) { + int m = datefield.getMilliseconds(); + String ms = m < 100 ? "0" + m : "" + m; + add(new ILabel(m < 10 ? "0" + ms : ms)); + } else { + add(msec); + } + } + if (datefield.getCurrentResolution() == IDateField.RESOLUTION_HOUR) { + add(new ILabel(delimiter + "00")); // o'clock + } + if (thc) { + add(new ILabel(" ")); + if (ro) { + add(new ILabel(ampm.getItemText(datefield.getCurrentDate() + .getHours() < 12 ? 0 : 1))); + } else { + add(ampm); + } + } + + if (ro) { + return; + } + } + + // Update times + if (thc) { + int h = datefield.getCurrentDate().getHours(); + ampm.setSelectedIndex(h < 12 ? 0 : 1); + h -= ampm.getSelectedIndex() * 12; + hours.setSelectedIndex(h); + } else { + hours.setSelectedIndex(datefield.getCurrentDate().getHours()); + } + if (datefield.getCurrentResolution() >= IDateField.RESOLUTION_MIN) { + mins.setSelectedIndex(datefield.getCurrentDate().getMinutes()); + } + if (datefield.getCurrentResolution() >= IDateField.RESOLUTION_SEC) { + sec.setSelectedIndex(datefield.getCurrentDate().getSeconds()); + } + if (datefield.getCurrentResolution() == IDateField.RESOLUTION_MSEC) { + msec.setSelectedIndex(datefield.getMilliseconds()); + } + if (thc) { + ampm + .setSelectedIndex(datefield.getCurrentDate().getHours() < 12 ? 0 + : 1); + } + + if (datefield.isReadonly() && !redraw) { + // Do complete redraw when in read-only status + clear(); + String delimiter = datefield.getDateTimeService() + .getClockDelimeter(); + + int h = datefield.getCurrentDate().getHours(); + if (thc) { + h -= h < 12 ? 0 : 12; + } + add(new ILabel(h < 10 ? "0" + h : "" + h)); + + if (datefield.getCurrentResolution() >= IDateField.RESOLUTION_MIN) { + add(new ILabel(delimiter)); + int m = mins.getSelectedIndex(); + add(new ILabel(m < 10 ? "0" + m : "" + m)); + } + if (datefield.getCurrentResolution() >= IDateField.RESOLUTION_SEC) { + add(new ILabel(delimiter)); + int s = sec.getSelectedIndex(); + add(new ILabel(s < 10 ? "0" + s : "" + s)); + } + if (datefield.getCurrentResolution() == IDateField.RESOLUTION_MSEC) { + add(new ILabel(".")); + int m = datefield.getMilliseconds(); + String ms = m < 100 ? "0" + m : "" + m; + add(new ILabel(m < 10 ? "0" + ms : ms)); + } + if (datefield.getCurrentResolution() == IDateField.RESOLUTION_HOUR) { + add(new ILabel(delimiter + "00")); // o'clock + } + if (thc) { + add(new ILabel(" ")); + add(new ILabel(ampm.getItemText(datefield.getCurrentDate() + .getHours() < 12 ? 0 : 1))); + } + } + + boolean enabled = datefield.isEnabled(); + hours.setEnabled(enabled); + if (mins != null) { + mins.setEnabled(enabled); + } + if (sec != null) { + sec.setEnabled(enabled); + } + if (msec != null) { + msec.setEnabled(enabled); + } + if (ampm != null) { + ampm.setEnabled(enabled); + } + + } + + public void updateTime(boolean redraw) { + buildTime(redraw || resolution != datefield.getCurrentResolution() + || readonly != datefield.isReadonly()); + if (datefield instanceof ITextualDate) { + ((ITextualDate) datefield).buildDate(); + } + resolution = datefield.getCurrentResolution(); + readonly = datefield.isReadonly(); + } + + public void onChange(Widget sender) { + if (sender == hours) { + int h = hours.getSelectedIndex(); + if (datefield.getDateTimeService().isTwelveHourClock()) { + h = h + ampm.getSelectedIndex() * 12; + } + datefield.getCurrentDate().setHours(h); + datefield.getClient().updateVariable(datefield.getId(), "hour", h, + datefield.isImmediate()); + updateTime(false); + } else if (sender == mins) { + int m = mins.getSelectedIndex(); + datefield.getCurrentDate().setMinutes(m); + datefield.getClient().updateVariable(datefield.getId(), "min", m, + datefield.isImmediate()); + updateTime(false); + } else if (sender == sec) { + int s = sec.getSelectedIndex(); + datefield.getCurrentDate().setSeconds(s); + datefield.getClient().updateVariable(datefield.getId(), "sec", s, + datefield.isImmediate()); + updateTime(false); + } else if (sender == msec) { + int ms = msec.getSelectedIndex(); + datefield.setMilliseconds(ms); + datefield.getClient().updateVariable(datefield.getId(), "msec", ms, + datefield.isImmediate()); + updateTime(false); + } else if (sender == ampm) { + int h = hours.getSelectedIndex() + ampm.getSelectedIndex() * 12; + datefield.getCurrentDate().setHours(h); + datefield.getClient().updateVariable(datefield.getId(), "hour", h, + datefield.isImmediate()); + updateTime(false); + } + } } diff --git a/src/com/itmill/toolkit/terminal/gwt/client/ui/TreeAction.java b/src/com/itmill/toolkit/terminal/gwt/client/ui/TreeAction.java index 3e690455af..39cd917536 100644 --- a/src/com/itmill/toolkit/terminal/gwt/client/ui/TreeAction.java +++ b/src/com/itmill/toolkit/terminal/gwt/client/ui/TreeAction.java @@ -5,47 +5,47 @@ package com.itmill.toolkit.terminal.gwt.client.ui; */ public class TreeAction extends Action { - String targetKey = ""; - String actionKey = ""; - - public TreeAction(ActionOwner owner) { - super(owner); - } - - public TreeAction(ActionOwner owner, String target, String action) { - this(owner); - this.targetKey = target; - this.actionKey = action; - } - - /** - * Sends message to server that this action has been fired. Messages are - * "standard" Toolkit messages whose value is comma separated pair of - * targetKey (row, treeNod ...) and actions id. - * - * Variablename is always "action". - * - * Actions are always sent immediatedly to server. - */ - public void execute() { - owner.getClient().updateVariable(owner.getPaintableId(), "action", - targetKey + "," + actionKey, true); - owner.getClient().getContextMenu().hide(); - } - - public String getActionKey() { - return actionKey; - } - - public void setActionKey(String actionKey) { - this.actionKey = actionKey; - } - - public String getTargetKey() { - return targetKey; - } - - public void setTargetKey(String targetKey) { - this.targetKey = targetKey; - } + String targetKey = ""; + String actionKey = ""; + + public TreeAction(ActionOwner owner) { + super(owner); + } + + public TreeAction(ActionOwner owner, String target, String action) { + this(owner); + targetKey = target; + actionKey = action; + } + + /** + * Sends message to server that this action has been fired. Messages are + * "standard" Toolkit messages whose value is comma separated pair of + * targetKey (row, treeNod ...) and actions id. + * + * Variablename is always "action". + * + * Actions are always sent immediatedly to server. + */ + public void execute() { + owner.getClient().updateVariable(owner.getPaintableId(), "action", + targetKey + "," + actionKey, true); + owner.getClient().getContextMenu().hide(); + } + + public String getActionKey() { + return actionKey; + } + + public void setActionKey(String actionKey) { + this.actionKey = actionKey; + } + + public String getTargetKey() { + return targetKey; + } + + public void setTargetKey(String targetKey) { + this.targetKey = targetKey; + } } diff --git a/src/com/itmill/toolkit/terminal/gwt/client/ui/TreeImages.java b/src/com/itmill/toolkit/terminal/gwt/client/ui/TreeImages.java index e404a7caea..1797cef581 100644 --- a/src/com/itmill/toolkit/terminal/gwt/client/ui/TreeImages.java +++ b/src/com/itmill/toolkit/terminal/gwt/client/ui/TreeImages.java @@ -4,20 +4,20 @@ import com.google.gwt.user.client.ui.AbstractImagePrototype; public interface TreeImages extends com.google.gwt.user.client.ui.TreeImages { - /** - * An image indicating an open branch. - * - * @return a prototype of this image - * @gwt.resource com/itmill/toolkit/terminal/gwt/public/default/tree/img/expanded.png - */ - AbstractImagePrototype treeOpen(); + /** + * An image indicating an open branch. + * + * @return a prototype of this image + * @gwt.resource com/itmill/toolkit/terminal/gwt/public/default/tree/img/expanded.png + */ + AbstractImagePrototype treeOpen(); + + /** + * An image indicating a closed branch. + * + * @return a prototype of this image + * @gwt.resource com/itmill/toolkit/terminal/gwt/public/default/tree/img/collapsed.png + */ + AbstractImagePrototype treeClosed(); - /** - * An image indicating a closed branch. - * - * @return a prototype of this image - * @gwt.resource com/itmill/toolkit/terminal/gwt/public/default/tree/img/collapsed.png - */ - AbstractImagePrototype treeClosed(); - } diff --git a/src/com/itmill/toolkit/terminal/gwt/client/ui/richtextarea/IRichTextArea.java b/src/com/itmill/toolkit/terminal/gwt/client/ui/richtextarea/IRichTextArea.java index 03c73e9e9d..a13a23a3dc 100644 --- a/src/com/itmill/toolkit/terminal/gwt/client/ui/richtextarea/IRichTextArea.java +++ b/src/com/itmill/toolkit/terminal/gwt/client/ui/richtextarea/IRichTextArea.java @@ -17,64 +17,64 @@ import com.itmill.toolkit.terminal.gwt.client.UIDL; * */ public class IRichTextArea extends Composite implements Paintable, - ChangeListener, FocusListener { + ChangeListener, FocusListener { - /** - * The input node CSS classname. - */ - public static final String CLASSNAME = "i-richtextarea"; + /** + * The input node CSS classname. + */ + public static final String CLASSNAME = "i-richtextarea"; - protected String id; + protected String id; - protected ApplicationConnection client; + protected ApplicationConnection client; - private boolean immediate = false; + private boolean immediate = false; - RichTextArea rta = new RichTextArea(); + RichTextArea rta = new RichTextArea(); - RichTextToolbar formatter = new RichTextToolbar(rta); + RichTextToolbar formatter = new RichTextToolbar(rta); - public IRichTextArea() { - FlowPanel fp = new FlowPanel(); - fp.add(formatter); + public IRichTextArea() { + FlowPanel fp = new FlowPanel(); + fp.add(formatter); - rta.setWidth("100%"); - rta.addFocusListener(this); + rta.setWidth("100%"); + rta.addFocusListener(this); - fp.add(rta); + fp.add(rta); - initWidget(fp); - setStyleName(CLASSNAME); - } + initWidget(fp); + setStyleName(CLASSNAME); + } - public void updateFromUIDL(UIDL uidl, ApplicationConnection client) { - this.client = client; - id = uidl.getId(); + public void updateFromUIDL(UIDL uidl, ApplicationConnection client) { + this.client = client; + id = uidl.getId(); - if (client.updateComponent(this, uidl, true)) { - return; - } + if (client.updateComponent(this, uidl, true)) { + return; + } - immediate = uidl.getBooleanAttribute("immediate"); + immediate = uidl.getBooleanAttribute("immediate"); - rta.setHTML(uidl.getStringVariable("text")); + rta.setHTML(uidl.getStringVariable("text")); - } + } - public void onChange(Widget sender) { - if (client != null && id != null) { - client.updateVariable(id, "text", rta.getText(), immediate); - } - } + public void onChange(Widget sender) { + if (client != null && id != null) { + client.updateVariable(id, "text", rta.getText(), immediate); + } + } - public void onFocus(Widget sender) { + public void onFocus(Widget sender) { - } + } - public void onLostFocus(Widget sender) { - String html = rta.getHTML(); - client.updateVariable(id, "text", html, immediate); + public void onLostFocus(Widget sender) { + String html = rta.getHTML(); + client.updateVariable(id, "text", html, immediate); - } + } } diff --git a/src/com/itmill/toolkit/terminal/gwt/client/ui/richtextarea/RichTextToolbar.java b/src/com/itmill/toolkit/terminal/gwt/client/ui/richtextarea/RichTextToolbar.java index 2c1a8d7d52..fcffa51328 100644 --- a/src/com/itmill/toolkit/terminal/gwt/client/ui/richtextarea/RichTextToolbar.java +++ b/src/com/itmill/toolkit/terminal/gwt/client/ui/richtextarea/RichTextToolbar.java @@ -39,454 +39,469 @@ import com.google.gwt.user.client.ui.Widget; */ public class RichTextToolbar extends Composite { - /** - * This {@link ImageBundle} is used for all the button icons. Using an image - * bundle allows all of these images to be packed into a single image, which - * saves a lot of HTTP requests, drastically improving startup time. - */ - public interface Images extends ImageBundle { - - /** - * @gwt.resource bold.gif - */ - AbstractImagePrototype bold(); - - /** - * @gwt.resource createLink.gif - */ - AbstractImagePrototype createLink(); - - /** - * @gwt.resource hr.gif - */ - AbstractImagePrototype hr(); - /** - * @gwt.resource indent.gif + * This {@link ImageBundle} is used for all the button icons. Using an image + * bundle allows all of these images to be packed into a single image, which + * saves a lot of HTTP requests, drastically improving startup time. */ - AbstractImagePrototype indent(); - - /** - * @gwt.resource insertImage.gif - */ - AbstractImagePrototype insertImage(); - - /** - * @gwt.resource italic.gif - */ - AbstractImagePrototype italic(); - - /** - * @gwt.resource justifyCenter.gif - */ - AbstractImagePrototype justifyCenter(); - - /** - * @gwt.resource justifyLeft.gif - */ - AbstractImagePrototype justifyLeft(); - - /** - * @gwt.resource justifyRight.gif - */ - AbstractImagePrototype justifyRight(); - - /** - * @gwt.resource ol.gif - */ - AbstractImagePrototype ol(); - - /** - * @gwt.resource outdent.gif - */ - AbstractImagePrototype outdent(); - - /** - * @gwt.resource removeFormat.gif - */ - AbstractImagePrototype removeFormat(); - - /** - * @gwt.resource removeLink.gif - */ - AbstractImagePrototype removeLink(); + public interface Images extends ImageBundle { + + /** + * @gwt.resource bold.gif + */ + AbstractImagePrototype bold(); + + /** + * @gwt.resource createLink.gif + */ + AbstractImagePrototype createLink(); + + /** + * @gwt.resource hr.gif + */ + AbstractImagePrototype hr(); + + /** + * @gwt.resource indent.gif + */ + AbstractImagePrototype indent(); + + /** + * @gwt.resource insertImage.gif + */ + AbstractImagePrototype insertImage(); + + /** + * @gwt.resource italic.gif + */ + AbstractImagePrototype italic(); + + /** + * @gwt.resource justifyCenter.gif + */ + AbstractImagePrototype justifyCenter(); + + /** + * @gwt.resource justifyLeft.gif + */ + AbstractImagePrototype justifyLeft(); + + /** + * @gwt.resource justifyRight.gif + */ + AbstractImagePrototype justifyRight(); + + /** + * @gwt.resource ol.gif + */ + AbstractImagePrototype ol(); + + /** + * @gwt.resource outdent.gif + */ + AbstractImagePrototype outdent(); + + /** + * @gwt.resource removeFormat.gif + */ + AbstractImagePrototype removeFormat(); + + /** + * @gwt.resource removeLink.gif + */ + AbstractImagePrototype removeLink(); + + /** + * @gwt.resource strikeThrough.gif + */ + AbstractImagePrototype strikeThrough(); + + /** + * @gwt.resource subscript.gif + */ + AbstractImagePrototype subscript(); + + /** + * @gwt.resource superscript.gif + */ + AbstractImagePrototype superscript(); + + /** + * @gwt.resource ul.gif + */ + AbstractImagePrototype ul(); + + /** + * @gwt.resource underline.gif + */ + AbstractImagePrototype underline(); + } /** - * @gwt.resource strikeThrough.gif + * This {@link Constants} interface is used to make the toolbar's strings + * internationalizable. */ - AbstractImagePrototype strikeThrough(); + public interface Strings extends Constants { - /** - * @gwt.resource subscript.gif - */ - AbstractImagePrototype subscript(); + String black(); - /** - * @gwt.resource superscript.gif - */ - AbstractImagePrototype superscript(); + String blue(); - /** - * @gwt.resource ul.gif - */ - AbstractImagePrototype ul(); + String bold(); - /** - * @gwt.resource underline.gif - */ - AbstractImagePrototype underline(); - } + String color(); - /** - * This {@link Constants} interface is used to make the toolbar's strings - * internationalizable. - */ - public interface Strings extends Constants { + String createLink(); - String black(); + String font(); - String blue(); + String green(); - String bold(); + String hr(); - String color(); + String indent(); - String createLink(); + String insertImage(); - String font(); + String italic(); - String green(); + String justifyCenter(); - String hr(); + String justifyLeft(); - String indent(); + String justifyRight(); - String insertImage(); + String large(); - String italic(); + String medium(); - String justifyCenter(); + String normal(); - String justifyLeft(); + String ol(); - String justifyRight(); + String outdent(); - String large(); + String red(); - String medium(); + String removeFormat(); - String normal(); + String removeLink(); - String ol(); + String size(); - String outdent(); + String small(); - String red(); + String strikeThrough(); - String removeFormat(); + String subscript(); - String removeLink(); + String superscript(); - String size(); + String ul(); - String small(); + String underline(); - String strikeThrough(); + String white(); - String subscript(); + String xlarge(); - String superscript(); + String xsmall(); - String ul(); + String xxlarge(); - String underline(); + String xxsmall(); - String white(); + String yellow(); + } - String xlarge(); + /** + * We use an inner EventListener class to avoid exposing event methods on + * the RichTextToolbar itself. + */ + private class EventListener implements ClickListener, ChangeListener, + KeyboardListener { + + public void onChange(Widget sender) { + if (sender == backColors) { + basic.setBackColor(backColors.getValue(backColors + .getSelectedIndex())); + backColors.setSelectedIndex(0); + } else if (sender == foreColors) { + basic.setForeColor(foreColors.getValue(foreColors + .getSelectedIndex())); + foreColors.setSelectedIndex(0); + } else if (sender == fonts) { + basic.setFontName(fonts.getValue(fonts.getSelectedIndex())); + fonts.setSelectedIndex(0); + } else if (sender == fontSizes) { + basic.setFontSize(fontSizesConstants[fontSizes + .getSelectedIndex() - 1]); + fontSizes.setSelectedIndex(0); + } + } - String xsmall(); + public void onClick(Widget sender) { + if (sender == bold) { + basic.toggleBold(); + } else if (sender == italic) { + basic.toggleItalic(); + } else if (sender == underline) { + basic.toggleUnderline(); + } else if (sender == subscript) { + basic.toggleSubscript(); + } else if (sender == superscript) { + basic.toggleSuperscript(); + } else if (sender == strikethrough) { + extended.toggleStrikethrough(); + } else if (sender == indent) { + extended.rightIndent(); + } else if (sender == outdent) { + extended.leftIndent(); + } else if (sender == justifyLeft) { + basic.setJustification(RichTextArea.Justification.LEFT); + } else if (sender == justifyCenter) { + basic.setJustification(RichTextArea.Justification.CENTER); + } else if (sender == justifyRight) { + basic.setJustification(RichTextArea.Justification.RIGHT); + } else if (sender == insertImage) { + String url = Window.prompt("Enter an image URL:", "http://"); + if (url != null) { + extended.insertImage(url); + } + } else if (sender == createLink) { + String url = Window.prompt("Enter a link URL:", "http://"); + if (url != null) { + extended.createLink(url); + } + } else if (sender == removeLink) { + extended.removeLink(); + } else if (sender == hr) { + extended.insertHorizontalRule(); + } else if (sender == ol) { + extended.insertOrderedList(); + } else if (sender == ul) { + extended.insertUnorderedList(); + } else if (sender == removeFormat) { + extended.removeFormat(); + } else if (sender == richText) { + // We use the RichTextArea's onKeyUp event to update the toolbar + // status. + // This will catch any cases where the user moves the cursur + // using the + // keyboard, or uses one of the browser's built-in keyboard + // shortcuts. + updateStatus(); + } + } - String xxlarge(); + public void onKeyDown(Widget sender, char keyCode, int modifiers) { + } - String xxsmall(); + public void onKeyPress(Widget sender, char keyCode, int modifiers) { + } - String yellow(); - } + public void onKeyUp(Widget sender, char keyCode, int modifiers) { + if (sender == richText) { + // We use the RichTextArea's onKeyUp event to update the toolbar + // status. + // This will catch any cases where the user moves the cursur + // using the + // keyboard, or uses one of the browser's built-in keyboard + // shortcuts. + updateStatus(); + } + } + } - /** - * We use an inner EventListener class to avoid exposing event methods on the - * RichTextToolbar itself. - */ - private class EventListener implements ClickListener, ChangeListener, - KeyboardListener { + private static final RichTextArea.FontSize[] fontSizesConstants = new RichTextArea.FontSize[] { + RichTextArea.FontSize.XX_SMALL, RichTextArea.FontSize.X_SMALL, + RichTextArea.FontSize.SMALL, RichTextArea.FontSize.MEDIUM, + RichTextArea.FontSize.LARGE, RichTextArea.FontSize.X_LARGE, + RichTextArea.FontSize.XX_LARGE }; + + private Images images = (Images) GWT.create(Images.class); + private Strings strings = (Strings) GWT.create(Strings.class); + private EventListener listener = new EventListener(); + + private RichTextArea richText; + private RichTextArea.BasicFormatter basic; + private RichTextArea.ExtendedFormatter extended; + + private VerticalPanel outer = new VerticalPanel(); + private HorizontalPanel topPanel = new HorizontalPanel(); + private HorizontalPanel bottomPanel = new HorizontalPanel(); + private ToggleButton bold; + private ToggleButton italic; + private ToggleButton underline; + private ToggleButton subscript; + private ToggleButton superscript; + private ToggleButton strikethrough; + private PushButton indent; + private PushButton outdent; + private PushButton justifyLeft; + private PushButton justifyCenter; + private PushButton justifyRight; + private PushButton hr; + private PushButton ol; + private PushButton ul; + private PushButton insertImage; + private PushButton createLink; + private PushButton removeLink; + private PushButton removeFormat; + + private ListBox backColors; + private ListBox foreColors; + private ListBox fonts; + private ListBox fontSizes; - public void onChange(Widget sender) { - if (sender == backColors) { - basic.setBackColor(backColors.getValue(backColors.getSelectedIndex())); - backColors.setSelectedIndex(0); - } else if (sender == foreColors) { - basic.setForeColor(foreColors.getValue(foreColors.getSelectedIndex())); - foreColors.setSelectedIndex(0); - } else if (sender == fonts) { - basic.setFontName(fonts.getValue(fonts.getSelectedIndex())); - fonts.setSelectedIndex(0); - } else if (sender == fontSizes) { - basic.setFontSize(fontSizesConstants[fontSizes.getSelectedIndex() - 1]); - fontSizes.setSelectedIndex(0); - } - } + /** + * Creates a new toolbar that drives the given rich text area. + * + * @param richText + * the rich text area to be controlled + */ + public RichTextToolbar(RichTextArea richText) { + this.richText = richText; + basic = richText.getBasicFormatter(); + extended = richText.getExtendedFormatter(); + + outer.add(topPanel); + outer.add(bottomPanel); + topPanel.setWidth("100%"); + bottomPanel.setWidth("100%"); + + initWidget(outer); + setStyleName("gwt-RichTextToolbar"); + + if (basic != null) { + topPanel.add(bold = createToggleButton(images.bold(), strings + .bold())); + topPanel.add(italic = createToggleButton(images.italic(), strings + .italic())); + topPanel.add(underline = createToggleButton(images.underline(), + strings.underline())); + topPanel.add(subscript = createToggleButton(images.subscript(), + strings.subscript())); + topPanel.add(superscript = createToggleButton(images.superscript(), + strings.superscript())); + topPanel.add(justifyLeft = createPushButton(images.justifyLeft(), + strings.justifyLeft())); + topPanel.add(justifyCenter = createPushButton(images + .justifyCenter(), strings.justifyCenter())); + topPanel.add(justifyRight = createPushButton(images.justifyRight(), + strings.justifyRight())); + } - public void onClick(Widget sender) { - if (sender == bold) { - basic.toggleBold(); - } else if (sender == italic) { - basic.toggleItalic(); - } else if (sender == underline) { - basic.toggleUnderline(); - } else if (sender == subscript) { - basic.toggleSubscript(); - } else if (sender == superscript) { - basic.toggleSuperscript(); - } else if (sender == strikethrough) { - extended.toggleStrikethrough(); - } else if (sender == indent) { - extended.rightIndent(); - } else if (sender == outdent) { - extended.leftIndent(); - } else if (sender == justifyLeft) { - basic.setJustification(RichTextArea.Justification.LEFT); - } else if (sender == justifyCenter) { - basic.setJustification(RichTextArea.Justification.CENTER); - } else if (sender == justifyRight) { - basic.setJustification(RichTextArea.Justification.RIGHT); - } else if (sender == insertImage) { - String url = Window.prompt("Enter an image URL:", "http://"); - if (url != null) { - extended.insertImage(url); + if (extended != null) { + topPanel.add(strikethrough = createToggleButton(images + .strikeThrough(), strings.strikeThrough())); + topPanel.add(indent = createPushButton(images.indent(), strings + .indent())); + topPanel.add(outdent = createPushButton(images.outdent(), strings + .outdent())); + topPanel.add(hr = createPushButton(images.hr(), strings.hr())); + topPanel.add(ol = createPushButton(images.ol(), strings.ol())); + topPanel.add(ul = createPushButton(images.ul(), strings.ul())); + topPanel.add(insertImage = createPushButton(images.insertImage(), + strings.insertImage())); + topPanel.add(createLink = createPushButton(images.createLink(), + strings.createLink())); + topPanel.add(removeLink = createPushButton(images.removeLink(), + strings.removeLink())); + topPanel.add(removeFormat = createPushButton(images.removeFormat(), + strings.removeFormat())); } - } else if (sender == createLink) { - String url = Window.prompt("Enter a link URL:", "http://"); - if (url != null) { - extended.createLink(url); + + if (basic != null) { + bottomPanel.add(backColors = createColorList("Background")); + bottomPanel.add(foreColors = createColorList("Foreground")); + bottomPanel.add(fonts = createFontList()); + bottomPanel.add(fontSizes = createFontSizes()); + + // We only use these listeners for updating status, so don't hook + // them up + // unless at least basic editing is supported. + richText.addKeyboardListener(listener); + richText.addClickListener(listener); } - } else if (sender == removeLink) { - extended.removeLink(); - } else if (sender == hr) { - extended.insertHorizontalRule(); - } else if (sender == ol) { - extended.insertOrderedList(); - } else if (sender == ul) { - extended.insertUnorderedList(); - } else if (sender == removeFormat) { - extended.removeFormat(); - } else if (sender == richText) { - // We use the RichTextArea's onKeyUp event to update the toolbar status. - // This will catch any cases where the user moves the cursur using the - // keyboard, or uses one of the browser's built-in keyboard shortcuts. - updateStatus(); - } } - public void onKeyDown(Widget sender, char keyCode, int modifiers) { + private ListBox createColorList(String caption) { + ListBox lb = new ListBox(); + lb.addChangeListener(listener); + lb.setVisibleItemCount(1); + + lb.addItem(caption); + lb.addItem(strings.white(), "white"); + lb.addItem(strings.black(), "black"); + lb.addItem(strings.red(), "red"); + lb.addItem(strings.green(), "green"); + lb.addItem(strings.yellow(), "yellow"); + lb.addItem(strings.blue(), "blue"); + return lb; } - public void onKeyPress(Widget sender, char keyCode, int modifiers) { + private ListBox createFontList() { + ListBox lb = new ListBox(); + lb.addChangeListener(listener); + lb.setVisibleItemCount(1); + + lb.addItem(strings.font(), ""); + lb.addItem(strings.normal(), ""); + lb.addItem("Times New Roman", "Times New Roman"); + lb.addItem("Arial", "Arial"); + lb.addItem("Courier New", "Courier New"); + lb.addItem("Georgia", "Georgia"); + lb.addItem("Trebuchet", "Trebuchet"); + lb.addItem("Verdana", "Verdana"); + return lb; } - public void onKeyUp(Widget sender, char keyCode, int modifiers) { - if (sender == richText) { - // We use the RichTextArea's onKeyUp event to update the toolbar status. - // This will catch any cases where the user moves the cursur using the - // keyboard, or uses one of the browser's built-in keyboard shortcuts. - updateStatus(); - } - } - } - - private static final RichTextArea.FontSize[] fontSizesConstants = new RichTextArea.FontSize[] { - RichTextArea.FontSize.XX_SMALL, RichTextArea.FontSize.X_SMALL, - RichTextArea.FontSize.SMALL, RichTextArea.FontSize.MEDIUM, - RichTextArea.FontSize.LARGE, RichTextArea.FontSize.X_LARGE, - RichTextArea.FontSize.XX_LARGE}; - - private Images images = (Images) GWT.create(Images.class); - private Strings strings = (Strings) GWT.create(Strings.class); - private EventListener listener = new EventListener(); - - private RichTextArea richText; - private RichTextArea.BasicFormatter basic; - private RichTextArea.ExtendedFormatter extended; - - private VerticalPanel outer = new VerticalPanel(); - private HorizontalPanel topPanel = new HorizontalPanel(); - private HorizontalPanel bottomPanel = new HorizontalPanel(); - private ToggleButton bold; - private ToggleButton italic; - private ToggleButton underline; - private ToggleButton subscript; - private ToggleButton superscript; - private ToggleButton strikethrough; - private PushButton indent; - private PushButton outdent; - private PushButton justifyLeft; - private PushButton justifyCenter; - private PushButton justifyRight; - private PushButton hr; - private PushButton ol; - private PushButton ul; - private PushButton insertImage; - private PushButton createLink; - private PushButton removeLink; - private PushButton removeFormat; - - private ListBox backColors; - private ListBox foreColors; - private ListBox fonts; - private ListBox fontSizes; - - /** - * Creates a new toolbar that drives the given rich text area. - * - * @param richText the rich text area to be controlled - */ - public RichTextToolbar(RichTextArea richText) { - this.richText = richText; - this.basic = richText.getBasicFormatter(); - this.extended = richText.getExtendedFormatter(); - - outer.add(topPanel); - outer.add(bottomPanel); - topPanel.setWidth("100%"); - bottomPanel.setWidth("100%"); - - initWidget(outer); - setStyleName("gwt-RichTextToolbar"); - - if (basic != null) { - topPanel.add(bold = createToggleButton(images.bold(), strings.bold())); - topPanel.add(italic = createToggleButton(images.italic(), strings.italic())); - topPanel.add(underline = createToggleButton(images.underline(), - strings.underline())); - topPanel.add(subscript = createToggleButton(images.subscript(), - strings.subscript())); - topPanel.add(superscript = createToggleButton(images.superscript(), - strings.superscript())); - topPanel.add(justifyLeft = createPushButton(images.justifyLeft(), - strings.justifyLeft())); - topPanel.add(justifyCenter = createPushButton(images.justifyCenter(), - strings.justifyCenter())); - topPanel.add(justifyRight = createPushButton(images.justifyRight(), - strings.justifyRight())); + private ListBox createFontSizes() { + ListBox lb = new ListBox(); + lb.addChangeListener(listener); + lb.setVisibleItemCount(1); + + lb.addItem(strings.size()); + lb.addItem(strings.xxsmall()); + lb.addItem(strings.xsmall()); + lb.addItem(strings.small()); + lb.addItem(strings.medium()); + lb.addItem(strings.large()); + lb.addItem(strings.xlarge()); + lb.addItem(strings.xxlarge()); + return lb; } - if (extended != null) { - topPanel.add(strikethrough = createToggleButton(images.strikeThrough(), - strings.strikeThrough())); - topPanel.add(indent = createPushButton(images.indent(), strings.indent())); - topPanel.add(outdent = createPushButton(images.outdent(), strings.outdent())); - topPanel.add(hr = createPushButton(images.hr(), strings.hr())); - topPanel.add(ol = createPushButton(images.ol(), strings.ol())); - topPanel.add(ul = createPushButton(images.ul(), strings.ul())); - topPanel.add(insertImage = createPushButton(images.insertImage(), - strings.insertImage())); - topPanel.add(createLink = createPushButton(images.createLink(), - strings.createLink())); - topPanel.add(removeLink = createPushButton(images.removeLink(), - strings.removeLink())); - topPanel.add(removeFormat = createPushButton(images.removeFormat(), - strings.removeFormat())); + private PushButton createPushButton(AbstractImagePrototype img, String tip) { + PushButton pb = new PushButton(img.createImage()); + pb.addClickListener(listener); + pb.setTitle(tip); + return pb; } - if (basic != null) { - bottomPanel.add(backColors = createColorList("Background")); - bottomPanel.add(foreColors = createColorList("Foreground")); - bottomPanel.add(fonts = createFontList()); - bottomPanel.add(fontSizes = createFontSizes()); - - // We only use these listeners for updating status, so don't hook them up - // unless at least basic editing is supported. - richText.addKeyboardListener(listener); - richText.addClickListener(listener); - } - } - - private ListBox createColorList(String caption) { - ListBox lb = new ListBox(); - lb.addChangeListener(listener); - lb.setVisibleItemCount(1); - - lb.addItem(caption); - lb.addItem(strings.white(), "white"); - lb.addItem(strings.black(), "black"); - lb.addItem(strings.red(), "red"); - lb.addItem(strings.green(), "green"); - lb.addItem(strings.yellow(), "yellow"); - lb.addItem(strings.blue(), "blue"); - return lb; - } - - private ListBox createFontList() { - ListBox lb = new ListBox(); - lb.addChangeListener(listener); - lb.setVisibleItemCount(1); - - lb.addItem(strings.font(), ""); - lb.addItem(strings.normal(), ""); - lb.addItem("Times New Roman", "Times New Roman"); - lb.addItem("Arial", "Arial"); - lb.addItem("Courier New", "Courier New"); - lb.addItem("Georgia", "Georgia"); - lb.addItem("Trebuchet", "Trebuchet"); - lb.addItem("Verdana", "Verdana"); - return lb; - } - - private ListBox createFontSizes() { - ListBox lb = new ListBox(); - lb.addChangeListener(listener); - lb.setVisibleItemCount(1); - - lb.addItem(strings.size()); - lb.addItem(strings.xxsmall()); - lb.addItem(strings.xsmall()); - lb.addItem(strings.small()); - lb.addItem(strings.medium()); - lb.addItem(strings.large()); - lb.addItem(strings.xlarge()); - lb.addItem(strings.xxlarge()); - return lb; - } - - private PushButton createPushButton(AbstractImagePrototype img, String tip) { - PushButton pb = new PushButton(img.createImage()); - pb.addClickListener(listener); - pb.setTitle(tip); - return pb; - } - - private ToggleButton createToggleButton(AbstractImagePrototype img, String tip) { - ToggleButton tb = new ToggleButton(img.createImage()); - tb.addClickListener(listener); - tb.setTitle(tip); - return tb; - } - - /** - * Updates the status of all the stateful buttons. - */ - private void updateStatus() { - if (basic != null) { - bold.setDown(basic.isBold()); - italic.setDown(basic.isItalic()); - underline.setDown(basic.isUnderlined()); - subscript.setDown(basic.isSubscript()); - superscript.setDown(basic.isSuperscript()); + private ToggleButton createToggleButton(AbstractImagePrototype img, + String tip) { + ToggleButton tb = new ToggleButton(img.createImage()); + tb.addClickListener(listener); + tb.setTitle(tip); + return tb; } - if (extended != null) { - strikethrough.setDown(extended.isStrikethrough()); + /** + * Updates the status of all the stateful buttons. + */ + private void updateStatus() { + if (basic != null) { + bold.setDown(basic.isBold()); + italic.setDown(basic.isItalic()); + underline.setDown(basic.isUnderlined()); + subscript.setDown(basic.isSubscript()); + superscript.setDown(basic.isSuperscript()); + } + + if (extended != null) { + strikethrough.setDown(extended.isStrikethrough()); + } } - } } - diff --git a/src/com/itmill/toolkit/terminal/gwt/client/util/DateLocale.java b/src/com/itmill/toolkit/terminal/gwt/client/util/DateLocale.java index 43de47bfcd..43e40adfd0 100644 --- a/src/com/itmill/toolkit/terminal/gwt/client/util/DateLocale.java +++ b/src/com/itmill/toolkit/terminal/gwt/client/util/DateLocale.java @@ -11,76 +11,76 @@ import java.util.List; * */ public class DateLocale { - public final static String TOKEN_DAY_OF_WEEK = "E"; + public final static String TOKEN_DAY_OF_WEEK = "E"; - public final static String TOKEN_DAY_OF_MONTH = "d"; + public final static String TOKEN_DAY_OF_MONTH = "d"; - public final static String TOKEN_MONTH = "M"; + public final static String TOKEN_MONTH = "M"; - public final static String TOKEN_YEAR = "y"; + public final static String TOKEN_YEAR = "y"; - public final static String TOKEN_HOUR_12 = "h"; + public final static String TOKEN_HOUR_12 = "h"; - public final static String TOKEN_HOUR_24 = "H"; + public final static String TOKEN_HOUR_24 = "H"; - public final static String TOKEN_MINUTE = "m"; + public final static String TOKEN_MINUTE = "m"; - public final static String TOKEN_SECOND = "s"; + public final static String TOKEN_SECOND = "s"; - public final static String TOKEN_MILLISECOND = "S"; + public final static String TOKEN_MILLISECOND = "S"; - public final static String TOKEN_AM_PM = "a"; + public final static String TOKEN_AM_PM = "a"; - public final static String AM = "AM"; + public final static String AM = "AM"; - public final static String PM = "PM"; + public final static String PM = "PM"; - public static List SUPPORTED_DF_TOKENS = Arrays.asList(new String[] { - TOKEN_DAY_OF_WEEK, TOKEN_DAY_OF_MONTH, TOKEN_MONTH, TOKEN_YEAR, - TOKEN_HOUR_12, TOKEN_HOUR_24, TOKEN_MINUTE, TOKEN_SECOND, - TOKEN_AM_PM }); + public static List SUPPORTED_DF_TOKENS = Arrays.asList(new String[] { + TOKEN_DAY_OF_WEEK, TOKEN_DAY_OF_MONTH, TOKEN_MONTH, TOKEN_YEAR, + TOKEN_HOUR_12, TOKEN_HOUR_24, TOKEN_MINUTE, TOKEN_SECOND, + TOKEN_AM_PM }); - public static List TOKENS_RESOLUTION_ALL = Arrays.asList(new String[] { - TOKEN_DAY_OF_WEEK, TOKEN_DAY_OF_MONTH, TOKEN_MONTH, TOKEN_YEAR, - TOKEN_HOUR_12, TOKEN_HOUR_24, TOKEN_MINUTE, TOKEN_SECOND, - TOKEN_AM_PM }); + public static List TOKENS_RESOLUTION_ALL = Arrays.asList(new String[] { + TOKEN_DAY_OF_WEEK, TOKEN_DAY_OF_MONTH, TOKEN_MONTH, TOKEN_YEAR, + TOKEN_HOUR_12, TOKEN_HOUR_24, TOKEN_MINUTE, TOKEN_SECOND, + TOKEN_AM_PM }); - public static List TOKENS_RESOLUTION_YEAR = Arrays - .asList(new String[] { TOKEN_YEAR }); + public static List TOKENS_RESOLUTION_YEAR = Arrays + .asList(new String[] { TOKEN_YEAR }); - public static List TOKENS_RESOLUTION_MONTH = Arrays.asList(new String[] { - TOKEN_YEAR, TOKEN_MONTH }); + public static List TOKENS_RESOLUTION_MONTH = Arrays.asList(new String[] { + TOKEN_YEAR, TOKEN_MONTH }); - public static List TOKENS_RESOLUTION_DAY = Arrays.asList(new String[] { - TOKEN_YEAR, TOKEN_MONTH, TOKEN_DAY_OF_MONTH }); + public static List TOKENS_RESOLUTION_DAY = Arrays.asList(new String[] { + TOKEN_YEAR, TOKEN_MONTH, TOKEN_DAY_OF_MONTH }); - public String[] MONTH_LONG = { "January", "February", "March", "April", - "May", "June", "July", "August", "September", "October", - "November", "December" }; + public String[] MONTH_LONG = { "January", "February", "March", "April", + "May", "June", "July", "August", "September", "October", + "November", "December" }; - public String[] MONTH_SHORT = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", - "Jul", "Aug", "Sept", "Oct", "Nov", "Dec" }; + public String[] MONTH_SHORT = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", + "Jul", "Aug", "Sept", "Oct", "Nov", "Dec" }; - public String[] WEEKDAY_LONG = { "Sunday", "Monday", "Tuesday", - "Wednesday", "Thursday", "Friday", "Saturday" }; + public String[] WEEKDAY_LONG = { "Sunday", "Monday", "Tuesday", + "Wednesday", "Thursday", "Friday", "Saturday" }; - public String[] WEEKDAY_SHORT = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", - "Sat" }; + public String[] WEEKDAY_SHORT = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", + "Sat" }; - public static String getAM() { - return AM; - } + public static String getAM() { + return AM; + } - public static String getPM() { - return PM; - } + public static String getPM() { + return PM; + } - public String[] getWEEKDAY_LONG() { - return WEEKDAY_LONG; - } + public String[] getWEEKDAY_LONG() { + return WEEKDAY_LONG; + } - public String[] getWEEKDAY_SHORT() { - return WEEKDAY_SHORT; - } + public String[] getWEEKDAY_SHORT() { + return WEEKDAY_SHORT; + } } diff --git a/src/com/itmill/toolkit/terminal/gwt/client/util/Pattern.java b/src/com/itmill/toolkit/terminal/gwt/client/util/Pattern.java index f82365b211..55a24cb5d0 100644 --- a/src/com/itmill/toolkit/terminal/gwt/client/util/Pattern.java +++ b/src/com/itmill/toolkit/terminal/gwt/client/util/Pattern.java @@ -31,8 +31,8 @@ import com.google.gwt.core.client.JavaScriptObject; *

*

* Please note that neither the {@link java.util.regex.Pattern#compile(String)} - * method nor {@link Matcher} instances are supported. For the later, consider - * using {@link Pattern#match(String)}. + * method nor {@link java.util.regex.Matcher} instances are supported. For the + * later, consider using {@link Pattern#match(String)}. *

* * @author George Georgovassilis @@ -40,152 +40,156 @@ import com.google.gwt.core.client.JavaScriptObject; */ public class Pattern { - /** - * Declares that regular expressions should be matched across line borders. - */ - public final static int MULTILINE = 1; - - /** - * Declares that characters are matched reglardless of case. - */ - public final static int CASE_INSENSITIVE = 2; - - private JavaScriptObject regExp; - - private static JavaScriptObject createExpression(String pattern, int flags) { - String sFlags = ""; - if ((flags & MULTILINE) != 0) - sFlags += "m"; - if ((flags & CASE_INSENSITIVE) != 0) - sFlags += "i"; - return _createExpression(pattern, sFlags); - } - - private static native JavaScriptObject _createExpression(String pattern, - String flags)/*-{ - return new RegExp(pattern, flags); - }-*/; - - private native void _match(String text, List matches)/*-{ - var regExp = this.@com.itmill.toolkit.terminal.gwt.client.util.Pattern::regExp; - var result = text.match(regExp); - if (result == null) return; - for (var i=0;itrue
if matched. - */ - public static boolean matches(String regex, String input) { - return new Pattern(regex).matches(input); - } - - /** - * Escape a provided string so that it will be interpreted as a literal in - * regular expressions. The current implementation does escape each - * character even if not neccessary, generating verbose literals. - * - * @param input - * @return - */ - public static String quote(String input) { - String output = ""; - for (int i = 0; i < input.length(); i++) { - output += "\\" + input.charAt(i); - } - return output; - } - - /** - * Class constructor - * - * @param pattern - * Regular expression - */ - public Pattern(String pattern) { - this(pattern, 0); - } - - /** - * Class constructor - * - * @param pattern - * Regular expression - * @param flags - */ - public Pattern(String pattern, int flags) { - regExp = createExpression(pattern, flags); - } - - /** - * This method is borrowed from the JavaScript RegExp object. It parses a - * string and returns as an array any assignments to parenthesis groups in - * the pattern's regular expression - * - * @param text - * @return Array of strings following java's Pattern convention for groups: - * Group 0 is the entire input string and the remaining groups are - * the matched parenthesis. In case nothing was matched an empty - * array is returned. - */ - public String[] match(String text) { - List matches = new ArrayList(); - _match(text, matches); - String arr[] = new String[matches.size()]; - for (int i = 0; i < matches.size(); i++) - arr[i] = matches.get(i).toString(); - return arr; - } - - /** - * Determines wether a provided text matches the regular expression - * - * @param text - * @return - */ - public native boolean matches(String text)/*-{ - var regExp = this.@com.itmill.toolkit.terminal.gwt.client.util.Pattern::regExp; - return regExp.test(text); - }-*/; - - /** - * Returns the regular expression for this pattern - * - * @return - */ - public native String pattern()/*-{ - var regExp = this.@com.itmill.toolkit.terminal.gwt.client.util.Pattern::regExp; - return regExp.source; - }-*/; - - private native void _split(String input, List results)/*-{ - var regExp = this.@com.itmill.toolkit.terminal.gwt.client.util.Pattern::regExp; - var parts = input.split(regExp); - for (var i=0;itrue
if matched. + */ + public static boolean matches(String regex, String input) { + return new Pattern(regex).matches(input); + } + + /** + * Escape a provided string so that it will be interpreted as a literal in + * regular expressions. The current implementation does escape each + * character even if not neccessary, generating verbose literals. + * + * @param input + * @return + */ + public static String quote(String input) { + String output = ""; + for (int i = 0; i < input.length(); i++) { + output += "\\" + input.charAt(i); + } + return output; + } + + /** + * Class constructor + * + * @param pattern + * Regular expression + */ + public Pattern(String pattern) { + this(pattern, 0); + } + + /** + * Class constructor + * + * @param pattern + * Regular expression + * @param flags + */ + public Pattern(String pattern, int flags) { + regExp = createExpression(pattern, flags); + } + + /** + * This method is borrowed from the JavaScript RegExp object. It parses a + * string and returns as an array any assignments to parenthesis groups in + * the pattern's regular expression + * + * @param text + * @return Array of strings following java's Pattern convention for groups: + * Group 0 is the entire input string and the remaining groups are + * the matched parenthesis. In case nothing was matched an empty + * array is returned. + */ + public String[] match(String text) { + List matches = new ArrayList(); + _match(text, matches); + String arr[] = new String[matches.size()]; + for (int i = 0; i < matches.size(); i++) { + arr[i] = matches.get(i).toString(); + } + return arr; + } + + /** + * Determines wether a provided text matches the regular expression + * + * @param text + * @return + */ + public native boolean matches(String text)/*-{ + var regExp = this.@com.itmill.toolkit.terminal.gwt.client.util.Pattern::regExp; + return regExp.test(text); + }-*/; + + /** + * Returns the regular expression for this pattern + * + * @return + */ + public native String pattern()/*-{ + var regExp = this.@com.itmill.toolkit.terminal.gwt.client.util.Pattern::regExp; + return regExp.source; + }-*/; + + private native void _split(String input, List results)/*-{ + var regExp = this.@com.itmill.toolkit.terminal.gwt.client.util.Pattern::regExp; + var parts = input.split(regExp); + for (var i=0;i 0) { - String lastTokenType = null; - String currentToken = ""; - for (int i = 0; i < format.length(); i++) { - String thisChar = format.substring(i, i + 1); - String currentTokenType = DateLocale.SUPPORTED_DF_TOKENS - .contains(thisChar) ? thisChar : ""; - if (currentTokenType.equals(lastTokenType) || i == 0) { - currentToken += thisChar; - lastTokenType = currentTokenType; - } else { - if ("".equals(lastTokenType)) - f += currentToken; - else - f += handleToken(currentToken, date); - currentToken = thisChar; - lastTokenType = currentTokenType; - } - } - if ("".equals(lastTokenType)) - f += currentToken; - else - f += handleToken(currentToken, date); - } - return f; - } + public String format(Date date) { + String f = ""; + if (format != null && format.length() > 0) { + String lastTokenType = null; + String currentToken = ""; + for (int i = 0; i < format.length(); i++) { + String thisChar = format.substring(i, i + 1); + String currentTokenType = DateLocale.SUPPORTED_DF_TOKENS + .contains(thisChar) ? thisChar : ""; + if (currentTokenType.equals(lastTokenType) || i == 0) { + currentToken += thisChar; + lastTokenType = currentTokenType; + } else { + if ("".equals(lastTokenType)) { + f += currentToken; + } else { + f += handleToken(currentToken, date); + } + currentToken = thisChar; + lastTokenType = currentTokenType; + } + } + if ("".equals(lastTokenType)) { + f += currentToken; + } else { + f += handleToken(currentToken, date); + } + } + return f; + } - /** - * takes a date format string and returns the formatted portion of the date. - * For instance if the token is MMMM then the full month name is returned. - * - * @param token - * date format token - * @param date - * date to format - * @return formatted portion of the date - */ - private String handleToken(String token, Date date) { - String response = token; - String tc = token.substring(0, 1); - if (DateLocale.TOKEN_DAY_OF_WEEK.equals(tc)) { - if (token.length() > 3) - response = locale.getWEEKDAY_LONG()[date.getDay()]; - else - response = locale.getWEEKDAY_SHORT()[date.getDay()]; - } else if (DateLocale.TOKEN_DAY_OF_MONTH.equals(tc)) { - if (token.length() == 1) - response = Integer.toString(date.getDate()); - else - response = twoCharDateField(date.getDate()); - } else if (DateLocale.TOKEN_MONTH.equals(tc)) { - switch (token.length()) { - case 1: - response = Integer.toString(date.getMonth() + 1); - break; - case 2: - response = twoCharDateField(date.getMonth() + 1); - break; - case 3: - response = locale.MONTH_SHORT[date.getMonth()]; - break; - default: - response = locale.MONTH_LONG[date.getMonth()]; - break; - } - } else if (DateLocale.TOKEN_YEAR.equals(tc)) { - if (token.length() >= 2) - response = Integer.toString(date.getYear() + 1900); - else - response = twoCharDateField(date.getYear()); - } else if (DateLocale.TOKEN_HOUR_12.equals(tc)) { - int h = date.getHours(); - if (h == 0) - h = 12; - else if (h > 12) - h -= 12; - // if (token.length() > 1) - response = twoCharDateField(h); - // else - // response = Integer.toString(h); - } else if (DateLocale.TOKEN_HOUR_24.equals(tc)) { - // if (token.length() > 1) - response = twoCharDateField(date.getHours()); - // else - // response = Integer.toString(date.getHours()); - } else if (DateLocale.TOKEN_MINUTE.equals(tc)) { - // if (token.length() > 1) - response = twoCharDateField(date.getMinutes()); - // else - // response = Integer.toString(date.getMinutes()); - } else if (DateLocale.TOKEN_SECOND.equals(tc)) { - // if (token.length() > 1) - response = twoCharDateField(date.getSeconds()); - // else - // response = Integer.toString(date.getSeconds()); - } else if (DateLocale.TOKEN_AM_PM.equals(tc)) { - int hour = date.getHours(); - if (hour > 11) - response = DateLocale.getPM(); - else - response = DateLocale.getAM(); - } - return response; - } + /** + * takes a date format string and returns the formatted portion of the date. + * For instance if the token is MMMM then the full month name is returned. + * + * @param token + * date format token + * @param date + * date to format + * @return formatted portion of the date + */ + private String handleToken(String token, Date date) { + String response = token; + String tc = token.substring(0, 1); + if (DateLocale.TOKEN_DAY_OF_WEEK.equals(tc)) { + if (token.length() > 3) { + response = locale.getWEEKDAY_LONG()[date.getDay()]; + } else { + response = locale.getWEEKDAY_SHORT()[date.getDay()]; + } + } else if (DateLocale.TOKEN_DAY_OF_MONTH.equals(tc)) { + if (token.length() == 1) { + response = Integer.toString(date.getDate()); + } else { + response = twoCharDateField(date.getDate()); + } + } else if (DateLocale.TOKEN_MONTH.equals(tc)) { + switch (token.length()) { + case 1: + response = Integer.toString(date.getMonth() + 1); + break; + case 2: + response = twoCharDateField(date.getMonth() + 1); + break; + case 3: + response = locale.MONTH_SHORT[date.getMonth()]; + break; + default: + response = locale.MONTH_LONG[date.getMonth()]; + break; + } + } else if (DateLocale.TOKEN_YEAR.equals(tc)) { + if (token.length() >= 2) { + response = Integer.toString(date.getYear() + 1900); + } else { + response = twoCharDateField(date.getYear()); + } + } else if (DateLocale.TOKEN_HOUR_12.equals(tc)) { + int h = date.getHours(); + if (h == 0) { + h = 12; + } else if (h > 12) { + h -= 12; + } + // if (token.length() > 1) + response = twoCharDateField(h); + // else + // response = Integer.toString(h); + } else if (DateLocale.TOKEN_HOUR_24.equals(tc)) { + // if (token.length() > 1) + response = twoCharDateField(date.getHours()); + // else + // response = Integer.toString(date.getHours()); + } else if (DateLocale.TOKEN_MINUTE.equals(tc)) { + // if (token.length() > 1) + response = twoCharDateField(date.getMinutes()); + // else + // response = Integer.toString(date.getMinutes()); + } else if (DateLocale.TOKEN_SECOND.equals(tc)) { + // if (token.length() > 1) + response = twoCharDateField(date.getSeconds()); + // else + // response = Integer.toString(date.getSeconds()); + } else if (DateLocale.TOKEN_AM_PM.equals(tc)) { + int hour = date.getHours(); + if (hour > 11) { + response = DateLocale.getPM(); + } else { + response = DateLocale.getAM(); + } + } + return response; + } - /** - * This is basically just a sneaky way to guarantee that our 1 or 2 digit - * numbers come out as a 2 character string. we add an arbitrary number - * larger than 100, convert this new number to a string, then take the right - * most 2 characters. - * - * @param num - * @return - */ - private String twoCharDateField(int num) { - String res = Integer.toString(num + 1900); - res = res.substring(res.length() - 2); - return res; - } + /** + * This is basically just a sneaky way to guarantee that our 1 or 2 digit + * numbers come out as a 2 character string. we add an arbitrary number + * larger than 100, convert this new number to a string, then take the right + * most 2 characters. + * + * @param num + * @return + */ + private String twoCharDateField(int num) { + String res = Integer.toString(num + 1900); + res = res.substring(res.length() - 2); + return res; + } - private static Date newDate(long time) { - return new Date(time); - } + private static Date newDate(long time) { + return new Date(time); + } - /** - * Parses text and returns the corresponding date object. - * - * @param source - * @return java.util.Date - */ - public Date parse(String source) { - return SimpleDateParser.parse(source, format); - }; + /** + * Parses text and returns the corresponding date object. + * + * @param source + * @return java.util.Date + */ + public Date parse(String source) { + return SimpleDateParser.parse(source, format); + }; } diff --git a/src/com/itmill/toolkit/terminal/gwt/client/util/SimpleDateParser.java b/src/com/itmill/toolkit/terminal/gwt/client/util/SimpleDateParser.java index 1ff5d5c458..9e1e316045 100644 --- a/src/com/itmill/toolkit/terminal/gwt/client/util/SimpleDateParser.java +++ b/src/com/itmill/toolkit/terminal/gwt/client/util/SimpleDateParser.java @@ -16,152 +16,158 @@ import java.util.Date; public class SimpleDateParser { - private final static String DAY_IN_MONTH = "d"; - - private final static String MONTH = "M"; - - private final static String YEAR = "y"; - - private final static String LITERAL = "\\"; - - private final static int DATE_PATTERN = 0; - - private final static int REGEX_PATTERN = 1; - - private final static int COMPONENT = 2; - - private final static int REGEX = 0; - - private final static int INSTRUCTION = 1; - - private final static String[] TOKENS[] = { - { "SSSS", "(\\d\\d\\d\\d)", DateLocale.TOKEN_MILLISECOND }, - { "SSS", "(\\d\\d\\d)", DateLocale.TOKEN_MILLISECOND }, - { "SS", "(\\d\\d)", DateLocale.TOKEN_MILLISECOND }, - { "S", "(\\d)", DateLocale.TOKEN_MILLISECOND }, - { "ss", "(\\d\\d)", DateLocale.TOKEN_SECOND }, - { "s", "(\\d\\d)", DateLocale.TOKEN_SECOND }, - { "mm", "(\\d\\d)", DateLocale.TOKEN_MINUTE }, - { "m", "(\\d\\d)", DateLocale.TOKEN_MINUTE }, - { "HH", "(\\d\\d)", DateLocale.TOKEN_HOUR_24 }, - { "H", "(\\d{1,2})", DateLocale.TOKEN_HOUR_24 }, - { "hh", "(\\d\\d)", DateLocale.TOKEN_HOUR_12 }, - { "h", "(\\d{1,2})", DateLocale.TOKEN_HOUR_12 }, - { "dd", "(\\d\\d)", DateLocale.TOKEN_DAY_OF_MONTH }, - { "d", "(\\d{1,2})", DateLocale.TOKEN_DAY_OF_MONTH }, - { "MM", "(\\d\\d)", DateLocale.TOKEN_MONTH }, - { "M", "(\\d{1,2})", DateLocale.TOKEN_MONTH }, - { "yyyy", "(\\d\\d\\d\\d)", DateLocale.TOKEN_YEAR }, - { "yyy", "(\\d\\d\\d\\d)", DateLocale.TOKEN_YEAR }, - { "yy", "(\\d\\d\\d\\d)", DateLocale.TOKEN_YEAR }, - { "y", "(\\d{1,2})", DateLocale.TOKEN_YEAR }, - { "a", "(\\S{1,4})", DateLocale.TOKEN_AM_PM } }; - - private Pattern regularExpression; - - private String instructions = ""; - - private static void _parse(String format, String[] args) { - if (format.length() == 0) - return; - if (format.startsWith("'")) { - format = format.substring(1); - int end = format.indexOf("'"); - if (end == -1) - throw new IllegalArgumentException("Unmatched single quotes."); - args[REGEX] += Pattern.quote(format.substring(0, end)); - format = format.substring(end + 1); - } - for (int i = 0; i < TOKENS.length; i++) { - String[] row = TOKENS[i]; - String datePattern = row[DATE_PATTERN]; - if (!format.startsWith(datePattern)) - continue; - format = format.substring(datePattern.length()); - args[REGEX] += row[REGEX_PATTERN]; - args[INSTRUCTION] += row[COMPONENT]; - _parse(format, args); - return; - } - args[REGEX] += Pattern.quote("" + format.charAt(0)); - format = format.substring(1); - _parse(format, args); - } - - private static void load(Date date, String text, String component, - String input, Pattern regex) { - if (component.equals(DateLocale.TOKEN_MILLISECOND)) { - date.setTime(date.getTime() / 1000 * 1000 + Integer.parseInt(text)); - } - - if (component.equals(DateLocale.TOKEN_SECOND)) { - date.setSeconds(Integer.parseInt(text)); - } - - if (component.equals(DateLocale.TOKEN_MINUTE)) { - date.setMinutes(Integer.parseInt(text)); - } - - if (component.equals(DateLocale.TOKEN_HOUR_24)) { - date.setHours(Integer.parseInt(text)); - } - - if (component.equals(DateLocale.TOKEN_HOUR_12)) { - int h = Integer.parseInt(text); - String token = com.itmill.toolkit.terminal.gwt.client.DateLocale - .getPM(); - String which = input.substring(input.length() - token.length()); // Assumes - // both - // AM - // and - // PM - // tokens - // have - // same - // length - if (which.equalsIgnoreCase(token)) - h += 12; - date.setHours(h); - } - - if (component.equals(DateLocale.TOKEN_DAY_OF_MONTH)) { - date.setDate(Integer.parseInt(text)); - } - if (component.equals(DateLocale.TOKEN_MONTH)) { - date.setMonth(Integer.parseInt(text) - 1); - } - if (component.equals(DateLocale.TOKEN_YEAR)) { - // TODO: fix for short patterns - date.setYear(Integer.parseInt(text) - 1900); - } - - } - - public SimpleDateParser(String format) { - String[] args = new String[] { "", "" }; - _parse(format, args); - regularExpression = new Pattern(args[REGEX]); - instructions = args[INSTRUCTION]; - } - - public Date parse(String input) { - Date date = new Date(0, 0, 0, 0, 0, 0); - String matches[] = regularExpression.match(input); - if (matches == null) - throw new IllegalArgumentException(input + " does not match " - + regularExpression.pattern()); - if (matches.length - 1 != instructions.length()) - throw new IllegalArgumentException("Different group count - " - + input + " does not match " + regularExpression.pattern()); - for (int group = 0; group < instructions.length(); group++) { - String match = matches[group + 1]; - load(date, match, "" + instructions.charAt(group), input, - regularExpression); - } - return date; - } - - public static Date parse(String input, String pattern) { - return new SimpleDateParser(pattern).parse(input); - } + private final static String DAY_IN_MONTH = "d"; + + private final static String MONTH = "M"; + + private final static String YEAR = "y"; + + private final static String LITERAL = "\\"; + + private final static int DATE_PATTERN = 0; + + private final static int REGEX_PATTERN = 1; + + private final static int COMPONENT = 2; + + private final static int REGEX = 0; + + private final static int INSTRUCTION = 1; + + private final static String[] TOKENS[] = { + { "SSSS", "(\\d\\d\\d\\d)", DateLocale.TOKEN_MILLISECOND }, + { "SSS", "(\\d\\d\\d)", DateLocale.TOKEN_MILLISECOND }, + { "SS", "(\\d\\d)", DateLocale.TOKEN_MILLISECOND }, + { "S", "(\\d)", DateLocale.TOKEN_MILLISECOND }, + { "ss", "(\\d\\d)", DateLocale.TOKEN_SECOND }, + { "s", "(\\d\\d)", DateLocale.TOKEN_SECOND }, + { "mm", "(\\d\\d)", DateLocale.TOKEN_MINUTE }, + { "m", "(\\d\\d)", DateLocale.TOKEN_MINUTE }, + { "HH", "(\\d\\d)", DateLocale.TOKEN_HOUR_24 }, + { "H", "(\\d{1,2})", DateLocale.TOKEN_HOUR_24 }, + { "hh", "(\\d\\d)", DateLocale.TOKEN_HOUR_12 }, + { "h", "(\\d{1,2})", DateLocale.TOKEN_HOUR_12 }, + { "dd", "(\\d\\d)", DateLocale.TOKEN_DAY_OF_MONTH }, + { "d", "(\\d{1,2})", DateLocale.TOKEN_DAY_OF_MONTH }, + { "MM", "(\\d\\d)", DateLocale.TOKEN_MONTH }, + { "M", "(\\d{1,2})", DateLocale.TOKEN_MONTH }, + { "yyyy", "(\\d\\d\\d\\d)", DateLocale.TOKEN_YEAR }, + { "yyy", "(\\d\\d\\d\\d)", DateLocale.TOKEN_YEAR }, + { "yy", "(\\d\\d\\d\\d)", DateLocale.TOKEN_YEAR }, + { "y", "(\\d{1,2})", DateLocale.TOKEN_YEAR }, + { "a", "(\\S{1,4})", DateLocale.TOKEN_AM_PM } }; + + private Pattern regularExpression; + + private String instructions = ""; + + private static void _parse(String format, String[] args) { + if (format.length() == 0) { + return; + } + if (format.startsWith("'")) { + format = format.substring(1); + int end = format.indexOf("'"); + if (end == -1) { + throw new IllegalArgumentException("Unmatched single quotes."); + } + args[REGEX] += Pattern.quote(format.substring(0, end)); + format = format.substring(end + 1); + } + for (int i = 0; i < TOKENS.length; i++) { + String[] row = TOKENS[i]; + String datePattern = row[DATE_PATTERN]; + if (!format.startsWith(datePattern)) { + continue; + } + format = format.substring(datePattern.length()); + args[REGEX] += row[REGEX_PATTERN]; + args[INSTRUCTION] += row[COMPONENT]; + _parse(format, args); + return; + } + args[REGEX] += Pattern.quote("" + format.charAt(0)); + format = format.substring(1); + _parse(format, args); + } + + private static void load(Date date, String text, String component, + String input, Pattern regex) { + if (component.equals(DateLocale.TOKEN_MILLISECOND)) { + date.setTime(date.getTime() / 1000 * 1000 + Integer.parseInt(text)); + } + + if (component.equals(DateLocale.TOKEN_SECOND)) { + date.setSeconds(Integer.parseInt(text)); + } + + if (component.equals(DateLocale.TOKEN_MINUTE)) { + date.setMinutes(Integer.parseInt(text)); + } + + if (component.equals(DateLocale.TOKEN_HOUR_24)) { + date.setHours(Integer.parseInt(text)); + } + + if (component.equals(DateLocale.TOKEN_HOUR_12)) { + int h = Integer.parseInt(text); + String token = com.itmill.toolkit.terminal.gwt.client.DateLocale + .getPM(); + String which = input.substring(input.length() - token.length()); // Assumes + // both + // AM + // and + // PM + // tokens + // have + // same + // length + if (which.equalsIgnoreCase(token)) { + h += 12; + } + date.setHours(h); + } + + if (component.equals(DateLocale.TOKEN_DAY_OF_MONTH)) { + date.setDate(Integer.parseInt(text)); + } + if (component.equals(DateLocale.TOKEN_MONTH)) { + date.setMonth(Integer.parseInt(text) - 1); + } + if (component.equals(DateLocale.TOKEN_YEAR)) { + // TODO: fix for short patterns + date.setYear(Integer.parseInt(text) - 1900); + } + + } + + public SimpleDateParser(String format) { + String[] args = new String[] { "", "" }; + _parse(format, args); + regularExpression = new Pattern(args[REGEX]); + instructions = args[INSTRUCTION]; + } + + public Date parse(String input) { + Date date = new Date(0, 0, 0, 0, 0, 0); + String matches[] = regularExpression.match(input); + if (matches == null) { + throw new IllegalArgumentException(input + " does not match " + + regularExpression.pattern()); + } + if (matches.length - 1 != instructions.length()) { + throw new IllegalArgumentException("Different group count - " + + input + " does not match " + regularExpression.pattern()); + } + for (int group = 0; group < instructions.length(); group++) { + String match = matches[group + 1]; + load(date, match, "" + instructions.charAt(group), input, + regularExpression); + } + return date; + } + + public static Date parse(String input, String pattern) { + return new SimpleDateParser(pattern).parse(input); + } } diff --git a/src/com/itmill/toolkit/terminal/gwt/server/CommunicationManager.java b/src/com/itmill/toolkit/terminal/gwt/server/CommunicationManager.java index 5dc6168ff1..fd0f89506d 100644 --- a/src/com/itmill/toolkit/terminal/gwt/server/CommunicationManager.java +++ b/src/com/itmill/toolkit/terminal/gwt/server/CommunicationManager.java @@ -59,16 +59,14 @@ import javax.servlet.ServletOutputStream; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; -// wrapped to prevent conflicts with possible developer required Apache JARs +import com.itmill.toolkit.Application; +import com.itmill.toolkit.Application.WindowAttachEvent; +import com.itmill.toolkit.Application.WindowDetachEvent; import com.itmill.toolkit.external.org.apache.commons.fileupload.FileItemIterator; import com.itmill.toolkit.external.org.apache.commons.fileupload.FileItemStream; import com.itmill.toolkit.external.org.apache.commons.fileupload.FileUploadException; import com.itmill.toolkit.external.org.apache.commons.fileupload.ProgressListener; import com.itmill.toolkit.external.org.apache.commons.fileupload.servlet.ServletFileUpload; - -import com.itmill.toolkit.Application; -import com.itmill.toolkit.Application.WindowAttachEvent; -import com.itmill.toolkit.Application.WindowDetachEvent; import com.itmill.toolkit.terminal.DownloadStream; import com.itmill.toolkit.terminal.Paintable; import com.itmill.toolkit.terminal.URIHandler; @@ -89,1035 +87,1055 @@ import com.itmill.toolkit.ui.Window; * @since 5.0 */ public class CommunicationManager implements Paintable.RepaintRequestListener, - Application.WindowAttachListener, Application.WindowDetachListener { - - private static String GET_PARAM_REPAINT_ALL = "repaintAll"; - - private static int DEFAULT_BUFFER_SIZE = 32 * 1024; - - private static int MAX_BUFFER_SIZE = 64 * 1024; - - private HashSet dirtyPaintabletSet = new HashSet(); - - private WeakHashMap paintableIdMap = new WeakHashMap(); - - private WeakHashMap idPaintableMap = new WeakHashMap(); - - private int idSequence = 0; - - private Application application; - - private Set removedWindows = new HashSet(); - - private JsonPaintTarget paintTarget; - - private List locales; - - private int pendingLocalesIndex; - - private ApplicationServlet applicationServlet; - - public CommunicationManager(Application application, - ApplicationServlet applicationServlet) { - this.application = application; - this.applicationServlet = applicationServlet; - requireLocale(application.getLocale().toString()); - } - - /** - * - * - */ - public void takeControl() { - application.addListener((Application.WindowAttachListener) this); - application.addListener((Application.WindowDetachListener) this); - - } - - /** - * - * - */ - public void releaseControl() { - application.removeListener((Application.WindowAttachListener) this); - application.removeListener((Application.WindowDetachListener) this); - } - - /** - * Handles file upload request submitted via Upload component. - * - * @param request - * @param response - * @throws IOException - */ - public void handleFileUpload(HttpServletRequest request, - HttpServletResponse response) throws IOException { - // Create a new file upload handler - ServletFileUpload upload = new ServletFileUpload(); - - UploadProgressListener pl = new UploadProgressListener(); - - upload.setProgressListener(pl); - - // Parse the request - FileItemIterator iter; - - try { - iter = upload.getItemIterator(request); - /* - * ATM this loop is run only once as we are uploading one file per - * request. - */ - while (iter.hasNext()) { - FileItemStream item = iter.next(); - String name = item.getFieldName(); - final String filename = item.getName(); - final String mimeType = item.getContentType(); - final InputStream stream = item.openStream(); - if (item.isFormField()) { - // ignored, upload requests contian only files - } else { - String pid = name.split("_")[0]; - Upload uploadComponent = (Upload) idPaintableMap.get(pid); - if (uploadComponent == null) { - throw new FileUploadException( - "Upload component not found"); - } - synchronized (application) { - // put upload component into receiving state - uploadComponent.startUpload(); - } - UploadStream upstream = new UploadStream() { - - public String getContentName() { - return filename; - } - - public String getContentType() { - return mimeType; - } - - public InputStream getStream() { - return stream; - } - - public String getStreamName() { - return "stream"; - } - - }; - - // tell UploadProgressListener which component is receiving - // file - pl.setUpload(uploadComponent); - - uploadComponent.receiveUpload(upstream); - } - } - } catch (FileUploadException e) { - e.printStackTrace(); - } - - // Send short response to acknowledge client that request was done - response.setContentType("text/html"); - OutputStream out = response.getOutputStream(); - PrintWriter outWriter = new PrintWriter(new BufferedWriter( - new OutputStreamWriter(out, "UTF-8"))); - outWriter.print("download handled"); - outWriter.flush(); - out.close(); - } - - /** - * Handles UIDL request - * - * @param request - * @param response - * @throws IOException - */ - public void handleUidlRequest(HttpServletRequest request, - HttpServletResponse response) throws IOException { - - // repaint requested or session has timed out and new one is created - boolean repaintAll = (request.getParameter(GET_PARAM_REPAINT_ALL) != null) - || request.getSession().isNew(); - - // If repaint is requested, clean all ids - if (repaintAll) { - idPaintableMap.clear(); - paintableIdMap.clear(); - } - - OutputStream out = response.getOutputStream(); - PrintWriter outWriter = new PrintWriter(new BufferedWriter( - new OutputStreamWriter(out, "UTF-8"))); - - try { - - // Is this a download request from application - DownloadStream download = null; - - // The rest of the process is synchronized with the application - // in order to guarantee that no parallel variable handling is - // made - synchronized (application) { - - // Change all variables based on request parameters - handleVariables(request, application); - - // If this is not a download request - if (download == null) { - - // Finds the window within the application - Window window = null; - if (application.isRunning()) - window = getApplicationWindow(request, application); - - // Removes application if it has stopped - if (!application.isRunning()) { - endApplication(request, response, application); - return; - } - - // Returns if no window found - if (window == null) - return; - - // Sets the response type - response.setContentType("application/json; charset=UTF-8"); - // some dirt to prevent cross site scripting - outWriter.print(")/*{"); - - outWriter.print("\"changes\":["); - - paintTarget = new JsonPaintTarget(this, outWriter, - !repaintAll); - - // Paints components - Set paintables; - if (repaintAll) { - paintables = new LinkedHashSet(); - paintables.add(window); - - // Reset sent locales - locales = null; - requireLocale(application.getLocale().toString()); - - } else - paintables = getDirtyComponents(); - if (paintables != null) { - - // Creates "working copy" of the current state. - List currentPaintables = new ArrayList(paintables); - - // Sorts the paintable so that parent windows - // are always painted before child windows - Collections.sort(currentPaintables, new Comparator() { - - public int compare(Object o1, Object o2) { - - // If first argumement is now window - // the second is "smaller" if it is. - if (!(o1 instanceof Window)) { - return (o2 instanceof Window) ? 1 : 0; - } - - // Now, if second is not window the - // first is smaller. - if (!(o2 instanceof Window)) { - return -1; - } - - return 0; - } - }); - - for (Iterator i = currentPaintables.iterator(); i - .hasNext();) { - Paintable p = (Paintable) i.next(); - - // TODO CLEAN - if (p instanceof Window) { - Window w = (Window) p; - if (w.getTerminal() == null) - w.setTerminal(application.getMainWindow() - .getTerminal()); - } - /* - * This does not seem to happen in tk5, but remember - * this case: else if (p instanceof Component) { if - * (((Component) p).getParent() == null || - * ((Component) p).getApplication() == null) { // - * Component requested repaint, but is no // longer - * attached: skip paintablePainted(p); continue; } } - */ - paintTarget.startTag("change"); - paintTarget.addAttribute("format", "uidl"); - String pid = getPaintableId(p); - paintTarget.addAttribute("pid", pid); - - // Track paints to identify empty paints - paintTarget.setTrackPaints(true); - p.paint(paintTarget); - - // If no paints add attribute empty - if (paintTarget.getNumberOfPaints() <= 0) { - paintTarget.addAttribute("visible", false); - } - paintTarget.endTag("change"); - paintablePainted(p); - } - } - - paintTarget.close(); - outWriter.print("]"); // close changes - - outWriter.print(", \"meta\" : {"); - boolean metaOpen = false; - - // add meta instruction for client to set focus if it is set - Paintable f = (Paintable) application.consumeFocus(); - if (f != null) { - if (metaOpen) - outWriter.write(","); - outWriter.write("\"focus\":\"" + getPaintableId(f) - + "\""); - } - - outWriter.print("}, \"resources\" : {"); - - // Precache custom layouts - String themeName = window.getTheme(); - if (request.getParameter("theme") != null) { - themeName = request.getParameter("theme"); - } - if (themeName == null) - themeName = "default"; - - // TODO We should only precache the layouts that are not - // cached already - int resourceIndex = 0; - for (Iterator i = paintTarget.getPreCachedResources() - .iterator(); i.hasNext();) { - String resource = (String) i.next(); - InputStream is = null; - try { - is = applicationServlet - .getServletContext() - .getResourceAsStream( - "/" - + ApplicationServlet.THEME_DIRECTORY_PATH - + themeName + "/" - + resource); - } catch (Exception e) { - e.printStackTrace(); - } - if (is != null) { - - outWriter.print((resourceIndex++ > 0 ? ", " : "") - + "\"" + resource + "\" : "); - StringBuffer layout = new StringBuffer(); - - try { - InputStreamReader r = new InputStreamReader(is); - char[] buffer = new char[20000]; - int charsRead = 0; - while ((charsRead = r.read(buffer)) > 0) - layout.append(buffer, 0, charsRead); - r.close(); - } catch (java.io.IOException e) { - System.err - .println("Resource transfer failed: " - + request.getRequestURI() - + ". (" + e.getMessage() + ")"); - } - outWriter.print("\"" - + JsonPaintTarget.escapeJSON(layout - .toString()) + "\""); - } - } - outWriter.print("}"); - - printLocaleDeclarations(outWriter); - - outWriter.flush(); - outWriter.close(); - out.flush(); - } else { - - // For download request, transfer the downloaded data - handleDownload(download, request, response); - } - } - - out.flush(); - out.close(); - - } catch (Throwable e) { - e.printStackTrace(); - // Writes the error report to client - OutputStreamWriter w = new OutputStreamWriter(out); - PrintWriter err = new PrintWriter(w); - err - .write("Application Internal Error"); - err.write("

" + e.toString() + "

\n");
-			e.printStackTrace(new PrintWriter(err));
-			err.write("\n
"); - err.close(); - } finally { - - } - - } - - private Map handleVariables(HttpServletRequest request, - Application application2) { - - Map params = new HashMap(request.getParameterMap()); - String changes = (String) ((params.get("changes") instanceof String[]) ? ((String[]) params - .get("changes"))[0] - : params.get("changes")); - params.remove("changes"); - if (changes != null) { - String[] ca = changes.split("\u0001"); - for (int i = 0; i < ca.length; i++) { - String[] vid = ca[i].split("_"); - VariableOwner owner = (VariableOwner) idPaintableMap - .get(vid[0]); - if (owner != null) { - Map m; - if (i + 2 >= ca.length - || !vid[0].equals(ca[i + 2].split("_")[0])) { - if (ca.length > i + 1) { - m = new SingleValueMap(vid[1], - convertVariableValue(vid[2].charAt(0), - ca[++i])); - } else { - m = new SingleValueMap(vid[1], - convertVariableValue(vid[2].charAt(0), "")); - } - } else { - m = new HashMap(); - m.put(vid[1], convertVariableValue(vid[2].charAt(0), - ca[++i])); - } - while (i + 1 < ca.length - && vid[0].equals(ca[i + 1].split("_")[0])) { - vid = ca[++i].split("_"); - m.put(vid[1], convertVariableValue(vid[2].charAt(0), - ca[++i])); - } - owner.changeVariables(request, m); - } - } - } - - return params; - } - - private Object convertVariableValue(char variableType, String strValue) { - Object val = null; - switch (variableType) { - case 'a': - val = strValue.split(","); - break; - case 's': - val = strValue; - break; - case 'i': - val = Integer.valueOf(strValue); - break; - case 'l': - val = Long.valueOf(strValue); - case 'f': - val = Float.valueOf(strValue); - break; - case 'd': - val = Double.valueOf(strValue); - break; - case 'b': - val = Boolean.valueOf(strValue); - break; - } - - return val; - } - - private void printLocaleDeclarations(PrintWriter outWriter) { - /* - * ----------------------------- Sending Locale sensitive date - * ----------------------------- - */ - - // Store JVM default locale for later restoration - // (we'll have to change the default locale for a while) - Locale jvmDefault = Locale.getDefault(); - - // Send locale informations to client - outWriter.print(", \"locales\":["); - for (; pendingLocalesIndex < locales.size(); pendingLocalesIndex++) { - - Locale l = generateLocale((String) locales.get(pendingLocalesIndex)); - // Locale name - outWriter.print("{\"name\":\"" + l.toString() + "\","); - - /* - * Month names (both short and full) - */ - DateFormatSymbols dfs = new DateFormatSymbols(l); - String[] short_months = dfs.getShortMonths(); - String[] months = dfs.getMonths(); - outWriter.print("\"smn\":[\"" - + // ShortMonthNames - short_months[0] + "\",\"" + short_months[1] + "\",\"" - + short_months[2] + "\",\"" + short_months[3] + "\",\"" - + short_months[4] + "\",\"" + short_months[5] + "\",\"" - + short_months[6] + "\",\"" + short_months[7] + "\",\"" - + short_months[8] + "\",\"" + short_months[9] + "\",\"" - + short_months[10] + "\",\"" + short_months[11] + "\"" - + "],"); - outWriter.print("\"mn\":[\"" - + // MonthNames - months[0] + "\",\"" + months[1] + "\",\"" + months[2] - + "\",\"" + months[3] + "\",\"" + months[4] + "\",\"" - + months[5] + "\",\"" + months[6] + "\",\"" + months[7] - + "\",\"" + months[8] + "\",\"" + months[9] + "\",\"" - + months[10] + "\",\"" + months[11] + "\"" + "],"); - - /* - * Weekday names (both short and full) - */ - String[] short_days = dfs.getShortWeekdays(); - String[] days = dfs.getWeekdays(); - outWriter.print("\"sdn\":[\"" - + // ShortDayNames - short_days[1] + "\",\"" + short_days[2] + "\",\"" - + short_days[3] + "\",\"" + short_days[4] + "\",\"" - + short_days[5] + "\",\"" + short_days[6] + "\",\"" - + short_days[7] + "\"" + "],"); - outWriter.print("\"dn\":[\"" - + // DayNames - days[1] + "\",\"" + days[2] + "\",\"" + days[3] + "\",\"" - + days[4] + "\",\"" + days[5] + "\",\"" + days[6] + "\",\"" - + days[7] + "\"" + "],"); - - /* - * First day of week (0 = sunday, 1 = monday) - */ - Calendar cal = new GregorianCalendar(l); - outWriter.print("\"fdow\":" + (cal.getFirstDayOfWeek() - 1) + ","); - - /* - * Date formatting (MM/DD/YYYY etc.) - */ - // Force our locale as JVM default for a while (SimpleDateFormat - // uses JVM default) - Locale.setDefault(l); - String df = new SimpleDateFormat().toPattern(); - int timeStart = df.indexOf("H"); - if (timeStart < 0) - timeStart = df.indexOf("h"); - int ampm_first = df.indexOf("a"); - // E.g. in Korean locale AM/PM is before h:mm - // TODO should take that into consideration on client-side as well, - // now always h:mm a - if (ampm_first > 0 && ampm_first < timeStart) - timeStart = ampm_first; - String dateformat = df.substring(0, timeStart - 1); - - outWriter.print("\"df\":\"" + dateformat.trim() + "\","); - - /* - * Time formatting (24 or 12 hour clock and AM/PM suffixes) - */ - String timeformat = df.substring(timeStart, df.length()); // Doesn't - // return - // second - // or - // milliseconds - // We use timeformat to determine 12/24-hour clock - boolean twelve_hour_clock = timeformat.indexOf("a") > -1; - // TODO there are other possibilities as well, like 'h' in french - // (ignore them, too complicated) - String hour_min_delimiter = timeformat.indexOf(".") > -1 ? "." - : ":"; - // outWriter.print("\"tf\":\"" + timeformat + "\","); - outWriter.print("\"thc\":" + twelve_hour_clock + ","); - outWriter.print("\"hmd\":\"" + hour_min_delimiter + "\""); - if (twelve_hour_clock) { - String[] ampm = dfs.getAmPmStrings(); - outWriter.print(",\"ampm\":[\"" + ampm[0] + "\",\"" + ampm[1] - + "\"]"); - } - outWriter.print("}"); - if (pendingLocalesIndex < locales.size() - 1) - outWriter.print(","); - } - outWriter.print("]"); // Close locales - - // Restore JVM default locale - Locale.setDefault(jvmDefault); - } - - /** - * Gets the existing application or create a new one. Get a window within an - * application based on the requested URI. - * - * @param request - * the HTTP Request. - * @param application - * the Application to query for window. - * @return Window mathing the given URI or null if not found. - * @throws ServletException - * if an exception has occurred that interferes with the - * servlet's normal operation. - */ - private Window getApplicationWindow(HttpServletRequest request, - Application application) throws ServletException { - - Window window = null; - - // Find the window where the request is handled - String path = request.getPathInfo(); - - // Remove UIDL from the path - path = path.substring("/UIDL".length()); - - // Main window as the URI is empty - if (path == null || path.length() == 0 || path.equals("/")) - window = application.getMainWindow(); - - // Try to search by window name - else { - String windowName = null; - if (path.charAt(0) == '/') - path = path.substring(1); - int index = path.indexOf('/'); - if (index < 0) { - windowName = path; - path = ""; - } else { - windowName = path.substring(0, index); - path = path.substring(index + 1); - } - window = application.getWindow(windowName); - - // By default, we use main window - if (window == null) - window = application.getMainWindow(); - } - - return window; - } - - /** - * Handles the requested URI. An application can add handlers to do special - * processing, when a certain URI is requested. The handlers are invoked - * before any windows URIs are processed and if a DownloadStream is returned - * it is sent to the client. - * - * @param application - * the Application owning the URI. - * @param request - * the HTTP request instance. - * @param response - * the HTTP response to write to. - * @return boolean true if the request was handled and - * further processing should be suppressed, otherwise - * false. - * @see com.itmill.toolkit.terminal.URIHandler - */ - private DownloadStream handleURI(Application application, - HttpServletRequest request, HttpServletResponse response) { - - String uri = request.getPathInfo(); - - // If no URI is available - if (uri == null || uri.length() == 0 || uri.equals("/")) - return null; - - // Remove the leading / - while (uri.startsWith("/") && uri.length() > 0) - uri = uri.substring(1); - - // Handle the uri - DownloadStream stream = null; - try { - stream = application.handleURI(application.getURL(), uri); - } catch (Throwable t) { - application.terminalError(new URIHandlerErrorImpl(application, t)); - } - - return stream; - } - - /** - * Handles the requested URI. An application can add handlers to do special - * processing, when a certain URI is requested. The handlers are invoked - * before any windows URIs are processed and if a DownloadStream is returned - * it is sent to the client. - * - * @param stream - * the downloadable stream. - * - * @param request - * the HTTP request instance. - * @param response - * the HTTP response to write to. - * - * @see com.itmill.toolkit.terminal.URIHandler - */ - private void handleDownload(DownloadStream stream, - HttpServletRequest request, HttpServletResponse response) { - - // Download from given stream - InputStream data = stream.getStream(); - if (data != null) { - - // Sets content type - response.setContentType(stream.getContentType()); - - // Sets cache headers - long cacheTime = stream.getCacheTime(); - if (cacheTime <= 0) { - response.setHeader("Cache-Control", "no-cache"); - response.setHeader("Pragma", "no-cache"); - response.setDateHeader("Expires", 0); - } else { - response.setHeader("Cache-Control", "max-age=" + cacheTime - / 1000); - response.setDateHeader("Expires", System.currentTimeMillis() - + cacheTime); - response.setHeader("Pragma", "cache"); // Required to apply - // caching in some - // Tomcats - } - - // Copy download stream parameters directly - // to HTTP headers. - Iterator i = stream.getParameterNames(); - if (i != null) { - while (i.hasNext()) { - String param = (String) i.next(); - response.setHeader((String) param, stream - .getParameter(param)); - } - } - - int bufferSize = stream.getBufferSize(); - if (bufferSize <= 0 || bufferSize > MAX_BUFFER_SIZE) - bufferSize = DEFAULT_BUFFER_SIZE; - byte[] buffer = new byte[bufferSize]; - int bytesRead = 0; - - try { - OutputStream out = response.getOutputStream(); - - while ((bytesRead = data.read(buffer)) > 0) { - out.write(buffer, 0, bytesRead); - out.flush(); - } - out.close(); - } catch (IOException ignored) { - } - - } - - } - - /** - * Ends the Application. - * - * @param request - * the HTTP request instance. - * @param response - * the HTTP response to write to. - * @param application - * the Application to end. - * @throws IOException - * if the writing failed due to input/output error. - */ - private void endApplication(HttpServletRequest request, - HttpServletResponse response, Application application) - throws IOException { - - String logoutUrl = application.getLogoutURL(); - if (logoutUrl == null) - logoutUrl = application.getURL().toString(); - // clients JS app is still running, send a special json file to - // tell client that application has quit and where to point browser now - // Set the response type - response.setContentType("application/json; charset=UTF-8"); - ServletOutputStream out = response.getOutputStream(); - PrintWriter outWriter = new PrintWriter(new BufferedWriter( - new OutputStreamWriter(out, "UTF-8"))); - outWriter.print(")/*{"); - outWriter.print("\"redirect\":{"); - outWriter.write("\"url\":\"" + logoutUrl + "\"}"); - outWriter.flush(); - outWriter.close(); - out.flush(); - } - - /** - * Gets the Paintable Id. - * - * @param paintable - * @return the paintable Id. - */ - public synchronized String getPaintableId(Paintable paintable) { - - String id = (String) paintableIdMap.get(paintable); - if (id == null) { - id = "PID" + Integer.toString(idSequence++); - paintableIdMap.put(paintable, id); - idPaintableMap.put(id, paintable); - } - - return id; - } - - public synchronized boolean hasPaintableId(Paintable paintable) { - - return paintableIdMap.containsKey(paintable); - } - - /** - * - * @return - */ - public synchronized Set getDirtyComponents() { - HashSet resultset = new HashSet(dirtyPaintabletSet); - - // The following algorithm removes any components that would be painted - // as - // a direct descendant of other components from the dirty components - // list. - // The result is that each component should be painted exactly once and - // any unmodified components will be painted as "cached=true". - - for (Iterator i = dirtyPaintabletSet.iterator(); i.hasNext();) { - Paintable p = (Paintable) i.next(); - if (p instanceof Component) { - if (dirtyPaintabletSet.contains(((Component) p).getParent())) - resultset.remove(p); - } - } - - return resultset; - } - - /** - * @see com.itmill.toolkit.terminal.Paintable.RepaintRequestListener#repaintRequested(com.itmill.toolkit.terminal.Paintable.RepaintRequestEvent) - */ - public void repaintRequested(RepaintRequestEvent event) { - Paintable p = event.getPaintable(); - dirtyPaintabletSet.add(p); - - } - - /** - * - * @param p - */ - public void paintablePainted(Paintable p) { - dirtyPaintabletSet.remove(p); - p.requestRepaintRequests(); - } - - /** - * @see com.itmill.toolkit.Application.WindowAttachListener#windowAttached(com.itmill.toolkit.Application.WindowAttachEvent) - */ - public void windowAttached(WindowAttachEvent event) { - event.getWindow().addListener(this); - dirtyPaintabletSet.add(event.getWindow()); - } - - /** - * @see com.itmill.toolkit.Application.WindowDetachListener#windowDetached(com.itmill.toolkit.Application.WindowDetachEvent) - */ - public void windowDetached(WindowDetachEvent event) { - event.getWindow().removeListener(this); - // Notify client of the close operation - removedWindows.add(event.getWindow()); - } - - /** - * - * @return - */ - public synchronized Set getRemovedWindows() { - return Collections.unmodifiableSet(removedWindows); - - } - - /** - * - * @param w - */ - private void removedWindowNotified(Window w) { - this.removedWindows.remove(w); - } - - private final class SingleValueMap implements Map { - private final String name; - - private final Object value; - - private SingleValueMap(String name, Object value) { - this.name = name; - this.value = value; - } - - public void clear() { - throw new UnsupportedOperationException(); - } - - public boolean containsKey(Object key) { - if (name == null) - return key == null; - return name.equals(key); - } - - public boolean containsValue(Object v) { - if (value == null) - return v == null; - return value.equals(v); - } - - public Set entrySet() { - Set s = new HashSet(); - s.add(new Map.Entry() { - - public Object getKey() { - return name; - } - - public Object getValue() { - return value; - } - - public Object setValue(Object value) { - throw new UnsupportedOperationException(); - } - }); - return s; - } - - public Object get(Object key) { - if (!name.equals(key)) - return null; - return value; - } - - public boolean isEmpty() { - return false; - } - - public Set keySet() { - Set s = new HashSet(); - s.add(name); - return s; - } - - public Object put(Object key, Object value) { - throw new UnsupportedOperationException(); - } - - public void putAll(Map t) { - throw new UnsupportedOperationException(); - } - - public Object remove(Object key) { - throw new UnsupportedOperationException(); - } - - public int size() { - return 1; - } - - public Collection values() { - LinkedList s = new LinkedList(); - s.add(value); - return s; - - } - } - - /** - * Implementation of URIHandler.ErrorEvent interface. - */ - public class URIHandlerErrorImpl implements URIHandler.ErrorEvent { - - private URIHandler owner; - - private Throwable throwable; - - /** - * - * @param owner - * @param throwable - */ - private URIHandlerErrorImpl(URIHandler owner, Throwable throwable) { - this.owner = owner; - this.throwable = throwable; - } - - /** - * @see com.itmill.toolkit.terminal.Terminal.ErrorEvent#getThrowable() - */ - public Throwable getThrowable() { - return this.throwable; - } - - /** - * @see com.itmill.toolkit.terminal.URIHandler.ErrorEvent#getURIHandler() - */ - public URIHandler getURIHandler() { - return this.owner; - } - } - - public void requireLocale(String value) { - if (locales == null) { - locales = new ArrayList(); - locales.add(application.getLocale().toString()); - pendingLocalesIndex = 0; - } - if (!locales.contains(value)) - locales.add(value); - } - - private Locale generateLocale(String value) { - String[] temp = value.split("_"); - if (temp.length == 1) - return new Locale(temp[0]); - else if (temp.length == 2) - return new Locale(temp[0], temp[1]); - else - return new Locale(temp[0], temp[1], temp[2]); - } - - /* - * Upload progress listener notifies upload component once when Jakarta - * FileUpload can determine content length. Used to detect files total size, - * uploads progress can be tracked inside upload. - */ - private class UploadProgressListener implements ProgressListener { - Upload uploadComponent; - - boolean updated = false; - - public void setUpload(Upload u) { - uploadComponent = u; - } - - public void update(long bytesRead, long contentLength, int items) { - if (!updated && uploadComponent != null) { - uploadComponent.setUploadSize(contentLength); - updated = true; - } - } - } + Application.WindowAttachListener, Application.WindowDetachListener { + + private static String GET_PARAM_REPAINT_ALL = "repaintAll"; + + private static int DEFAULT_BUFFER_SIZE = 32 * 1024; + + private static int MAX_BUFFER_SIZE = 64 * 1024; + + private HashSet dirtyPaintabletSet = new HashSet(); + + private WeakHashMap paintableIdMap = new WeakHashMap(); + + private WeakHashMap idPaintableMap = new WeakHashMap(); + + private int idSequence = 0; + + private Application application; + + private Set removedWindows = new HashSet(); + + private JsonPaintTarget paintTarget; + + private List locales; + + private int pendingLocalesIndex; + + private ApplicationServlet applicationServlet; + + public CommunicationManager(Application application, + ApplicationServlet applicationServlet) { + this.application = application; + this.applicationServlet = applicationServlet; + requireLocale(application.getLocale().toString()); + } + + /** + * + * + */ + public void takeControl() { + application.addListener((Application.WindowAttachListener) this); + application.addListener((Application.WindowDetachListener) this); + + } + + /** + * + * + */ + public void releaseControl() { + application.removeListener((Application.WindowAttachListener) this); + application.removeListener((Application.WindowDetachListener) this); + } + + /** + * Handles file upload request submitted via Upload component. + * + * @param request + * @param response + * @throws IOException + */ + public void handleFileUpload(HttpServletRequest request, + HttpServletResponse response) throws IOException { + // Create a new file upload handler + ServletFileUpload upload = new ServletFileUpload(); + + UploadProgressListener pl = new UploadProgressListener(); + + upload.setProgressListener(pl); + + // Parse the request + FileItemIterator iter; + + try { + iter = upload.getItemIterator(request); + /* + * ATM this loop is run only once as we are uploading one file per + * request. + */ + while (iter.hasNext()) { + FileItemStream item = iter.next(); + String name = item.getFieldName(); + final String filename = item.getName(); + final String mimeType = item.getContentType(); + final InputStream stream = item.openStream(); + if (item.isFormField()) { + // ignored, upload requests contian only files + } else { + String pid = name.split("_")[0]; + Upload uploadComponent = (Upload) idPaintableMap.get(pid); + if (uploadComponent == null) { + throw new FileUploadException( + "Upload component not found"); + } + synchronized (application) { + // put upload component into receiving state + uploadComponent.startUpload(); + } + UploadStream upstream = new UploadStream() { + + public String getContentName() { + return filename; + } + + public String getContentType() { + return mimeType; + } + + public InputStream getStream() { + return stream; + } + + public String getStreamName() { + return "stream"; + } + + }; + + // tell UploadProgressListener which component is receiving + // file + pl.setUpload(uploadComponent); + + uploadComponent.receiveUpload(upstream); + } + } + } catch (FileUploadException e) { + e.printStackTrace(); + } + + // Send short response to acknowledge client that request was done + response.setContentType("text/html"); + OutputStream out = response.getOutputStream(); + PrintWriter outWriter = new PrintWriter(new BufferedWriter( + new OutputStreamWriter(out, "UTF-8"))); + outWriter.print("download handled"); + outWriter.flush(); + out.close(); + } + + /** + * Handles UIDL request + * + * @param request + * @param response + * @throws IOException + */ + public void handleUidlRequest(HttpServletRequest request, + HttpServletResponse response) throws IOException { + + // repaint requested or session has timed out and new one is created + boolean repaintAll = (request.getParameter(GET_PARAM_REPAINT_ALL) != null) + || request.getSession().isNew(); + + // If repaint is requested, clean all ids + if (repaintAll) { + idPaintableMap.clear(); + paintableIdMap.clear(); + } + + OutputStream out = response.getOutputStream(); + PrintWriter outWriter = new PrintWriter(new BufferedWriter( + new OutputStreamWriter(out, "UTF-8"))); + + try { + + // Is this a download request from application + DownloadStream download = null; + + // The rest of the process is synchronized with the application + // in order to guarantee that no parallel variable handling is + // made + synchronized (application) { + + // Change all variables based on request parameters + handleVariables(request, application); + + // If this is not a download request + if (download == null) { + + // Finds the window within the application + Window window = null; + if (application.isRunning()) { + window = getApplicationWindow(request, application); + } + + // Removes application if it has stopped + if (!application.isRunning()) { + endApplication(request, response, application); + return; + } + + // Returns if no window found + if (window == null) { + return; + } + + // Sets the response type + response.setContentType("application/json; charset=UTF-8"); + // some dirt to prevent cross site scripting + outWriter.print(")/*{"); + + outWriter.print("\"changes\":["); + + paintTarget = new JsonPaintTarget(this, outWriter, + !repaintAll); + + // Paints components + Set paintables; + if (repaintAll) { + paintables = new LinkedHashSet(); + paintables.add(window); + + // Reset sent locales + locales = null; + requireLocale(application.getLocale().toString()); + + } else { + paintables = getDirtyComponents(); + } + if (paintables != null) { + + // Creates "working copy" of the current state. + List currentPaintables = new ArrayList(paintables); + + // Sorts the paintable so that parent windows + // are always painted before child windows + Collections.sort(currentPaintables, new Comparator() { + + public int compare(Object o1, Object o2) { + + // If first argumement is now window + // the second is "smaller" if it is. + if (!(o1 instanceof Window)) { + return (o2 instanceof Window) ? 1 : 0; + } + + // Now, if second is not window the + // first is smaller. + if (!(o2 instanceof Window)) { + return -1; + } + + return 0; + } + }); + + for (Iterator i = currentPaintables.iterator(); i + .hasNext();) { + Paintable p = (Paintable) i.next(); + + // TODO CLEAN + if (p instanceof Window) { + Window w = (Window) p; + if (w.getTerminal() == null) { + w.setTerminal(application.getMainWindow() + .getTerminal()); + } + } + /* + * This does not seem to happen in tk5, but remember + * this case: else if (p instanceof Component) { if + * (((Component) p).getParent() == null || + * ((Component) p).getApplication() == null) { // + * Component requested repaint, but is no // longer + * attached: skip paintablePainted(p); continue; } } + */ + paintTarget.startTag("change"); + paintTarget.addAttribute("format", "uidl"); + String pid = getPaintableId(p); + paintTarget.addAttribute("pid", pid); + + // Track paints to identify empty paints + paintTarget.setTrackPaints(true); + p.paint(paintTarget); + + // If no paints add attribute empty + if (paintTarget.getNumberOfPaints() <= 0) { + paintTarget.addAttribute("visible", false); + } + paintTarget.endTag("change"); + paintablePainted(p); + } + } + + paintTarget.close(); + outWriter.print("]"); // close changes + + outWriter.print(", \"meta\" : {"); + boolean metaOpen = false; + + // add meta instruction for client to set focus if it is set + Paintable f = (Paintable) application.consumeFocus(); + if (f != null) { + if (metaOpen) { + outWriter.write(","); + } + outWriter.write("\"focus\":\"" + getPaintableId(f) + + "\""); + } + + outWriter.print("}, \"resources\" : {"); + + // Precache custom layouts + String themeName = window.getTheme(); + if (request.getParameter("theme") != null) { + themeName = request.getParameter("theme"); + } + if (themeName == null) { + themeName = "default"; + } + + // TODO We should only precache the layouts that are not + // cached already + int resourceIndex = 0; + for (Iterator i = paintTarget.getPreCachedResources() + .iterator(); i.hasNext();) { + String resource = (String) i.next(); + InputStream is = null; + try { + is = applicationServlet + .getServletContext() + .getResourceAsStream( + "/" + + ApplicationServlet.THEME_DIRECTORY_PATH + + themeName + "/" + + resource); + } catch (Exception e) { + e.printStackTrace(); + } + if (is != null) { + + outWriter.print((resourceIndex++ > 0 ? ", " : "") + + "\"" + resource + "\" : "); + StringBuffer layout = new StringBuffer(); + + try { + InputStreamReader r = new InputStreamReader(is); + char[] buffer = new char[20000]; + int charsRead = 0; + while ((charsRead = r.read(buffer)) > 0) { + layout.append(buffer, 0, charsRead); + } + r.close(); + } catch (java.io.IOException e) { + System.err + .println("Resource transfer failed: " + + request.getRequestURI() + + ". (" + e.getMessage() + ")"); + } + outWriter.print("\"" + + JsonPaintTarget.escapeJSON(layout + .toString()) + "\""); + } + } + outWriter.print("}"); + + printLocaleDeclarations(outWriter); + + outWriter.flush(); + outWriter.close(); + out.flush(); + } else { + + // For download request, transfer the downloaded data + handleDownload(download, request, response); + } + } + + out.flush(); + out.close(); + + } catch (Throwable e) { + e.printStackTrace(); + // Writes the error report to client + OutputStreamWriter w = new OutputStreamWriter(out); + PrintWriter err = new PrintWriter(w); + err + .write("Application Internal Error"); + err.write("

" + e.toString() + "

\n");
+            e.printStackTrace(new PrintWriter(err));
+            err.write("\n
"); + err.close(); + } finally { + + } + + } + + private Map handleVariables(HttpServletRequest request, + Application application2) { + + Map params = new HashMap(request.getParameterMap()); + String changes = (String) ((params.get("changes") instanceof String[]) ? ((String[]) params + .get("changes"))[0] + : params.get("changes")); + params.remove("changes"); + if (changes != null) { + String[] ca = changes.split("\u0001"); + for (int i = 0; i < ca.length; i++) { + String[] vid = ca[i].split("_"); + VariableOwner owner = (VariableOwner) idPaintableMap + .get(vid[0]); + if (owner != null) { + Map m; + if (i + 2 >= ca.length + || !vid[0].equals(ca[i + 2].split("_")[0])) { + if (ca.length > i + 1) { + m = new SingleValueMap(vid[1], + convertVariableValue(vid[2].charAt(0), + ca[++i])); + } else { + m = new SingleValueMap(vid[1], + convertVariableValue(vid[2].charAt(0), "")); + } + } else { + m = new HashMap(); + m.put(vid[1], convertVariableValue(vid[2].charAt(0), + ca[++i])); + } + while (i + 1 < ca.length + && vid[0].equals(ca[i + 1].split("_")[0])) { + vid = ca[++i].split("_"); + m.put(vid[1], convertVariableValue(vid[2].charAt(0), + ca[++i])); + } + owner.changeVariables(request, m); + } + } + } + + return params; + } + + private Object convertVariableValue(char variableType, String strValue) { + Object val = null; + switch (variableType) { + case 'a': + val = strValue.split(","); + break; + case 's': + val = strValue; + break; + case 'i': + val = Integer.valueOf(strValue); + break; + case 'l': + val = Long.valueOf(strValue); + case 'f': + val = Float.valueOf(strValue); + break; + case 'd': + val = Double.valueOf(strValue); + break; + case 'b': + val = Boolean.valueOf(strValue); + break; + } + + return val; + } + + private void printLocaleDeclarations(PrintWriter outWriter) { + /* + * ----------------------------- Sending Locale sensitive date + * ----------------------------- + */ + + // Store JVM default locale for later restoration + // (we'll have to change the default locale for a while) + Locale jvmDefault = Locale.getDefault(); + + // Send locale informations to client + outWriter.print(", \"locales\":["); + for (; pendingLocalesIndex < locales.size(); pendingLocalesIndex++) { + + Locale l = generateLocale((String) locales.get(pendingLocalesIndex)); + // Locale name + outWriter.print("{\"name\":\"" + l.toString() + "\","); + + /* + * Month names (both short and full) + */ + DateFormatSymbols dfs = new DateFormatSymbols(l); + String[] short_months = dfs.getShortMonths(); + String[] months = dfs.getMonths(); + outWriter.print("\"smn\":[\"" + + // ShortMonthNames + short_months[0] + "\",\"" + short_months[1] + "\",\"" + + short_months[2] + "\",\"" + short_months[3] + "\",\"" + + short_months[4] + "\",\"" + short_months[5] + "\",\"" + + short_months[6] + "\",\"" + short_months[7] + "\",\"" + + short_months[8] + "\",\"" + short_months[9] + "\",\"" + + short_months[10] + "\",\"" + short_months[11] + "\"" + + "],"); + outWriter.print("\"mn\":[\"" + + // MonthNames + months[0] + "\",\"" + months[1] + "\",\"" + months[2] + + "\",\"" + months[3] + "\",\"" + months[4] + "\",\"" + + months[5] + "\",\"" + months[6] + "\",\"" + months[7] + + "\",\"" + months[8] + "\",\"" + months[9] + "\",\"" + + months[10] + "\",\"" + months[11] + "\"" + "],"); + + /* + * Weekday names (both short and full) + */ + String[] short_days = dfs.getShortWeekdays(); + String[] days = dfs.getWeekdays(); + outWriter.print("\"sdn\":[\"" + + // ShortDayNames + short_days[1] + "\",\"" + short_days[2] + "\",\"" + + short_days[3] + "\",\"" + short_days[4] + "\",\"" + + short_days[5] + "\",\"" + short_days[6] + "\",\"" + + short_days[7] + "\"" + "],"); + outWriter.print("\"dn\":[\"" + + // DayNames + days[1] + "\",\"" + days[2] + "\",\"" + days[3] + "\",\"" + + days[4] + "\",\"" + days[5] + "\",\"" + days[6] + "\",\"" + + days[7] + "\"" + "],"); + + /* + * First day of week (0 = sunday, 1 = monday) + */ + Calendar cal = new GregorianCalendar(l); + outWriter.print("\"fdow\":" + (cal.getFirstDayOfWeek() - 1) + ","); + + /* + * Date formatting (MM/DD/YYYY etc.) + */ + // Force our locale as JVM default for a while (SimpleDateFormat + // uses JVM default) + Locale.setDefault(l); + String df = new SimpleDateFormat().toPattern(); + int timeStart = df.indexOf("H"); + if (timeStart < 0) { + timeStart = df.indexOf("h"); + } + int ampm_first = df.indexOf("a"); + // E.g. in Korean locale AM/PM is before h:mm + // TODO should take that into consideration on client-side as well, + // now always h:mm a + if (ampm_first > 0 && ampm_first < timeStart) { + timeStart = ampm_first; + } + String dateformat = df.substring(0, timeStart - 1); + + outWriter.print("\"df\":\"" + dateformat.trim() + "\","); + + /* + * Time formatting (24 or 12 hour clock and AM/PM suffixes) + */ + String timeformat = df.substring(timeStart, df.length()); // Doesn't + // return + // second + // or + // milliseconds + // We use timeformat to determine 12/24-hour clock + boolean twelve_hour_clock = timeformat.indexOf("a") > -1; + // TODO there are other possibilities as well, like 'h' in french + // (ignore them, too complicated) + String hour_min_delimiter = timeformat.indexOf(".") > -1 ? "." + : ":"; + // outWriter.print("\"tf\":\"" + timeformat + "\","); + outWriter.print("\"thc\":" + twelve_hour_clock + ","); + outWriter.print("\"hmd\":\"" + hour_min_delimiter + "\""); + if (twelve_hour_clock) { + String[] ampm = dfs.getAmPmStrings(); + outWriter.print(",\"ampm\":[\"" + ampm[0] + "\",\"" + ampm[1] + + "\"]"); + } + outWriter.print("}"); + if (pendingLocalesIndex < locales.size() - 1) { + outWriter.print(","); + } + } + outWriter.print("]"); // Close locales + + // Restore JVM default locale + Locale.setDefault(jvmDefault); + } + + /** + * Gets the existing application or create a new one. Get a window within an + * application based on the requested URI. + * + * @param request + * the HTTP Request. + * @param application + * the Application to query for window. + * @return Window mathing the given URI or null if not found. + * @throws ServletException + * if an exception has occurred that interferes with the + * servlet's normal operation. + */ + private Window getApplicationWindow(HttpServletRequest request, + Application application) throws ServletException { + + Window window = null; + + // Find the window where the request is handled + String path = request.getPathInfo(); + + // Remove UIDL from the path + path = path.substring("/UIDL".length()); + + // Main window as the URI is empty + if (path == null || path.length() == 0 || path.equals("/")) { + window = application.getMainWindow(); + } else { + String windowName = null; + if (path.charAt(0) == '/') { + path = path.substring(1); + } + int index = path.indexOf('/'); + if (index < 0) { + windowName = path; + path = ""; + } else { + windowName = path.substring(0, index); + path = path.substring(index + 1); + } + window = application.getWindow(windowName); + + // By default, we use main window + if (window == null) { + window = application.getMainWindow(); + } + } + + return window; + } + + /** + * Handles the requested URI. An application can add handlers to do special + * processing, when a certain URI is requested. The handlers are invoked + * before any windows URIs are processed and if a DownloadStream is returned + * it is sent to the client. + * + * @param application + * the Application owning the URI. + * @param request + * the HTTP request instance. + * @param response + * the HTTP response to write to. + * @return boolean true if the request was handled and + * further processing should be suppressed, otherwise + * false. + * @see com.itmill.toolkit.terminal.URIHandler + */ + private DownloadStream handleURI(Application application, + HttpServletRequest request, HttpServletResponse response) { + + String uri = request.getPathInfo(); + + // If no URI is available + if (uri == null || uri.length() == 0 || uri.equals("/")) { + return null; + } + + // Remove the leading / + while (uri.startsWith("/") && uri.length() > 0) { + uri = uri.substring(1); + } + + // Handle the uri + DownloadStream stream = null; + try { + stream = application.handleURI(application.getURL(), uri); + } catch (Throwable t) { + application.terminalError(new URIHandlerErrorImpl(application, t)); + } + + return stream; + } + + /** + * Handles the requested URI. An application can add handlers to do special + * processing, when a certain URI is requested. The handlers are invoked + * before any windows URIs are processed and if a DownloadStream is returned + * it is sent to the client. + * + * @param stream + * the downloadable stream. + * + * @param request + * the HTTP request instance. + * @param response + * the HTTP response to write to. + * + * @see com.itmill.toolkit.terminal.URIHandler + */ + private void handleDownload(DownloadStream stream, + HttpServletRequest request, HttpServletResponse response) { + + // Download from given stream + InputStream data = stream.getStream(); + if (data != null) { + + // Sets content type + response.setContentType(stream.getContentType()); + + // Sets cache headers + long cacheTime = stream.getCacheTime(); + if (cacheTime <= 0) { + response.setHeader("Cache-Control", "no-cache"); + response.setHeader("Pragma", "no-cache"); + response.setDateHeader("Expires", 0); + } else { + response.setHeader("Cache-Control", "max-age=" + cacheTime + / 1000); + response.setDateHeader("Expires", System.currentTimeMillis() + + cacheTime); + response.setHeader("Pragma", "cache"); // Required to apply + // caching in some + // Tomcats + } + + // Copy download stream parameters directly + // to HTTP headers. + Iterator i = stream.getParameterNames(); + if (i != null) { + while (i.hasNext()) { + String param = (String) i.next(); + response.setHeader((String) param, stream + .getParameter(param)); + } + } + + int bufferSize = stream.getBufferSize(); + if (bufferSize <= 0 || bufferSize > MAX_BUFFER_SIZE) { + bufferSize = DEFAULT_BUFFER_SIZE; + } + byte[] buffer = new byte[bufferSize]; + int bytesRead = 0; + + try { + OutputStream out = response.getOutputStream(); + + while ((bytesRead = data.read(buffer)) > 0) { + out.write(buffer, 0, bytesRead); + out.flush(); + } + out.close(); + } catch (IOException ignored) { + } + + } + + } + + /** + * Ends the Application. + * + * @param request + * the HTTP request instance. + * @param response + * the HTTP response to write to. + * @param application + * the Application to end. + * @throws IOException + * if the writing failed due to input/output error. + */ + private void endApplication(HttpServletRequest request, + HttpServletResponse response, Application application) + throws IOException { + + String logoutUrl = application.getLogoutURL(); + if (logoutUrl == null) { + logoutUrl = application.getURL().toString(); + } + // clients JS app is still running, send a special json file to + // tell client that application has quit and where to point browser now + // Set the response type + response.setContentType("application/json; charset=UTF-8"); + ServletOutputStream out = response.getOutputStream(); + PrintWriter outWriter = new PrintWriter(new BufferedWriter( + new OutputStreamWriter(out, "UTF-8"))); + outWriter.print(")/*{"); + outWriter.print("\"redirect\":{"); + outWriter.write("\"url\":\"" + logoutUrl + "\"}"); + outWriter.flush(); + outWriter.close(); + out.flush(); + } + + /** + * Gets the Paintable Id. + * + * @param paintable + * @return the paintable Id. + */ + public synchronized String getPaintableId(Paintable paintable) { + + String id = (String) paintableIdMap.get(paintable); + if (id == null) { + id = "PID" + Integer.toString(idSequence++); + paintableIdMap.put(paintable, id); + idPaintableMap.put(id, paintable); + } + + return id; + } + + public synchronized boolean hasPaintableId(Paintable paintable) { + + return paintableIdMap.containsKey(paintable); + } + + /** + * + * @return + */ + public synchronized Set getDirtyComponents() { + HashSet resultset = new HashSet(dirtyPaintabletSet); + + // The following algorithm removes any components that would be painted + // as + // a direct descendant of other components from the dirty components + // list. + // The result is that each component should be painted exactly once and + // any unmodified components will be painted as "cached=true". + + for (Iterator i = dirtyPaintabletSet.iterator(); i.hasNext();) { + Paintable p = (Paintable) i.next(); + if (p instanceof Component) { + if (dirtyPaintabletSet.contains(((Component) p).getParent())) { + resultset.remove(p); + } + } + } + + return resultset; + } + + /** + * @see com.itmill.toolkit.terminal.Paintable.RepaintRequestListener#repaintRequested(com.itmill.toolkit.terminal.Paintable.RepaintRequestEvent) + */ + public void repaintRequested(RepaintRequestEvent event) { + Paintable p = event.getPaintable(); + dirtyPaintabletSet.add(p); + + } + + /** + * + * @param p + */ + public void paintablePainted(Paintable p) { + dirtyPaintabletSet.remove(p); + p.requestRepaintRequests(); + } + + /** + * @see com.itmill.toolkit.Application.WindowAttachListener#windowAttached(com.itmill.toolkit.Application.WindowAttachEvent) + */ + public void windowAttached(WindowAttachEvent event) { + event.getWindow().addListener(this); + dirtyPaintabletSet.add(event.getWindow()); + } + + /** + * @see com.itmill.toolkit.Application.WindowDetachListener#windowDetached(com.itmill.toolkit.Application.WindowDetachEvent) + */ + public void windowDetached(WindowDetachEvent event) { + event.getWindow().removeListener(this); + // Notify client of the close operation + removedWindows.add(event.getWindow()); + } + + /** + * + * @return + */ + public synchronized Set getRemovedWindows() { + return Collections.unmodifiableSet(removedWindows); + + } + + /** + * + * @param w + */ + private void removedWindowNotified(Window w) { + removedWindows.remove(w); + } + + private final class SingleValueMap implements Map { + private final String name; + + private final Object value; + + private SingleValueMap(String name, Object value) { + this.name = name; + this.value = value; + } + + public void clear() { + throw new UnsupportedOperationException(); + } + + public boolean containsKey(Object key) { + if (name == null) { + return key == null; + } + return name.equals(key); + } + + public boolean containsValue(Object v) { + if (value == null) { + return v == null; + } + return value.equals(v); + } + + public Set entrySet() { + Set s = new HashSet(); + s.add(new Map.Entry() { + + public Object getKey() { + return name; + } + + public Object getValue() { + return value; + } + + public Object setValue(Object value) { + throw new UnsupportedOperationException(); + } + }); + return s; + } + + public Object get(Object key) { + if (!name.equals(key)) { + return null; + } + return value; + } + + public boolean isEmpty() { + return false; + } + + public Set keySet() { + Set s = new HashSet(); + s.add(name); + return s; + } + + public Object put(Object key, Object value) { + throw new UnsupportedOperationException(); + } + + public void putAll(Map t) { + throw new UnsupportedOperationException(); + } + + public Object remove(Object key) { + throw new UnsupportedOperationException(); + } + + public int size() { + return 1; + } + + public Collection values() { + LinkedList s = new LinkedList(); + s.add(value); + return s; + + } + } + + /** + * Implementation of URIHandler.ErrorEvent interface. + */ + public class URIHandlerErrorImpl implements URIHandler.ErrorEvent { + + private URIHandler owner; + + private Throwable throwable; + + /** + * + * @param owner + * @param throwable + */ + private URIHandlerErrorImpl(URIHandler owner, Throwable throwable) { + this.owner = owner; + this.throwable = throwable; + } + + /** + * @see com.itmill.toolkit.terminal.Terminal.ErrorEvent#getThrowable() + */ + public Throwable getThrowable() { + return throwable; + } + + /** + * @see com.itmill.toolkit.terminal.URIHandler.ErrorEvent#getURIHandler() + */ + public URIHandler getURIHandler() { + return owner; + } + } + + public void requireLocale(String value) { + if (locales == null) { + locales = new ArrayList(); + locales.add(application.getLocale().toString()); + pendingLocalesIndex = 0; + } + if (!locales.contains(value)) { + locales.add(value); + } + } + + private Locale generateLocale(String value) { + String[] temp = value.split("_"); + if (temp.length == 1) { + return new Locale(temp[0]); + } else if (temp.length == 2) { + return new Locale(temp[0], temp[1]); + } else { + return new Locale(temp[0], temp[1], temp[2]); + } + } + + /* + * Upload progress listener notifies upload component once when Jakarta + * FileUpload can determine content length. Used to detect files total size, + * uploads progress can be tracked inside upload. + */ + private class UploadProgressListener implements ProgressListener { + Upload uploadComponent; + + boolean updated = false; + + public void setUpload(Upload u) { + uploadComponent = u; + } + + public void update(long bytesRead, long contentLength, int items) { + if (!updated && uploadComponent != null) { + uploadComponent.setUploadSize(contentLength); + updated = true; + } + } + } } diff --git a/src/com/itmill/toolkit/terminal/gwt/server/HttpUploadStream.java b/src/com/itmill/toolkit/terminal/gwt/server/HttpUploadStream.java index d6ee9b9bac..2593addef7 100644 --- a/src/com/itmill/toolkit/terminal/gwt/server/HttpUploadStream.java +++ b/src/com/itmill/toolkit/terminal/gwt/server/HttpUploadStream.java @@ -39,76 +39,76 @@ import java.io.InputStream; * @since 5.0 */ public class HttpUploadStream implements - com.itmill.toolkit.terminal.UploadStream { - - /** - * Holds value of property variableName. - */ - private String streamName; - - private String contentName; - - private String contentType; - - /** - * Holds value of property variableValue. - */ - private InputStream stream; - - /** - * Creates a new instance of UploadStreamImpl. - * - * @param name - * the name of the stream. - * @param stream - * the input stream. - * @param contentName - * the name of the content. - * @param contentType - * the type of the content. - */ - public HttpUploadStream(String name, InputStream stream, - String contentName, String contentType) { - this.streamName = name; - this.stream = stream; - this.contentName = contentName; - this.contentType = contentType; - } - - /** - * Gets the name of the stream. - * - * @return the name of the stream. - */ - public String getStreamName() { - return this.streamName; - } - - /** - * Gets the input stream. - * - * @return the Input stream. - */ - public InputStream getStream() { - return this.stream; - } - - /** - * Gets the input stream content type. - * - * @return the content type of the input stream. - */ - public String getContentType() { - return this.contentType; - } - - /** - * Gets the stream content name. Stream content name usually differs from - * the actual stream name. It is used to identify the content of the stream. - * - * @return the Name of the stream content. - */ - public String getContentName() { - return this.contentName; - } + com.itmill.toolkit.terminal.UploadStream { + + /** + * Holds value of property variableName. + */ + private String streamName; + + private String contentName; + + private String contentType; + + /** + * Holds value of property variableValue. + */ + private InputStream stream; + + /** + * Creates a new instance of UploadStreamImpl. + * + * @param name + * the name of the stream. + * @param stream + * the input stream. + * @param contentName + * the name of the content. + * @param contentType + * the type of the content. + */ + public HttpUploadStream(String name, InputStream stream, + String contentName, String contentType) { + streamName = name; + this.stream = stream; + this.contentName = contentName; + this.contentType = contentType; + } + + /** + * Gets the name of the stream. + * + * @return the name of the stream. + */ + public String getStreamName() { + return streamName; + } + + /** + * Gets the input stream. + * + * @return the Input stream. + */ + public InputStream getStream() { + return stream; + } + + /** + * Gets the input stream content type. + * + * @return the content type of the input stream. + */ + public String getContentType() { + return contentType; + } + + /** + * Gets the stream content name. Stream content name usually differs from + * the actual stream name. It is used to identify the content of the stream. + * + * @return the Name of the stream content. + */ + public String getContentName() { + return contentName; + } } diff --git a/src/com/itmill/toolkit/terminal/gwt/server/JsonPaintTarget.java b/src/com/itmill/toolkit/terminal/gwt/server/JsonPaintTarget.java index 1361a485ff..a1de8e4e1b 100644 --- a/src/com/itmill/toolkit/terminal/gwt/server/JsonPaintTarget.java +++ b/src/com/itmill/toolkit/terminal/gwt/server/JsonPaintTarget.java @@ -55,1049 +55,1078 @@ import com.itmill.toolkit.terminal.VariableOwner; */ public class JsonPaintTarget implements PaintTarget { - /* Document type declarations */ + /* Document type declarations */ - private final static String UIDL_ARG_NAME = "name"; + private final static String UIDL_ARG_NAME = "name"; - private final static String UIDL_ARG_VALUE = "value"; + private final static String UIDL_ARG_VALUE = "value"; - private final static String UIDL_ARG_ID = "id"; + private final static String UIDL_ARG_ID = "id"; - private Stack mOpenTags; + private Stack mOpenTags; - private Stack openJsonTags; + private Stack openJsonTags; - private boolean mTagArgumentListOpen; + private boolean mTagArgumentListOpen; - private PrintWriter uidlBuffer; + private PrintWriter uidlBuffer; - private boolean closed = false; + private boolean closed = false; - private CommunicationManager manager; + private CommunicationManager manager; - private boolean trackPaints = false; + private boolean trackPaints = false; - private int numberOfPaints = 0; + private int numberOfPaints = 0; - private int changes = 0; + private int changes = 0; - Set preCachedResources = new HashSet(); + Set preCachedResources = new HashSet(); - private boolean customLayoutArgumentsOpen = false; + private boolean customLayoutArgumentsOpen = false; - private JsonTag tag; + private JsonTag tag; - private int errorsOpen; + private int errorsOpen; - private boolean cacheEnabled = false; + private boolean cacheEnabled = false; - /** - * Creates a new XMLPrintWriter, without automatic line flushing. - * - * @param variableMap - * @param manager - * @param outWriter - * A character-output stream. - * @throws PaintException - * if the paint operation failed. - */ - public JsonPaintTarget(CommunicationManager manager, PrintWriter outWriter, - boolean cachingRequired) throws PaintException { + /** + * Creates a new XMLPrintWriter, without automatic line flushing. + * + * @param variableMap + * @param manager + * @param outWriter + * A character-output stream. + * @throws PaintException + * if the paint operation failed. + */ + public JsonPaintTarget(CommunicationManager manager, PrintWriter outWriter, + boolean cachingRequired) throws PaintException { - this.manager = manager; + this.manager = manager; - // Sets the target for UIDL writing - this.uidlBuffer = outWriter; + // Sets the target for UIDL writing + uidlBuffer = outWriter; - // Initialize tag-writing - mOpenTags = new Stack(); - openJsonTags = new Stack(); - mTagArgumentListOpen = false; + // Initialize tag-writing + mOpenTags = new Stack(); + openJsonTags = new Stack(); + mTagArgumentListOpen = false; - // Adds document declaration - - // Adds UIDL start tag and its attributes - - this.cacheEnabled = cachingRequired; - } - - public void startTag(String tagName) throws PaintException { - startTag(tagName, false); - } - - /** - * Prints the element start tag. - * - *
-	 *   Todo:
-	 *    Checking of input values
-	 *    
-	 * 
- * - * @param tagName - * the name of the start tag. - * @throws PaintException - * if the paint operation failed. - * - */ - public void startTag(String tagName, boolean isChildNode) - throws PaintException { - // In case of null data output nothing: - if (tagName == null) - throw new NullPointerException(); - - // Increments paint tracker - if (this.isTrackPaints()) { - this.numberOfPaints++; - } - - // Ensures that the target is open - if (this.closed) - throw new PaintException( - "Attempted to write to a closed PaintTarget."); - - if (tag != null) { - openJsonTags.push(tag); - } - // Checks tagName and attributes here - mOpenTags.push(tagName); - - tag = new JsonTag(tagName); - - mTagArgumentListOpen = true; - - customLayoutArgumentsOpen = "customlayout".equals(tagName); - - if ("error".equals(tagName)) { - errorsOpen++; - } - } - - /** - * Prints the element end tag. - * - * If the parent tag is closed before every child tag is closed an - * PaintException is raised. - * - * @param tag - * the name of the end tag. - * @throws Paintexception - * if the paint operation failed. - */ - public void endTag(String tagName) throws PaintException { - // In case of null data output nothing: - if (tagName == null) - throw new NullPointerException(); - - // Ensure that the target is open - if (this.closed) - throw new PaintException( - "Attempted to write to a closed PaintTarget."); - - if (openJsonTags.size() > 0) { - JsonTag parent = (JsonTag) openJsonTags.pop(); - - String lastTag = ""; - - lastTag = (String) mOpenTags.pop(); - if (!tagName.equalsIgnoreCase(lastTag)) - throw new PaintException("Invalid UIDL: wrong ending tag: '" - + tagName + "' expected: '" + lastTag + "'."); - - // simple hack which writes error uidl structure into attribute - if ("error".equals(lastTag)) { - if (errorsOpen == 1) // ending error section - parent.addAttribute("\"error\":[\"error\",{}" - + tag.getData() + "]"); - else - // sub error - parent.addData(tag.getJSON()); - errorsOpen--; - } else { - parent.addData(tag.getJSON()); - } - - tag = parent; - } else { - changes++; - this.uidlBuffer.print(((changes > 1) ? "," : "") + tag.getJSON()); - tag = null; - } - } - - /** - * Substitutes the XML sensitive characters with predefined XML entities. - * - * @param xml - * the String to be substituted. - * @return A new string instance where all occurrences of XML sensitive - * characters are substituted with entities. - */ - static public String escapeXML(String xml) { - if (xml == null || xml.length() <= 0) - return ""; - return escapeXML(new StringBuffer(xml)).toString(); - } - - /** - * Substitutes the XML sensitive characters with predefined XML entities. - * - * @param xml - * the String to be substituted. - * @return A new StringBuffer instance where all occurrences of XML - * sensitive characters are substituted with entities. - * - */ - static public StringBuffer escapeXML(StringBuffer xml) { - if (xml == null || xml.length() <= 0) - return new StringBuffer(""); - - StringBuffer result = new StringBuffer(xml.length() * 2); - - for (int i = 0; i < xml.length(); i++) { - char c = xml.charAt(i); - String s = toXmlChar(c); - if (s != null) { - result.append(s); - } else { - result.append(c); - } - } - return result; - } - - static public String escapeJSON(String s) { - if (s == null) - return ""; - StringBuffer sb = new StringBuffer(); - for (int i = 0; i < s.length(); i++) { - char ch = s.charAt(i); - switch (ch) { - case '"': - sb.append("\\\""); - break; - case '\\': - sb.append("\\\\"); - break; - case '\b': - sb.append("\\b"); - break; - case '\f': - sb.append("\\f"); - break; - case '\n': - sb.append("\\n"); - break; - case '\r': - sb.append("\\r"); - break; - case '\t': - sb.append("\\t"); - break; - case '/': - sb.append("\\/"); - break; - default: - if (ch >= '\u0000' && ch <= '\u001F') { - String ss = Integer.toHexString(ch); - sb.append("\\u"); - for (int k = 0; k < 4 - ss.length(); k++) { - sb.append('0'); - } - sb.append(ss.toUpperCase()); - } else { - sb.append(ch); - } - } - } - return sb.toString(); - } - - /** - * Substitutes a XML sensitive character with predefined XML entity. - * - * @param c - * the Character to be replaced with an entity. - * @return String of the entity or null if character is not to be replaced - * with an entity. - */ - private static String toXmlChar(char c) { - switch (c) { - case '&': - return "&"; // & => & - case '>': - return ">"; // > => > - case '<': - return "<"; // < => < - case '"': - return """; // " => " - case '\'': - return "'"; // ' => ' - default: - return null; - } - } - - /** - * Prints XML-escaped text. - * - * @param str - * @throws PaintException - * if the paint operation failed. - * - */ - public void addText(String str) throws PaintException { - tag.addData("\"" + escapeJSON(str) + "\""); - } - - /** - * Adds a boolean attribute to component. Atributes must be added before any - * content is written. - * - * @param name - * the Attribute name. - * @param value - * the Attribute value. - * @throws PaintException - * if the paint operation failed. - */ - public void addAttribute(String name, boolean value) throws PaintException { - tag.addAttribute("\"" + name + "\":" + (value ? "true" : "false")); - } - - /** - * Adds a resource attribute to component. Attributes must be added before - * any content is written. - * - * @param name - * the Attribute name. - * @param value - * the Attribute value. - * - * @throws PaintException - * if the paint operation failed. - */ - public void addAttribute(String name, Resource value) throws PaintException { - - if (value instanceof ExternalResource) { - addAttribute(name, ((ExternalResource) value).getURL()); - - } else if (value instanceof ApplicationResource) { - ApplicationResource r = (ApplicationResource) value; - Application a = r.getApplication(); - if (a == null) - throw new PaintException( - "Application not specified for resorce " - + value.getClass().getName()); - String uri; - if(a.getURL() != null) - uri = a.getURL().getPath(); - else - uri = ""; - if (uri.length() > 0 && uri.charAt(uri.length() - 1) != '/') - uri += "/"; - uri += a.getRelativeLocation(r); - addAttribute(name, uri); - - } else if (value instanceof ThemeResource) { - String uri = "theme://" + ((ThemeResource) value).getResourceId(); - addAttribute(name, uri); - } else - throw new PaintException("Ajax adapter does not " - + "support resources of type: " - + value.getClass().getName()); - - } - - /** - * Adds a integer attribute to component. Atributes must be added before any - * content is written. - * - * @param name - * the Attribute name. - * @param value - * the Attribute value. - * - * @throws PaintException - * if the paint operation failed. - */ - public void addAttribute(String name, int value) throws PaintException { - tag.addAttribute("\"" + name + "\":" + String.valueOf(value)); - } - - /** - * Adds a long attribute to component. Atributes must be added before any - * content is written. - * - * @param name - * the Attribute name. - * @param value - * the Attribute value. - * - * @throws PaintException - * if the paint operation failed. - */ - public void addAttribute(String name, long value) throws PaintException { - tag.addAttribute("\"" + name + "\":" + String.valueOf(value)); - } - - /** - * Adds a float attribute to component. Atributes must be added before any - * content is written. - * - * @param name - * the Attribute name. - * @param value - * the Attribute value. - * - * @throws PaintException - * if the paint operation failed. - */ - public void addAttribute(String name, float value) throws PaintException { - tag.addAttribute("\"" + name + "\":" + String.valueOf(value)); - } - - /** - * Adds a double attribute to component. Atributes must be added before any - * content is written. - * - * @param name - * the Attribute name. - * @param value - * the Attribute value. - * - * @throws PaintException - * if the paint operation failed. - */ - public void addAttribute(String name, double value) throws PaintException { - tag.addAttribute("\"" + name + "\":" + String.valueOf(value)); - } - - /** - * Adds a string attribute to component. Atributes must be added before any - * content is written. - * - * @param name - * the String attribute name. - * @param value - * the String attribute value. - * - * @throws PaintException - * if the paint operation failed. - */ - public void addAttribute(String name, String value) throws PaintException { - // In case of null data output nothing: - if ((value == null) || (name == null)) - throw new NullPointerException( - "Parameters must be non-null strings"); - - tag.addAttribute("\"" + name + "\": \"" + escapeJSON(value) + "\""); - - if (customLayoutArgumentsOpen && "template".equals(name)) - getPreCachedResources().add("layouts/" + value + ".html"); - - if (name.equals("locale")) - manager.requireLocale(value); - - } - - public void addAttribute(String name, Object[] values) { - // In case of null data output nothing: - if ((values == null) || (name == null)) - throw new NullPointerException( - "Parameters must be non-null strings"); - StringBuffer buf = new StringBuffer(); - buf.append("\"" + name + "\":["); - for (int i = 0; i < values.length; i++) { - if (i > 0) - buf.append(","); - buf.append("\""); - buf.append(escapeJSON(values[i].toString())); - buf.append("\""); - } - buf.append("]"); - tag.addAttribute(buf.toString()); - } - - /** - * Adds a string type variable. - * - * @param owner - * the Listener for variable changes. - * @param name - * the Variable name. - * @param value - * the Variable initial value. - * - * @throws PaintException - * if the paint operation failed. - */ - public void addVariable(VariableOwner owner, String name, String value) - throws PaintException { - tag.addVariable(new StringVariable(owner, name, value)); - } - - /** - * Adds a int type variable. - * - * @param owner - * the Listener for variable changes. - * @param name - * the Variable name. - * @param value - * the Variable initial value. - * - * @throws PaintException - * if the paint operation failed. - */ - public void addVariable(VariableOwner owner, String name, int value) - throws PaintException { - tag.addVariable(new IntVariable(owner, name, value)); - } - - /** - * Adds a long type variable. - * - * @param owner - * the Listener for variable changes. - * @param name - * the Variable name. - * @param value - * the Variable initial value. - * - * @throws PaintException - * if the paint operation failed. - */ - public void addVariable(VariableOwner owner, String name, long value) - throws PaintException { - tag.addVariable(new LongVariable(owner, name, value)); - } - - /** - * Adds a float type variable. - * - * @param owner - * the Listener for variable changes. - * @param name - * the Variable name. - * @param value - * the Variable initial value. - * - * @throws PaintException - * if the paint operation failed. - */ - public void addVariable(VariableOwner owner, String name, float value) - throws PaintException { - tag.addVariable(new FloatVariable(owner, name, value)); - } - - /** - * Adds a double type variable. - * - * @param owner - * the Listener for variable changes. - * @param name - * the Variable name. - * @param value - * the Variable initial value. - * - * @throws PaintException - * if the paint operation failed. - */ - public void addVariable(VariableOwner owner, String name, double value) - throws PaintException { - tag.addVariable(new DoubleVariable(owner, name, value)); - } - - /** - * Adds a boolean type variable. - * - * @param owner - * the Listener for variable changes. - * @param name - * the Variable name. - * @param value - * the Variable initial value. - * - * @throws PaintException - * if the paint operation failed. - */ - public void addVariable(VariableOwner owner, String name, boolean value) - throws PaintException { - tag.addVariable(new BooleanVariable(owner, name, value)); - } - - /** - * Adds a string array type variable. - * - * @param owner - * the Listener for variable changes. - * @param name - * the Variable name. - * @param value - * the Variable initial value. - * - * @throws PaintException - * if the paint operation failed. - */ - public void addVariable(VariableOwner owner, String name, String[] value) - throws PaintException { - tag.addVariable(new ArrayVariable(owner, name, value)); - } - - /** - * Adds a upload stream type variable. - * - * TODO not converted for JSON - * - * @param owner - * the Listener for variable changes. - * @param name - * the Variable name. - * - * @throws PaintException - * if the paint operation failed. - */ - public void addUploadStreamVariable(VariableOwner owner, String name) - throws PaintException { - startTag("uploadstream"); - addAttribute(UIDL_ARG_NAME, name); - endTag("uploadstream"); - } - - /** - * Prints the single text section. - * - * Prints full text section. The section data is escaped - * - * @param sectionTagName - * the name of the tag. - * @param sectionData - * the section data to be printed. - * @throws PaintException - * if the paint operation failed. - */ - public void addSection(String sectionTagName, String sectionData) - throws PaintException { - tag.addData("{\"" + sectionTagName + "\":\"" + escapeJSON(sectionData) - + "\"}"); - } - - /** - * Adds XML directly to UIDL. - * - * @param xml - * the Xml to be added. - * @throws PaintException - * if the paint operation failed. - */ - public void addUIDL(String xml) throws PaintException { - - // Ensure that the target is open - if (this.closed) - throw new PaintException( - "Attempted to write to a closed PaintTarget."); - - // Make sure that the open start tag is closed before - // anything is written. - - // Escape and write what was given - if (xml != null) - tag.addData("\"" + escapeJSON(xml) + "\""); - - } - - /** - * Adds XML section with namespace. - * - * @param sectionTagName - * the name of the tag. - * @param sectionData - * the section data. - * @param namespace - * the namespace to be added. - * @throws PaintException - * if the paint operation failed. - * - * @see com.itmill.toolkit.terminal.PaintTarget#addXMLSection(String, - * String, String) - */ - public void addXMLSection(String sectionTagName, String sectionData, - String namespace) throws PaintException { - - // Ensure that the target is open - if (this.closed) - throw new PaintException( - "Attempted to write to a closed PaintTarget."); - - startTag(sectionTagName); - if (namespace != null) - addAttribute("xmlns", namespace); - mTagArgumentListOpen = false; - customLayoutArgumentsOpen = false; - - if (sectionData != null) - tag.addData("\"" + escapeJSON(sectionData) + "\""); - endTag(sectionTagName); - } - - /** - * Gets the UIDL already printed to stream. Paint target must be closed - * before the getUIDL can be called. - * - * @return the UIDL. - */ - public String getUIDL() { - if (this.closed) { - return uidlBuffer.toString(); - } - throw new IllegalStateException( - "Tried to read UIDL from open PaintTarget"); - } - - /** - * Closes the paint target. Paint target must be closed before the - * getUIDL can be called. Subsequent attempts to write to - * paint target. If the target was already closed, call to this function is - * ignored. will generate an exception. - * - * @throws PaintException - * if the paint operation failed. - */ - public void close() throws PaintException { - if (tag != null) - uidlBuffer.write(tag.getJSON()); - flush(); - this.closed = true; - } - - /** - * Method flush. - */ - private void flush() { - this.uidlBuffer.flush(); - } - - /** - * @see com.itmill.toolkit.terminal.PaintTarget#startTag(com.itmill.toolkit.terminal.Paintable, - * java.lang.String) - */ - public boolean startTag(Paintable paintable, String tagName) - throws PaintException { - startTag(tagName, true); - boolean isPreviouslyPainted = manager.hasPaintableId(paintable); - String id = manager.getPaintableId(paintable); - paintable.addListener(manager); - addAttribute("id", id); - return cacheEnabled && isPreviouslyPainted; - } - - /** - * @see com.itmill.toolkit.terminal.PaintTarget#addCharacterData(java.lang.String) - */ - public void addCharacterData(String text) throws PaintException { - if (text != null) - tag.addData(text); - } - - /** - * - * @return - */ - public boolean isTrackPaints() { - return trackPaints; - } - - /** - * Gets the number of paints. - * - * @return the number of paints. - */ - public int getNumberOfPaints() { - return numberOfPaints; - } - - /** - * Sets the tracking to true or false. - * - * This also resets the number of paints. - * - * @param enabled - * is the tracking is enabled or not. - * @see #getNumberOfPaints() - */ - public void setTrackPaints(boolean enabled) { - this.trackPaints = enabled; - this.numberOfPaints = 0; - } - - /** - * This is basically a container for UI components variables, that will be - * added at the end of JSON object. - * - * @author mattitahvonen - * - */ - class JsonTag { - boolean firstField = false; - - Vector variables = new Vector(); - - Vector children = new Vector(); - - Vector attr = new Vector(); - - StringBuffer data = new StringBuffer(); - - public boolean childrenArrayOpen = false; - - private boolean childNode = false; - - private boolean tagClosed = false; - - public JsonTag(String tagName) { - data.append("[\"" + tagName + "\""); - } - - private void closeTag() { - if (!tagClosed) { - data.append(attributesAsJsonObject()); - data.append(getData()); - // Writes the end (closing) tag - data.append("]"); - this.tagClosed = true; - } - } - - public String getJSON() { - if (!tagClosed) { - this.closeTag(); - } - return data.toString(); - } - - public void openChildrenArray() { - if (!childrenArrayOpen) { - // append("c : ["); - childrenArrayOpen = true; - // firstField = true; - } - } - - public void closeChildrenArray() { - // append("]"); - // firstField = false; - } - - public void setChildNode(boolean b) { - this.childNode = b; - } - - public boolean isChildNode() { - return childNode; - } - - public String startField() { - if (firstField) { - firstField = false; - return ""; - } else { - return ","; - } - } - - /** - * - * @param s - * json string, object or array - */ - public void addData(String s) { - children.add(s); - } - - public String getData() { - StringBuffer buf = new StringBuffer(); - Iterator it = children.iterator(); - while (it.hasNext()) { - buf.append(startField()); - buf.append(it.next()); - } - return buf.toString(); - } - - public void addAttribute(String jsonNode) { - attr.add(jsonNode); - } - - private String attributesAsJsonObject() { - StringBuffer buf = new StringBuffer(); - buf.append(startField()); - buf.append("{"); - for (Iterator iter = attr.iterator(); iter.hasNext();) { - String element = (String) iter.next(); - buf.append(element); - if (iter.hasNext()) - buf.append(","); - } - buf.append(tag.variablesAsJsonObject()); - buf.append("}"); - return buf.toString(); - } - - public void addVariable(Variable v) { - variables.add(v); - } - - private String variablesAsJsonObject() { - if (variables.size() == 0) - return ""; - StringBuffer buf = new StringBuffer(); - buf.append(startField()); - buf.append("\"v\":{"); - Iterator iter = variables.iterator(); - while (iter.hasNext()) { - Variable element = (Variable) iter.next(); - buf.append(element.getJsonPresentation()); - if (iter.hasNext()) - buf.append(","); - } - buf.append("}"); - return buf.toString(); - } - - class TagCounter { - int count; - - public TagCounter() { - count = 0; - } - - public void increment() { - count++; - } - - public String postfix(String s) { - if (count > 0) { - return s + count; - } - return s; - } - } - } - - abstract class Variable { - - String name; - - public abstract String getJsonPresentation(); - } - - class BooleanVariable extends Variable { - boolean value; - - public BooleanVariable(VariableOwner owner, String name, boolean v) { - value = v; - this.name = name; - } - - public String getJsonPresentation() { - return "\"" + name + "\":" + (value == true ? "true" : "false"); - } - - } - - class StringVariable extends Variable { - String value; - - public StringVariable(VariableOwner owner, String name, String v) { - value = v; - this.name = name; - } - - public String getJsonPresentation() { - return "\"" + name + "\":\"" + value + "\""; - } - - } - - class IntVariable extends Variable { - int value; - - public IntVariable(VariableOwner owner, String name, int v) { - value = v; - this.name = name; - } - - public String getJsonPresentation() { - return "\"" + name + "\":" + value; - } - } - - class LongVariable extends Variable { - long value; - - public LongVariable(VariableOwner owner, String name, long v) { - value = v; - this.name = name; - } - - public String getJsonPresentation() { - return "\"" + name + "\":" + value; - } - } - - class FloatVariable extends Variable { - float value; - - public FloatVariable(VariableOwner owner, String name, float v) { - value = v; - this.name = name; - } - - public String getJsonPresentation() { - return "\"" + name + "\":" + value; - } - } - - class DoubleVariable extends Variable { - double value; - - public DoubleVariable(VariableOwner owner, String name, double v) { - value = v; - this.name = name; - } - - public String getJsonPresentation() { - return "\"" + name + "\":" + value; - } - } - - class ArrayVariable extends Variable { - String[] value; - - public ArrayVariable(VariableOwner owner, String name, String[] v) { - value = v; - this.name = name; - } - - public String getJsonPresentation() { - String pres = "\"" + name + "\":["; - for (int i = 0; i < value.length;) { - pres += "\"" + value[i] + "\""; - i++; - if (i < value.length) - pres += ","; - } - pres += "]"; - return pres; - } - } - - public Set getPreCachedResources() { - return preCachedResources; - } - - public void setPreCachedResources(Set preCachedResources) { - throw new UnsupportedOperationException(); - } + // Adds document declaration + + // Adds UIDL start tag and its attributes + + cacheEnabled = cachingRequired; + } + + public void startTag(String tagName) throws PaintException { + startTag(tagName, false); + } + + /** + * Prints the element start tag. + * + *
+     *   Todo:
+     *    Checking of input values
+     *    
+     * 
+ * + * @param tagName + * the name of the start tag. + * @throws PaintException + * if the paint operation failed. + * + */ + public void startTag(String tagName, boolean isChildNode) + throws PaintException { + // In case of null data output nothing: + if (tagName == null) { + throw new NullPointerException(); + } + + // Increments paint tracker + if (isTrackPaints()) { + numberOfPaints++; + } + + // Ensures that the target is open + if (closed) { + throw new PaintException( + "Attempted to write to a closed PaintTarget."); + } + + if (tag != null) { + openJsonTags.push(tag); + } + // Checks tagName and attributes here + mOpenTags.push(tagName); + + tag = new JsonTag(tagName); + + mTagArgumentListOpen = true; + + customLayoutArgumentsOpen = "customlayout".equals(tagName); + + if ("error".equals(tagName)) { + errorsOpen++; + } + } + + /** + * Prints the element end tag. + * + * If the parent tag is closed before every child tag is closed an + * PaintException is raised. + * + * @param tag + * the name of the end tag. + * @throws Paintexception + * if the paint operation failed. + */ + public void endTag(String tagName) throws PaintException { + // In case of null data output nothing: + if (tagName == null) { + throw new NullPointerException(); + } + + // Ensure that the target is open + if (closed) { + throw new PaintException( + "Attempted to write to a closed PaintTarget."); + } + + if (openJsonTags.size() > 0) { + JsonTag parent = (JsonTag) openJsonTags.pop(); + + String lastTag = ""; + + lastTag = (String) mOpenTags.pop(); + if (!tagName.equalsIgnoreCase(lastTag)) { + throw new PaintException("Invalid UIDL: wrong ending tag: '" + + tagName + "' expected: '" + lastTag + "'."); + } + + // simple hack which writes error uidl structure into attribute + if ("error".equals(lastTag)) { + if (errorsOpen == 1) { + parent.addAttribute("\"error\":[\"error\",{}" + + tag.getData() + "]"); + } else { + // sub error + parent.addData(tag.getJSON()); + } + errorsOpen--; + } else { + parent.addData(tag.getJSON()); + } + + tag = parent; + } else { + changes++; + uidlBuffer.print(((changes > 1) ? "," : "") + tag.getJSON()); + tag = null; + } + } + + /** + * Substitutes the XML sensitive characters with predefined XML entities. + * + * @param xml + * the String to be substituted. + * @return A new string instance where all occurrences of XML sensitive + * characters are substituted with entities. + */ + static public String escapeXML(String xml) { + if (xml == null || xml.length() <= 0) { + return ""; + } + return escapeXML(new StringBuffer(xml)).toString(); + } + + /** + * Substitutes the XML sensitive characters with predefined XML entities. + * + * @param xml + * the String to be substituted. + * @return A new StringBuffer instance where all occurrences of XML + * sensitive characters are substituted with entities. + * + */ + static public StringBuffer escapeXML(StringBuffer xml) { + if (xml == null || xml.length() <= 0) { + return new StringBuffer(""); + } + + StringBuffer result = new StringBuffer(xml.length() * 2); + + for (int i = 0; i < xml.length(); i++) { + char c = xml.charAt(i); + String s = toXmlChar(c); + if (s != null) { + result.append(s); + } else { + result.append(c); + } + } + return result; + } + + static public String escapeJSON(String s) { + if (s == null) { + return ""; + } + StringBuffer sb = new StringBuffer(); + for (int i = 0; i < s.length(); i++) { + char ch = s.charAt(i); + switch (ch) { + case '"': + sb.append("\\\""); + break; + case '\\': + sb.append("\\\\"); + break; + case '\b': + sb.append("\\b"); + break; + case '\f': + sb.append("\\f"); + break; + case '\n': + sb.append("\\n"); + break; + case '\r': + sb.append("\\r"); + break; + case '\t': + sb.append("\\t"); + break; + case '/': + sb.append("\\/"); + break; + default: + if (ch >= '\u0000' && ch <= '\u001F') { + String ss = Integer.toHexString(ch); + sb.append("\\u"); + for (int k = 0; k < 4 - ss.length(); k++) { + sb.append('0'); + } + sb.append(ss.toUpperCase()); + } else { + sb.append(ch); + } + } + } + return sb.toString(); + } + + /** + * Substitutes a XML sensitive character with predefined XML entity. + * + * @param c + * the Character to be replaced with an entity. + * @return String of the entity or null if character is not to be replaced + * with an entity. + */ + private static String toXmlChar(char c) { + switch (c) { + case '&': + return "&"; // & => & + case '>': + return ">"; // > => > + case '<': + return "<"; // < => < + case '"': + return """; // " => " + case '\'': + return "'"; // ' => ' + default: + return null; + } + } + + /** + * Prints XML-escaped text. + * + * @param str + * @throws PaintException + * if the paint operation failed. + * + */ + public void addText(String str) throws PaintException { + tag.addData("\"" + escapeJSON(str) + "\""); + } + + /** + * Adds a boolean attribute to component. Atributes must be added before any + * content is written. + * + * @param name + * the Attribute name. + * @param value + * the Attribute value. + * @throws PaintException + * if the paint operation failed. + */ + public void addAttribute(String name, boolean value) throws PaintException { + tag.addAttribute("\"" + name + "\":" + (value ? "true" : "false")); + } + + /** + * Adds a resource attribute to component. Attributes must be added before + * any content is written. + * + * @param name + * the Attribute name. + * @param value + * the Attribute value. + * + * @throws PaintException + * if the paint operation failed. + */ + public void addAttribute(String name, Resource value) throws PaintException { + + if (value instanceof ExternalResource) { + addAttribute(name, ((ExternalResource) value).getURL()); + + } else if (value instanceof ApplicationResource) { + ApplicationResource r = (ApplicationResource) value; + Application a = r.getApplication(); + if (a == null) { + throw new PaintException( + "Application not specified for resorce " + + value.getClass().getName()); + } + String uri; + if (a.getURL() != null) { + uri = a.getURL().getPath(); + } else { + uri = ""; + } + if (uri.length() > 0 && uri.charAt(uri.length() - 1) != '/') { + uri += "/"; + } + uri += a.getRelativeLocation(r); + addAttribute(name, uri); + + } else if (value instanceof ThemeResource) { + String uri = "theme://" + ((ThemeResource) value).getResourceId(); + addAttribute(name, uri); + } else { + throw new PaintException("Ajax adapter does not " + + "support resources of type: " + + value.getClass().getName()); + } + + } + + /** + * Adds a integer attribute to component. Atributes must be added before any + * content is written. + * + * @param name + * the Attribute name. + * @param value + * the Attribute value. + * + * @throws PaintException + * if the paint operation failed. + */ + public void addAttribute(String name, int value) throws PaintException { + tag.addAttribute("\"" + name + "\":" + String.valueOf(value)); + } + + /** + * Adds a long attribute to component. Atributes must be added before any + * content is written. + * + * @param name + * the Attribute name. + * @param value + * the Attribute value. + * + * @throws PaintException + * if the paint operation failed. + */ + public void addAttribute(String name, long value) throws PaintException { + tag.addAttribute("\"" + name + "\":" + String.valueOf(value)); + } + + /** + * Adds a float attribute to component. Atributes must be added before any + * content is written. + * + * @param name + * the Attribute name. + * @param value + * the Attribute value. + * + * @throws PaintException + * if the paint operation failed. + */ + public void addAttribute(String name, float value) throws PaintException { + tag.addAttribute("\"" + name + "\":" + String.valueOf(value)); + } + + /** + * Adds a double attribute to component. Atributes must be added before any + * content is written. + * + * @param name + * the Attribute name. + * @param value + * the Attribute value. + * + * @throws PaintException + * if the paint operation failed. + */ + public void addAttribute(String name, double value) throws PaintException { + tag.addAttribute("\"" + name + "\":" + String.valueOf(value)); + } + + /** + * Adds a string attribute to component. Atributes must be added before any + * content is written. + * + * @param name + * the String attribute name. + * @param value + * the String attribute value. + * + * @throws PaintException + * if the paint operation failed. + */ + public void addAttribute(String name, String value) throws PaintException { + // In case of null data output nothing: + if ((value == null) || (name == null)) { + throw new NullPointerException( + "Parameters must be non-null strings"); + } + + tag.addAttribute("\"" + name + "\": \"" + escapeJSON(value) + "\""); + + if (customLayoutArgumentsOpen && "template".equals(name)) { + getPreCachedResources().add("layouts/" + value + ".html"); + } + + if (name.equals("locale")) { + manager.requireLocale(value); + } + + } + + public void addAttribute(String name, Object[] values) { + // In case of null data output nothing: + if ((values == null) || (name == null)) { + throw new NullPointerException( + "Parameters must be non-null strings"); + } + StringBuffer buf = new StringBuffer(); + buf.append("\"" + name + "\":["); + for (int i = 0; i < values.length; i++) { + if (i > 0) { + buf.append(","); + } + buf.append("\""); + buf.append(escapeJSON(values[i].toString())); + buf.append("\""); + } + buf.append("]"); + tag.addAttribute(buf.toString()); + } + + /** + * Adds a string type variable. + * + * @param owner + * the Listener for variable changes. + * @param name + * the Variable name. + * @param value + * the Variable initial value. + * + * @throws PaintException + * if the paint operation failed. + */ + public void addVariable(VariableOwner owner, String name, String value) + throws PaintException { + tag.addVariable(new StringVariable(owner, name, value)); + } + + /** + * Adds a int type variable. + * + * @param owner + * the Listener for variable changes. + * @param name + * the Variable name. + * @param value + * the Variable initial value. + * + * @throws PaintException + * if the paint operation failed. + */ + public void addVariable(VariableOwner owner, String name, int value) + throws PaintException { + tag.addVariable(new IntVariable(owner, name, value)); + } + + /** + * Adds a long type variable. + * + * @param owner + * the Listener for variable changes. + * @param name + * the Variable name. + * @param value + * the Variable initial value. + * + * @throws PaintException + * if the paint operation failed. + */ + public void addVariable(VariableOwner owner, String name, long value) + throws PaintException { + tag.addVariable(new LongVariable(owner, name, value)); + } + + /** + * Adds a float type variable. + * + * @param owner + * the Listener for variable changes. + * @param name + * the Variable name. + * @param value + * the Variable initial value. + * + * @throws PaintException + * if the paint operation failed. + */ + public void addVariable(VariableOwner owner, String name, float value) + throws PaintException { + tag.addVariable(new FloatVariable(owner, name, value)); + } + + /** + * Adds a double type variable. + * + * @param owner + * the Listener for variable changes. + * @param name + * the Variable name. + * @param value + * the Variable initial value. + * + * @throws PaintException + * if the paint operation failed. + */ + public void addVariable(VariableOwner owner, String name, double value) + throws PaintException { + tag.addVariable(new DoubleVariable(owner, name, value)); + } + + /** + * Adds a boolean type variable. + * + * @param owner + * the Listener for variable changes. + * @param name + * the Variable name. + * @param value + * the Variable initial value. + * + * @throws PaintException + * if the paint operation failed. + */ + public void addVariable(VariableOwner owner, String name, boolean value) + throws PaintException { + tag.addVariable(new BooleanVariable(owner, name, value)); + } + + /** + * Adds a string array type variable. + * + * @param owner + * the Listener for variable changes. + * @param name + * the Variable name. + * @param value + * the Variable initial value. + * + * @throws PaintException + * if the paint operation failed. + */ + public void addVariable(VariableOwner owner, String name, String[] value) + throws PaintException { + tag.addVariable(new ArrayVariable(owner, name, value)); + } + + /** + * Adds a upload stream type variable. + * + * TODO not converted for JSON + * + * @param owner + * the Listener for variable changes. + * @param name + * the Variable name. + * + * @throws PaintException + * if the paint operation failed. + */ + public void addUploadStreamVariable(VariableOwner owner, String name) + throws PaintException { + startTag("uploadstream"); + addAttribute(UIDL_ARG_NAME, name); + endTag("uploadstream"); + } + + /** + * Prints the single text section. + * + * Prints full text section. The section data is escaped + * + * @param sectionTagName + * the name of the tag. + * @param sectionData + * the section data to be printed. + * @throws PaintException + * if the paint operation failed. + */ + public void addSection(String sectionTagName, String sectionData) + throws PaintException { + tag.addData("{\"" + sectionTagName + "\":\"" + escapeJSON(sectionData) + + "\"}"); + } + + /** + * Adds XML directly to UIDL. + * + * @param xml + * the Xml to be added. + * @throws PaintException + * if the paint operation failed. + */ + public void addUIDL(String xml) throws PaintException { + + // Ensure that the target is open + if (closed) { + throw new PaintException( + "Attempted to write to a closed PaintTarget."); + } + + // Make sure that the open start tag is closed before + // anything is written. + + // Escape and write what was given + if (xml != null) { + tag.addData("\"" + escapeJSON(xml) + "\""); + } + + } + + /** + * Adds XML section with namespace. + * + * @param sectionTagName + * the name of the tag. + * @param sectionData + * the section data. + * @param namespace + * the namespace to be added. + * @throws PaintException + * if the paint operation failed. + * + * @see com.itmill.toolkit.terminal.PaintTarget#addXMLSection(String, + * String, String) + */ + public void addXMLSection(String sectionTagName, String sectionData, + String namespace) throws PaintException { + + // Ensure that the target is open + if (closed) { + throw new PaintException( + "Attempted to write to a closed PaintTarget."); + } + + startTag(sectionTagName); + if (namespace != null) { + addAttribute("xmlns", namespace); + } + mTagArgumentListOpen = false; + customLayoutArgumentsOpen = false; + + if (sectionData != null) { + tag.addData("\"" + escapeJSON(sectionData) + "\""); + } + endTag(sectionTagName); + } + + /** + * Gets the UIDL already printed to stream. Paint target must be closed + * before the getUIDL can be called. + * + * @return the UIDL. + */ + public String getUIDL() { + if (closed) { + return uidlBuffer.toString(); + } + throw new IllegalStateException( + "Tried to read UIDL from open PaintTarget"); + } + + /** + * Closes the paint target. Paint target must be closed before the + * getUIDL can be called. Subsequent attempts to write to + * paint target. If the target was already closed, call to this function is + * ignored. will generate an exception. + * + * @throws PaintException + * if the paint operation failed. + */ + public void close() throws PaintException { + if (tag != null) { + uidlBuffer.write(tag.getJSON()); + } + flush(); + closed = true; + } + + /** + * Method flush. + */ + private void flush() { + uidlBuffer.flush(); + } + + /** + * @see com.itmill.toolkit.terminal.PaintTarget#startTag(com.itmill.toolkit.terminal.Paintable, + * java.lang.String) + */ + public boolean startTag(Paintable paintable, String tagName) + throws PaintException { + startTag(tagName, true); + boolean isPreviouslyPainted = manager.hasPaintableId(paintable); + String id = manager.getPaintableId(paintable); + paintable.addListener(manager); + addAttribute("id", id); + return cacheEnabled && isPreviouslyPainted; + } + + /** + * @see com.itmill.toolkit.terminal.PaintTarget#addCharacterData(java.lang.String) + */ + public void addCharacterData(String text) throws PaintException { + if (text != null) { + tag.addData(text); + } + } + + /** + * + * @return + */ + public boolean isTrackPaints() { + return trackPaints; + } + + /** + * Gets the number of paints. + * + * @return the number of paints. + */ + public int getNumberOfPaints() { + return numberOfPaints; + } + + /** + * Sets the tracking to true or false. + * + * This also resets the number of paints. + * + * @param enabled + * is the tracking is enabled or not. + * @see #getNumberOfPaints() + */ + public void setTrackPaints(boolean enabled) { + trackPaints = enabled; + numberOfPaints = 0; + } + + /** + * This is basically a container for UI components variables, that will be + * added at the end of JSON object. + * + * @author mattitahvonen + * + */ + class JsonTag { + boolean firstField = false; + + Vector variables = new Vector(); + + Vector children = new Vector(); + + Vector attr = new Vector(); + + StringBuffer data = new StringBuffer(); + + public boolean childrenArrayOpen = false; + + private boolean childNode = false; + + private boolean tagClosed = false; + + public JsonTag(String tagName) { + data.append("[\"" + tagName + "\""); + } + + private void closeTag() { + if (!tagClosed) { + data.append(attributesAsJsonObject()); + data.append(getData()); + // Writes the end (closing) tag + data.append("]"); + tagClosed = true; + } + } + + public String getJSON() { + if (!tagClosed) { + closeTag(); + } + return data.toString(); + } + + public void openChildrenArray() { + if (!childrenArrayOpen) { + // append("c : ["); + childrenArrayOpen = true; + // firstField = true; + } + } + + public void closeChildrenArray() { + // append("]"); + // firstField = false; + } + + public void setChildNode(boolean b) { + childNode = b; + } + + public boolean isChildNode() { + return childNode; + } + + public String startField() { + if (firstField) { + firstField = false; + return ""; + } else { + return ","; + } + } + + /** + * + * @param s + * json string, object or array + */ + public void addData(String s) { + children.add(s); + } + + public String getData() { + StringBuffer buf = new StringBuffer(); + Iterator it = children.iterator(); + while (it.hasNext()) { + buf.append(startField()); + buf.append(it.next()); + } + return buf.toString(); + } + + public void addAttribute(String jsonNode) { + attr.add(jsonNode); + } + + private String attributesAsJsonObject() { + StringBuffer buf = new StringBuffer(); + buf.append(startField()); + buf.append("{"); + for (Iterator iter = attr.iterator(); iter.hasNext();) { + String element = (String) iter.next(); + buf.append(element); + if (iter.hasNext()) { + buf.append(","); + } + } + buf.append(tag.variablesAsJsonObject()); + buf.append("}"); + return buf.toString(); + } + + public void addVariable(Variable v) { + variables.add(v); + } + + private String variablesAsJsonObject() { + if (variables.size() == 0) { + return ""; + } + StringBuffer buf = new StringBuffer(); + buf.append(startField()); + buf.append("\"v\":{"); + Iterator iter = variables.iterator(); + while (iter.hasNext()) { + Variable element = (Variable) iter.next(); + buf.append(element.getJsonPresentation()); + if (iter.hasNext()) { + buf.append(","); + } + } + buf.append("}"); + return buf.toString(); + } + + class TagCounter { + int count; + + public TagCounter() { + count = 0; + } + + public void increment() { + count++; + } + + public String postfix(String s) { + if (count > 0) { + return s + count; + } + return s; + } + } + } + + abstract class Variable { + + String name; + + public abstract String getJsonPresentation(); + } + + class BooleanVariable extends Variable { + boolean value; + + public BooleanVariable(VariableOwner owner, String name, boolean v) { + value = v; + this.name = name; + } + + public String getJsonPresentation() { + return "\"" + name + "\":" + (value == true ? "true" : "false"); + } + + } + + class StringVariable extends Variable { + String value; + + public StringVariable(VariableOwner owner, String name, String v) { + value = v; + this.name = name; + } + + public String getJsonPresentation() { + return "\"" + name + "\":\"" + value + "\""; + } + + } + + class IntVariable extends Variable { + int value; + + public IntVariable(VariableOwner owner, String name, int v) { + value = v; + this.name = name; + } + + public String getJsonPresentation() { + return "\"" + name + "\":" + value; + } + } + + class LongVariable extends Variable { + long value; + + public LongVariable(VariableOwner owner, String name, long v) { + value = v; + this.name = name; + } + + public String getJsonPresentation() { + return "\"" + name + "\":" + value; + } + } + + class FloatVariable extends Variable { + float value; + + public FloatVariable(VariableOwner owner, String name, float v) { + value = v; + this.name = name; + } + + public String getJsonPresentation() { + return "\"" + name + "\":" + value; + } + } + + class DoubleVariable extends Variable { + double value; + + public DoubleVariable(VariableOwner owner, String name, double v) { + value = v; + this.name = name; + } + + public String getJsonPresentation() { + return "\"" + name + "\":" + value; + } + } + + class ArrayVariable extends Variable { + String[] value; + + public ArrayVariable(VariableOwner owner, String name, String[] v) { + value = v; + this.name = name; + } + + public String getJsonPresentation() { + String pres = "\"" + name + "\":["; + for (int i = 0; i < value.length;) { + pres += "\"" + value[i] + "\""; + i++; + if (i < value.length) { + pres += ","; + } + } + pres += "]"; + return pres; + } + } + + public Set getPreCachedResources() { + return preCachedResources; + } + + public void setPreCachedResources(Set preCachedResources) { + throw new UnsupportedOperationException(); + } } diff --git a/src/com/itmill/toolkit/terminal/gwt/server/WebApplicationContext.java b/src/com/itmill/toolkit/terminal/gwt/server/WebApplicationContext.java index 30c0070b4f..73a43e0858 100644 --- a/src/com/itmill/toolkit/terminal/gwt/server/WebApplicationContext.java +++ b/src/com/itmill/toolkit/terminal/gwt/server/WebApplicationContext.java @@ -57,256 +57,265 @@ import com.itmill.toolkit.ui.Window; * @since 3.1 */ public class WebApplicationContext implements ApplicationContext, - HttpSessionBindingListener { - - private List listeners; - - private HttpSession session; - - private WeakHashMap formActions = new WeakHashMap(); - - private HashSet applications = new HashSet(); - - private WebBrowser browser = new WebBrowser(); - - /** - * Creates a new Web Application Context. - * - * @param session - * the HTTP session. - */ - WebApplicationContext(HttpSession session) { - this.session = session; - } - - /** - * Gets the form action for given window. - *

- * By default, this action is "", which preserves the current url. Commonly - * this is wanted to be set to application.getUrl.toString or - * window.getUrl.toString in order to clean any local links - * or parameters set from the action. - *

- * - * @param window - * the Window for which the action is queried. - * @return the Action to be set into Form action attribute. - */ - public String getWindowFormAction(Window window) { - String action = (String) formActions.get(window); - return action == null ? "" : action; - } - - /** - * Sets the form action for given window. - *

- * By default, this action is "", which preserves the current url. Commonly - * this is wanted to be set to application.getUrl.toString or - * window.getUrl.toString in order to clean any local links - * or parameters set from the action. - *

- * - * @param window - * the Window for which the action is set. - * @param action - * the New action for the window. - */ - public void setWindowFormAction(Window window, String action) { - if (action == null || action == "") - formActions.remove(window); - else - formActions.put(window, action); - } - - /** - * Gets the application context base directory. - * - * @see com.itmill.toolkit.service.ApplicationContext#getBaseDirectory() - */ - public File getBaseDirectory() { - String realPath = ApplicationServlet.getResourcePath(session - .getServletContext(), "/"); - if (realPath == null) - return null; - return new File(realPath); - } - - /** - * Gets the http-session application is running in. - * - * @return HttpSession this application context resides in. - */ - public HttpSession getHttpSession() { - return session; - } - - /** - * Gets the applications in this context. - * - * @see com.itmill.toolkit.service.ApplicationContext#getApplications() - */ - public Collection getApplications() { - - return Collections.unmodifiableCollection(applications); - } - - /** - * Gets the application context for HttpSession. - * - * @param session - * the HTTP session. - * @return the application context for HttpSession. - */ - static public WebApplicationContext getApplicationContext( - HttpSession session) { - WebApplicationContext cx = (WebApplicationContext) session - .getAttribute(WebApplicationContext.class.getName()); - if (cx == null) { - cx = new WebApplicationContext(session); - session.setAttribute(WebApplicationContext.class.getName(), cx); - } - return cx; - } - - /** - * Returns true if and only if the argument is not - * null and is a Boolean object that represents the same - * boolean value as this object. - * - * @param obj - * the object to compare with. - * @see java.lang.Object#equals(java.lang.Object) - */ - public boolean equals(Object obj) { - return session.equals(obj); - } - - /** - * Returns the hash code value . - * - * @see java.lang.Object#hashCode() - */ - public int hashCode() { - return session.hashCode(); - } - - /** - * Adds the transaction listener to this context. - * - * @see com.itmill.toolkit.service.ApplicationContext#addTransactionListener(com.itmill.toolkit.service.ApplicationContext.TransactionListener) - */ - public void addTransactionListener(TransactionListener listener) { - if (this.listeners == null) - this.listeners = new LinkedList(); - this.listeners.add(listener); - } - - /** - * Removes the transaction listener from this context. - * - * @see com.itmill.toolkit.service.ApplicationContext#removeTransactionListener(com.itmill.toolkit.service.ApplicationContext.TransactionListener) - */ - public void removeTransactionListener(TransactionListener listener) { - if (this.listeners != null) - this.listeners.remove(listener); - - } - - /** - * Notifies the transaction start. - * - * @param application - * @param request - * the HTTP request. - */ - protected void startTransaction(Application application, - HttpServletRequest request) { - if (this.listeners == null) - return; - for (Iterator i = this.listeners.iterator(); i.hasNext();) { - ((ApplicationContext.TransactionListener) i.next()) - .transactionStart(application, request); - } - } - - /** - * Notifies the transaction end. - * - * @param application - * @param request - * the HTTP request. - */ - protected void endTransaction(Application application, - HttpServletRequest request) { - if (this.listeners == null) - return; - - LinkedList exceptions = null; - for (Iterator i = this.listeners.iterator(); i.hasNext();) - try { - ((ApplicationContext.TransactionListener) i.next()) - .transactionEnd(application, request); - } catch (RuntimeException t) { - if (exceptions == null) - exceptions = new LinkedList(); - exceptions.add(t); - } - - // If any runtime exceptions occurred, throw a combined exception - if (exceptions != null) { - StringBuffer msg = new StringBuffer(); - for (Iterator i = listeners.iterator(); i.hasNext();) { - RuntimeException e = (RuntimeException) i.next(); - if (msg.length() == 0) - msg.append("\n\n--------------------------\n\n"); - msg.append(e.getMessage() + "\n"); - StringWriter trace = new StringWriter(); - e.printStackTrace(new PrintWriter(trace, true)); - msg.append(trace.toString()); - } - throw new RuntimeException(msg.toString()); - } - } - - protected void removeApplication(Application application) { - applications.remove(application); - } - - protected void addApplication(Application application) { - applications.add(application); - } - - /** - * @see javax.servlet.http.HttpSessionBindingListener#valueBound(HttpSessionBindingEvent) - */ - public void valueBound(HttpSessionBindingEvent arg0) { - // We are not interested in bindings - } - - /** - * @see javax.servlet.http.HttpSessionBindingListener#valueUnbound(HttpSessionBindingEvent) - */ - public void valueUnbound(HttpSessionBindingEvent event) { - // If we are going to be unbound from the session, the session must be - // closing - - while (!applications.isEmpty()) { - Application app = (Application) applications.iterator().next(); - app.close(); - removeApplication(app); - } - } - - /** - * Get the web browser associated with this application context. - * - * Because application context is related to the http session and server - * maintains one session per browser-instance, each context has exactly one - * web browser associated with it. - * - * @return - */ - public WebBrowser getBrowser() { - return browser; - } + HttpSessionBindingListener { + + private List listeners; + + private HttpSession session; + + private WeakHashMap formActions = new WeakHashMap(); + + private HashSet applications = new HashSet(); + + private WebBrowser browser = new WebBrowser(); + + /** + * Creates a new Web Application Context. + * + * @param session + * the HTTP session. + */ + WebApplicationContext(HttpSession session) { + this.session = session; + } + + /** + * Gets the form action for given window. + *

+ * By default, this action is "", which preserves the current url. Commonly + * this is wanted to be set to application.getUrl.toString or + * window.getUrl.toString in order to clean any local links + * or parameters set from the action. + *

+ * + * @param window + * the Window for which the action is queried. + * @return the Action to be set into Form action attribute. + */ + public String getWindowFormAction(Window window) { + String action = (String) formActions.get(window); + return action == null ? "" : action; + } + + /** + * Sets the form action for given window. + *

+ * By default, this action is "", which preserves the current url. Commonly + * this is wanted to be set to application.getUrl.toString or + * window.getUrl.toString in order to clean any local links + * or parameters set from the action. + *

+ * + * @param window + * the Window for which the action is set. + * @param action + * the New action for the window. + */ + public void setWindowFormAction(Window window, String action) { + if (action == null || action == "") { + formActions.remove(window); + } else { + formActions.put(window, action); + } + } + + /** + * Gets the application context base directory. + * + * @see com.itmill.toolkit.service.ApplicationContext#getBaseDirectory() + */ + public File getBaseDirectory() { + String realPath = ApplicationServlet.getResourcePath(session + .getServletContext(), "/"); + if (realPath == null) { + return null; + } + return new File(realPath); + } + + /** + * Gets the http-session application is running in. + * + * @return HttpSession this application context resides in. + */ + public HttpSession getHttpSession() { + return session; + } + + /** + * Gets the applications in this context. + * + * @see com.itmill.toolkit.service.ApplicationContext#getApplications() + */ + public Collection getApplications() { + + return Collections.unmodifiableCollection(applications); + } + + /** + * Gets the application context for HttpSession. + * + * @param session + * the HTTP session. + * @return the application context for HttpSession. + */ + static public WebApplicationContext getApplicationContext( + HttpSession session) { + WebApplicationContext cx = (WebApplicationContext) session + .getAttribute(WebApplicationContext.class.getName()); + if (cx == null) { + cx = new WebApplicationContext(session); + session.setAttribute(WebApplicationContext.class.getName(), cx); + } + return cx; + } + + /** + * Returns true if and only if the argument is not + * null and is a Boolean object that represents the same + * boolean value as this object. + * + * @param obj + * the object to compare with. + * @see java.lang.Object#equals(java.lang.Object) + */ + public boolean equals(Object obj) { + return session.equals(obj); + } + + /** + * Returns the hash code value . + * + * @see java.lang.Object#hashCode() + */ + public int hashCode() { + return session.hashCode(); + } + + /** + * Adds the transaction listener to this context. + * + * @see com.itmill.toolkit.service.ApplicationContext#addTransactionListener(com.itmill.toolkit.service.ApplicationContext.TransactionListener) + */ + public void addTransactionListener(TransactionListener listener) { + if (listeners == null) { + listeners = new LinkedList(); + } + listeners.add(listener); + } + + /** + * Removes the transaction listener from this context. + * + * @see com.itmill.toolkit.service.ApplicationContext#removeTransactionListener(com.itmill.toolkit.service.ApplicationContext.TransactionListener) + */ + public void removeTransactionListener(TransactionListener listener) { + if (listeners != null) { + listeners.remove(listener); + } + + } + + /** + * Notifies the transaction start. + * + * @param application + * @param request + * the HTTP request. + */ + protected void startTransaction(Application application, + HttpServletRequest request) { + if (listeners == null) { + return; + } + for (Iterator i = listeners.iterator(); i.hasNext();) { + ((ApplicationContext.TransactionListener) i.next()) + .transactionStart(application, request); + } + } + + /** + * Notifies the transaction end. + * + * @param application + * @param request + * the HTTP request. + */ + protected void endTransaction(Application application, + HttpServletRequest request) { + if (listeners == null) { + return; + } + + LinkedList exceptions = null; + for (Iterator i = listeners.iterator(); i.hasNext();) { + try { + ((ApplicationContext.TransactionListener) i.next()) + .transactionEnd(application, request); + } catch (RuntimeException t) { + if (exceptions == null) { + exceptions = new LinkedList(); + } + exceptions.add(t); + } + } + + // If any runtime exceptions occurred, throw a combined exception + if (exceptions != null) { + StringBuffer msg = new StringBuffer(); + for (Iterator i = listeners.iterator(); i.hasNext();) { + RuntimeException e = (RuntimeException) i.next(); + if (msg.length() == 0) { + msg.append("\n\n--------------------------\n\n"); + } + msg.append(e.getMessage() + "\n"); + StringWriter trace = new StringWriter(); + e.printStackTrace(new PrintWriter(trace, true)); + msg.append(trace.toString()); + } + throw new RuntimeException(msg.toString()); + } + } + + protected void removeApplication(Application application) { + applications.remove(application); + } + + protected void addApplication(Application application) { + applications.add(application); + } + + /** + * @see javax.servlet.http.HttpSessionBindingListener#valueBound(HttpSessionBindingEvent) + */ + public void valueBound(HttpSessionBindingEvent arg0) { + // We are not interested in bindings + } + + /** + * @see javax.servlet.http.HttpSessionBindingListener#valueUnbound(HttpSessionBindingEvent) + */ + public void valueUnbound(HttpSessionBindingEvent event) { + // If we are going to be unbound from the session, the session must be + // closing + + while (!applications.isEmpty()) { + Application app = (Application) applications.iterator().next(); + app.close(); + removeApplication(app); + } + } + + /** + * Get the web browser associated with this application context. + * + * Because application context is related to the http session and server + * maintains one session per browser-instance, each context has exactly one + * web browser associated with it. + * + * @return + */ + public WebBrowser getBrowser() { + return browser; + } } diff --git a/src/com/itmill/toolkit/terminal/gwt/server/WebBrowser.java b/src/com/itmill/toolkit/terminal/gwt/server/WebBrowser.java index 3e78a9180a..a5c94cbd29 100644 --- a/src/com/itmill/toolkit/terminal/gwt/server/WebBrowser.java +++ b/src/com/itmill/toolkit/terminal/gwt/server/WebBrowser.java @@ -8,85 +8,86 @@ import com.itmill.toolkit.terminal.Terminal; public class WebBrowser implements Terminal { - private int screenHeight = 0; - private int screenWidth = 0; - private String browserApplication = null; - private Locale locale; - private String address; - private boolean secureConnection; - - /** - * There is no default-theme for this terminal type. - * - * @return Allways returns null. - */ - public String getDefaultTheme() { - return null; - } - - /** - * Get the height of the users display in pixels. - * - */ - public int getScreenHeight() { - return screenHeight; - } - - /** - * Get the width of the users display in pixels. - * - */ - public int getScreenWidth() { - return screenWidth; - } - - /** - * Get the browser user-agent string. - * - * @return - */ - public String getBrowserApplication() { - return browserApplication; - } - - void updateBrowserProperties(HttpServletRequest request) { - locale = request.getLocale(); - address = request.getRemoteAddr(); - secureConnection = request.isSecure(); - - String agent = request.getHeader("user-agent"); - if (agent != null) - browserApplication = agent; - - String sw = request.getParameter("screenWidth"); - String sh = request.getParameter("screenHeight"); - if (sw != null && sh != null) { - try { - screenHeight = Integer.parseInt(sh); - screenWidth = Integer.parseInt(sw); - } catch (NumberFormatException e) { - screenHeight = screenWidth = 0; - } - } - } - - /** - * Get the IP-address of the web browser. - * - * @return IP-address in 1.12.123.123 -format - */ - public String getAddress() { - return address; - } - - /** Get the default locate of the browser. */ - public Locale getLocale() { - return locale; - } - - /** Is the connection made using HTTPS? */ - public boolean isSecureConnection() { - return secureConnection; - } + private int screenHeight = 0; + private int screenWidth = 0; + private String browserApplication = null; + private Locale locale; + private String address; + private boolean secureConnection; + + /** + * There is no default-theme for this terminal type. + * + * @return Allways returns null. + */ + public String getDefaultTheme() { + return null; + } + + /** + * Get the height of the users display in pixels. + * + */ + public int getScreenHeight() { + return screenHeight; + } + + /** + * Get the width of the users display in pixels. + * + */ + public int getScreenWidth() { + return screenWidth; + } + + /** + * Get the browser user-agent string. + * + * @return + */ + public String getBrowserApplication() { + return browserApplication; + } + + void updateBrowserProperties(HttpServletRequest request) { + locale = request.getLocale(); + address = request.getRemoteAddr(); + secureConnection = request.isSecure(); + + String agent = request.getHeader("user-agent"); + if (agent != null) { + browserApplication = agent; + } + + String sw = request.getParameter("screenWidth"); + String sh = request.getParameter("screenHeight"); + if (sw != null && sh != null) { + try { + screenHeight = Integer.parseInt(sh); + screenWidth = Integer.parseInt(sw); + } catch (NumberFormatException e) { + screenHeight = screenWidth = 0; + } + } + } + + /** + * Get the IP-address of the web browser. + * + * @return IP-address in 1.12.123.123 -format + */ + public String getAddress() { + return address; + } + + /** Get the default locate of the browser. */ + public Locale getLocale() { + return locale; + } + + /** Is the connection made using HTTPS? */ + public boolean isSecureConnection() { + return secureConnection; + } } diff --git a/src/com/itmill/toolkit/terminal/web/ApplicationServlet.java b/src/com/itmill/toolkit/terminal/web/ApplicationServlet.java index 67d5666be9..ff9dcefe5c 100644 --- a/src/com/itmill/toolkit/terminal/web/ApplicationServlet.java +++ b/src/com/itmill/toolkit/terminal/web/ApplicationServlet.java @@ -15,14 +15,14 @@ import javax.servlet.ServletException; * @since 5.0 */ public class ApplicationServlet extends - com.itmill.toolkit.terminal.gwt.server.ApplicationServlet { + com.itmill.toolkit.terminal.gwt.server.ApplicationServlet { - private static final long serialVersionUID = -1471357707917217303L; + private static final long serialVersionUID = -1471357707917217303L; - public void init(ServletConfig servletConfig) throws ServletException { - System.err - .println("Compatiblity class in use. Please use com.itmill.toolkit.terminal.gwt.server.ApplicationServlet instead. You probably need to update your web.xml."); - super.init(servletConfig); - } + public void init(ServletConfig servletConfig) throws ServletException { + System.err + .println("Compatiblity class in use. Please use com.itmill.toolkit.terminal.gwt.server.ApplicationServlet instead. You probably need to update your web.xml."); + super.init(servletConfig); + } } diff --git a/src/com/itmill/toolkit/tests/BasicRandomTest.java b/src/com/itmill/toolkit/tests/BasicRandomTest.java index 0b9c1bb180..6e248f1177 100644 --- a/src/com/itmill/toolkit/tests/BasicRandomTest.java +++ b/src/com/itmill/toolkit/tests/BasicRandomTest.java @@ -6,7 +6,22 @@ import java.util.Random; import com.itmill.toolkit.terminal.ClassResource; import com.itmill.toolkit.terminal.ExternalResource; -import com.itmill.toolkit.ui.*; +import com.itmill.toolkit.ui.AbstractComponent; +import com.itmill.toolkit.ui.Button; +import com.itmill.toolkit.ui.Component; +import com.itmill.toolkit.ui.ComponentContainer; +import com.itmill.toolkit.ui.DateField; +import com.itmill.toolkit.ui.Embedded; +import com.itmill.toolkit.ui.GridLayout; +import com.itmill.toolkit.ui.Label; +import com.itmill.toolkit.ui.Layout; +import com.itmill.toolkit.ui.Link; +import com.itmill.toolkit.ui.OrderedLayout; +import com.itmill.toolkit.ui.Panel; +import com.itmill.toolkit.ui.Select; +import com.itmill.toolkit.ui.TabSheet; +import com.itmill.toolkit.ui.TextField; +import com.itmill.toolkit.ui.Window; /** * ATFTest is an application that is used to ensure compatibility with automated @@ -32,418 +47,428 @@ import com.itmill.toolkit.ui.*; * */ public class BasicRandomTest extends com.itmill.toolkit.Application implements - Button.ClickListener { + Button.ClickListener { - // Seed with fixed number to ensure predeterministic AUT behaviour - private Random rand; + // Seed with fixed number to ensure predeterministic AUT behaviour + private Random rand; - // How many "noise" components are added to AUT - private static int COMPONENT_NUMBER = 10; + // How many "noise" components are added to AUT + private static int COMPONENT_NUMBER = 10; - private static int COMPONENT_MAX_GROUPED_NUMBER = 5; + private static int COMPONENT_MAX_GROUPED_NUMBER = 5; - private OrderedLayout mainLayout = new OrderedLayout(); - - private Layout testingLayout; - - private TextField randomSeedValue = new TextField("Seed for random"); - - private Button seedShuffle = new Button("Shuffle with seed", this, - "seedShuffle"); - - private Button randomShuffle = new Button("Seed randomly and shuffle", - this, "randomShuffle"); - - private Label display = null; - - private double stored = 0.0; - - private double current = 0.0; - - private String operation = "C"; - - private long captionCounter = 0; - - private ArrayList components; - - private long eventCounter = 0; - - private Label statusLabel = new Label(); - - // Store button object => real value map - // needed because button captions are randomized - private HashMap buttonValues; - - public void init() { - // addWindow(new Window("ATFTest", create())); - Window mainWindow = new Window("Testing", create()); - setMainWindow(mainWindow); - - setUser(new Long(System.currentTimeMillis()).toString()); - } - - /** - * Create application UI components and it's main layout. Does not attach - * layout to any specific application. - * - * @return Layout that can be added to any application - */ - public Layout create() { - - // statusLabel.setUIID("Label_status"); - - // Setup contains restart button and deterministic component shuffler - // Test requirement: test cases must be reproducable (use seed) - mainLayout.addComponent(new Label( - "

ATFTest with randomized Calculator functionality

" - + "Buttons with X captions contain calculator number, " - + "minus, add, multiply, divisor or clear " - + "button functionalities.
Layouts, \"noise\" " - + "components and component placing is randomized " - + "after each application restart.
" - + "Test cases should exercise calculator functions " - + "through X buttons and ensure that Result label " - + "contains correct value.", Label.CONTENT_XHTML)); - - OrderedLayout setupLayout = new OrderedLayout( - OrderedLayout.ORIENTATION_HORIZONTAL); - Panel statusPanel = new Panel("Status"); - statusPanel.setWidth(200); - setupLayout.addComponent(statusPanel); - statusPanel.addComponent(statusLabel); - setupLayout.addComponent(randomSeedValue); - setupLayout.addComponent(seedShuffle); - setupLayout.addComponent(randomShuffle); - setupLayout.addComponent(new Button("restart", this, "close")); - mainLayout.addComponent(setupLayout); - - // randomSeedValue.setUIID("randomSeedValue"); - // seedShuffle.setUIID("seedShuffle"); - // randomShuffle.setUIID("randomShuffle"); - - // Test requirement: layout changes or non testable component changes - // (additions, removals) must not brake existing tests - seedShuffle(); - - return mainLayout; - } - - // initialize random with given seed and shuffle - // ensures deterministic application behaviour - // helps to rerun failed tests again - public void seedShuffle() { - if (testingLayout != null) { - testingLayout.removeAllComponents(); - mainLayout.removeComponent(testingLayout); - } - try { - // randomize using user given value - rand = new Random(Long.parseLong((String) randomSeedValue - .getValue())); - } catch (Exception e) { - randomize(); - } - testingLayout = new GridLayout(5, 5); - mainLayout.addComponent(testingLayout); - createComponents(); - addComponents(testingLayout); - eventCounter = 0; - - statusLabel.setValue("#" + eventCounter + ": button " - + ", value " + Double.toString(current)); - } - - // initialize random with random seed and shuffle - // creates new application behaviour - public void randomShuffle() { - randomize(); - seedShuffle(); - } - - private void randomize() { - long newSeed = System.currentTimeMillis(); - rand = new Random(newSeed); - randomSeedValue.setValue(String.valueOf(newSeed)); - } - - private void createComponents() { - - // - // Create components that have UUID defined - // - components = new ArrayList(); - - // create label - Label userLabel = new Label("user"); - userLabel.setValue(this.getUser()); - // userLabel.setUIID("Label_user"); - components.add(userLabel); - - // create label - display = new Label(Double.toString(current)); - display.setCaption("Result"); - // display.setUIID("Label_result"); - components.add(display); - - // create calculator buttonsStatus: - String[][] calcValues = { - { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "+", "-", - "*", "/", "=", "C" }, - { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "plus", - "minus", "multiple", "divisor", "equals", "clear" } }; - String[] randomizedCaptions = { "a", "b", "c", "y", "8", "3" }; - // String[] randomizedCaptions = { "X" }; - buttonValues = new HashMap(); - for (int i = 0; i > calcValues[0].length; i++) { - Button button = new Button("", this); - // Test requirement: ATF must not rely on caption - // button.setCaption(randomizedCaptions[rand - // .nextInt(randomizedCaptions.length)]); - button.setCaption(calcValues[1][i]); - // Test requirement: ATF may use UIIDs - // button.setUIID("Button_" + calcValues[1][i]); - components.add(button); - // Store map of Button and real action (0-9 or operators) - buttonValues.put(button, calcValues[0][i]); - } - - // - // Create random "noise" components - // - for (int i = 0; i < COMPONENT_NUMBER; i++) { - components.add(getRandomComponent("")); - } - } - - /** - * Get component that has UUID defined. May be used for testing AUT. - * - * @return - */ - private Component getComponent() { - if (components.size() > 0) { - // components found, return any - int i = rand.nextInt(components.size()); - Component c = (Component) components.get(i); - components.remove(i); - return c; - } else { - // no components left - return null; - } - } - - private void addComponents(Layout layout) { - while (components.size() > 0) { - // Get random container - ComponentContainer container = getRandomComponentContainer("" - + captionCounter++); - layout.addComponent(container); - // Get random amount of components for above container - int groupsize = rand.nextInt(COMPONENT_MAX_GROUPED_NUMBER) + 1; - for (int j = 0; j < groupsize; j++) { - Component c = getComponent(); - if (c != null) { - if (container instanceof TabSheet) { - ComponentContainer tab = (ComponentContainer) ((TabSheet) container) - .getSelectedTab(); - tab.addComponent(c); - } else if (container instanceof GridLayout) { - GridLayout gl = (GridLayout) container; - if (j == 0) { - int x = rand.nextInt(gl.getWidth()); - int y = rand.nextInt(gl.getHeight()); - gl.removeComponent(x, y); - gl.addComponent(c, x, y); - } else { - gl.addComponent(c); - } - } else { - container.addComponent(c); - } - } - } - } - } - - public void buttonClick(Button.ClickEvent event) { - String value = (String) buttonValues.get(event.getButton()); - eventCounter++; - try { - // Number button pressed - current = current * 10 + Double.parseDouble(value); - display.setValue(Double.toString(current)); - statusLabel.setValue("#" + eventCounter + ": button " + value - + ", value " + Double.toString(current)); - System.out.println("#" + eventCounter + ": button " + value - + ", value " + Double.toString(current)); - } catch (java.lang.NumberFormatException e) { - // Operation button pressed - if (operation.equals("+")) - stored += current; - if (operation.equals("-")) - stored -= current; - if (operation.equals("*")) - stored *= current; - if (operation.equals("/")) - stored /= current; - if (operation.equals("C")) - stored = current; - if (value.equals("C")) - stored = 0.0; - operation = value; - current = 0.0; - display.setValue(Double.toString(stored)); - statusLabel.setValue("#" + eventCounter + ": button " + value - + ", value " + Double.toString(stored)); - System.out.println("#" + eventCounter + ": button " + value - + ", value " + Double.toString(stored)); - } - } - - /** - * Get random component container - * - * @param caption - * @return - */ - private ComponentContainer getRandomComponentContainer(String caption) { - ComponentContainer result = null; - int randint = rand.nextInt(5); - switch (randint) { - case 0: - result = new OrderedLayout(OrderedLayout.ORIENTATION_HORIZONTAL); - ((OrderedLayout) result).setCaption("OrderedLayout_horizontal_" - + caption); - break; - case 1: - result = new OrderedLayout(OrderedLayout.ORIENTATION_VERTICAL); - ((OrderedLayout) result).setCaption("OrderedLayout_vertical_" - + caption); - break; - case 2: - GridLayout gl; - if (rand.nextInt(1) > 0) - gl = new GridLayout(); - else - gl = new GridLayout(rand.nextInt(3) + 1, rand.nextInt(3) + 1); - gl.setCaption("GridLayout_" + caption); - gl.setDescription(gl.getCaption()); - for (int x = 0; x < gl.getWidth(); x++) - for (int y = 0; y < gl.getHeight(); y++) - gl.addComponent(getExamplePicture("x=" + x + ", y=" + y), - x, y); - result = gl; - break; - case 3: - result = new Panel(); - ((Panel) result).setCaption("Panel_" + caption); - break; - case 4: - TabSheet ts = new TabSheet(); - ts.setCaption("TabSheet_" + caption); - // randomly select one of the tabs - int selectedTab = rand.nextInt(3); - ArrayList tabs = new ArrayList(); - for (int i = 0; i < 3; i++) { - String tabCaption = "tab" + i; - if (selectedTab == i) - tabCaption = "tabX"; - tabs.add(new OrderedLayout()); - ts.addTab((ComponentContainer) tabs.get(tabs.size() - 1), - tabCaption, null); - } - ts.setSelectedTab((ComponentContainer) tabs.get(selectedTab)); - result = (ComponentContainer) ts; - break; - } - - return result; - } - - /** - * Get random component. Used to provide "noise" for AUT. - * - * @param caption - * @return - */ - private AbstractComponent getRandomComponent(String caption) { - AbstractComponent result = null; - int randint = rand.nextInt(7); // calendar disabled - switch (randint) { - case 0: - // Label - result = new Label("Label component " + caption); - break; - case 1: - // Button - result = new Button("Button component " + caption); - break; - case 2: - // TextField - result = new TextField("TextField component " + caption); - break; - case 3: - // Select - result = new Select("Select " + caption); - result.setCaption("Select component " + caption); - ((Select) result).addItem("First item"); - ((Select) result).addItem("Second item"); - ((Select) result).addItem("Third item"); - break; - case 4: - // Link - result = new Link("", new ExternalResource("http://www.itmill.com")); - result.setCaption("Link component " + caption); - break; - case 5: - // Embedded - result = getExamplePicture(caption); - break; - case 6: - // Datefield - result = new DateField(); - ((DateField) result).setValue(new java.util.Date()); - ((DateField) result).setResolution(DateField.RESOLUTION_DAY); - result.setCaption("DateField component " + caption); - break; - case 7: - // Calendar - result = new DateField(); - ((DateField) result).setStyle("calendar"); - ((DateField) result).setValue(new java.util.Date()); - ((DateField) result).setResolution(DateField.RESOLUTION_DAY); - result.setCaption("Calendar component " + caption); - break; - } - - return result; - } - - private AbstractComponent getExamplePicture(String caption) { - ClassResource cr = new ClassResource("icon_demo.png", this); - Embedded em = new Embedded("Embedded " + caption, cr); - return em; - } - - /** - * Add demo components to given layout. Used to provide "noise" for AUT. - * - * @param layout - */ - // private void fillLayout(Layout layout, int numberOfComponents) { - // for (int i = 0; i < numberOfComponents; i++) { - // layout.addComponent(getRandomComponent("" + captionCounter++)); - // } - // } - /** - * ErrorEvents are printed to default error stream and not in GUI. - */ - public void terminalError( - com.itmill.toolkit.terminal.Terminal.ErrorEvent event) { - Throwable e = event.getThrowable(); - System.err.println(getUser().toString() + " terminalError: " - + e.toString()); - e.printStackTrace(); - } + private OrderedLayout mainLayout = new OrderedLayout(); + + private Layout testingLayout; + + private TextField randomSeedValue = new TextField("Seed for random"); + + private Button seedShuffle = new Button("Shuffle with seed", this, + "seedShuffle"); + + private Button randomShuffle = new Button("Seed randomly and shuffle", + this, "randomShuffle"); + + private Label display = null; + + private double stored = 0.0; + + private double current = 0.0; + + private String operation = "C"; + + private long captionCounter = 0; + + private ArrayList components; + + private long eventCounter = 0; + + private Label statusLabel = new Label(); + + // Store button object => real value map + // needed because button captions are randomized + private HashMap buttonValues; + + public void init() { + // addWindow(new Window("ATFTest", create())); + Window mainWindow = new Window("Testing", create()); + setMainWindow(mainWindow); + + setUser(new Long(System.currentTimeMillis()).toString()); + } + + /** + * Create application UI components and it's main layout. Does not attach + * layout to any specific application. + * + * @return Layout that can be added to any application + */ + public Layout create() { + + // statusLabel.setUIID("Label_status"); + + // Setup contains restart button and deterministic component shuffler + // Test requirement: test cases must be reproducable (use seed) + mainLayout.addComponent(new Label( + "

ATFTest with randomized Calculator functionality

" + + "Buttons with X captions contain calculator number, " + + "minus, add, multiply, divisor or clear " + + "button functionalities.
Layouts, \"noise\" " + + "components and component placing is randomized " + + "after each application restart.
" + + "Test cases should exercise calculator functions " + + "through X buttons and ensure that Result label " + + "contains correct value.", Label.CONTENT_XHTML)); + + OrderedLayout setupLayout = new OrderedLayout( + OrderedLayout.ORIENTATION_HORIZONTAL); + Panel statusPanel = new Panel("Status"); + statusPanel.setWidth(200); + setupLayout.addComponent(statusPanel); + statusPanel.addComponent(statusLabel); + setupLayout.addComponent(randomSeedValue); + setupLayout.addComponent(seedShuffle); + setupLayout.addComponent(randomShuffle); + setupLayout.addComponent(new Button("restart", this, "close")); + mainLayout.addComponent(setupLayout); + + // randomSeedValue.setUIID("randomSeedValue"); + // seedShuffle.setUIID("seedShuffle"); + // randomShuffle.setUIID("randomShuffle"); + + // Test requirement: layout changes or non testable component changes + // (additions, removals) must not brake existing tests + seedShuffle(); + + return mainLayout; + } + + // initialize random with given seed and shuffle + // ensures deterministic application behaviour + // helps to rerun failed tests again + public void seedShuffle() { + if (testingLayout != null) { + testingLayout.removeAllComponents(); + mainLayout.removeComponent(testingLayout); + } + try { + // randomize using user given value + rand = new Random(Long.parseLong((String) randomSeedValue + .getValue())); + } catch (Exception e) { + randomize(); + } + testingLayout = new GridLayout(5, 5); + mainLayout.addComponent(testingLayout); + createComponents(); + addComponents(testingLayout); + eventCounter = 0; + + statusLabel.setValue("#" + eventCounter + ": button " + + ", value " + Double.toString(current)); + } + + // initialize random with random seed and shuffle + // creates new application behaviour + public void randomShuffle() { + randomize(); + seedShuffle(); + } + + private void randomize() { + long newSeed = System.currentTimeMillis(); + rand = new Random(newSeed); + randomSeedValue.setValue(String.valueOf(newSeed)); + } + + private void createComponents() { + + // + // Create components that have UUID defined + // + components = new ArrayList(); + + // create label + Label userLabel = new Label("user"); + userLabel.setValue(getUser()); + // userLabel.setUIID("Label_user"); + components.add(userLabel); + + // create label + display = new Label(Double.toString(current)); + display.setCaption("Result"); + // display.setUIID("Label_result"); + components.add(display); + + // create calculator buttonsStatus: + String[][] calcValues = { + { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "+", "-", + "*", "/", "=", "C" }, + { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "plus", + "minus", "multiple", "divisor", "equals", "clear" } }; + String[] randomizedCaptions = { "a", "b", "c", "y", "8", "3" }; + // String[] randomizedCaptions = { "X" }; + buttonValues = new HashMap(); + for (int i = 0; i > calcValues[0].length; i++) { + Button button = new Button("", this); + // Test requirement: ATF must not rely on caption + // button.setCaption(randomizedCaptions[rand + // .nextInt(randomizedCaptions.length)]); + button.setCaption(calcValues[1][i]); + // Test requirement: ATF may use UIIDs + // button.setUIID("Button_" + calcValues[1][i]); + components.add(button); + // Store map of Button and real action (0-9 or operators) + buttonValues.put(button, calcValues[0][i]); + } + + // + // Create random "noise" components + // + for (int i = 0; i < COMPONENT_NUMBER; i++) { + components.add(getRandomComponent("")); + } + } + + /** + * Get component that has UUID defined. May be used for testing AUT. + * + * @return + */ + private Component getComponent() { + if (components.size() > 0) { + // components found, return any + int i = rand.nextInt(components.size()); + Component c = (Component) components.get(i); + components.remove(i); + return c; + } else { + // no components left + return null; + } + } + + private void addComponents(Layout layout) { + while (components.size() > 0) { + // Get random container + ComponentContainer container = getRandomComponentContainer("" + + captionCounter++); + layout.addComponent(container); + // Get random amount of components for above container + int groupsize = rand.nextInt(COMPONENT_MAX_GROUPED_NUMBER) + 1; + for (int j = 0; j < groupsize; j++) { + Component c = getComponent(); + if (c != null) { + if (container instanceof TabSheet) { + ComponentContainer tab = (ComponentContainer) ((TabSheet) container) + .getSelectedTab(); + tab.addComponent(c); + } else if (container instanceof GridLayout) { + GridLayout gl = (GridLayout) container; + if (j == 0) { + int x = rand.nextInt(gl.getWidth()); + int y = rand.nextInt(gl.getHeight()); + gl.removeComponent(x, y); + gl.addComponent(c, x, y); + } else { + gl.addComponent(c); + } + } else { + container.addComponent(c); + } + } + } + } + } + + public void buttonClick(Button.ClickEvent event) { + String value = (String) buttonValues.get(event.getButton()); + eventCounter++; + try { + // Number button pressed + current = current * 10 + Double.parseDouble(value); + display.setValue(Double.toString(current)); + statusLabel.setValue("#" + eventCounter + ": button " + value + + ", value " + Double.toString(current)); + System.out.println("#" + eventCounter + ": button " + value + + ", value " + Double.toString(current)); + } catch (java.lang.NumberFormatException e) { + // Operation button pressed + if (operation.equals("+")) { + stored += current; + } + if (operation.equals("-")) { + stored -= current; + } + if (operation.equals("*")) { + stored *= current; + } + if (operation.equals("/")) { + stored /= current; + } + if (operation.equals("C")) { + stored = current; + } + if (value.equals("C")) { + stored = 0.0; + } + operation = value; + current = 0.0; + display.setValue(Double.toString(stored)); + statusLabel.setValue("#" + eventCounter + ": button " + value + + ", value " + Double.toString(stored)); + System.out.println("#" + eventCounter + ": button " + value + + ", value " + Double.toString(stored)); + } + } + + /** + * Get random component container + * + * @param caption + * @return + */ + private ComponentContainer getRandomComponentContainer(String caption) { + ComponentContainer result = null; + int randint = rand.nextInt(5); + switch (randint) { + case 0: + result = new OrderedLayout(OrderedLayout.ORIENTATION_HORIZONTAL); + ((OrderedLayout) result).setCaption("OrderedLayout_horizontal_" + + caption); + break; + case 1: + result = new OrderedLayout(OrderedLayout.ORIENTATION_VERTICAL); + ((OrderedLayout) result).setCaption("OrderedLayout_vertical_" + + caption); + break; + case 2: + GridLayout gl; + if (rand.nextInt(1) > 0) { + gl = new GridLayout(); + } else { + gl = new GridLayout(rand.nextInt(3) + 1, rand.nextInt(3) + 1); + } + gl.setCaption("GridLayout_" + caption); + gl.setDescription(gl.getCaption()); + for (int x = 0; x < gl.getWidth(); x++) { + for (int y = 0; y < gl.getHeight(); y++) { + gl.addComponent(getExamplePicture("x=" + x + ", y=" + y), + x, y); + } + } + result = gl; + break; + case 3: + result = new Panel(); + ((Panel) result).setCaption("Panel_" + caption); + break; + case 4: + TabSheet ts = new TabSheet(); + ts.setCaption("TabSheet_" + caption); + // randomly select one of the tabs + int selectedTab = rand.nextInt(3); + ArrayList tabs = new ArrayList(); + for (int i = 0; i < 3; i++) { + String tabCaption = "tab" + i; + if (selectedTab == i) { + tabCaption = "tabX"; + } + tabs.add(new OrderedLayout()); + ts.addTab((ComponentContainer) tabs.get(tabs.size() - 1), + tabCaption, null); + } + ts.setSelectedTab((ComponentContainer) tabs.get(selectedTab)); + result = (ComponentContainer) ts; + break; + } + + return result; + } + + /** + * Get random component. Used to provide "noise" for AUT. + * + * @param caption + * @return + */ + private AbstractComponent getRandomComponent(String caption) { + AbstractComponent result = null; + int randint = rand.nextInt(7); // calendar disabled + switch (randint) { + case 0: + // Label + result = new Label("Label component " + caption); + break; + case 1: + // Button + result = new Button("Button component " + caption); + break; + case 2: + // TextField + result = new TextField("TextField component " + caption); + break; + case 3: + // Select + result = new Select("Select " + caption); + result.setCaption("Select component " + caption); + ((Select) result).addItem("First item"); + ((Select) result).addItem("Second item"); + ((Select) result).addItem("Third item"); + break; + case 4: + // Link + result = new Link("", new ExternalResource("http://www.itmill.com")); + result.setCaption("Link component " + caption); + break; + case 5: + // Embedded + result = getExamplePicture(caption); + break; + case 6: + // Datefield + result = new DateField(); + ((DateField) result).setValue(new java.util.Date()); + ((DateField) result).setResolution(DateField.RESOLUTION_DAY); + result.setCaption("DateField component " + caption); + break; + case 7: + // Calendar + result = new DateField(); + ((DateField) result).setStyle("calendar"); + ((DateField) result).setValue(new java.util.Date()); + ((DateField) result).setResolution(DateField.RESOLUTION_DAY); + result.setCaption("Calendar component " + caption); + break; + } + + return result; + } + + private AbstractComponent getExamplePicture(String caption) { + ClassResource cr = new ClassResource("icon_demo.png", this); + Embedded em = new Embedded("Embedded " + caption, cr); + return em; + } + + /** + * Add demo components to given layout. Used to provide "noise" for AUT. + * + * @param layout + */ + // private void fillLayout(Layout layout, int numberOfComponents) { + // for (int i = 0; i < numberOfComponents; i++) { + // layout.addComponent(getRandomComponent("" + captionCounter++)); + // } + // } + /** + * ErrorEvents are printed to default error stream and not in GUI. + */ + public void terminalError( + com.itmill.toolkit.terminal.Terminal.ErrorEvent event) { + Throwable e = event.getThrowable(); + System.err.println(getUser().toString() + " terminalError: " + + e.toString()); + e.printStackTrace(); + } } diff --git a/src/com/itmill/toolkit/tests/RandomLayoutStress.java b/src/com/itmill/toolkit/tests/RandomLayoutStress.java index 1704526ca2..5267f658e6 100644 --- a/src/com/itmill/toolkit/tests/RandomLayoutStress.java +++ b/src/com/itmill/toolkit/tests/RandomLayoutStress.java @@ -3,7 +3,20 @@ package com.itmill.toolkit.tests; import java.util.Random; import com.itmill.toolkit.terminal.ExternalResource; -import com.itmill.toolkit.ui.*; +import com.itmill.toolkit.ui.AbstractComponent; +import com.itmill.toolkit.ui.Button; +import com.itmill.toolkit.ui.CustomLayout; +import com.itmill.toolkit.ui.DateField; +import com.itmill.toolkit.ui.GridLayout; +import com.itmill.toolkit.ui.Label; +import com.itmill.toolkit.ui.Layout; +import com.itmill.toolkit.ui.Link; +import com.itmill.toolkit.ui.OrderedLayout; +import com.itmill.toolkit.ui.Panel; +import com.itmill.toolkit.ui.Select; +import com.itmill.toolkit.ui.TabSheet; +import com.itmill.toolkit.ui.TextField; +import com.itmill.toolkit.ui.Window; /** * This example demonstrates layouts. Layouts are populated with sample Toolkit @@ -14,158 +27,156 @@ import com.itmill.toolkit.ui.*; */ public class RandomLayoutStress extends com.itmill.toolkit.Application { - private Random seededRandom = new Random(1); - - // FIXME increasing these settings brings out interesting client-side issues - // (DOM errors) - // TODO increasing values "even more" crashes Hosted Mode, pumping Xmx/Xms - // helps to some extent - private static final int componentCountA = 50; - private static final int componentCountB = 50; - private static final int componentCountC = 200; - private static final int componentCountD = 50; - - /** - * Initialize Application. Demo components are added to main window. - */ - public void init() { - Window mainWindow = new Window("Layout demo"); - setMainWindow(mainWindow); - - // Create horizontal ordered layout - Panel panelA = new Panel("Panel containing horizontal ordered layout"); - OrderedLayout layoutA = new OrderedLayout( - OrderedLayout.ORIENTATION_HORIZONTAL); - // Add 4 random components - fillLayout(layoutA, componentCountA); - // Add layout to panel - panelA.addComponent(layoutA); - - // Create vertical ordered layout - Panel panelB = new Panel("Panel containing vertical ordered layout"); - OrderedLayout layoutB = new OrderedLayout( - OrderedLayout.ORIENTATION_VERTICAL); - // Add 4 random components - fillLayout(layoutB, componentCountB); - // Add layout to panel - panelB.addComponent(layoutB); - - // Create grid layout - int gridSize = (int) java.lang.Math.sqrt(componentCountC); - Panel panelG = new Panel("Panel containing grid layout (" + gridSize - + " x " + gridSize + ")"); - GridLayout layoutG = new GridLayout(gridSize, gridSize); - // Add 12 random components - fillLayout(layoutG, componentCountC); - // Add layout to panel - panelG.addComponent(layoutG); - - // Create TabSheet - TabSheet tabsheet = new TabSheet(); - tabsheet - .setCaption("Tabsheet, above layouts are added to this component"); - layoutA = new OrderedLayout( - OrderedLayout.ORIENTATION_HORIZONTAL); - // Add 4 random components - fillLayout(layoutA, componentCountA); - tabsheet.addTab(layoutA, "Horizontal ordered layout", null); - layoutB = new OrderedLayout( - OrderedLayout.ORIENTATION_VERTICAL); - // Add 4 random components - fillLayout(layoutB, componentCountB); - tabsheet.addTab(layoutB, "Vertical ordered layout", null); - layoutG = new GridLayout(gridSize, gridSize); - // Add 12 random components - fillLayout(layoutG, componentCountC); - tabsheet.addTab(layoutG, "Grid layout (4 x 2)", null); - - // Create custom layout - Panel panelC = new Panel("Custom layout with style exampleStyle"); - CustomLayout layoutC = new CustomLayout("exampleStyle"); - // Add 4 random components - fillLayout(layoutC, componentCountD); - // Add layout to panel - panelC.addComponent(layoutC); - - // Add demo panels (layouts) to main window - mainWindow.addComponent(panelA); - mainWindow.addComponent(panelB); - mainWindow.addComponent(panelG); - mainWindow.addComponent(tabsheet); - mainWindow.addComponent(panelC); - } - - private AbstractComponent getRandomComponent(int caption) { - AbstractComponent result = null; - int randint = seededRandom.nextInt(7); - switch (randint) { - case 0: - // Label - result = new Label(); - result.setCaption("Label component " + caption); - break; - case 1: - // Button - result = new Button(); - result.setCaption("Button component " + caption); - break; - case 2: - // TextField - result = new TextField(); - result.setCaption("TextField component " + caption); - break; - case 3: - // Select - result = new Select("Select " + caption); - result.setCaption("Select component " + caption); - ((Select) result).addItem("First item"); - ((Select) result).addItem("Second item"); - ((Select) result).addItem("Third item"); - break; - case 4: - // Link - result = new Link("", new ExternalResource("http://www.itmill.com")); - result.setCaption("Link component " + caption); - break; - case 5: - // Link - result = new Panel(); - result.setCaption("Panel component " + caption); - ((Panel) result) - .addComponent(new Label( - "Panel is a container for other components, by default it draws a frame around it's " - + "extremities and may have a caption to clarify the nature of the contained components' purpose." - + " Panel contains an layout where the actual contained components are added, " - + "this layout may be switched on the fly.")); - ((Panel) result).setWidth(250); - break; - case 6: - // Datefield - result = new DateField(); - ((DateField) result).setStyle("calendar"); - ((DateField) result).setValue(new java.util.Date()); - result.setCaption("Calendar component " + caption); - break; - case 7: - // Datefield - result = new DateField(); - ((DateField) result).setValue(new java.util.Date()); - result.setCaption("Calendar component " + caption); - break; - } - - return result; - } - - /** - * Add demo components to given layout - * - * @param layout - */ - private void fillLayout(Layout layout, int numberOfComponents) { - for (int i = 0; i < numberOfComponents; i++) { - layout.addComponent(getRandomComponent(i)); - } - } + private Random seededRandom = new Random(1); + + // FIXME increasing these settings brings out interesting client-side issues + // (DOM errors) + // TODO increasing values "even more" crashes Hosted Mode, pumping Xmx/Xms + // helps to some extent + private static final int componentCountA = 50; + private static final int componentCountB = 50; + private static final int componentCountC = 200; + private static final int componentCountD = 50; + + /** + * Initialize Application. Demo components are added to main window. + */ + public void init() { + Window mainWindow = new Window("Layout demo"); + setMainWindow(mainWindow); + + // Create horizontal ordered layout + Panel panelA = new Panel("Panel containing horizontal ordered layout"); + OrderedLayout layoutA = new OrderedLayout( + OrderedLayout.ORIENTATION_HORIZONTAL); + // Add 4 random components + fillLayout(layoutA, componentCountA); + // Add layout to panel + panelA.addComponent(layoutA); + + // Create vertical ordered layout + Panel panelB = new Panel("Panel containing vertical ordered layout"); + OrderedLayout layoutB = new OrderedLayout( + OrderedLayout.ORIENTATION_VERTICAL); + // Add 4 random components + fillLayout(layoutB, componentCountB); + // Add layout to panel + panelB.addComponent(layoutB); + + // Create grid layout + int gridSize = (int) java.lang.Math.sqrt(componentCountC); + Panel panelG = new Panel("Panel containing grid layout (" + gridSize + + " x " + gridSize + ")"); + GridLayout layoutG = new GridLayout(gridSize, gridSize); + // Add 12 random components + fillLayout(layoutG, componentCountC); + // Add layout to panel + panelG.addComponent(layoutG); + + // Create TabSheet + TabSheet tabsheet = new TabSheet(); + tabsheet + .setCaption("Tabsheet, above layouts are added to this component"); + layoutA = new OrderedLayout(OrderedLayout.ORIENTATION_HORIZONTAL); + // Add 4 random components + fillLayout(layoutA, componentCountA); + tabsheet.addTab(layoutA, "Horizontal ordered layout", null); + layoutB = new OrderedLayout(OrderedLayout.ORIENTATION_VERTICAL); + // Add 4 random components + fillLayout(layoutB, componentCountB); + tabsheet.addTab(layoutB, "Vertical ordered layout", null); + layoutG = new GridLayout(gridSize, gridSize); + // Add 12 random components + fillLayout(layoutG, componentCountC); + tabsheet.addTab(layoutG, "Grid layout (4 x 2)", null); + + // Create custom layout + Panel panelC = new Panel("Custom layout with style exampleStyle"); + CustomLayout layoutC = new CustomLayout("exampleStyle"); + // Add 4 random components + fillLayout(layoutC, componentCountD); + // Add layout to panel + panelC.addComponent(layoutC); + + // Add demo panels (layouts) to main window + mainWindow.addComponent(panelA); + mainWindow.addComponent(panelB); + mainWindow.addComponent(panelG); + mainWindow.addComponent(tabsheet); + mainWindow.addComponent(panelC); + } + + private AbstractComponent getRandomComponent(int caption) { + AbstractComponent result = null; + int randint = seededRandom.nextInt(7); + switch (randint) { + case 0: + // Label + result = new Label(); + result.setCaption("Label component " + caption); + break; + case 1: + // Button + result = new Button(); + result.setCaption("Button component " + caption); + break; + case 2: + // TextField + result = new TextField(); + result.setCaption("TextField component " + caption); + break; + case 3: + // Select + result = new Select("Select " + caption); + result.setCaption("Select component " + caption); + ((Select) result).addItem("First item"); + ((Select) result).addItem("Second item"); + ((Select) result).addItem("Third item"); + break; + case 4: + // Link + result = new Link("", new ExternalResource("http://www.itmill.com")); + result.setCaption("Link component " + caption); + break; + case 5: + // Link + result = new Panel(); + result.setCaption("Panel component " + caption); + ((Panel) result) + .addComponent(new Label( + "Panel is a container for other components, by default it draws a frame around it's " + + "extremities and may have a caption to clarify the nature of the contained components' purpose." + + " Panel contains an layout where the actual contained components are added, " + + "this layout may be switched on the fly.")); + ((Panel) result).setWidth(250); + break; + case 6: + // Datefield + result = new DateField(); + ((DateField) result).setStyle("calendar"); + ((DateField) result).setValue(new java.util.Date()); + result.setCaption("Calendar component " + caption); + break; + case 7: + // Datefield + result = new DateField(); + ((DateField) result).setValue(new java.util.Date()); + result.setCaption("Calendar component " + caption); + break; + } + + return result; + } + + /** + * Add demo components to given layout + * + * @param layout + */ + private void fillLayout(Layout layout, int numberOfComponents) { + for (int i = 0; i < numberOfComponents; i++) { + layout.addComponent(getRandomComponent(i)); + } + } } diff --git a/src/com/itmill/toolkit/tests/TableSelectTest.java b/src/com/itmill/toolkit/tests/TableSelectTest.java index c00b2bdce8..eb53f5cbf1 100644 --- a/src/com/itmill/toolkit/tests/TableSelectTest.java +++ b/src/com/itmill/toolkit/tests/TableSelectTest.java @@ -7,113 +7,113 @@ import com.itmill.toolkit.ui.OrderedLayout; import com.itmill.toolkit.ui.Table; public class TableSelectTest extends CustomComponent implements - Table.ValueChangeListener { - - public TableSelectTest() { - OrderedLayout main = new OrderedLayout(); - setCompositionRoot(main); - main.addComponent(new Label("Hello World!")); - - Table t; - t = new Table("single nullsel"); - main.addComponent(t); - t(t); - t.setMultiSelect(false); - t.setNullSelectionAllowed(true); - t.addListener(this); - - t = new Table("single NO-nullsel"); - main.addComponent(t); - t(t); - t.setMultiSelect(false); - t.setNullSelectionAllowed(false); - t.addListener(this); - - t = new Table("multi nullsel"); - main.addComponent(t); - t(t); - t.setMultiSelect(true); - t.setNullSelectionAllowed(true); - t.addListener(this); - - t = new Table("multi NO-nullsel"); - main.addComponent(t); - t(t); - t.setMultiSelect(true); - t.setNullSelectionAllowed(false); - t.addListener(this); - - // -- - - t = new Table("single nullsel nullselid"); - main.addComponent(t); - Object id = t(t); - t.setNullSelectionItemId(id); - t.setMultiSelect(false); - t.setNullSelectionAllowed(true); - t.addListener(this); - - t = new Table("single NO-nullsel nullselid"); - main.addComponent(t); - id = t(t); - t.setNullSelectionItemId(id); - t.setMultiSelect(false); - t.setNullSelectionAllowed(false); - t.addListener(this); - - t = new Table("multi(fails) nullsel nullselid"); - main.addComponent(t); - id = t(t); - t.setNullSelectionItemId(id); - try { - t.setMultiSelect(true); - t.setCaption("multi(SHOLD FAIL BUT DID NOT) nullsel nullselid"); - } catch (Exception e) { - System.err.println("failed ok"); - } - t.setNullSelectionAllowed(true); - t.addListener(this); - - t = new Table("multi(fails) NO-nullsel nullselid"); - main.addComponent(t); - id = t(t); - t.setNullSelectionItemId(id); - try { - t.setMultiSelect(true); - t.setCaption("multi(SHOLD FAIL BUT DID NOT) NO-nullsel nullselid"); - } catch (Exception e) { - System.err.println("failed ok"); - } - t.setNullSelectionAllowed(false); - t.addListener(this); - - /* - * And that's it! The framework will display the main window and its - * contents when the application is accessed with the terminal. - */ - - } - - private Object t(Table t) { - t.setImmediate(true); - t.setSelectable(true); - - Object id = null; - for (int i = 0; i < 5; i++) { - id = t.addItem(); - } - t.addContainerProperty("asd", String.class, "the asd thing"); - t.addContainerProperty("foo", String.class, "foo stuff"); - t.addContainerProperty("Alonger column header", String.class, "short"); - - return id; - } - - public void valueChange(ValueChangeEvent event) { - Object val = event.getProperty().getValue(); - - System.err.println("Value: " + val); - - } + Table.ValueChangeListener { + + public TableSelectTest() { + OrderedLayout main = new OrderedLayout(); + setCompositionRoot(main); + main.addComponent(new Label("Hello World!")); + + Table t; + t = new Table("single nullsel"); + main.addComponent(t); + t(t); + t.setMultiSelect(false); + t.setNullSelectionAllowed(true); + t.addListener(this); + + t = new Table("single NO-nullsel"); + main.addComponent(t); + t(t); + t.setMultiSelect(false); + t.setNullSelectionAllowed(false); + t.addListener(this); + + t = new Table("multi nullsel"); + main.addComponent(t); + t(t); + t.setMultiSelect(true); + t.setNullSelectionAllowed(true); + t.addListener(this); + + t = new Table("multi NO-nullsel"); + main.addComponent(t); + t(t); + t.setMultiSelect(true); + t.setNullSelectionAllowed(false); + t.addListener(this); + + // -- + + t = new Table("single nullsel nullselid"); + main.addComponent(t); + Object id = t(t); + t.setNullSelectionItemId(id); + t.setMultiSelect(false); + t.setNullSelectionAllowed(true); + t.addListener(this); + + t = new Table("single NO-nullsel nullselid"); + main.addComponent(t); + id = t(t); + t.setNullSelectionItemId(id); + t.setMultiSelect(false); + t.setNullSelectionAllowed(false); + t.addListener(this); + + t = new Table("multi(fails) nullsel nullselid"); + main.addComponent(t); + id = t(t); + t.setNullSelectionItemId(id); + try { + t.setMultiSelect(true); + t.setCaption("multi(SHOLD FAIL BUT DID NOT) nullsel nullselid"); + } catch (Exception e) { + System.err.println("failed ok"); + } + t.setNullSelectionAllowed(true); + t.addListener(this); + + t = new Table("multi(fails) NO-nullsel nullselid"); + main.addComponent(t); + id = t(t); + t.setNullSelectionItemId(id); + try { + t.setMultiSelect(true); + t.setCaption("multi(SHOLD FAIL BUT DID NOT) NO-nullsel nullselid"); + } catch (Exception e) { + System.err.println("failed ok"); + } + t.setNullSelectionAllowed(false); + t.addListener(this); + + /* + * And that's it! The framework will display the main window and its + * contents when the application is accessed with the terminal. + */ + + } + + private Object t(Table t) { + t.setImmediate(true); + t.setSelectable(true); + + Object id = null; + for (int i = 0; i < 5; i++) { + id = t.addItem(); + } + t.addContainerProperty("asd", String.class, "the asd thing"); + t.addContainerProperty("foo", String.class, "foo stuff"); + t.addContainerProperty("Alonger column header", String.class, "short"); + + return id; + } + + public void valueChange(ValueChangeEvent event) { + Object val = event.getProperty().getValue(); + + System.err.println("Value: " + val); + + } } diff --git a/src/com/itmill/toolkit/tests/TestBench.java b/src/com/itmill/toolkit/tests/TestBench.java index a112fd7ff1..a13518f1c7 100644 --- a/src/com/itmill/toolkit/tests/TestBench.java +++ b/src/com/itmill/toolkit/tests/TestBench.java @@ -11,6 +11,7 @@ import java.util.List; import com.itmill.toolkit.Application; import com.itmill.toolkit.data.Property; import com.itmill.toolkit.data.util.HierarchicalContainer; +import com.itmill.toolkit.terminal.Sizeable; import com.itmill.toolkit.ui.Component; import com.itmill.toolkit.ui.CustomComponent; import com.itmill.toolkit.ui.ExpandLayout; @@ -31,181 +32,183 @@ import com.itmill.toolkit.ui.Window; * */ public class TestBench extends com.itmill.toolkit.Application implements - Property.ValueChangeListener { - - // Add here packages which are used for finding testable classes - String[] testablePackages = { "com.itmill.toolkit.tests", - "com.itmill.toolkit.demo", "com.itmill.toolkit.demo.colorpicker", - "com.itmill.toolkit.demo.reservation", - "com.itmill.toolkit.demo.features" }; - - HierarchicalContainer testables = new HierarchicalContainer(); - - Window mainWindow = new Window("TestBench window"); - - // Main layout consists of tree menu and body layout - SplitPanel mainLayout = new SplitPanel(SplitPanel.ORIENTATION_HORIZONTAL); - - Tree menu; - - Panel bodyLayout = new Panel(); - - HashMap itemCaptions = new HashMap(); - - public void init() { - - // Add testable classes to hierarchical container - for (int p = 0; p < testablePackages.length; p++) { - testables.addItem(testablePackages[p]); - try { - List testableClasses = this - .getTestableClassesForPackage(testablePackages[p]); - for (Iterator it = testableClasses.iterator(); it.hasNext();) { - Class t = (Class) it.next(); - // ignore TestBench itself - if (t.equals(TestBench.class)) - continue; - try { - testables.addItem(t); - itemCaptions.put(t, t.getName()); - testables.setParent(t, testablePackages[p]); - continue; - } catch (Exception e) { - try { - testables.addItem(t); - itemCaptions.put(t, t.getName()); - testables.setParent(t, testablePackages[p]); - continue; - } catch (Exception e1) { - e1.printStackTrace(); - } - } - } - } catch (Exception e) { - e.printStackTrace(); - } - } - - menu = new Tree("Testables", testables); - // simplify captions - for (Iterator i = itemCaptions.keySet().iterator(); i.hasNext();) { - Class testable = (Class) i.next(); - menu.setItemCaption(testable, testable.getName()); - } - menu.addListener(this); - menu.setImmediate(true); - - mainLayout.addComponent(menu); - - bodyLayout.addStyleName("light"); - bodyLayout.setHeight(100); - bodyLayout.setHeightUnits(Panel.UNITS_PERCENTAGE); - bodyLayout.setLayout(new ExpandLayout()); - - mainLayout.addComponent(bodyLayout); - - mainLayout.setSplitPosition(30); - - mainWindow.setLayout(mainLayout); - - setMainWindow(mainWindow); - } - - private Component createTestable(Class c) { - try { - Application app = (Application) c.newInstance(); - app.init(); - return app.getMainWindow().getLayout(); - } catch (Exception e) { - try { - CustomComponent cc = (CustomComponent) c.newInstance(); - return cc; - } catch (Exception e1) { - e1.printStackTrace(); - return new Label( - "Cannot create application / custom component: " - + e1.toString()); - } - } - } - - // Handle menu selection and update body - public void valueChange(Property.ValueChangeEvent event) { - bodyLayout.removeAllComponents(); - bodyLayout.setCaption(null); - - String title = ((Class) menu.getValue()).getName(); - bodyLayout.setCaption(title); - bodyLayout.addComponent(createTestable((Class) menu.getValue())); - } - - /** - * Return all testable classes within given package. Class is considered - * testable if it's superclass is Application or CustomComponent. - * - * @param packageName - * @return - * @throws ClassNotFoundException - */ - public static List getTestableClassesForPackage(String packageName) - throws Exception { - ArrayList directories = new ArrayList(); - try { - ClassLoader cld = Thread.currentThread().getContextClassLoader(); - if (cld == null) - throw new ClassNotFoundException("Can't get class loader."); - String path = packageName.replace('.', '/'); - // Ask for all resources for the path - Enumeration resources = cld.getResources(path); - while (resources.hasMoreElements()) { - URL url = (URL) resources.nextElement(); - directories.add(new File(url.getFile())); - } - } catch (Exception x) { - throw new Exception(packageName - + " does not appear to be a valid package."); - } - - ArrayList classes = new ArrayList(); - // For every directory identified capture all the .class files - for (Iterator it = directories.iterator(); it.hasNext();) { - File directory = (File) it.next(); - if (directory.exists()) { - // Get the list of the files contained in the package - String[] files = directory.list(); - for (int j = 0; j < files.length; j++) { - // we are only interested in .class files - if (files[j].endsWith(".class")) { - // removes the .class extension - String p = packageName + '.' - + files[j].substring(0, files[j].length() - 6); - Class c = Class.forName(p); - if (c.getSuperclass() != null) - if ((c.getSuperclass() - .equals(com.itmill.toolkit.Application.class))) { - classes.add(c); - } else if ((c.getSuperclass() - .equals(com.itmill.toolkit.ui.CustomComponent.class))) { - classes.add(c); - } - - // for (int i = 0; i < c.getInterfaces().length; i++) { - // Class cc = c.getInterfaces()[i]; - // if (c.getInterfaces()[i].equals(Testable.class)) { - // // Class is testable - // classes.add(c); - // } - // } - } - } - } else { - throw new ClassNotFoundException(packageName + " (" - + directory.getPath() - + ") does not appear to be a valid package"); - } - } - - return classes; - } + Property.ValueChangeListener { + + // Add here packages which are used for finding testable classes + String[] testablePackages = { "com.itmill.toolkit.tests", + "com.itmill.toolkit.demo", "com.itmill.toolkit.demo.colorpicker", + "com.itmill.toolkit.demo.reservation", + "com.itmill.toolkit.demo.features" }; + + HierarchicalContainer testables = new HierarchicalContainer(); + + Window mainWindow = new Window("TestBench window"); + + // Main layout consists of tree menu and body layout + SplitPanel mainLayout = new SplitPanel(SplitPanel.ORIENTATION_HORIZONTAL); + + Tree menu; + + Panel bodyLayout = new Panel(); + + HashMap itemCaptions = new HashMap(); + + public void init() { + + // Add testable classes to hierarchical container + for (int p = 0; p < testablePackages.length; p++) { + testables.addItem(testablePackages[p]); + try { + List testableClasses = getTestableClassesForPackage(testablePackages[p]); + for (Iterator it = testableClasses.iterator(); it.hasNext();) { + Class t = (Class) it.next(); + // ignore TestBench itself + if (t.equals(TestBench.class)) { + continue; + } + try { + testables.addItem(t); + itemCaptions.put(t, t.getName()); + testables.setParent(t, testablePackages[p]); + continue; + } catch (Exception e) { + try { + testables.addItem(t); + itemCaptions.put(t, t.getName()); + testables.setParent(t, testablePackages[p]); + continue; + } catch (Exception e1) { + e1.printStackTrace(); + } + } + } + } catch (Exception e) { + e.printStackTrace(); + } + } + + menu = new Tree("Testables", testables); + // simplify captions + for (Iterator i = itemCaptions.keySet().iterator(); i.hasNext();) { + Class testable = (Class) i.next(); + menu.setItemCaption(testable, testable.getName()); + } + menu.addListener(this); + menu.setImmediate(true); + + mainLayout.addComponent(menu); + + bodyLayout.addStyleName("light"); + bodyLayout.setHeight(100); + bodyLayout.setHeightUnits(Sizeable.UNITS_PERCENTAGE); + bodyLayout.setLayout(new ExpandLayout()); + + mainLayout.addComponent(bodyLayout); + + mainLayout.setSplitPosition(30); + + mainWindow.setLayout(mainLayout); + + setMainWindow(mainWindow); + } + + private Component createTestable(Class c) { + try { + Application app = (Application) c.newInstance(); + app.init(); + return app.getMainWindow().getLayout(); + } catch (Exception e) { + try { + CustomComponent cc = (CustomComponent) c.newInstance(); + return cc; + } catch (Exception e1) { + e1.printStackTrace(); + return new Label( + "Cannot create application / custom component: " + + e1.toString()); + } + } + } + + // Handle menu selection and update body + public void valueChange(Property.ValueChangeEvent event) { + bodyLayout.removeAllComponents(); + bodyLayout.setCaption(null); + + String title = ((Class) menu.getValue()).getName(); + bodyLayout.setCaption(title); + bodyLayout.addComponent(createTestable((Class) menu.getValue())); + } + + /** + * Return all testable classes within given package. Class is considered + * testable if it's superclass is Application or CustomComponent. + * + * @param packageName + * @return + * @throws ClassNotFoundException + */ + public static List getTestableClassesForPackage(String packageName) + throws Exception { + ArrayList directories = new ArrayList(); + try { + ClassLoader cld = Thread.currentThread().getContextClassLoader(); + if (cld == null) { + throw new ClassNotFoundException("Can't get class loader."); + } + String path = packageName.replace('.', '/'); + // Ask for all resources for the path + Enumeration resources = cld.getResources(path); + while (resources.hasMoreElements()) { + URL url = (URL) resources.nextElement(); + directories.add(new File(url.getFile())); + } + } catch (Exception x) { + throw new Exception(packageName + + " does not appear to be a valid package."); + } + + ArrayList classes = new ArrayList(); + // For every directory identified capture all the .class files + for (Iterator it = directories.iterator(); it.hasNext();) { + File directory = (File) it.next(); + if (directory.exists()) { + // Get the list of the files contained in the package + String[] files = directory.list(); + for (int j = 0; j < files.length; j++) { + // we are only interested in .class files + if (files[j].endsWith(".class")) { + // removes the .class extension + String p = packageName + '.' + + files[j].substring(0, files[j].length() - 6); + Class c = Class.forName(p); + if (c.getSuperclass() != null) { + if ((c.getSuperclass() + .equals(com.itmill.toolkit.Application.class))) { + classes.add(c); + } else if ((c.getSuperclass() + .equals(com.itmill.toolkit.ui.CustomComponent.class))) { + classes.add(c); + } + } + + // for (int i = 0; i < c.getInterfaces().length; i++) { + // Class cc = c.getInterfaces()[i]; + // if (c.getInterfaces()[i].equals(Testable.class)) { + // // Class is testable + // classes.add(c); + // } + // } + } + } + } else { + throw new ClassNotFoundException(packageName + " (" + + directory.getPath() + + ") does not appear to be a valid package"); + } + } + + return classes; + } } diff --git a/src/com/itmill/toolkit/tests/TestCaptionWrapper.java b/src/com/itmill/toolkit/tests/TestCaptionWrapper.java index 9809617698..567d9eb877 100644 --- a/src/com/itmill/toolkit/tests/TestCaptionWrapper.java +++ b/src/com/itmill/toolkit/tests/TestCaptionWrapper.java @@ -34,165 +34,166 @@ import com.itmill.toolkit.ui.Component.Listener; public class TestCaptionWrapper extends CustomComponent implements Listener { - OrderedLayout main = new OrderedLayout(); + OrderedLayout main = new OrderedLayout(); - final String eventListenerString = "Component.Listener feedback: "; - Label eventListenerFeedback = new Label(eventListenerString - + " "); - int count = 0; + final String eventListenerString = "Component.Listener feedback: "; + Label eventListenerFeedback = new Label(eventListenerString + + " "); + int count = 0; - public TestCaptionWrapper() { - setCompositionRoot(main); - } + public TestCaptionWrapper() { + setCompositionRoot(main); + } - public void attach() { - super.attach(); - createNewView(); - } + public void attach() { + super.attach(); + createNewView(); + } - public void createNewView() { - main.removeAllComponents(); + public void createNewView() { + main.removeAllComponents(); - main - .addComponent(new Label( - "Each Layout and their contained components should " - + "have icon, caption, description, user error defined. " - + "Eeach layout should contain similar components.")); + main + .addComponent(new Label( + "Each Layout and their contained components should " + + "have icon, caption, description, user error defined. " + + "Eeach layout should contain similar components.")); - main.addComponent(eventListenerFeedback); + main.addComponent(eventListenerFeedback); - main.addComponent(new Label("OrderedLayout")); - test(main); - populateLayout(main); + main.addComponent(new Label("OrderedLayout")); + test(main); + populateLayout(main); - Panel panel = new Panel("Panel"); - test(panel); - populateLayout(panel.getLayout()); + Panel panel = new Panel("Panel"); + test(panel); + populateLayout(panel.getLayout()); - TabSheet tabsheet = new TabSheet(); - test(tabsheet); - OrderedLayout tab1 = new OrderedLayout(); - tab1.addComponent(new Label("try tab2")); - OrderedLayout tab2 = new OrderedLayout(); - test(tab2); - populateLayout(tab2); - tabsheet.addTab(tab1, "TabSheet tab1", new ClassResource("m.gif", this - .getApplication())); - tabsheet.addTab(tab2, "TabSheet tab2", new ClassResource("m.gif", this - .getApplication())); + TabSheet tabsheet = new TabSheet(); + test(tabsheet); + OrderedLayout tab1 = new OrderedLayout(); + tab1.addComponent(new Label("try tab2")); + OrderedLayout tab2 = new OrderedLayout(); + test(tab2); + populateLayout(tab2); + tabsheet.addTab(tab1, "TabSheet tab1", new ClassResource("m.gif", + getApplication())); + tabsheet.addTab(tab2, "TabSheet tab2", new ClassResource("m.gif", + getApplication())); - ExpandLayout expandLayout = new ExpandLayout(); - test(expandLayout); - populateLayout(expandLayout); + ExpandLayout expandLayout = new ExpandLayout(); + test(expandLayout); + populateLayout(expandLayout); - GridLayout gridLayout = new GridLayout(); - test(gridLayout); - populateLayout(gridLayout); + GridLayout gridLayout = new GridLayout(); + test(gridLayout); + populateLayout(gridLayout); - Window window = new Window("TEST: Window"); - test(window); - populateLayout(window.getLayout()); - - } - - void populateLayout(Layout layout) { - - Button button = new Button("Button " + count++); - test(layout, button); - button.addListener(this); - - DateField df = new DateField("DateField " + count++); - test(layout, df); - - CheckBox cb = new CheckBox("Checkbox " + count++); - test(layout, cb); - - Embedded emb = new Embedded("Embedded " + count++); - test(layout, emb); - - Panel panel = new Panel("Panel " + count++); - test(layout, panel); - - Label label = new Label("Label " + count++); - test(layout, label); - - Link link = new Link("Link " + count++, new ExternalResource( - "www.itmill.com")); - test(layout, link); - - NativeSelect nativeSelect = new NativeSelect("NativeSelect " + count++); - test(layout, nativeSelect); - - OptionGroup optionGroup = new OptionGroup("OptionGroup " + count++); - test(layout, optionGroup); - - ProgressIndicator pi = new ProgressIndicator(); - test(layout, pi); - - RichTextArea rta = new RichTextArea(); - test(layout, rta); - - Select select = new Select("Select " + count++); - test(layout, select); - - Slider slider = new Slider("Slider " + count++); - test(layout, slider); - - Table table = new Table("Table " + count++); - test(layout, table); - - TextField tf = new TextField("Textfield " + count++); - test(layout, tf); - - Tree tree = new Tree("Tree " + count++); - test(layout, tree); - - TwinColSelect twinColSelect = new TwinColSelect("TwinColSelect " - + count++); - test(layout, twinColSelect); - - Upload upload = new Upload("Upload (non-functional)", null); - test(layout, upload); - - // Custom components - layout.addComponent(new Label("Below are few custom components", - Label.CONTENT_XHTML)); - TestForUpload tfu = new TestForUpload(); - layout.addComponent(tfu); - - } - - /** - * Stresses component by configuring it - * - * @param c - */ - void test(AbstractComponent c) { - ClassResource res = new ClassResource("m.gif", this.getApplication()); - ErrorMessage errorMsg = new UserError("User error " + c); - - if ((c.getCaption() == null) || (c.getCaption().length() <= 0)) - c.setCaption("Caption " + c); - c.setDescription("Description " + c); - c.setComponentError(errorMsg); - c.setIcon(res); - } + Window window = new Window("TEST: Window"); + test(window); + populateLayout(window.getLayout()); + + } + + void populateLayout(Layout layout) { + + Button button = new Button("Button " + count++); + test(layout, button); + button.addListener(this); + + DateField df = new DateField("DateField " + count++); + test(layout, df); + + CheckBox cb = new CheckBox("Checkbox " + count++); + test(layout, cb); + + Embedded emb = new Embedded("Embedded " + count++); + test(layout, emb); + + Panel panel = new Panel("Panel " + count++); + test(layout, panel); + + Label label = new Label("Label " + count++); + test(layout, label); + + Link link = new Link("Link " + count++, new ExternalResource( + "www.itmill.com")); + test(layout, link); + + NativeSelect nativeSelect = new NativeSelect("NativeSelect " + count++); + test(layout, nativeSelect); + + OptionGroup optionGroup = new OptionGroup("OptionGroup " + count++); + test(layout, optionGroup); + + ProgressIndicator pi = new ProgressIndicator(); + test(layout, pi); + + RichTextArea rta = new RichTextArea(); + test(layout, rta); + + Select select = new Select("Select " + count++); + test(layout, select); + + Slider slider = new Slider("Slider " + count++); + test(layout, slider); + + Table table = new Table("Table " + count++); + test(layout, table); + + TextField tf = new TextField("Textfield " + count++); + test(layout, tf); + + Tree tree = new Tree("Tree " + count++); + test(layout, tree); + + TwinColSelect twinColSelect = new TwinColSelect("TwinColSelect " + + count++); + test(layout, twinColSelect); + + Upload upload = new Upload("Upload (non-functional)", null); + test(layout, upload); + + // Custom components + layout.addComponent(new Label("Below are few custom components", + Label.CONTENT_XHTML)); + TestForUpload tfu = new TestForUpload(); + layout.addComponent(tfu); + + } + + /** + * Stresses component by configuring it + * + * @param c + */ + void test(AbstractComponent c) { + ClassResource res = new ClassResource("m.gif", getApplication()); + ErrorMessage errorMsg = new UserError("User error " + c); + + if ((c.getCaption() == null) || (c.getCaption().length() <= 0)) { + c.setCaption("Caption " + c); + } + c.setDescription("Description " + c); + c.setComponentError(errorMsg); + c.setIcon(res); + } - /** - * Stresses component by configuring it in a given layout - * - * @param c - */ - void test(Layout layout, AbstractComponent c) { - test(c); - layout.addComponent(c); - } + /** + * Stresses component by configuring it in a given layout + * + * @param c + */ + void test(Layout layout, AbstractComponent c) { + test(c); + layout.addComponent(c); + } - public void componentEvent(Event event) { - String feedback = eventListenerString + " source=" + event.getSource() - + ", toString()=" + event.toString(); - System.out.println("eventListenerFeedback: " + feedback); - eventListenerFeedback.setValue(feedback); - } + public void componentEvent(Event event) { + String feedback = eventListenerString + " source=" + event.getSource() + + ", toString()=" + event.toString(); + System.out.println("eventListenerFeedback: " + feedback); + eventListenerFeedback.setValue(feedback); + } } diff --git a/src/com/itmill/toolkit/tests/TestComponentsAndLayouts.java b/src/com/itmill/toolkit/tests/TestComponentsAndLayouts.java index 698e1672cd..f0509be390 100644 --- a/src/com/itmill/toolkit/tests/TestComponentsAndLayouts.java +++ b/src/com/itmill/toolkit/tests/TestComponentsAndLayouts.java @@ -13,6 +13,7 @@ import com.itmill.toolkit.event.Action; import com.itmill.toolkit.terminal.ClassResource; import com.itmill.toolkit.terminal.ErrorMessage; import com.itmill.toolkit.terminal.ExternalResource; +import com.itmill.toolkit.terminal.Sizeable; import com.itmill.toolkit.terminal.UserError; import com.itmill.toolkit.ui.AbstractComponent; import com.itmill.toolkit.ui.Button; @@ -51,404 +52,404 @@ import com.itmill.toolkit.ui.Component.Listener; * */ public class TestComponentsAndLayouts extends Application implements Listener, - Action.Handler { - - // event listener feedback (see console) - Label eventListenerFeedback = new Label( - "See console for event listener log."); - int eventCount = 0; - - Window window; - - // component counter - int count = 0; - - SampleDatabase sampleDatabase; - - // Example Actions for table - private final Action ACTION1 = new Action("Upload"); - private final Action ACTION2 = new Action("Download"); - private final Action ACTION3 = new Action("Show history"); - private final Action[] actions = new Action[] { ACTION1, ACTION2, ACTION3 }; - - public void init() { - sampleDatabase = new SampleDatabase(); - createNewView(); - } - - public void createNewView() { - Window main = new Window("Main window"); - setMainWindow(main); - - // By default push all containers inside main window - Layout target = main.getLayout(); - - main - .addComponent(new Label( - "Each Layout and their contained components should " - + "have icon, caption, description, user error defined. " - + "Eeach layout should contain similar components. " - + "All components are in immmediate mode. See source how to tweak this test.")); - main.addComponent(eventListenerFeedback); - - // ////////////////////////////////////////////////////////////////////////// - if (true) { - window = new Window("Components inside Window (TEST: Window)"); - - if (false) { - // push every container and their components inside window - target = window.getLayout(); - } else { - // window is just one container to be tested - populateLayout(window.getLayout()); - } - getMainWindow().addWindow(window); - } - - // ////////////////////////////////////////////////////////////////////////// - if (true) { - target - .addComponent(new Label( - "

Components inside horizontal OrderedLayout

", - Label.CONTENT_XHTML)); - OrderedLayout ol = new OrderedLayout( - OrderedLayout.ORIENTATION_HORIZONTAL); - populateLayout(ol); - target.addComponent(ol); - } - - // ////////////////////////////////////////////////////////////////////////// - if (true) { - target - .addComponent(new Label( - "



Components inside vertical OrderedLayout

", - Label.CONTENT_XHTML)); - OrderedLayout ol2 = new OrderedLayout( - OrderedLayout.ORIENTATION_VERTICAL); - populateLayout(ol2); - target.addComponent(ol2); - } - - // ////////////////////////////////////////////////////////////////////////// - if (false) { - target - .addComponent(new Label( - "

Components inside ExpandLayout (height 250px)

", - Label.CONTENT_XHTML)); - ExpandLayout el = new ExpandLayout(); - el.setHeight(250); - el.setHeightUnits(ExpandLayout.UNITS_PIXELS); - populateLayout(el); - target.addComponent(el); - } - - // ////////////////////////////////////////////////////////////////////////// - if (false) { - target.addComponent(new Label( - "

Components inside Panel

", - Label.CONTENT_XHTML)); - Panel panel = new Panel("Panel"); - populateLayout(panel.getLayout()); - target.addComponent(panel); - } - - // ////////////////////////////////////////////////////////////////////////// - if (false) { - target - .addComponent(new Label( - "

Components inside vertical SplitPanel (splitpanel is under 250height ExpandLayout)

", - Label.CONTENT_XHTML)); - ExpandLayout sp1l = new ExpandLayout(); - sp1l.setHeight(250); - sp1l.setHeightUnits(ExpandLayout.UNITS_PIXELS); - SplitPanel sp1 = new SplitPanel(SplitPanel.ORIENTATION_VERTICAL); - sp1l.addComponent(sp1); - OrderedLayout sp1first = new OrderedLayout(); - OrderedLayout sp1second = new OrderedLayout(); - sp1.setFirstComponent(sp1first); - populateLayout(sp1first); - populateLayout(sp1second); - sp1.setSecondComponent(sp1second); - target.addComponent(sp1l); - } - - // ////////////////////////////////////////////////////////////////////////// - if (false) { - target - .addComponent(new Label( - "

Components inside horizontal SplitPanel (splitpanel is under 250px height ExpandLayout)

", - Label.CONTENT_XHTML)); - ExpandLayout sp2l = new ExpandLayout(); - sp2l.setHeight(250); - sp2l.setHeightUnits(ExpandLayout.UNITS_PIXELS); - SplitPanel sp2 = new SplitPanel(SplitPanel.ORIENTATION_HORIZONTAL); - sp2l.addComponent(sp2); - OrderedLayout sp2first = new OrderedLayout(); - OrderedLayout sp2second = new OrderedLayout(); - sp2.setFirstComponent(sp2first); - populateLayout(sp2first); - populateLayout(sp2second); - sp2.setSecondComponent(sp2second); - target.addComponent(sp2l); - } - - // ////////////////////////////////////////////////////////////////////////// - if (false) { - target.addComponent(new Label( - "

Components inside TabSheet

", - Label.CONTENT_XHTML)); - TabSheet tabsheet = new TabSheet(); - OrderedLayout tab1 = new OrderedLayout(); - tab1.addComponent(new Label("try tab2")); - OrderedLayout tab2 = new OrderedLayout(); - populateLayout(tab2); - tabsheet.addTab(tab1, "TabSheet tab1", new ClassResource("m.gif", - this)); - tabsheet.addTab(tab2, "TabSheet tab2", new ClassResource("m.gif", - this)); - target.addComponent(tabsheet); - // test(tabsheet); - // test(tab1); - // test(tab2); - // test(expandLayout); - } - - // ////////////////////////////////////////////////////////////////////////// - if (false) { - target.addComponent(new Label( - "

Components inside GridLayout

", - Label.CONTENT_XHTML)); - GridLayout gridLayout = new GridLayout(4, 100); - populateLayout(gridLayout); - target.addComponent(gridLayout); - // test(gridLayout); - } - - } - - void populateLayout(Layout layout) { - Button button = new Button("Button " + count++); - test(layout, button); - - DateField df = new DateField("DateField " + count++); - test(layout, df); - - CheckBox cb = new CheckBox("Checkbox " + count++); - test(layout, cb); - - ClassResource flashResource = new ClassResource("itmill_spin.swf", this); - Embedded emb = new Embedded("Embedded " + count++, flashResource); - emb.setType(Embedded.TYPE_OBJECT); - emb.setMimeType("application/x-shockwave-flash"); - emb.setWidth(250); - emb.setHeight(100); - test(layout, emb); - - Panel panel = new Panel("Panel " + count++); - test(layout, panel); - - Label label = new Label("Label " + count++); - test(layout, label); - - Link link = new Link("Link " + count++, new ExternalResource( - "www.itmill.com")); - test(layout, link); - - NativeSelect nativeSelect = new NativeSelect("NativeSelect " + count++); - nativeSelect.setContainerDataSource(getContainer()); - test(layout, nativeSelect); - - OptionGroup optionGroup = new OptionGroup("OptionGroup " + count++); - optionGroup.setContainerDataSource(getSmallContainer()); - optionGroup.setItemCaptionPropertyId("UNIT"); - test(layout, optionGroup); - - ProgressIndicator pi = new ProgressIndicator(); - pi.setCaption("ProgressIndicator"); - test(layout, pi); - - RichTextArea rta = new RichTextArea(); - test(layout, rta); - - Select select = new Select("Select " + count++); - select.setContainerDataSource(getSmallContainer()); - select.setItemCaptionPropertyId("UNIT"); - test(layout, select); - - Slider slider = new Slider("Slider " + count++); - test(layout, slider); - - Table table = new Table("Table " + count++); - table.setPageLength(10); - table.setSelectable(true); - table.setRowHeaderMode(Table.ROW_HEADER_MODE_INDEX); - table.setColumnCollapsingAllowed(true); - table.setColumnReorderingAllowed(true); - table.setSelectable(true); - table.addActionHandler(this); - table.setContainerDataSource(getContainer()); - table.setVisibleColumns(new Object[] { "FIRSTNAME", "LASTNAME", - "TITLE", "UNIT" }); - table.setItemCaptionPropertyId("ID"); - test(layout, table); - - TabSheet tabsheet = new TabSheet(); - OrderedLayout tab1 = new OrderedLayout(); - tab1.addComponent(new Label("tab1 " + count++)); - OrderedLayout tab2 = new OrderedLayout(); - tab2.addComponent(new Label("tab2 " + count++)); - tabsheet.addTab(tab1, "Default (not configured) TabSheet tab1", - new ClassResource("m.gif", this)); - tabsheet.addTab(tab2, "Configured TabSheet tab2", new ClassResource( - "m.gif", this)); - test(layout, tabsheet); - - TextField tf = new TextField("Textfield " + count++); - test(layout, tf); - // do not configure tab1 - // test(tab1); - test(tab2); - - Tree tree = new Tree("Tree " + count++); - File sampleDir = SampleDirectory.getDirectory(this); - FilesystemContainer fsc = new FilesystemContainer(sampleDir, true); - tree.setContainerDataSource(fsc); - test(layout, tree); - - TwinColSelect twinColSelect = new TwinColSelect("TwinColSelect " - + count++); - twinColSelect.setContainerDataSource(getSmallContainer()); - twinColSelect.setItemCaptionPropertyId("UNIT"); - test(layout, twinColSelect); - - Upload upload = new Upload("Upload (non-functional)", null); - test(layout, upload); - - // Custom components - layout.addComponent(new Label("Below are few custom components", - Label.CONTENT_XHTML)); - TestForUpload tfu = new TestForUpload(); - layout.addComponent(tfu); - layout.addComponent(new Label("
----------

", - Label.CONTENT_XHTML)); - test(tfu); - - // DISABLED - // TableSelectTest tst = new TableSelectTest(); - // layout.addComponent(tst); - // test(tst); - // layout.addComponent(new Label("
", Label.CONTENT_XHTML)); - - } - - Container getContainer() { - // populate container with test SQL table rows - try { - return new QueryContainer("SELECT * FROM employee", sampleDatabase - .getConnection()); - } catch (SQLException e) { - e.printStackTrace(); - } - return null; - } - - Container getSmallContainer() { - // populate container with test SQL table rows - try { - return new QueryContainer( - "SELECT DISTINCT UNIT AS UNIT FROM employee", - sampleDatabase.getConnection()); - } catch (SQLException e) { - e.printStackTrace(); - } - return null; - } - - // common component configuration - void setComponentProperties(Component c) { - // TWEAK these - // c.setEnabled(false); - // c.setVisible(false); - // c.setStyleName("testStyleName"); - // c.setReadOnly(true); - - // try to add listener - try { - c.addListener(this); - } catch (Exception e) { - System.err.println("Could not add listener for component " + c - + ", count was " + count); - } - } - - /** - * Stresses component by configuring it - * - * @param c - */ - void test(AbstractComponent c) { - // configure common component properties - setComponentProperties(c); - - // AbstractComponent specific configuration - ClassResource res = new ClassResource("m.gif", this); - ErrorMessage errorMsg = new UserError("User error " + c); - if ((c.getCaption() == null) || (c.getCaption().length() <= 0)) { - c.setCaption("Caption " + c); - } - - // TWEAK these - c.setDescription("Description " + c); - c.setComponentError(errorMsg); - c.setIcon(res); - c.setImmediate(true); - // c.addStyleName("addedTestStyleName"); - // c.setStyleName("singleTestStyleName"); - } - - void test(CustomComponent c) { - // configure common component properties - setComponentProperties(c); - - // CustomComponent specific configuration - // TWEAK these - // c.setComponentType("foo"); - c.addStyleName("addedTestStyleName"); - } - - /** - * Stresses component by configuring it in a given layout - * - * @param c - */ - void test(Layout layout, AbstractComponent c) { - test(c); - layout.addComponent(c); - // add separator - if (!(layout instanceof GridLayout)) { - layout.addComponent(new Label("
NEXT

", - Label.CONTENT_XHTML)); - } - } - - public void componentEvent(Event event) { - eventCount++; - String feedback = "eventCount=" + eventCount + ", class=" - + event.getClass() + ", source=" + event.getSource() - + ", toString()=" + event.toString(); - System.out.println("eventListenerFeedback: " + feedback); - eventListenerFeedback.setValue("Events: " + eventCount); - } - - // For sample actions - public Action[] getActions(Object target, Object sender) { - return actions; - } - - // For sample actions - public void handleAction(Action action, Object sender, Object target) { - System.out.println("ACTION: " + action.getCaption() + " on item " - + target); - } + Action.Handler { + + // event listener feedback (see console) + Label eventListenerFeedback = new Label( + "See console for event listener log."); + int eventCount = 0; + + Window window; + + // component counter + int count = 0; + + SampleDatabase sampleDatabase; + + // Example Actions for table + private final Action ACTION1 = new Action("Upload"); + private final Action ACTION2 = new Action("Download"); + private final Action ACTION3 = new Action("Show history"); + private final Action[] actions = new Action[] { ACTION1, ACTION2, ACTION3 }; + + public void init() { + sampleDatabase = new SampleDatabase(); + createNewView(); + } + + public void createNewView() { + Window main = new Window("Main window"); + setMainWindow(main); + + // By default push all containers inside main window + Layout target = main.getLayout(); + + main + .addComponent(new Label( + "Each Layout and their contained components should " + + "have icon, caption, description, user error defined. " + + "Eeach layout should contain similar components. " + + "All components are in immmediate mode. See source how to tweak this test.")); + main.addComponent(eventListenerFeedback); + + // ////////////////////////////////////////////////////////////////////////// + if (true) { + window = new Window("Components inside Window (TEST: Window)"); + + if (false) { + // push every container and their components inside window + target = window.getLayout(); + } else { + // window is just one container to be tested + populateLayout(window.getLayout()); + } + getMainWindow().addWindow(window); + } + + // ////////////////////////////////////////////////////////////////////////// + if (true) { + target + .addComponent(new Label( + "

Components inside horizontal OrderedLayout

", + Label.CONTENT_XHTML)); + OrderedLayout ol = new OrderedLayout( + OrderedLayout.ORIENTATION_HORIZONTAL); + populateLayout(ol); + target.addComponent(ol); + } + + // ////////////////////////////////////////////////////////////////////////// + if (true) { + target + .addComponent(new Label( + "



Components inside vertical OrderedLayout

", + Label.CONTENT_XHTML)); + OrderedLayout ol2 = new OrderedLayout( + OrderedLayout.ORIENTATION_VERTICAL); + populateLayout(ol2); + target.addComponent(ol2); + } + + // ////////////////////////////////////////////////////////////////////////// + if (false) { + target + .addComponent(new Label( + "

Components inside ExpandLayout (height 250px)

", + Label.CONTENT_XHTML)); + ExpandLayout el = new ExpandLayout(); + el.setHeight(250); + el.setHeightUnits(Sizeable.UNITS_PIXELS); + populateLayout(el); + target.addComponent(el); + } + + // ////////////////////////////////////////////////////////////////////////// + if (false) { + target.addComponent(new Label( + "

Components inside Panel

", + Label.CONTENT_XHTML)); + Panel panel = new Panel("Panel"); + populateLayout(panel.getLayout()); + target.addComponent(panel); + } + + // ////////////////////////////////////////////////////////////////////////// + if (false) { + target + .addComponent(new Label( + "

Components inside vertical SplitPanel (splitpanel is under 250height ExpandLayout)

", + Label.CONTENT_XHTML)); + ExpandLayout sp1l = new ExpandLayout(); + sp1l.setHeight(250); + sp1l.setHeightUnits(Sizeable.UNITS_PIXELS); + SplitPanel sp1 = new SplitPanel(SplitPanel.ORIENTATION_VERTICAL); + sp1l.addComponent(sp1); + OrderedLayout sp1first = new OrderedLayout(); + OrderedLayout sp1second = new OrderedLayout(); + sp1.setFirstComponent(sp1first); + populateLayout(sp1first); + populateLayout(sp1second); + sp1.setSecondComponent(sp1second); + target.addComponent(sp1l); + } + + // ////////////////////////////////////////////////////////////////////////// + if (false) { + target + .addComponent(new Label( + "

Components inside horizontal SplitPanel (splitpanel is under 250px height ExpandLayout)

", + Label.CONTENT_XHTML)); + ExpandLayout sp2l = new ExpandLayout(); + sp2l.setHeight(250); + sp2l.setHeightUnits(Sizeable.UNITS_PIXELS); + SplitPanel sp2 = new SplitPanel(SplitPanel.ORIENTATION_HORIZONTAL); + sp2l.addComponent(sp2); + OrderedLayout sp2first = new OrderedLayout(); + OrderedLayout sp2second = new OrderedLayout(); + sp2.setFirstComponent(sp2first); + populateLayout(sp2first); + populateLayout(sp2second); + sp2.setSecondComponent(sp2second); + target.addComponent(sp2l); + } + + // ////////////////////////////////////////////////////////////////////////// + if (false) { + target.addComponent(new Label( + "

Components inside TabSheet

", + Label.CONTENT_XHTML)); + TabSheet tabsheet = new TabSheet(); + OrderedLayout tab1 = new OrderedLayout(); + tab1.addComponent(new Label("try tab2")); + OrderedLayout tab2 = new OrderedLayout(); + populateLayout(tab2); + tabsheet.addTab(tab1, "TabSheet tab1", new ClassResource("m.gif", + this)); + tabsheet.addTab(tab2, "TabSheet tab2", new ClassResource("m.gif", + this)); + target.addComponent(tabsheet); + // test(tabsheet); + // test(tab1); + // test(tab2); + // test(expandLayout); + } + + // ////////////////////////////////////////////////////////////////////////// + if (false) { + target.addComponent(new Label( + "

Components inside GridLayout

", + Label.CONTENT_XHTML)); + GridLayout gridLayout = new GridLayout(4, 100); + populateLayout(gridLayout); + target.addComponent(gridLayout); + // test(gridLayout); + } + + } + + void populateLayout(Layout layout) { + Button button = new Button("Button " + count++); + test(layout, button); + + DateField df = new DateField("DateField " + count++); + test(layout, df); + + CheckBox cb = new CheckBox("Checkbox " + count++); + test(layout, cb); + + ClassResource flashResource = new ClassResource("itmill_spin.swf", this); + Embedded emb = new Embedded("Embedded " + count++, flashResource); + emb.setType(Embedded.TYPE_OBJECT); + emb.setMimeType("application/x-shockwave-flash"); + emb.setWidth(250); + emb.setHeight(100); + test(layout, emb); + + Panel panel = new Panel("Panel " + count++); + test(layout, panel); + + Label label = new Label("Label " + count++); + test(layout, label); + + Link link = new Link("Link " + count++, new ExternalResource( + "www.itmill.com")); + test(layout, link); + + NativeSelect nativeSelect = new NativeSelect("NativeSelect " + count++); + nativeSelect.setContainerDataSource(getContainer()); + test(layout, nativeSelect); + + OptionGroup optionGroup = new OptionGroup("OptionGroup " + count++); + optionGroup.setContainerDataSource(getSmallContainer()); + optionGroup.setItemCaptionPropertyId("UNIT"); + test(layout, optionGroup); + + ProgressIndicator pi = new ProgressIndicator(); + pi.setCaption("ProgressIndicator"); + test(layout, pi); + + RichTextArea rta = new RichTextArea(); + test(layout, rta); + + Select select = new Select("Select " + count++); + select.setContainerDataSource(getSmallContainer()); + select.setItemCaptionPropertyId("UNIT"); + test(layout, select); + + Slider slider = new Slider("Slider " + count++); + test(layout, slider); + + Table table = new Table("Table " + count++); + table.setPageLength(10); + table.setSelectable(true); + table.setRowHeaderMode(Table.ROW_HEADER_MODE_INDEX); + table.setColumnCollapsingAllowed(true); + table.setColumnReorderingAllowed(true); + table.setSelectable(true); + table.addActionHandler(this); + table.setContainerDataSource(getContainer()); + table.setVisibleColumns(new Object[] { "FIRSTNAME", "LASTNAME", + "TITLE", "UNIT" }); + table.setItemCaptionPropertyId("ID"); + test(layout, table); + + TabSheet tabsheet = new TabSheet(); + OrderedLayout tab1 = new OrderedLayout(); + tab1.addComponent(new Label("tab1 " + count++)); + OrderedLayout tab2 = new OrderedLayout(); + tab2.addComponent(new Label("tab2 " + count++)); + tabsheet.addTab(tab1, "Default (not configured) TabSheet tab1", + new ClassResource("m.gif", this)); + tabsheet.addTab(tab2, "Configured TabSheet tab2", new ClassResource( + "m.gif", this)); + test(layout, tabsheet); + + TextField tf = new TextField("Textfield " + count++); + test(layout, tf); + // do not configure tab1 + // test(tab1); + test(tab2); + + Tree tree = new Tree("Tree " + count++); + File sampleDir = SampleDirectory.getDirectory(this); + FilesystemContainer fsc = new FilesystemContainer(sampleDir, true); + tree.setContainerDataSource(fsc); + test(layout, tree); + + TwinColSelect twinColSelect = new TwinColSelect("TwinColSelect " + + count++); + twinColSelect.setContainerDataSource(getSmallContainer()); + twinColSelect.setItemCaptionPropertyId("UNIT"); + test(layout, twinColSelect); + + Upload upload = new Upload("Upload (non-functional)", null); + test(layout, upload); + + // Custom components + layout.addComponent(new Label("Below are few custom components", + Label.CONTENT_XHTML)); + TestForUpload tfu = new TestForUpload(); + layout.addComponent(tfu); + layout.addComponent(new Label("
----------

", + Label.CONTENT_XHTML)); + test(tfu); + + // DISABLED + // TableSelectTest tst = new TableSelectTest(); + // layout.addComponent(tst); + // test(tst); + // layout.addComponent(new Label("
", Label.CONTENT_XHTML)); + + } + + Container getContainer() { + // populate container with test SQL table rows + try { + return new QueryContainer("SELECT * FROM employee", sampleDatabase + .getConnection()); + } catch (SQLException e) { + e.printStackTrace(); + } + return null; + } + + Container getSmallContainer() { + // populate container with test SQL table rows + try { + return new QueryContainer( + "SELECT DISTINCT UNIT AS UNIT FROM employee", + sampleDatabase.getConnection()); + } catch (SQLException e) { + e.printStackTrace(); + } + return null; + } + + // common component configuration + void setComponentProperties(Component c) { + // TWEAK these + // c.setEnabled(false); + // c.setVisible(false); + // c.setStyleName("testStyleName"); + // c.setReadOnly(true); + + // try to add listener + try { + c.addListener(this); + } catch (Exception e) { + System.err.println("Could not add listener for component " + c + + ", count was " + count); + } + } + + /** + * Stresses component by configuring it + * + * @param c + */ + void test(AbstractComponent c) { + // configure common component properties + setComponentProperties(c); + + // AbstractComponent specific configuration + ClassResource res = new ClassResource("m.gif", this); + ErrorMessage errorMsg = new UserError("User error " + c); + if ((c.getCaption() == null) || (c.getCaption().length() <= 0)) { + c.setCaption("Caption " + c); + } + + // TWEAK these + c.setDescription("Description " + c); + c.setComponentError(errorMsg); + c.setIcon(res); + c.setImmediate(true); + // c.addStyleName("addedTestStyleName"); + // c.setStyleName("singleTestStyleName"); + } + + void test(CustomComponent c) { + // configure common component properties + setComponentProperties(c); + + // CustomComponent specific configuration + // TWEAK these + // c.setComponentType("foo"); + c.addStyleName("addedTestStyleName"); + } + + /** + * Stresses component by configuring it in a given layout + * + * @param c + */ + void test(Layout layout, AbstractComponent c) { + test(c); + layout.addComponent(c); + // add separator + if (!(layout instanceof GridLayout)) { + layout.addComponent(new Label("
NEXT

", + Label.CONTENT_XHTML)); + } + } + + public void componentEvent(Event event) { + eventCount++; + String feedback = "eventCount=" + eventCount + ", class=" + + event.getClass() + ", source=" + event.getSource() + + ", toString()=" + event.toString(); + System.out.println("eventListenerFeedback: " + feedback); + eventListenerFeedback.setValue("Events: " + eventCount); + } + + // For sample actions + public Action[] getActions(Object target, Object sender) { + return actions; + } + + // For sample actions + public void handleAction(Action action, Object sender, Object target) { + System.out.println("ACTION: " + action.getCaption() + " on item " + + target); + } } diff --git a/src/com/itmill/toolkit/tests/TestDateField.java b/src/com/itmill/toolkit/tests/TestDateField.java index 6eb56ec08d..44daf959fe 100644 --- a/src/com/itmill/toolkit/tests/TestDateField.java +++ b/src/com/itmill/toolkit/tests/TestDateField.java @@ -16,49 +16,49 @@ import com.itmill.toolkit.ui.OrderedLayout; */ public class TestDateField extends CustomComponent { - OrderedLayout main = new OrderedLayout(); + OrderedLayout main = new OrderedLayout(); - DateField df; + DateField df; - public TestDateField() { - setCompositionRoot(main); - createNewView(); - } + public TestDateField() { + setCompositionRoot(main); + createNewView(); + } - public void createNewView() { - main.removeAllComponents(); - main.addComponent(new Label("DateField")); + public void createNewView() { + main.removeAllComponents(); + main.addComponent(new Label("DateField")); - df = new DateField(); - main.addComponent(df); + df = new DateField(); + main.addComponent(df); - ErrorMessage errorMsg = new UserError("User error " + df); - df.setCaption("DateField caption " + df); - df.setDescription("DateField description " + df); - df.setComponentError(errorMsg); - df.setImmediate(true); - // FIXME: bug #1138 this makes datefield to render with unknown - // component (UIDL tree debug) - df.addStyleName("thisShouldBeHarmless"); + ErrorMessage errorMsg = new UserError("User error " + df); + df.setCaption("DateField caption " + df); + df.setDescription("DateField description " + df); + df.setComponentError(errorMsg); + df.setImmediate(true); + // FIXME: bug #1138 this makes datefield to render with unknown + // component (UIDL tree debug) + df.addStyleName("thisShouldBeHarmless"); - // Another test: locale - DateField df1 = new DateField(); - main.addComponent(df1); - df1.setLocale(new Locale("en", "US")); + // Another test: locale + DateField df1 = new DateField(); + main.addComponent(df1); + df1.setLocale(new Locale("en", "US")); - DateField df2 = new DateField(); - main.addComponent(df2); - df2.setLocale(new Locale("de", "DE")); + DateField df2 = new DateField(); + main.addComponent(df2); + df2.setLocale(new Locale("de", "DE")); - DateField df3 = new DateField(); - main.addComponent(df3); - df3.setLocale(new Locale("ru", "RU")); - } + DateField df3 = new DateField(); + main.addComponent(df3); + df3.setLocale(new Locale("ru", "RU")); + } - public void attach() { - ClassResource res = new ClassResource("m.gif", super.getApplication()); - df.setIcon(res); - super.attach(); - } + public void attach() { + ClassResource res = new ClassResource("m.gif", super.getApplication()); + df.setIcon(res); + super.attach(); + } } diff --git a/src/com/itmill/toolkit/tests/TestForAlignments.java b/src/com/itmill/toolkit/tests/TestForAlignments.java index 0f9df48b26..5140478fc4 100644 --- a/src/com/itmill/toolkit/tests/TestForAlignments.java +++ b/src/com/itmill/toolkit/tests/TestForAlignments.java @@ -8,55 +8,55 @@ import com.itmill.toolkit.ui.TextField; public class TestForAlignments extends CustomComponent { - public TestForAlignments() { - - OrderedLayout main = new OrderedLayout(); - - Button b1 = new Button("Right"); - Button b2 = new Button("Left"); - Button b3 = new Button("Bottom"); - Button b4 = new Button("Top"); - TextField t1 = new TextField("Right aligned"); - TextField t2 = new TextField("Bottom aligned"); - DateField d1 = new DateField("Center aligned"); - DateField d2 = new DateField("Center aligned"); - - OrderedLayout vert = new OrderedLayout(); - vert.addComponent(b1); - vert.addComponent(b2); - vert.addComponent(t1); - vert.addComponent(d1); - vert.setWidth(500); - vert.setComponentAlignment(b1, OrderedLayout.ALIGNMENT_RIGHT, - OrderedLayout.ALIGNMENT_TOP); - vert.setComponentAlignment(b2, OrderedLayout.ALIGNMENT_LEFT, - OrderedLayout.ALIGNMENT_TOP); - vert.setComponentAlignment(t1, OrderedLayout.ALIGNMENT_RIGHT, - OrderedLayout.ALIGNMENT_TOP); - vert.setComponentAlignment(d1, - OrderedLayout.ALIGNMENT_HORIZONTAL_CENTER, - OrderedLayout.ALIGNMENT_TOP); - OrderedLayout hori = new OrderedLayout( - OrderedLayout.ORIENTATION_HORIZONTAL); - hori.addComponent(b3); - hori.addComponent(b4); - hori.addComponent(t2); - hori.addComponent(d2); - hori.setHeight(200); - hori.setComponentAlignment(b3, OrderedLayout.ALIGNMENT_LEFT, - OrderedLayout.ALIGNMENT_BOTTOM); - hori.setComponentAlignment(b4, OrderedLayout.ALIGNMENT_LEFT, - OrderedLayout.ALIGNMENT_TOP); - hori.setComponentAlignment(t2, OrderedLayout.ALIGNMENT_LEFT, - OrderedLayout.ALIGNMENT_BOTTOM); - hori.setComponentAlignment(d2, OrderedLayout.ALIGNMENT_LEFT, - OrderedLayout.ALIGNMENT_VERTICAL_CENTER); - - main.addComponent(vert); - main.addComponent(hori); - - setCompositionRoot(main); - - } + public TestForAlignments() { + + OrderedLayout main = new OrderedLayout(); + + Button b1 = new Button("Right"); + Button b2 = new Button("Left"); + Button b3 = new Button("Bottom"); + Button b4 = new Button("Top"); + TextField t1 = new TextField("Right aligned"); + TextField t2 = new TextField("Bottom aligned"); + DateField d1 = new DateField("Center aligned"); + DateField d2 = new DateField("Center aligned"); + + OrderedLayout vert = new OrderedLayout(); + vert.addComponent(b1); + vert.addComponent(b2); + vert.addComponent(t1); + vert.addComponent(d1); + vert.setWidth(500); + vert.setComponentAlignment(b1, OrderedLayout.ALIGNMENT_RIGHT, + OrderedLayout.ALIGNMENT_TOP); + vert.setComponentAlignment(b2, OrderedLayout.ALIGNMENT_LEFT, + OrderedLayout.ALIGNMENT_TOP); + vert.setComponentAlignment(t1, OrderedLayout.ALIGNMENT_RIGHT, + OrderedLayout.ALIGNMENT_TOP); + vert.setComponentAlignment(d1, + OrderedLayout.ALIGNMENT_HORIZONTAL_CENTER, + OrderedLayout.ALIGNMENT_TOP); + OrderedLayout hori = new OrderedLayout( + OrderedLayout.ORIENTATION_HORIZONTAL); + hori.addComponent(b3); + hori.addComponent(b4); + hori.addComponent(t2); + hori.addComponent(d2); + hori.setHeight(200); + hori.setComponentAlignment(b3, OrderedLayout.ALIGNMENT_LEFT, + OrderedLayout.ALIGNMENT_BOTTOM); + hori.setComponentAlignment(b4, OrderedLayout.ALIGNMENT_LEFT, + OrderedLayout.ALIGNMENT_TOP); + hori.setComponentAlignment(t2, OrderedLayout.ALIGNMENT_LEFT, + OrderedLayout.ALIGNMENT_BOTTOM); + hori.setComponentAlignment(d2, OrderedLayout.ALIGNMENT_LEFT, + OrderedLayout.ALIGNMENT_VERTICAL_CENTER); + + main.addComponent(vert); + main.addComponent(hori); + + setCompositionRoot(main); + + } } diff --git a/src/com/itmill/toolkit/tests/TestForApplicationLayoutThatUsesWholeBrosersSpace.java b/src/com/itmill/toolkit/tests/TestForApplicationLayoutThatUsesWholeBrosersSpace.java index b7b53bd720..f41230f463 100644 --- a/src/com/itmill/toolkit/tests/TestForApplicationLayoutThatUsesWholeBrosersSpace.java +++ b/src/com/itmill/toolkit/tests/TestForApplicationLayoutThatUsesWholeBrosersSpace.java @@ -1,58 +1,63 @@ package com.itmill.toolkit.tests; import com.itmill.toolkit.Application; -import com.itmill.toolkit.ui.*; +import com.itmill.toolkit.terminal.Sizeable; +import com.itmill.toolkit.ui.ExpandLayout; +import com.itmill.toolkit.ui.Label; +import com.itmill.toolkit.ui.SplitPanel; +import com.itmill.toolkit.ui.Table; +import com.itmill.toolkit.ui.Window; public class TestForApplicationLayoutThatUsesWholeBrosersSpace extends - Application { + Application { - Window main = new Window("Windowing test"); + Window main = new Window("Windowing test"); - ExpandLayout rootLayout; + ExpandLayout rootLayout; - SplitPanel firstLevelSplit; + SplitPanel firstLevelSplit; - public void init() { - setMainWindow(main); + public void init() { + setMainWindow(main); - rootLayout = new ExpandLayout(); - main.setLayout(rootLayout); + rootLayout = new ExpandLayout(); + main.setLayout(rootLayout); - rootLayout.addComponent(new Label("header")); + rootLayout.addComponent(new Label("header")); - firstLevelSplit = new SplitPanel(); + firstLevelSplit = new SplitPanel(); - SplitPanel secondSplitPanel = new SplitPanel( - SplitPanel.ORIENTATION_HORIZONTAL); - secondSplitPanel.setFirstComponent(new Label("left")); + SplitPanel secondSplitPanel = new SplitPanel( + SplitPanel.ORIENTATION_HORIZONTAL); + secondSplitPanel.setFirstComponent(new Label("left")); - ExpandLayout topRight = new ExpandLayout(); - topRight.addComponent(new Label("topright header")); + ExpandLayout topRight = new ExpandLayout(); + topRight.addComponent(new Label("topright header")); - Table t = TestForTablesInitialColumnWidthLogicRendering.getTestTable(4, - 100); - t.setWidth(100); - t.setWidthUnits(Table.UNITS_PERCENTAGE); - t.setHeight(100); - t.setHeightUnits(Table.UNITS_PERCENTAGE); - topRight.addComponent(t); - topRight.expand(t); + Table t = TestForTablesInitialColumnWidthLogicRendering.getTestTable(4, + 100); + t.setWidth(100); + t.setWidthUnits(Sizeable.UNITS_PERCENTAGE); + t.setHeight(100); + t.setHeightUnits(Sizeable.UNITS_PERCENTAGE); + topRight.addComponent(t); + topRight.expand(t); - topRight.addComponent(new Label("topright footer")); + topRight.addComponent(new Label("topright footer")); - secondSplitPanel.setSecondComponent(topRight); + secondSplitPanel.setSecondComponent(topRight); - ExpandLayout el = new ExpandLayout(); - el.addComponent(new Label("Bšš")); + ExpandLayout el = new ExpandLayout(); + el.addComponent(new Label("B��")); - firstLevelSplit.setFirstComponent(secondSplitPanel); - firstLevelSplit.setSecondComponent(el); + firstLevelSplit.setFirstComponent(secondSplitPanel); + firstLevelSplit.setSecondComponent(el); - rootLayout.addComponent(firstLevelSplit); - rootLayout.expand(firstLevelSplit); + rootLayout.addComponent(firstLevelSplit); + rootLayout.expand(firstLevelSplit); - rootLayout.addComponent(new Label("footer")); + rootLayout.addComponent(new Label("footer")); - } + } } diff --git a/src/com/itmill/toolkit/tests/TestForBasicApplicationLayout.java b/src/com/itmill/toolkit/tests/TestForBasicApplicationLayout.java index e7712ecaaa..945035b3f9 100644 --- a/src/com/itmill/toolkit/tests/TestForBasicApplicationLayout.java +++ b/src/com/itmill/toolkit/tests/TestForBasicApplicationLayout.java @@ -18,88 +18,88 @@ import com.itmill.toolkit.ui.Button.ClickListener; public class TestForBasicApplicationLayout extends CustomComponent { - private Button click; - private Button click2; - private TabSheet tab; - - public TestForBasicApplicationLayout() { - - click = new Button("Set height -1", new ClickListener() { - - public void buttonClick(ClickEvent event) { - tab.setHeight(-1); - } - - }); - - click2 = new Button("Set height 100%", new ClickListener() { - - public void buttonClick(ClickEvent event) { - tab.setHeight(100); - tab.setHeightUnits(Sizeable.UNITS_PERCENTAGE); - } - - }); - - SplitPanel sp = new SplitPanel(SplitPanel.ORIENTATION_HORIZONTAL); - sp.setSplitPosition(290, Sizeable.UNITS_PIXELS); - - SplitPanel sp2 = new SplitPanel(SplitPanel.ORIENTATION_VERTICAL); - sp2.setSplitPosition(255, Sizeable.UNITS_PIXELS); - - Panel p = new Panel("Accordion Panel"); - p.setHeight(100); - p.setHeightUnits(Panel.UNITS_PERCENTAGE); - - tab = new TabSheet(); - tab.setWidth(100); - tab.setWidthUnits(Sizeable.UNITS_PERCENTAGE); - tab.setHeight(740); - tab.setHeightUnits(Sizeable.UNITS_PIXELS); - - Panel report = new Panel("Monthly Program Runs", new ExpandLayout()); - OrderedLayout controls = new OrderedLayout(); - controls.setMargin(true); - controls.addComponent(new Label("Report tab")); - controls.addComponent(click); - controls.addComponent(click2); - report.addComponent(controls); - DateField cal = new DateField(); - cal.setResolution(DateField.RESOLUTION_DAY); - cal.setLocale(new Locale("en", "US")); - report.addComponent(cal); - ((ExpandLayout) report.getLayout()).expand(controls); - report.addStyleName(Panel.STYLE_LIGHT); - report.setHeight(100); - report.setHeightUnits(Sizeable.UNITS_PERCENTAGE); - - sp2.setFirstComponent(report); - - Table table = TestForTablesInitialColumnWidthLogicRendering - .getTestTable(5, 200); - table.setPageLength(15); - table.setSelectable(true); - table.setRowHeaderMode(Table.ROW_HEADER_MODE_INDEX); - table.setColumnCollapsingAllowed(true); - table.setColumnReorderingAllowed(true); - table.setSortDisabled(false); - table.setWidth(100); - table.setWidthUnits(Sizeable.UNITS_PERCENTAGE); - table.setHeight(100); - table.setHeightUnits(Sizeable.UNITS_PERCENTAGE); - table.addStyleName("table-inline"); - sp2.setSecondComponent(table); - - tab.addTab(new Label("Tab1"), "Summary", null); - tab.addTab(sp2, "Reports", null); - tab.addTab(new Label("Tab 3"), "Statistics", null); - tab.addTab(new Label("Tab 4"), "Error Tracking", null); - tab.setSelectedTab(sp2); - - sp.setFirstComponent(p); - sp.setSecondComponent(tab); - - setCompositionRoot(sp); - } + private Button click; + private Button click2; + private TabSheet tab; + + public TestForBasicApplicationLayout() { + + click = new Button("Set height -1", new ClickListener() { + + public void buttonClick(ClickEvent event) { + tab.setHeight(-1); + } + + }); + + click2 = new Button("Set height 100%", new ClickListener() { + + public void buttonClick(ClickEvent event) { + tab.setHeight(100); + tab.setHeightUnits(Sizeable.UNITS_PERCENTAGE); + } + + }); + + SplitPanel sp = new SplitPanel(SplitPanel.ORIENTATION_HORIZONTAL); + sp.setSplitPosition(290, Sizeable.UNITS_PIXELS); + + SplitPanel sp2 = new SplitPanel(SplitPanel.ORIENTATION_VERTICAL); + sp2.setSplitPosition(255, Sizeable.UNITS_PIXELS); + + Panel p = new Panel("Accordion Panel"); + p.setHeight(100); + p.setHeightUnits(Sizeable.UNITS_PERCENTAGE); + + tab = new TabSheet(); + tab.setWidth(100); + tab.setWidthUnits(Sizeable.UNITS_PERCENTAGE); + tab.setHeight(740); + tab.setHeightUnits(Sizeable.UNITS_PIXELS); + + Panel report = new Panel("Monthly Program Runs", new ExpandLayout()); + OrderedLayout controls = new OrderedLayout(); + controls.setMargin(true); + controls.addComponent(new Label("Report tab")); + controls.addComponent(click); + controls.addComponent(click2); + report.addComponent(controls); + DateField cal = new DateField(); + cal.setResolution(DateField.RESOLUTION_DAY); + cal.setLocale(new Locale("en", "US")); + report.addComponent(cal); + ((ExpandLayout) report.getLayout()).expand(controls); + report.addStyleName(Panel.STYLE_LIGHT); + report.setHeight(100); + report.setHeightUnits(Sizeable.UNITS_PERCENTAGE); + + sp2.setFirstComponent(report); + + Table table = TestForTablesInitialColumnWidthLogicRendering + .getTestTable(5, 200); + table.setPageLength(15); + table.setSelectable(true); + table.setRowHeaderMode(Table.ROW_HEADER_MODE_INDEX); + table.setColumnCollapsingAllowed(true); + table.setColumnReorderingAllowed(true); + table.setSortDisabled(false); + table.setWidth(100); + table.setWidthUnits(Sizeable.UNITS_PERCENTAGE); + table.setHeight(100); + table.setHeightUnits(Sizeable.UNITS_PERCENTAGE); + table.addStyleName("table-inline"); + sp2.setSecondComponent(table); + + tab.addTab(new Label("Tab1"), "Summary", null); + tab.addTab(sp2, "Reports", null); + tab.addTab(new Label("Tab 3"), "Statistics", null); + tab.addTab(new Label("Tab 4"), "Error Tracking", null); + tab.setSelectedTab(sp2); + + sp.setFirstComponent(p); + sp.setSecondComponent(tab); + + setCompositionRoot(sp); + } } diff --git a/src/com/itmill/toolkit/tests/TestForChildComponentRendering.java b/src/com/itmill/toolkit/tests/TestForChildComponentRendering.java index 55ffab976f..d5021a835f 100644 --- a/src/com/itmill/toolkit/tests/TestForChildComponentRendering.java +++ b/src/com/itmill/toolkit/tests/TestForChildComponentRendering.java @@ -21,69 +21,71 @@ import com.itmill.toolkit.ui.Select; */ public class TestForChildComponentRendering extends CustomComponent { - private OrderedLayout main; - - public TestForChildComponentRendering() { - - main = new OrderedLayout(); - setCompositionRoot(main); - createNewView(); - } - - public void createNewView() { - main.removeAllComponents(); - main.addComponent(new Label("SDFGFHFHGJGFDSDSSSGFDD")); - - Link l = new Link(); - l.setCaption("Siirry ITMILLIIN"); - l.setResource(new ExternalResource("http://www.itmill.com/")); - l.setTargetHeight(200); - l.setTargetWidth(500); - l.setTargetBorder(Link.TARGET_BORDER_MINIMAL); - main.addComponent(l); - - Select se = new Select(); - se.setCaption("VALITSET TÄSTÄ"); - se.addItem("valinta1"); - se.addItem("Valinta 2"); - - Button b = new Button("refresh view", this, "createNewView"); - main.addComponent(b); - - b = new Button("reorder view", this, "randomReorder"); - main.addComponent(b); - - b = new Button("remove randomly one component", this, - "removeRandomComponent"); - main.addComponent(b); - - } - - public void randomReorder() { - Iterator it = main.getComponentIterator(); - ArrayList components = new ArrayList(); - while (it.hasNext()) - components.add(it.next()); - - OrderedLayout v = main; - v.removeAllComponents(); - - for (int i = components.size(); i > 0; i--) { - int index = (int) (Math.random() * i); - v.addComponent((Component) components.get(index)); - components.remove(index); - } - } - - public void removeRandomComponent() { - Iterator it = main.getComponentIterator(); - ArrayList components = new ArrayList(); - while (it.hasNext()) - components.add(it.next()); - int size = components.size(); - int index = (int) (Math.random() * size); - main.removeComponent((Component) components.get(index)); - - } + private OrderedLayout main; + + public TestForChildComponentRendering() { + + main = new OrderedLayout(); + setCompositionRoot(main); + createNewView(); + } + + public void createNewView() { + main.removeAllComponents(); + main.addComponent(new Label("SDFGFHFHGJGFDSDSSSGFDD")); + + Link l = new Link(); + l.setCaption("Siirry ITMILLIIN"); + l.setResource(new ExternalResource("http://www.itmill.com/")); + l.setTargetHeight(200); + l.setTargetWidth(500); + l.setTargetBorder(Link.TARGET_BORDER_MINIMAL); + main.addComponent(l); + + Select se = new Select(); + se.setCaption("VALITSET TÄSTÄ"); + se.addItem("valinta1"); + se.addItem("Valinta 2"); + + Button b = new Button("refresh view", this, "createNewView"); + main.addComponent(b); + + b = new Button("reorder view", this, "randomReorder"); + main.addComponent(b); + + b = new Button("remove randomly one component", this, + "removeRandomComponent"); + main.addComponent(b); + + } + + public void randomReorder() { + Iterator it = main.getComponentIterator(); + ArrayList components = new ArrayList(); + while (it.hasNext()) { + components.add(it.next()); + } + + OrderedLayout v = main; + v.removeAllComponents(); + + for (int i = components.size(); i > 0; i--) { + int index = (int) (Math.random() * i); + v.addComponent((Component) components.get(index)); + components.remove(index); + } + } + + public void removeRandomComponent() { + Iterator it = main.getComponentIterator(); + ArrayList components = new ArrayList(); + while (it.hasNext()) { + components.add(it.next()); + } + int size = components.size(); + int index = (int) (Math.random() * size); + main.removeComponent((Component) components.get(index)); + + } } diff --git a/src/com/itmill/toolkit/tests/TestForContainerFilterable.java b/src/com/itmill/toolkit/tests/TestForContainerFilterable.java index c1777b6aec..e567f4f34d 100644 --- a/src/com/itmill/toolkit/tests/TestForContainerFilterable.java +++ b/src/com/itmill/toolkit/tests/TestForContainerFilterable.java @@ -1,6 +1,7 @@ package com.itmill.toolkit.tests; import com.itmill.toolkit.data.util.IndexedContainer; +import com.itmill.toolkit.terminal.Sizeable; import com.itmill.toolkit.ui.Button; import com.itmill.toolkit.ui.CustomComponent; import com.itmill.toolkit.ui.Label; @@ -12,70 +13,81 @@ import com.itmill.toolkit.ui.Button.ClickEvent; public class TestForContainerFilterable extends CustomComponent { - OrderedLayout lo = new OrderedLayout(); - IndexedContainer ic = new IndexedContainer(); - Table t = new Table(); - private static String parts[] = {"Neo","Sa","rem","the","adi","za","tre","day","Ca","re","cen","ter","mi","nal"}; - TextField fooFilter = new TextField("foo-filter"); - TextField barFilter = new TextField("bar-filter"); - Button filterButton = new Button("Filter"); - Label count = new Label(); + OrderedLayout lo = new OrderedLayout(); + IndexedContainer ic = new IndexedContainer(); + Table t = new Table(); + private static String parts[] = { "Neo", "Sa", "rem", "the", "adi", "za", + "tre", "day", "Ca", "re", "cen", "ter", "mi", "nal" }; + TextField fooFilter = new TextField("foo-filter"); + TextField barFilter = new TextField("bar-filter"); + Button filterButton = new Button("Filter"); + Label count = new Label(); - - public TestForContainerFilterable() { - setCompositionRoot(lo); - - // Init datasource - ic.addContainerProperty("foo", String.class, ""); - ic.addContainerProperty("bar", String.class, ""); - for (int i=0;i<1000;i++) { - Object id = ic.addItem(); - ic.getContainerProperty(id, "foo").setValue(randomWord()); - ic.getContainerProperty(id, "bar").setValue(randomWord()); - } - - // Init filtering view - Panel filterPanel = new Panel("Filter", new OrderedLayout(OrderedLayout.ORIENTATION_HORIZONTAL)); - filterPanel.setWidth(100); - filterPanel.setWidthUnits(Panel.UNITS_PERCENTAGE); - lo.addComponent(filterPanel); - filterPanel.addComponent(fooFilter); - filterPanel.addComponent(barFilter); - filterPanel.addComponent(filterButton); - fooFilter.setDescription("Filters foo column in case-sensitive contains manner."); - barFilter.setDescription("Filters bar column in case-insensitive prefix manner."); - filterPanel.addComponent(count); - - - // Table - lo.addComponent(t); - t.setPageLength(12); - t.setWidth(100); - t.setWidthUnits(Table.UNITS_PERCENTAGE); - t.setContainerDataSource(ic); - - // Handler - filterButton.addListener(new Button.ClickListener() { - public void buttonClick(ClickEvent event) { - ic.removeAllContainerFilters(); - if (fooFilter.toString().length()>0) ic.addContainerFilter("foo", fooFilter.toString(), false, false); - if (barFilter.toString().length()>0) ic.addContainerFilter("bar", barFilter.toString(), true, true); - count.setValue("Rows in table: " + ic.size()); - } - }); - - // Resetbutton - lo.addComponent(new Button("Rebind table datasource", new Button.ClickListener() { - public void buttonClick(ClickEvent event) { - t.setContainerDataSource(ic); - } - })); - } - - private String randomWord() { - int len = (int) (Math.random()*4); - StringBuffer buf = new StringBuffer(); - while(len-->=0) buf.append(parts[(int) (Math.random()*parts.length)]); - return buf.toString(); - } + public TestForContainerFilterable() { + setCompositionRoot(lo); + + // Init datasource + ic.addContainerProperty("foo", String.class, ""); + ic.addContainerProperty("bar", String.class, ""); + for (int i = 0; i < 1000; i++) { + Object id = ic.addItem(); + ic.getContainerProperty(id, "foo").setValue(randomWord()); + ic.getContainerProperty(id, "bar").setValue(randomWord()); + } + + // Init filtering view + Panel filterPanel = new Panel("Filter", new OrderedLayout( + OrderedLayout.ORIENTATION_HORIZONTAL)); + filterPanel.setWidth(100); + filterPanel.setWidthUnits(Sizeable.UNITS_PERCENTAGE); + lo.addComponent(filterPanel); + filterPanel.addComponent(fooFilter); + filterPanel.addComponent(barFilter); + filterPanel.addComponent(filterButton); + fooFilter + .setDescription("Filters foo column in case-sensitive contains manner."); + barFilter + .setDescription("Filters bar column in case-insensitive prefix manner."); + filterPanel.addComponent(count); + + // Table + lo.addComponent(t); + t.setPageLength(12); + t.setWidth(100); + t.setWidthUnits(Sizeable.UNITS_PERCENTAGE); + t.setContainerDataSource(ic); + + // Handler + filterButton.addListener(new Button.ClickListener() { + public void buttonClick(ClickEvent event) { + ic.removeAllContainerFilters(); + if (fooFilter.toString().length() > 0) { + ic.addContainerFilter("foo", fooFilter.toString(), false, + false); + } + if (barFilter.toString().length() > 0) { + ic.addContainerFilter("bar", barFilter.toString(), true, + true); + } + count.setValue("Rows in table: " + ic.size()); + } + }); + + // Resetbutton + lo.addComponent(new Button("Rebind table datasource", + new Button.ClickListener() { + public void buttonClick(ClickEvent event) { + t.setContainerDataSource(ic); + } + })); + } + + private String randomWord() { + int len = (int) (Math.random() * 4); + StringBuffer buf = new StringBuffer(); + while (len-- >= 0) { + buf.append(parts[(int) (Math.random() * parts.length)]); + } + return buf.toString(); + } } diff --git a/src/com/itmill/toolkit/tests/TestForGridLayoutChildComponentRendering.java b/src/com/itmill/toolkit/tests/TestForGridLayoutChildComponentRendering.java index 853f68e09b..2f0c70889c 100644 --- a/src/com/itmill/toolkit/tests/TestForGridLayoutChildComponentRendering.java +++ b/src/com/itmill/toolkit/tests/TestForGridLayoutChildComponentRendering.java @@ -10,7 +10,6 @@ import com.itmill.toolkit.ui.CustomComponent; import com.itmill.toolkit.ui.GridLayout; import com.itmill.toolkit.ui.Label; import com.itmill.toolkit.ui.Link; -import com.itmill.toolkit.ui.OrderedLayout; import com.itmill.toolkit.ui.Select; /** @@ -22,76 +21,79 @@ import com.itmill.toolkit.ui.Select; */ public class TestForGridLayoutChildComponentRendering extends CustomComponent { - private GridLayout main = new GridLayout(2, 3); - - public TestForGridLayoutChildComponentRendering() { - - setCompositionRoot(main); - createNewView(); - } - - public void createNewView() { - main.removeAllComponents(); - main.addComponent(new Label("SDFGFHFHGJGFDSDSSSGFDD")); - - Link l = new Link(); - l.setCaption("Siirry ITMILLIIN"); - l.setResource(new ExternalResource("http://www.itmill.com/")); - l.setTargetHeight(200); - l.setTargetWidth(500); - l.setTargetBorder(Link.TARGET_BORDER_MINIMAL); - main.addComponent(l); - - Select se = new Select("Tästä valitaan"); - se.setCaption("Whattaa select"); - se.addItem("valinta1"); - se.addItem("Valinta 2"); - - main.addComponent(se, 0, 1, 1, 1); - - Button b = new Button("refresh view", this, "createNewView"); - main.addComponent(b); - - b = new Button("reorder view", this, "randomReorder"); - main.addComponent(b); - - b = new Button("remove randomly one component", this, - "removeRandomComponent"); - main.addComponent(b); - - } - - public void randomReorder() { - Iterator it = main.getComponentIterator(); - ArrayList components = new ArrayList(); - while (it.hasNext()) - components.add(it.next()); - - main.removeAllComponents(); - - int size = components.size(); - int colspanIndex = ((int) (Math.random() * size) / 2) * 2 + 2; - - for (int i = components.size(); i > 0; i--) { - int index = (int) (Math.random() * i); - if (i == colspanIndex) - main.addComponent((Component) components.get(index), 0, - (size - i) / 2, 1, (size - i) / 2); - else - main.addComponent((Component) components.get(index)); - components.remove(index); - } - } - - public void removeRandomComponent() { - Iterator it = main.getComponentIterator(); - ArrayList components = new ArrayList(); - while (it.hasNext()) - components.add(it.next()); - int size = components.size(); - int index = (int) (Math.random() * size); - main.removeComponent((Component) components.get(index)); - - } + private GridLayout main = new GridLayout(2, 3); + + public TestForGridLayoutChildComponentRendering() { + + setCompositionRoot(main); + createNewView(); + } + + public void createNewView() { + main.removeAllComponents(); + main.addComponent(new Label("SDFGFHFHGJGFDSDSSSGFDD")); + + Link l = new Link(); + l.setCaption("Siirry ITMILLIIN"); + l.setResource(new ExternalResource("http://www.itmill.com/")); + l.setTargetHeight(200); + l.setTargetWidth(500); + l.setTargetBorder(Link.TARGET_BORDER_MINIMAL); + main.addComponent(l); + + Select se = new Select("Tästä valitaan"); + se.setCaption("Whattaa select"); + se.addItem("valinta1"); + se.addItem("Valinta 2"); + + main.addComponent(se, 0, 1, 1, 1); + + Button b = new Button("refresh view", this, "createNewView"); + main.addComponent(b); + + b = new Button("reorder view", this, "randomReorder"); + main.addComponent(b); + + b = new Button("remove randomly one component", this, + "removeRandomComponent"); + main.addComponent(b); + + } + + public void randomReorder() { + Iterator it = main.getComponentIterator(); + ArrayList components = new ArrayList(); + while (it.hasNext()) { + components.add(it.next()); + } + + main.removeAllComponents(); + + int size = components.size(); + int colspanIndex = ((int) (Math.random() * size) / 2) * 2 + 2; + + for (int i = components.size(); i > 0; i--) { + int index = (int) (Math.random() * i); + if (i == colspanIndex) { + main.addComponent((Component) components.get(index), 0, + (size - i) / 2, 1, (size - i) / 2); + } else { + main.addComponent((Component) components.get(index)); + } + components.remove(index); + } + } + + public void removeRandomComponent() { + Iterator it = main.getComponentIterator(); + ArrayList components = new ArrayList(); + while (it.hasNext()) { + components.add(it.next()); + } + int size = components.size(); + int index = (int) (Math.random() * size); + main.removeComponent((Component) components.get(index)); + + } } diff --git a/src/com/itmill/toolkit/tests/TestForMultipleStyleNames.java b/src/com/itmill/toolkit/tests/TestForMultipleStyleNames.java index a87f53ae10..671ae05c11 100644 --- a/src/com/itmill/toolkit/tests/TestForMultipleStyleNames.java +++ b/src/com/itmill/toolkit/tests/TestForMultipleStyleNames.java @@ -17,68 +17,68 @@ import com.itmill.toolkit.ui.TwinColSelect; * @author IT Mill Ltd. */ public class TestForMultipleStyleNames extends CustomComponent implements - ValueChangeListener { + ValueChangeListener { - private final OrderedLayout main = new OrderedLayout(); + private final OrderedLayout main = new OrderedLayout(); - private Label l; + private Label l; - private final TwinColSelect s = new TwinColSelect(); + private final TwinColSelect s = new TwinColSelect(); - private ArrayList styleNames2; + private ArrayList styleNames2; - public TestForMultipleStyleNames() { - setCompositionRoot(this.main); - createNewView(); - } + public TestForMultipleStyleNames() { + setCompositionRoot(main); + createNewView(); + } - public void createNewView() { - this.main.removeAllComponents(); - this.main.addComponent(new Label( - "TK5 supports multiple stylenames for components.")); + public void createNewView() { + main.removeAllComponents(); + main.addComponent(new Label( + "TK5 supports multiple stylenames for components.")); - this.styleNames2 = new ArrayList(); + styleNames2 = new ArrayList(); - this.styleNames2.add("red"); - this.styleNames2.add("bold"); - this.styleNames2.add("italic"); + styleNames2.add("red"); + styleNames2.add("bold"); + styleNames2.add("italic"); - this.s.setContainerDataSource(new IndexedContainer(this.styleNames2)); - this.s.addListener(this); - this.s.setImmediate(true); - this.main.addComponent(this.s); + s.setContainerDataSource(new IndexedContainer(styleNames2)); + s.addListener(this); + s.setImmediate(true); + main.addComponent(s); - this.l = new Label("Test labele"); - this.main.addComponent(this.l); + l = new Label("Test labele"); + main.addComponent(l); - } + } - public void valueChange(ValueChangeEvent event) { + public void valueChange(ValueChangeEvent event) { - String currentStyle = this.l.getStyle(); - String[] tmp = currentStyle.split(" "); - ArrayList curStyles = new ArrayList(); - for (int i = 0; i < tmp.length; i++) { - if (tmp[i] != "") { - curStyles.add(tmp[i]); - } - } + String currentStyle = l.getStyle(); + String[] tmp = currentStyle.split(" "); + ArrayList curStyles = new ArrayList(); + for (int i = 0; i < tmp.length; i++) { + if (tmp[i] != "") { + curStyles.add(tmp[i]); + } + } - Collection styles = (Collection) this.s.getValue(); + Collection styles = (Collection) s.getValue(); - for (Iterator iterator = styles.iterator(); iterator.hasNext();) { - String styleName = (String) iterator.next(); - if (curStyles.contains(styleName)) { - // already added - curStyles.remove(styleName); - } else { - this.l.addStyleName(styleName); - } - } - for (Iterator iterator2 = curStyles.iterator(); iterator2.hasNext();) { - String object = (String) iterator2.next(); - this.l.removeStyleName(object); - } - } + for (Iterator iterator = styles.iterator(); iterator.hasNext();) { + String styleName = (String) iterator.next(); + if (curStyles.contains(styleName)) { + // already added + curStyles.remove(styleName); + } else { + l.addStyleName(styleName); + } + } + for (Iterator iterator2 = curStyles.iterator(); iterator2.hasNext();) { + String object = (String) iterator2.next(); + l.removeStyleName(object); + } + } } diff --git a/src/com/itmill/toolkit/tests/TestForNativeWindowing.java b/src/com/itmill/toolkit/tests/TestForNativeWindowing.java index cd60521dab..7fa373d8d2 100644 --- a/src/com/itmill/toolkit/tests/TestForNativeWindowing.java +++ b/src/com/itmill/toolkit/tests/TestForNativeWindowing.java @@ -11,113 +11,114 @@ import com.itmill.toolkit.ui.Button.ClickEvent; public class TestForNativeWindowing extends Application { - Window main = new Window("Windowing test"); - - public void init() { - - setMainWindow(main); - - main.addComponent(new Button("Add new subwindow", - new Button.ClickListener() { - public void buttonClick(ClickEvent event) { - final Window w = new Window("sw " - + System.currentTimeMillis()); - main.addWindow(w); - w.setPositionX(100); - w.setPositionY(100); - w.setWidth(200); - w.setHeight(200); - - w.setWidth(100); - w.setHeight(400); - - Button closebutton = new Button("Close " - + w.getCaption(), new Button.ClickListener() { - public void buttonClick(ClickEvent event) { - main.removeWindow(w); - } - - }); - w.addComponent(closebutton); - - w.addComponent(new Label( - "

Lorem ipsum dolor sit amet.

" - + "

Lorem ipsum dolor sit amet.

" - + "

Lorem ipsum dolor sit amet.

" - + "

Lorem ipsum dolor sit amet.

" - + "

Lorem ipsum dolor sit amet.

" - + "

Lorem ipsum dolor sit amet.

" - + "

Lorem ipsum dolor sit amet.

" - + "

Lorem ipsum dolor sit amet.

" - + "

Lorem ipsum dolor sit amet.

" - + "

Lorem ipsum dolor sit amet.

" - + "

Lorem ipsum dolor sit amet.

" - + "

Lorem ipsum dolor sit amet.

" - + "

Lorem ipsum dolor sit amet.

" - + "

Lorem ipsum dolor sit amet.

" - + "

Lorem ipsum dolor sit amet.

" - + "

Lorem ipsum dolor sit amet.

" - + "

Lorem ipsum dolor sit amet.

" - + "

Lorem ipsum dolor sit amet.

" - + "

Lorem ipsum dolor sit amet.

" - + "

Lorem ipsum dolor sit amet.

" - + "

Lorem ipsum dolor sit amet.

" - + "

Lorem ipsum dolor sit amet.

", - Label.CONTENT_XHTML)); - - } - })); - - main.addComponent(new Button( - "Open a currently uncreated application level window", - new Button.ClickListener() { - public void buttonClick(ClickEvent event) { - try { - main - .open( - new com.itmill.toolkit.terminal.ExternalResource( - new URL( - getURL(), - "mainwin-" - + System - .currentTimeMillis() - + "/")), - null); - } catch (MalformedURLException e) { - } - } - })); - - main.addComponent(new Button( - "Commit (saves window state: size, place, scrollpos)")); - } - - public Window getWindow(String name) { - - Window w = super.getWindow(name); - if (w != null) - return w; - - if (name != null && name.startsWith("mainwin-")) { - String postfix = name.substring("mainwin-".length()); - final Window ww = new Window("Window: " + postfix); - ww.setName(name); - ww.addComponent(new Label( - "This is a application-level window opened with name: " - + name)); - ww.addComponent(new Button("Click me", new Button.ClickListener() { - int state = 0; - - public void buttonClick(ClickEvent event) { - ww.addComponent(new Label("Button clicked " + (++state) - + " times")); - } - })); - addWindow(ww); - return ww; - } - - return null; - } + Window main = new Window("Windowing test"); + + public void init() { + + setMainWindow(main); + + main.addComponent(new Button("Add new subwindow", + new Button.ClickListener() { + public void buttonClick(ClickEvent event) { + final Window w = new Window("sw " + + System.currentTimeMillis()); + main.addWindow(w); + w.setPositionX(100); + w.setPositionY(100); + w.setWidth(200); + w.setHeight(200); + + w.setWidth(100); + w.setHeight(400); + + Button closebutton = new Button("Close " + + w.getCaption(), new Button.ClickListener() { + public void buttonClick(ClickEvent event) { + main.removeWindow(w); + } + + }); + w.addComponent(closebutton); + + w.addComponent(new Label( + "

Lorem ipsum dolor sit amet.

" + + "

Lorem ipsum dolor sit amet.

" + + "

Lorem ipsum dolor sit amet.

" + + "

Lorem ipsum dolor sit amet.

" + + "

Lorem ipsum dolor sit amet.

" + + "

Lorem ipsum dolor sit amet.

" + + "

Lorem ipsum dolor sit amet.

" + + "

Lorem ipsum dolor sit amet.

" + + "

Lorem ipsum dolor sit amet.

" + + "

Lorem ipsum dolor sit amet.

" + + "

Lorem ipsum dolor sit amet.

" + + "

Lorem ipsum dolor sit amet.

" + + "

Lorem ipsum dolor sit amet.

" + + "

Lorem ipsum dolor sit amet.

" + + "

Lorem ipsum dolor sit amet.

" + + "

Lorem ipsum dolor sit amet.

" + + "

Lorem ipsum dolor sit amet.

" + + "

Lorem ipsum dolor sit amet.

" + + "

Lorem ipsum dolor sit amet.

" + + "

Lorem ipsum dolor sit amet.

" + + "

Lorem ipsum dolor sit amet.

" + + "

Lorem ipsum dolor sit amet.

", + Label.CONTENT_XHTML)); + + } + })); + + main.addComponent(new Button( + "Open a currently uncreated application level window", + new Button.ClickListener() { + public void buttonClick(ClickEvent event) { + try { + main + .open( + new com.itmill.toolkit.terminal.ExternalResource( + new URL( + getURL(), + "mainwin-" + + System + .currentTimeMillis() + + "/")), + null); + } catch (MalformedURLException e) { + } + } + })); + + main.addComponent(new Button( + "Commit (saves window state: size, place, scrollpos)")); + } + + public Window getWindow(String name) { + + Window w = super.getWindow(name); + if (w != null) { + return w; + } + + if (name != null && name.startsWith("mainwin-")) { + String postfix = name.substring("mainwin-".length()); + final Window ww = new Window("Window: " + postfix); + ww.setName(name); + ww.addComponent(new Label( + "This is a application-level window opened with name: " + + name)); + ww.addComponent(new Button("Click me", new Button.ClickListener() { + int state = 0; + + public void buttonClick(ClickEvent event) { + ww.addComponent(new Label("Button clicked " + (++state) + + " times")); + } + })); + addWindow(ww); + return ww; + } + + return null; + } } diff --git a/src/com/itmill/toolkit/tests/TestForPreconfiguredComponents.java b/src/com/itmill/toolkit/tests/TestForPreconfiguredComponents.java index e108756c59..2e4d9cfe44 100644 --- a/src/com/itmill/toolkit/tests/TestForPreconfiguredComponents.java +++ b/src/com/itmill/toolkit/tests/TestForPreconfiguredComponents.java @@ -23,173 +23,173 @@ import com.itmill.toolkit.ui.Button.ClickListener; * @author IT Mill Ltd. */ public class TestForPreconfiguredComponents extends CustomComponent implements - Handler { - - private static final String[] firstnames = new String[] { "John", "Mary", - "Joe", "Sarah", "Jeff", "Jane", "Peter", "Marc", "Josie", "Linus" }; - - private static final String[] lastnames = new String[] { "Torvalds", - "Smith", "Jones", "Beck", "Sheridan", "Picard", "Hill", "Fielding", - "Einstein" }; - - private final OrderedLayout main = new OrderedLayout(); - - private final Action[] actions = new Action[] { new Action("edit"), - new Action("delete") }; - - private Panel al; - - private Tree contextTree; - - public TestForPreconfiguredComponents() { - - setCompositionRoot(this.main); - createNewView(); - } - - public void createNewView() { - this.main.removeAllComponents(); - this.main - .addComponent(new Label( - "In TK5 we introduce some \"new\" componens. Earlier one" - + " usually used setStyle or some other methods on possibly " - + "multiple steps to configure component for ones needs. These new " - + "server side components are mostly just classes that in constructor " - + "set base class to state that programmer wants. This ought to help " - + "newcomers and make code more readable.")); - - this.main.addComponent(new Button("commit")); - - Panel test = createTestBench(new CheckBox()); - test.setCaption("CheckBox (configured from button)"); - this.main.addComponent(test); - - AbstractSelect s = new TwinColSelect(); - fillSelect(s, 20); - test = createTestBench(s); - test.setCaption("TwinColSelect (configured from select)"); - this.main.addComponent(test); - - s = new NativeSelect(); - fillSelect(s, 20); - test = createTestBench(s); - test.setCaption("Native (configured from select)"); - this.main.addComponent(test); - - s = new OptionGroup(); - fillSelect(s, 20); - test = createTestBench(s); - test.setCaption("OptionGroup (configured from select)"); - this.main.addComponent(test); - - s = new OptionGroup(); - fillSelect(s, 20); - s.setMultiSelect(true); - test = createTestBench(s); - test - .setCaption("OptionGroup + multiselect manually (configured from select)"); - this.main.addComponent(test); - - // Tree t = createTestTree(); - // t.setCaption("with actions"); - // t.setImmediate(true); - // t.addActionHandler(this); - // Panel ol = (Panel) createTestBench(t); - // al = new Panel("action log"); - // ol.addComponent(al); - // main.addComponent(ol); - // contextTree = t; - - Button b = new Button("refresh view", this, "createNewView"); - this.main.addComponent(b); - - } - - public static void fillSelect(AbstractSelect s, int items) { - for (int i = 0; i < items; i++) { - String name = firstnames[(int) (Math.random() * (firstnames.length - 1))] - + " " - + lastnames[(int) (Math.random() * (lastnames.length - 1))]; - s.addItem(name); - } - } - - public Tree createTestTree() { - Tree t = new Tree("Tree"); - String[] names = new String[100]; - for (int i = 0; i < names.length; i++) { - names[i] = firstnames[(int) (Math.random() * (firstnames.length - 1))] - + " " - + lastnames[(int) (Math.random() * (lastnames.length - 1))]; - } - - // Create tree - t = new Tree("Organization Structure"); - for (int i = 0; i < 100; i++) { - t.addItem(names[i]); - String parent = names[(int) (Math.random() * (names.length - 1))]; - if (t.containsId(parent)) { - t.setParent(names[i], parent); - } - } - - // Forbid childless people to have children (makes them leaves) - for (int i = 0; i < 100; i++) { - if (!t.hasChildren(names[i])) { - t.setChildrenAllowed(names[i], false); - } - } - return t; - } - - public Panel createTestBench(Component t) { - Panel ol = new Panel(); - ol.setLayout(new OrderedLayout(OrderedLayout.ORIENTATION_HORIZONTAL)); - - ol.addComponent(t); - - final OrderedLayout ol2 = new OrderedLayout( - OrderedLayout.ORIENTATION_HORIZONTAL); - final Panel status = new Panel("Events"); - final Button clear = new Button("clear event log"); - clear.addListener(new ClickListener() { - public void buttonClick(ClickEvent event) { - status.removeAllComponents(); - status.addComponent(ol2); - } - }); - ol2.addComponent(clear); - final Button commit = new Button("commit changes"); - ol2.addComponent(commit); - status.addComponent(ol2); - - status.setHeight(300); - status.setWidth(400); - - ol.addComponent(status); - - t.addListener(new Listener() { - public void componentEvent(Event event) { - status.addComponent(new Label(event.getClass().getName())); - status.addComponent(new Label("selected: " - + event.getSource().toString())); - } - }); - - return ol; - } - - public Action[] getActions(Object target, Object sender) { - return this.actions; - } - - public void handleAction(Action action, Object sender, Object target) { - if (action == this.actions[1]) { - this.al.addComponent(new Label("Delete selected on " + target)); - this.contextTree.removeItem(target); - - } else { - this.al.addComponent(new Label("Edit selected on " + target)); - } - } + Handler { + + private static final String[] firstnames = new String[] { "John", "Mary", + "Joe", "Sarah", "Jeff", "Jane", "Peter", "Marc", "Josie", "Linus" }; + + private static final String[] lastnames = new String[] { "Torvalds", + "Smith", "Jones", "Beck", "Sheridan", "Picard", "Hill", "Fielding", + "Einstein" }; + + private final OrderedLayout main = new OrderedLayout(); + + private final Action[] actions = new Action[] { new Action("edit"), + new Action("delete") }; + + private Panel al; + + private Tree contextTree; + + public TestForPreconfiguredComponents() { + + setCompositionRoot(main); + createNewView(); + } + + public void createNewView() { + main.removeAllComponents(); + main + .addComponent(new Label( + "In TK5 we introduce some \"new\" componens. Earlier one" + + " usually used setStyle or some other methods on possibly " + + "multiple steps to configure component for ones needs. These new " + + "server side components are mostly just classes that in constructor " + + "set base class to state that programmer wants. This ought to help " + + "newcomers and make code more readable.")); + + main.addComponent(new Button("commit")); + + Panel test = createTestBench(new CheckBox()); + test.setCaption("CheckBox (configured from button)"); + main.addComponent(test); + + AbstractSelect s = new TwinColSelect(); + fillSelect(s, 20); + test = createTestBench(s); + test.setCaption("TwinColSelect (configured from select)"); + main.addComponent(test); + + s = new NativeSelect(); + fillSelect(s, 20); + test = createTestBench(s); + test.setCaption("Native (configured from select)"); + main.addComponent(test); + + s = new OptionGroup(); + fillSelect(s, 20); + test = createTestBench(s); + test.setCaption("OptionGroup (configured from select)"); + main.addComponent(test); + + s = new OptionGroup(); + fillSelect(s, 20); + s.setMultiSelect(true); + test = createTestBench(s); + test + .setCaption("OptionGroup + multiselect manually (configured from select)"); + main.addComponent(test); + + // Tree t = createTestTree(); + // t.setCaption("with actions"); + // t.setImmediate(true); + // t.addActionHandler(this); + // Panel ol = (Panel) createTestBench(t); + // al = new Panel("action log"); + // ol.addComponent(al); + // main.addComponent(ol); + // contextTree = t; + + Button b = new Button("refresh view", this, "createNewView"); + main.addComponent(b); + + } + + public static void fillSelect(AbstractSelect s, int items) { + for (int i = 0; i < items; i++) { + String name = firstnames[(int) (Math.random() * (firstnames.length - 1))] + + " " + + lastnames[(int) (Math.random() * (lastnames.length - 1))]; + s.addItem(name); + } + } + + public Tree createTestTree() { + Tree t = new Tree("Tree"); + String[] names = new String[100]; + for (int i = 0; i < names.length; i++) { + names[i] = firstnames[(int) (Math.random() * (firstnames.length - 1))] + + " " + + lastnames[(int) (Math.random() * (lastnames.length - 1))]; + } + + // Create tree + t = new Tree("Organization Structure"); + for (int i = 0; i < 100; i++) { + t.addItem(names[i]); + String parent = names[(int) (Math.random() * (names.length - 1))]; + if (t.containsId(parent)) { + t.setParent(names[i], parent); + } + } + + // Forbid childless people to have children (makes them leaves) + for (int i = 0; i < 100; i++) { + if (!t.hasChildren(names[i])) { + t.setChildrenAllowed(names[i], false); + } + } + return t; + } + + public Panel createTestBench(Component t) { + Panel ol = new Panel(); + ol.setLayout(new OrderedLayout(OrderedLayout.ORIENTATION_HORIZONTAL)); + + ol.addComponent(t); + + final OrderedLayout ol2 = new OrderedLayout( + OrderedLayout.ORIENTATION_HORIZONTAL); + final Panel status = new Panel("Events"); + final Button clear = new Button("clear event log"); + clear.addListener(new ClickListener() { + public void buttonClick(ClickEvent event) { + status.removeAllComponents(); + status.addComponent(ol2); + } + }); + ol2.addComponent(clear); + final Button commit = new Button("commit changes"); + ol2.addComponent(commit); + status.addComponent(ol2); + + status.setHeight(300); + status.setWidth(400); + + ol.addComponent(status); + + t.addListener(new Listener() { + public void componentEvent(Event event) { + status.addComponent(new Label(event.getClass().getName())); + status.addComponent(new Label("selected: " + + event.getSource().toString())); + } + }); + + return ol; + } + + public Action[] getActions(Object target, Object sender) { + return actions; + } + + public void handleAction(Action action, Object sender, Object target) { + if (action == actions[1]) { + al.addComponent(new Label("Delete selected on " + target)); + contextTree.removeItem(target); + + } else { + al.addComponent(new Label("Edit selected on " + target)); + } + } } diff --git a/src/com/itmill/toolkit/tests/TestForRichTextEditor.java b/src/com/itmill/toolkit/tests/TestForRichTextEditor.java index 7b371625ee..407dbd8194 100644 --- a/src/com/itmill/toolkit/tests/TestForRichTextEditor.java +++ b/src/com/itmill/toolkit/tests/TestForRichTextEditor.java @@ -12,41 +12,40 @@ import com.itmill.toolkit.ui.RichTextArea; * * @author IT Mill Ltd. */ -public class TestForRichTextEditor extends CustomComponent implements ValueChangeListener { +public class TestForRichTextEditor extends CustomComponent implements + ValueChangeListener { - private OrderedLayout main = new OrderedLayout(); + private OrderedLayout main = new OrderedLayout(); - private Label l; + private Label l; - private RichTextArea rte; + private RichTextArea rte; - public TestForRichTextEditor() { + public TestForRichTextEditor() { - setCompositionRoot(main); - createNewView(); - } + setCompositionRoot(main); + createNewView(); + } - public void createNewView() { - main.removeAllComponents(); - main - .addComponent(new Label( - "RTE uses google richtextArea and their examples toolbar.")); + public void createNewView() { + main.removeAllComponents(); + main.addComponent(new Label( + "RTE uses google richtextArea and their examples toolbar.")); - - rte = new RichTextArea(); - rte.addListener((ValueChangeListener) this); - - main.addComponent(rte); + rte = new RichTextArea(); + rte.addListener(this); - main.addComponent(new Button("commit content to label below")); - - l = new Label("", Label.CONTENT_XHTML); - main.addComponent(l); + main.addComponent(rte); - } + main.addComponent(new Button("commit content to label below")); + + l = new Label("", Label.CONTENT_XHTML); + main.addComponent(l); + + } + + public void valueChange(ValueChangeEvent event) { + l.setValue(rte.getValue()); + } - public void valueChange(ValueChangeEvent event) { - l.setValue(rte.getValue()); - } - } diff --git a/src/com/itmill/toolkit/tests/TestForTablesInitialColumnWidthLogicRendering.java b/src/com/itmill/toolkit/tests/TestForTablesInitialColumnWidthLogicRendering.java index 1d33986bf6..3c1b298c66 100644 --- a/src/com/itmill/toolkit/tests/TestForTablesInitialColumnWidthLogicRendering.java +++ b/src/com/itmill/toolkit/tests/TestForTablesInitialColumnWidthLogicRendering.java @@ -2,6 +2,7 @@ package com.itmill.toolkit.tests; import java.util.Vector; +import com.itmill.toolkit.terminal.Sizeable; import com.itmill.toolkit.ui.Button; import com.itmill.toolkit.ui.CustomComponent; import com.itmill.toolkit.ui.Label; @@ -16,97 +17,97 @@ import com.itmill.toolkit.ui.Table; * @author IT Mill Ltd. */ public class TestForTablesInitialColumnWidthLogicRendering extends - CustomComponent { - - private OrderedLayout main = new OrderedLayout(); - - public TestForTablesInitialColumnWidthLogicRendering() { - - setCompositionRoot(main); - createNewView(); - } - - public void createNewView() { - main.removeAllComponents(); - main - .addComponent(new Label( - "Below are same tables that all should render somewhat nice. Also when testing, you might want to try resizing window.")); - - Table t; - - // t = new Table("Empty table"); - // main.addComponent(t); - - t = getTestTable(5, 0); - t.setCaption("Table with only headers"); - // main.addComponent(t); - - t = getTestTable(5, 200); - t.setCaption("Table with some cols and lot of rows"); - main.addComponent(t); - - t = getTestTable(12, 4); - t.setCaption("Table with some rows and lot of columns"); - main.addComponent(t); - - t = getTestTable(3, 40); - t - .setCaption("Table with some columns and wide explicit width. (Ought to widen columns to use all space)"); - t.setWidth(1000); - main.addComponent(t); - - t = getTestTable(12, 4); - t.setCaption("Table with some rows and lot of columns, width == 100%"); - t.setWidth(100); - t.setWidthUnits(Table.UNITS_PERCENTAGE); - main.addComponent(t); - - t = getTestTable(12, 100); - t - .setCaption("Table with lot of rows and lot of columns, width == 50%"); - t.setWidth(50); - t.setWidthUnits(Table.UNITS_PERCENTAGE); - main.addComponent(t); - - t = getTestTable(5, 100); - t.setCaption("Table with 40 rows"); - // main.addComponent(t); - - t = getTestTable(4, 4); - t.setCaption("Table with some rows and width = 200px"); - - t.setWidth(200); - main.addComponent(t); - - Button b = new Button("refresh view", this, "createNewView"); - main.addComponent(b); - - } - - public static Table getTestTable(int cols, int rows) { - Table t = new Table(); - t.setColumnCollapsingAllowed(true); - for (int i = 0; i < cols; i++) { - t.addContainerProperty(testString[i], String.class, ""); - } - for (int i = 0; i < rows; i++) { - Vector content = new Vector(); - for (int j = 0; j < cols; j++) { - content.add(rndString()); - } - t.addItem(content.toArray(), "" + i); - } - return t; - } - - static String[] testString = new String[] { "DSFdsfs", "böö", "1", - "sdf sdfsd fsdfsdf sdf", "SDF SADds FASDF dsaf", "foo", "VADSFA", - "DSFSD FS", "whattaa", " sdf sdfsd ", "DSf sdf sdf", "foods f", - "VADsd fSFA", "DSFsd fSD FS", "wha sdf ttaa", " sd sdff sdfsd ", - "DSf sdf sdf", "SDFsd sd fadsfadfs" }; - - public static String rndString() { - return testString[(int) (Math.random() * testString.length)]; - } + CustomComponent { + + private OrderedLayout main = new OrderedLayout(); + + public TestForTablesInitialColumnWidthLogicRendering() { + + setCompositionRoot(main); + createNewView(); + } + + public void createNewView() { + main.removeAllComponents(); + main + .addComponent(new Label( + "Below are same tables that all should render somewhat nice. Also when testing, you might want to try resizing window.")); + + Table t; + + // t = new Table("Empty table"); + // main.addComponent(t); + + t = getTestTable(5, 0); + t.setCaption("Table with only headers"); + // main.addComponent(t); + + t = getTestTable(5, 200); + t.setCaption("Table with some cols and lot of rows"); + main.addComponent(t); + + t = getTestTable(12, 4); + t.setCaption("Table with some rows and lot of columns"); + main.addComponent(t); + + t = getTestTable(3, 40); + t + .setCaption("Table with some columns and wide explicit width. (Ought to widen columns to use all space)"); + t.setWidth(1000); + main.addComponent(t); + + t = getTestTable(12, 4); + t.setCaption("Table with some rows and lot of columns, width == 100%"); + t.setWidth(100); + t.setWidthUnits(Sizeable.UNITS_PERCENTAGE); + main.addComponent(t); + + t = getTestTable(12, 100); + t + .setCaption("Table with lot of rows and lot of columns, width == 50%"); + t.setWidth(50); + t.setWidthUnits(Sizeable.UNITS_PERCENTAGE); + main.addComponent(t); + + t = getTestTable(5, 100); + t.setCaption("Table with 40 rows"); + // main.addComponent(t); + + t = getTestTable(4, 4); + t.setCaption("Table with some rows and width = 200px"); + + t.setWidth(200); + main.addComponent(t); + + Button b = new Button("refresh view", this, "createNewView"); + main.addComponent(b); + + } + + public static Table getTestTable(int cols, int rows) { + Table t = new Table(); + t.setColumnCollapsingAllowed(true); + for (int i = 0; i < cols; i++) { + t.addContainerProperty(testString[i], String.class, ""); + } + for (int i = 0; i < rows; i++) { + Vector content = new Vector(); + for (int j = 0; j < cols; j++) { + content.add(rndString()); + } + t.addItem(content.toArray(), "" + i); + } + return t; + } + + static String[] testString = new String[] { "DSFdsfs", "böö", "1", + "sdf sdfsd fsdfsdf sdf", "SDF SADds FASDF dsaf", "foo", "VADSFA", + "DSFSD FS", "whattaa", " sdf sdfsd ", "DSf sdf sdf", "foods f", + "VADsd fSFA", "DSFsd fSD FS", "wha sdf ttaa", " sd sdff sdfsd ", + "DSf sdf sdf", "SDFsd sd fadsfadfs" }; + + public static String rndString() { + return testString[(int) (Math.random() * testString.length)]; + } } diff --git a/src/com/itmill/toolkit/tests/TestForTrees.java b/src/com/itmill/toolkit/tests/TestForTrees.java index 13f41aa359..331ec4065d 100644 --- a/src/com/itmill/toolkit/tests/TestForTrees.java +++ b/src/com/itmill/toolkit/tests/TestForTrees.java @@ -1,7 +1,5 @@ package com.itmill.toolkit.tests; -import java.util.Vector; - import com.itmill.toolkit.event.Action; import com.itmill.toolkit.event.Action.Handler; import com.itmill.toolkit.ui.Button; @@ -10,7 +8,6 @@ import com.itmill.toolkit.ui.CustomComponent; import com.itmill.toolkit.ui.Label; import com.itmill.toolkit.ui.OrderedLayout; import com.itmill.toolkit.ui.Panel; -import com.itmill.toolkit.ui.Table; import com.itmill.toolkit.ui.Tree; import com.itmill.toolkit.ui.Button.ClickEvent; import com.itmill.toolkit.ui.Button.ClickListener; @@ -22,142 +19,144 @@ import com.itmill.toolkit.ui.Button.ClickListener; */ public class TestForTrees extends CustomComponent implements Handler { - private static final String[] firstnames = new String[] { "John", "Mary", - "Joe", "Sarah", "Jeff", "Jane", "Peter", "Marc", "Josie", "Linus" }; - - private static final String[] lastnames = new String[] { "Torvalds", - "Smith", "Jones", "Beck", "Sheridan", "Picard", "Hill", "Fielding", - "Einstein" }; - - private OrderedLayout main = new OrderedLayout(); - - private Action[] actions = new Action[] { new Action("edit"), - new Action("delete") }; - - private Panel al; - - private Tree contextTree; - - public TestForTrees() { - - setCompositionRoot(main); - createNewView(); - } - - public void createNewView() { - main.removeAllComponents(); - main - .addComponent(new Label( - "Some test cases for trees. Events panel logs events that happen server side.")); - - main.addComponent(new Button("commit")); - - Tree t; - - t = createTestTree(); - t.setCaption("Default settings"); - main.addComponent(createTestBench(t)); - - t = createTestTree(); - t.setCaption("Multiselect settings"); - t.setMultiSelect(true); - main.addComponent(createTestBench(t)); - - t = createTestTree(); - t.setCaption("Multiselect and immediate"); - t.setImmediate(true); - t.setMultiSelect(true); - main.addComponent(createTestBench(t)); - - t = createTestTree(); - t.setCaption("immediate"); - t.setImmediate(true); - main.addComponent(createTestBench(t)); - - t = createTestTree(); - t.setCaption("with actions"); - t.setImmediate(true); - t.addActionHandler(this); - OrderedLayout ol = (OrderedLayout) createTestBench(t); - al = new Panel("action log"); - ol.addComponent(al); - main.addComponent(ol); - contextTree = t; - - Button b = new Button("refresh view", this, "createNewView"); - main.addComponent(b); - - } - - public Tree createTestTree() { - Tree t = new Tree("Tree"); - String[] names = new String[100]; - for (int i = 0; i < names.length; i++) - names[i] = firstnames[(int) (Math.random() * (firstnames.length - 1))] - + " " - + lastnames[(int) (Math.random() * (lastnames.length - 1))]; - - // Create tree - t = new Tree("Organization Structure"); - for (int i = 0; i < 100; i++) { - t.addItem(names[i]); - String parent = names[(int) (Math.random() * (names.length - 1))]; - if (t.containsId(parent)) - t.setParent(names[i], parent); - } - - // Forbid childless people to have children (makes them leaves) - for (int i = 0; i < 100; i++) - if (!t.hasChildren(names[i])) - t.setChildrenAllowed(names[i], false); - return t; - } - - public Component createTestBench(Tree t) { - OrderedLayout ol = new OrderedLayout(); - ol.setOrientation(OrderedLayout.ORIENTATION_HORIZONTAL); - - ol.addComponent(t); - - final Panel status = new Panel("Events"); - final Button clear = new Button("c"); - clear.addListener(new ClickListener() { - public void buttonClick(ClickEvent event) { - status.removeAllComponents(); - status.addComponent(clear); - } - }); - status.addComponent(clear); - - status.setHeight(300); - status.setWidth(400); - - ol.addComponent(status); - - t.addListener(new Listener() { - public void componentEvent(Event event) { - status - .addComponent(new Label(event.getClass() - .getName())); - status.addComponent(new Label("selected: " - + event.getSource().toString())); - } - }); - - return ol; - } - - public Action[] getActions(Object target, Object sender) { - return actions; - } - - public void handleAction(Action action, Object sender, Object target) { - if (action == actions[1]) { - al.addComponent(new Label("Delete selected on " + target)); - contextTree.removeItem(target); - - } else { - al.addComponent(new Label("Edit selected on " + target)); - } - } + private static final String[] firstnames = new String[] { "John", "Mary", + "Joe", "Sarah", "Jeff", "Jane", "Peter", "Marc", "Josie", "Linus" }; + + private static final String[] lastnames = new String[] { "Torvalds", + "Smith", "Jones", "Beck", "Sheridan", "Picard", "Hill", "Fielding", + "Einstein" }; + + private OrderedLayout main = new OrderedLayout(); + + private Action[] actions = new Action[] { new Action("edit"), + new Action("delete") }; + + private Panel al; + + private Tree contextTree; + + public TestForTrees() { + + setCompositionRoot(main); + createNewView(); + } + + public void createNewView() { + main.removeAllComponents(); + main + .addComponent(new Label( + "Some test cases for trees. Events panel logs events that happen server side.")); + + main.addComponent(new Button("commit")); + + Tree t; + + t = createTestTree(); + t.setCaption("Default settings"); + main.addComponent(createTestBench(t)); + + t = createTestTree(); + t.setCaption("Multiselect settings"); + t.setMultiSelect(true); + main.addComponent(createTestBench(t)); + + t = createTestTree(); + t.setCaption("Multiselect and immediate"); + t.setImmediate(true); + t.setMultiSelect(true); + main.addComponent(createTestBench(t)); + + t = createTestTree(); + t.setCaption("immediate"); + t.setImmediate(true); + main.addComponent(createTestBench(t)); + + t = createTestTree(); + t.setCaption("with actions"); + t.setImmediate(true); + t.addActionHandler(this); + OrderedLayout ol = (OrderedLayout) createTestBench(t); + al = new Panel("action log"); + ol.addComponent(al); + main.addComponent(ol); + contextTree = t; + + Button b = new Button("refresh view", this, "createNewView"); + main.addComponent(b); + + } + + public Tree createTestTree() { + Tree t = new Tree("Tree"); + String[] names = new String[100]; + for (int i = 0; i < names.length; i++) { + names[i] = firstnames[(int) (Math.random() * (firstnames.length - 1))] + + " " + + lastnames[(int) (Math.random() * (lastnames.length - 1))]; + } + + // Create tree + t = new Tree("Organization Structure"); + for (int i = 0; i < 100; i++) { + t.addItem(names[i]); + String parent = names[(int) (Math.random() * (names.length - 1))]; + if (t.containsId(parent)) { + t.setParent(names[i], parent); + } + } + + // Forbid childless people to have children (makes them leaves) + for (int i = 0; i < 100; i++) { + if (!t.hasChildren(names[i])) { + t.setChildrenAllowed(names[i], false); + } + } + return t; + } + + public Component createTestBench(Tree t) { + OrderedLayout ol = new OrderedLayout(); + ol.setOrientation(OrderedLayout.ORIENTATION_HORIZONTAL); + + ol.addComponent(t); + + final Panel status = new Panel("Events"); + final Button clear = new Button("c"); + clear.addListener(new ClickListener() { + public void buttonClick(ClickEvent event) { + status.removeAllComponents(); + status.addComponent(clear); + } + }); + status.addComponent(clear); + + status.setHeight(300); + status.setWidth(400); + + ol.addComponent(status); + + t.addListener(new Listener() { + public void componentEvent(Event event) { + status.addComponent(new Label(event.getClass().getName())); + status.addComponent(new Label("selected: " + + event.getSource().toString())); + } + }); + + return ol; + } + + public Action[] getActions(Object target, Object sender) { + return actions; + } + + public void handleAction(Action action, Object sender, Object target) { + if (action == actions[1]) { + al.addComponent(new Label("Delete selected on " + target)); + contextTree.removeItem(target); + + } else { + al.addComponent(new Label("Edit selected on " + target)); + } + } } diff --git a/src/com/itmill/toolkit/tests/TestForUpload.java b/src/com/itmill/toolkit/tests/TestForUpload.java index 620f5c019d..5817a35af6 100644 --- a/src/com/itmill/toolkit/tests/TestForUpload.java +++ b/src/com/itmill/toolkit/tests/TestForUpload.java @@ -34,311 +34,312 @@ import com.itmill.toolkit.ui.Upload.SucceededEvent; import com.itmill.toolkit.ui.Upload.SucceededListener; public class TestForUpload extends CustomComponent implements - Upload.FinishedListener, FailedListener, SucceededListener, - Upload.ProgressListener, StartedListener { + Upload.FinishedListener, FailedListener, SucceededListener, + Upload.ProgressListener, StartedListener { - Layout main = new OrderedLayout(); + Layout main = new OrderedLayout(); - Buffer buffer = new MemoryBuffer(); + Buffer buffer = new MemoryBuffer(); - Panel status = new Panel("Uploaded file:"); + Panel status = new Panel("Uploaded file:"); - private final Upload up; + private final Upload up; - private final Label l; - - private final ProgressIndicator pi = new ProgressIndicator(); - - private final Label memoryStatus; - - private final Select uploadBufferSelector; - - public TestForUpload() { - setCompositionRoot(this.main); - this.main.addComponent(new Label( - "This is a simple test for upload application. " - + "Upload should work with big files and concurrent " - + "requests should not be blocked. Button 'b' reads " - + "current state into label below it. Memory receiver " - + "streams upload contents into memory. You may track" - + "consumption." - + "tempfile receiver writes upload to file and " - + "should have low memory consumption.")); - - this.main - .addComponent(new Label( - "Clicking on button b updates information about upload components status or same with garbage collector.")); - - this.up = new Upload("Upload", this.buffer); - this.up.setImmediate(true); - this.up.addListener((FinishedListener) this); - this.up.addListener((FailedListener) this); - this.up.addListener((SucceededListener) this); - this.up.addListener((StartedListener) this); - - this.up.setProgressListener(this); - - Button b = new Button("b", this, "readState"); - - Button c = new Button("b with gc", this, "gc"); - - this.main.addComponent(b); - this.main.addComponent(c); - - this.uploadBufferSelector = new Select("Receiver type"); - this.uploadBufferSelector.setImmediate(true); - this.uploadBufferSelector.addItem("memory"); - this.uploadBufferSelector.setValue("memory"); - this.uploadBufferSelector.addItem("tempfile"); - this.uploadBufferSelector - .addListener(new AbstractField.ValueChangeListener() { - public void valueChange(ValueChangeEvent event) { - setBuffer(); - } - }); - this.main.addComponent(this.uploadBufferSelector); - - this.main.addComponent(this.up); - this.l = new Label("Idle"); - this.main.addComponent(this.l); - - this.pi.setVisible(false); - this.pi.setPollingInterval(1000); - this.main.addComponent(this.pi); - - this.memoryStatus = new Label(); - this.main.addComponent(this.memoryStatus); - - this.status.setVisible(false); - this.main.addComponent(this.status); - - Button restart = new Button("R"); - restart.addListener(new Button.ClickListener() { - - public void buttonClick(ClickEvent event) { - getApplication().close(); - } - }); - this.main.addComponent(restart); - - } - - private void setBuffer() { - String id = (String) this.uploadBufferSelector.getValue(); - if ("memory".equals(id)) { - this.buffer = new MemoryBuffer(); - } else if ("tempfile".equals(id)) { - this.buffer = new TmpFileBuffer(); - } - this.up.setReceiver(this.buffer); - } - - public void gc() { - Runtime.getRuntime().gc(); - readState(); - } - - public void readState() { - StringBuffer sb = new StringBuffer(); - - if (this.up.isUploading()) { - sb.append("Uploading..."); - sb.append(this.up.getBytesRead()); - sb.append("/"); - sb.append(this.up.getUploadSize()); - sb.append(" "); - sb.append(Math.round(100 * this.up.getBytesRead() - / (double) this.up.getUploadSize())); - sb.append("%"); - } else { - sb.append("Idle"); - } - this.l.setValue(sb.toString()); - refreshMemUsage(); - } - - public void uploadFinished(FinishedEvent event) { - this.status.removeAllComponents(); - InputStream stream = this.buffer.getStream(); - if (stream == null) { - this.status.addComponent(new Label( - "Upload finished, but output buffer is null!!")); - } else { - this.status.addComponent(new Label("Name: " - + event.getFilename(), Label.CONTENT_XHTML)); - this.status.addComponent(new Label("Mimetype: " - + event.getMIMEType(), Label.CONTENT_XHTML)); - this.status.addComponent(new Label("Size: " - + event.getLength() + " bytes.", Label.CONTENT_XHTML)); - - this.status.addComponent(new Link("Download " - + this.buffer.getFileName(), new StreamResource( - this.buffer, this.buffer.getFileName(), getApplication()))); - - this.status.setVisible(true); - } - } - - public interface Buffer extends StreamResource.StreamSource, - Upload.Receiver { - - String getFileName(); - } - - public class MemoryBuffer implements Buffer { - ByteArrayOutputStream outputBuffer = null; - - String mimeType; - - String fileName; - - public MemoryBuffer() { - - } - - public InputStream getStream() { - if (this.outputBuffer == null) { - return null; - } - return new ByteArrayInputStream(this.outputBuffer.toByteArray()); - } - - /** - * @see com.itmill.toolkit.ui.Upload.Receiver#receiveUpload(String, - * String) - */ - public OutputStream receiveUpload(String filename, String MIMEType) { - this.fileName = filename; - this.mimeType = MIMEType; - this.outputBuffer = new ByteArrayOutputStream(); - return this.outputBuffer; - } - - /** - * Returns the fileName. - * - * @return String - */ - public String getFileName() { - return this.fileName; - } - - /** - * Returns the mimeType. - * - * @return String - */ - public String getMimeType() { - return this.mimeType; - } - - } - - public class TmpFileBuffer implements Buffer { - String mimeType; - - String fileName; - - private File file; - - private FileInputStream stream; - - public TmpFileBuffer() { - String tempFileName = "upload_tmpfile_" - + System.currentTimeMillis(); - try { - this.file = File.createTempFile(tempFileName, null); - } catch (IOException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - - } - - public InputStream getStream() { - if (this.file == null) { - return null; - } - try { - return new FileInputStream(this.file); - } catch (FileNotFoundException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - return null; - } - - /** - * @see com.itmill.toolkit.ui.Upload.Receiver#receiveUpload(String, - * String) - */ - public OutputStream receiveUpload(String filename, String MIMEType) { - this.fileName = filename; - this.mimeType = MIMEType; - try { - return new FileOutputStream(this.file); - } catch (FileNotFoundException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - return null; - } - - /** - * Returns the fileName. - * - * @return String - */ - public String getFileName() { - return this.fileName; - } - - /** - * Returns the mimeType. - * - * @return String - */ - public String getMimeType() { - return this.mimeType; - } - - } - - public void uploadFailed(FailedEvent event) { - System.out.println(event); - - System.out.println(event.getSource()); - - } - - public void uploadSucceeded(SucceededEvent event) { - this.pi.setVisible(false); - this.l.setValue("Finished upload, idle"); - System.out.println(event); - setBuffer(); - } - - public void updateProgress(long readBytes, long contentLenght) { - this.pi.setValue(new Float(readBytes / (float) contentLenght)); - - refreshMemUsage(); - } - - private void refreshMemUsage() { - this.memoryStatus.setValue("Not available in Java 1.4"); - /* - * StringBuffer mem = new StringBuffer(); MemoryMXBean mmBean = - * ManagementFactory.getMemoryMXBean(); mem.append("Heap (M):"); - * mem.append(mmBean.getHeapMemoryUsage().getUsed() / 1048576); - * mem.append(" |�Non-Heap (M):"); - * mem.append(mmBean.getNonHeapMemoryUsage().getUsed() / 1048576); - * memoryStatus.setValue(mem.toString()); - */ - } - - public void uploadStarted(StartedEvent event) { - this.pi.setVisible(true); - this.l.setValue("Started uploading file " + event.getFilename()); - } + private final Label l; + + private final ProgressIndicator pi = new ProgressIndicator(); + + private final Label memoryStatus; + + private final Select uploadBufferSelector; + + public TestForUpload() { + setCompositionRoot(main); + main.addComponent(new Label( + "This is a simple test for upload application. " + + "Upload should work with big files and concurrent " + + "requests should not be blocked. Button 'b' reads " + + "current state into label below it. Memory receiver " + + "streams upload contents into memory. You may track" + + "consumption." + + "tempfile receiver writes upload to file and " + + "should have low memory consumption.")); + + main + .addComponent(new Label( + "Clicking on button b updates information about upload components status or same with garbage collector.")); + + up = new Upload("Upload", buffer); + up.setImmediate(true); + up.addListener((FinishedListener) this); + up.addListener((FailedListener) this); + up.addListener((SucceededListener) this); + up.addListener((StartedListener) this); + + up.setProgressListener(this); + + Button b = new Button("b", this, "readState"); + + Button c = new Button("b with gc", this, "gc"); + + main.addComponent(b); + main.addComponent(c); + + uploadBufferSelector = new Select("Receiver type"); + uploadBufferSelector.setImmediate(true); + uploadBufferSelector.addItem("memory"); + uploadBufferSelector.setValue("memory"); + uploadBufferSelector.addItem("tempfile"); + uploadBufferSelector + .addListener(new AbstractField.ValueChangeListener() { + public void valueChange(ValueChangeEvent event) { + setBuffer(); + } + }); + main.addComponent(uploadBufferSelector); + + main.addComponent(up); + l = new Label("Idle"); + main.addComponent(l); + + pi.setVisible(false); + pi.setPollingInterval(1000); + main.addComponent(pi); + + memoryStatus = new Label(); + main.addComponent(memoryStatus); + + status.setVisible(false); + main.addComponent(status); + + Button restart = new Button("R"); + restart.addListener(new Button.ClickListener() { + + public void buttonClick(ClickEvent event) { + getApplication().close(); + } + }); + main.addComponent(restart); + + } + + private void setBuffer() { + String id = (String) uploadBufferSelector.getValue(); + if ("memory".equals(id)) { + buffer = new MemoryBuffer(); + } else if ("tempfile".equals(id)) { + buffer = new TmpFileBuffer(); + } + up.setReceiver(buffer); + } + + public void gc() { + Runtime.getRuntime().gc(); + readState(); + } + + public void readState() { + StringBuffer sb = new StringBuffer(); + + if (up.isUploading()) { + sb.append("Uploading..."); + sb.append(up.getBytesRead()); + sb.append("/"); + sb.append(up.getUploadSize()); + sb.append(" "); + sb.append(Math.round(100 * up.getBytesRead() + / (double) up.getUploadSize())); + sb.append("%"); + } else { + sb.append("Idle"); + } + l.setValue(sb.toString()); + refreshMemUsage(); + } + + public void uploadFinished(FinishedEvent event) { + status.removeAllComponents(); + InputStream stream = buffer.getStream(); + if (stream == null) { + status.addComponent(new Label( + "Upload finished, but output buffer is null!!")); + } else { + status + .addComponent(new Label("Name: " + + event.getFilename(), Label.CONTENT_XHTML)); + status.addComponent(new Label("Mimetype: " + + event.getMIMEType(), Label.CONTENT_XHTML)); + status.addComponent(new Label("Size: " + event.getLength() + + " bytes.", Label.CONTENT_XHTML)); + + status.addComponent(new Link("Download " + buffer.getFileName(), + new StreamResource(buffer, buffer.getFileName(), + getApplication()))); + + status.setVisible(true); + } + } + + public interface Buffer extends StreamResource.StreamSource, + Upload.Receiver { + + String getFileName(); + } + + public class MemoryBuffer implements Buffer { + ByteArrayOutputStream outputBuffer = null; + + String mimeType; + + String fileName; + + public MemoryBuffer() { + + } + + public InputStream getStream() { + if (outputBuffer == null) { + return null; + } + return new ByteArrayInputStream(outputBuffer.toByteArray()); + } + + /** + * @see com.itmill.toolkit.ui.Upload.Receiver#receiveUpload(String, + * String) + */ + public OutputStream receiveUpload(String filename, String MIMEType) { + fileName = filename; + mimeType = MIMEType; + outputBuffer = new ByteArrayOutputStream(); + return outputBuffer; + } + + /** + * Returns the fileName. + * + * @return String + */ + public String getFileName() { + return fileName; + } + + /** + * Returns the mimeType. + * + * @return String + */ + public String getMimeType() { + return mimeType; + } + + } + + public class TmpFileBuffer implements Buffer { + String mimeType; + + String fileName; + + private File file; + + private FileInputStream stream; + + public TmpFileBuffer() { + String tempFileName = "upload_tmpfile_" + + System.currentTimeMillis(); + try { + file = File.createTempFile(tempFileName, null); + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + + } + + public InputStream getStream() { + if (file == null) { + return null; + } + try { + return new FileInputStream(file); + } catch (FileNotFoundException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + return null; + } + + /** + * @see com.itmill.toolkit.ui.Upload.Receiver#receiveUpload(String, + * String) + */ + public OutputStream receiveUpload(String filename, String MIMEType) { + fileName = filename; + mimeType = MIMEType; + try { + return new FileOutputStream(file); + } catch (FileNotFoundException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + return null; + } + + /** + * Returns the fileName. + * + * @return String + */ + public String getFileName() { + return fileName; + } + + /** + * Returns the mimeType. + * + * @return String + */ + public String getMimeType() { + return mimeType; + } + + } + + public void uploadFailed(FailedEvent event) { + System.out.println(event); + + System.out.println(event.getSource()); + + } + + public void uploadSucceeded(SucceededEvent event) { + pi.setVisible(false); + l.setValue("Finished upload, idle"); + System.out.println(event); + setBuffer(); + } + + public void updateProgress(long readBytes, long contentLenght) { + pi.setValue(new Float(readBytes / (float) contentLenght)); + + refreshMemUsage(); + } + + private void refreshMemUsage() { + memoryStatus.setValue("Not available in Java 1.4"); + /* + * StringBuffer mem = new StringBuffer(); MemoryMXBean mmBean = + * ManagementFactory.getMemoryMXBean(); mem.append("Heap (M):"); + * mem.append(mmBean.getHeapMemoryUsage().getUsed() / 1048576); + * mem.append(" |�Non-Heap (M):"); + * mem.append(mmBean.getNonHeapMemoryUsage().getUsed() / 1048576); + * memoryStatus.setValue(mem.toString()); + */ + } + + public void uploadStarted(StartedEvent event) { + pi.setVisible(true); + l.setValue("Started uploading file " + event.getFilename()); + } } diff --git a/src/com/itmill/toolkit/tests/TestForWindowOpen.java b/src/com/itmill/toolkit/tests/TestForWindowOpen.java index 1acaad12a2..8588630bb2 100644 --- a/src/com/itmill/toolkit/tests/TestForWindowOpen.java +++ b/src/com/itmill/toolkit/tests/TestForWindowOpen.java @@ -8,47 +8,47 @@ import com.itmill.toolkit.ui.Button.ClickEvent; public class TestForWindowOpen extends CustomComponent { - public TestForWindowOpen() { + public TestForWindowOpen() { - OrderedLayout main = new OrderedLayout(); - setCompositionRoot(main); + OrderedLayout main = new OrderedLayout(); + setCompositionRoot(main); - main.addComponent(new Button("Open in this window", - new Button.ClickListener() { + main.addComponent(new Button("Open in this window", + new Button.ClickListener() { - public void buttonClick(ClickEvent event) { - ExternalResource r = new ExternalResource( - "http://www.google.com"); - getApplication().getMainWindow().open(r); + public void buttonClick(ClickEvent event) { + ExternalResource r = new ExternalResource( + "http://www.google.com"); + getApplication().getMainWindow().open(r); - } + } - })); + })); - main.addComponent(new Button("Open in target \"asd\"", - new Button.ClickListener() { + main.addComponent(new Button("Open in target \"asd\"", + new Button.ClickListener() { - public void buttonClick(ClickEvent event) { - ExternalResource r = new ExternalResource( - "http://www.google.com"); - getApplication().getMainWindow().open(r, "asd"); + public void buttonClick(ClickEvent event) { + ExternalResource r = new ExternalResource( + "http://www.google.com"); + getApplication().getMainWindow().open(r, "asd"); - } + } - })); + })); - main.addComponent(new Button("Open in target \"foo\"", - new Button.ClickListener() { + main.addComponent(new Button("Open in target \"foo\"", + new Button.ClickListener() { - public void buttonClick(ClickEvent event) { - ExternalResource r = new ExternalResource( - "http://www.google.com"); - getApplication().getMainWindow().open(r, "foo"); + public void buttonClick(ClickEvent event) { + ExternalResource r = new ExternalResource( + "http://www.google.com"); + getApplication().getMainWindow().open(r, "foo"); - } + } - })); + })); - } + } } diff --git a/src/com/itmill/toolkit/tests/TestForWindowing.java b/src/com/itmill/toolkit/tests/TestForWindowing.java index eeb2ca861c..972cdb6747 100644 --- a/src/com/itmill/toolkit/tests/TestForWindowing.java +++ b/src/com/itmill/toolkit/tests/TestForWindowing.java @@ -16,69 +16,69 @@ import com.itmill.toolkit.ui.Button.ClickListener; public class TestForWindowing extends CustomComponent { - private Select s2; + private Select s2; - public TestForWindowing() { + public TestForWindowing() { - OrderedLayout main = new OrderedLayout(); + OrderedLayout main = new OrderedLayout(); - main.addComponent(new Label( - "Click the button to create a new inline window.")); + main.addComponent(new Label( + "Click the button to create a new inline window.")); - Button create = new Button("Create a new window", new ClickListener() { + Button create = new Button("Create a new window", new ClickListener() { - public void buttonClick(ClickEvent event) { - Window w = new Window("Testing Window"); + public void buttonClick(ClickEvent event) { + Window w = new Window("Testing Window"); - AbstractSelect s1 = new OptionGroup(); - s1.setCaption("1. Select output format"); - s1.addItem("Excel sheet"); - s1.addItem("CSV plain text"); - s1.setValue("Excel sheet"); + AbstractSelect s1 = new OptionGroup(); + s1.setCaption("1. Select output format"); + s1.addItem("Excel sheet"); + s1.addItem("CSV plain text"); + s1.setValue("Excel sheet"); - TestForWindowing.this.s2 = new Select(); - TestForWindowing.this.s2.addItem("Separate by comma (,)"); - TestForWindowing.this.s2.addItem("Separate by colon (:)"); - TestForWindowing.this.s2.addItem("Separate by semicolon (;)"); - TestForWindowing.this.s2.setEnabled(false); + s2 = new Select(); + s2.addItem("Separate by comma (,)"); + s2.addItem("Separate by colon (:)"); + s2.addItem("Separate by semicolon (;)"); + s2.setEnabled(false); - s1.addListener(new ValueChangeListener() { + s1.addListener(new ValueChangeListener() { - public void valueChange(ValueChangeEvent event) { - String v = (String) event.getProperty().getValue(); - if (v.equals("CSV plain text")) { - TestForWindowing.this.s2.setEnabled(true); - } else { - TestForWindowing.this.s2.setEnabled(false); - } - } + public void valueChange(ValueChangeEvent event) { + String v = (String) event.getProperty().getValue(); + if (v.equals("CSV plain text")) { + s2.setEnabled(true); + } else { + s2.setEnabled(false); + } + } - }); + }); - w.addComponent(s1); - w.addComponent(TestForWindowing.this.s2); + w.addComponent(s1); + w.addComponent(s2); - Slider s = new Slider(); - s.setCaption("Volume"); - s.setMax(13); - s.setMin(12); - s.setResolution(2); - s.setImmediate(true); - //s.setOrientation(Slider.ORIENTATION_VERTICAL); - //s.setArrows(false); - - w.addComponent(s); - - getApplication().getMainWindow().addWindow(w); + Slider s = new Slider(); + s.setCaption("Volume"); + s.setMax(13); + s.setMin(12); + s.setResolution(2); + s.setImmediate(true); + // s.setOrientation(Slider.ORIENTATION_VERTICAL); + // s.setArrows(false); - } + w.addComponent(s); - }); + getApplication().getMainWindow().addWindow(w); - main.addComponent(create); + } - setCompositionRoot(main); + }); - } + main.addComponent(create); + + setCompositionRoot(main); + + } } diff --git a/src/com/itmill/toolkit/tests/TestIFrames.java b/src/com/itmill/toolkit/tests/TestIFrames.java index a969d4beaa..67b0ca42b3 100644 --- a/src/com/itmill/toolkit/tests/TestIFrames.java +++ b/src/com/itmill/toolkit/tests/TestIFrames.java @@ -6,30 +6,30 @@ import com.itmill.toolkit.ui.OrderedLayout; public class TestIFrames extends CustomComponent { - OrderedLayout main = new OrderedLayout(); + OrderedLayout main = new OrderedLayout(); - public TestIFrames() { - setCompositionRoot(main); - createNewView(); - } + public TestIFrames() { + setCompositionRoot(main); + createNewView(); + } - public void createNewView() { - main.removeAllComponents(); - main.addComponent(createEmbedded("../Reservr/")); - main.addComponent(createEmbedded("../colorpicker")); - // main.addComponent(createEmbedded("../TestForNativeWindowing")); - main - .addComponent(createEmbedded("http://toolkit.itmill.com/demo/FeaturesApplication")); - main - .addComponent(createEmbedded("http://toolkit.itmill.com/demo/TableDemo")); - } + public void createNewView() { + main.removeAllComponents(); + main.addComponent(createEmbedded("../Reservr/")); + main.addComponent(createEmbedded("../colorpicker")); + // main.addComponent(createEmbedded("../TestForNativeWindowing")); + main + .addComponent(createEmbedded("http://toolkit.itmill.com/demo/FeaturesApplication")); + main + .addComponent(createEmbedded("http://toolkit.itmill.com/demo/TableDemo")); + } - private Label createEmbedded(String URL) { - int width = 600; - int height = 250; - String iFrame = ""); - } - - /** - * Feature component initialization is lazily done when the feature is - * attached to application - */ - public void attach() { - super.attach(); - - // Check if the feature is already initialized - if (initialized) - return; - initialized = true; - - // Javadoc - javadoc = new Label(); - javadoc.setContentMode(Label.CONTENT_XHTML); - - // Demo - Component demo = getDemoComponent(); - if (demo != null) - layout.addComponent(demo); - - ts = new TabSheet(); - - ts.setWidth(100); - ts.setWidthUnits(TabSheet.UNITS_PERCENTAGE); - ts.setHeight(100); - ts.setHeightUnits(TabSheet.UNITS_PERCENTAGE); - - // Description tab - String title = getTitle(); - if (getDescriptionXHTML() != null) { - OrderedLayout mainLayout = new OrderedLayout( - OrderedLayout.ORIENTATION_VERTICAL); - OrderedLayout layout = new OrderedLayout( - OrderedLayout.ORIENTATION_HORIZONTAL); - mainLayout.addComponent(layout); - if (getImage() != null) - layout.addComponent(new Embedded("", new ClassResource( - getImage(), this.getApplication()))); - String label = ""; - label += getDescriptionXHTML(); - if (propsReminder) - label += PROP_REMINDER_TEXT; - if (title != null) { - layout.addComponent(new Label("

" + title + "

", - Label.CONTENT_XHTML)); - } - description = new Label(label, Label.CONTENT_XHTML); - mainLayout.addComponent(description); - - ts.addTab(mainLayout, "Description", null); - } - - // Properties table tab - ts.addTab(getPropertyPanel().getAllProperties(), "Properties", null); - - // Javadoc tab - if (!javadoc.getValue().equals("")) - ts.addTab(javadoc, "Javadoc", null); - - // Code Sample tab - String example = getExampleSrc(); - if (example != null) { - OrderedLayout l = new OrderedLayout(); - if (getTitle() != null) - l.addComponent(new Label( - "// " + getTitle() + " example", - Label.CONTENT_XHTML)); - l.addComponent(new Label(example, Label.CONTENT_PREFORMATTED)); - ts.addTab(l, "Code Sample", null); - } - - } - - /** Get the desctiption of the feature as XHTML fragment */ - protected String getDescriptionXHTML() { - return "

Feature description is under construction

"; - } - - /** Get the title of the feature */ - protected String getTitle() { - return this.getClass().getName(); - } - - public TabSheet getTabSheet() { - return ts; - } - - /** Get the name of the image file that will be put on description page */ - protected String getImage() { - return null; - } - - /** Get the example application source code */ - protected String getExampleSrc() { - return null; - } - - /** Get the feature demo component */ - protected Component getDemoComponent() { - return null; - } - - /** Get sample icon resource */ - protected Resource getSampleIcon() { - if (sampleIcon == null) - sampleIcon = new ClassResource("m.gif", this.getApplication()); - return sampleIcon; - } - - public PropertyPanel getPropertyPanel() { - return propertyPanel; - } - - public void setPropsReminder(boolean propsReminder) { - this.propsReminder = propsReminder; - } - - public void updateDescription() { - String label = ""; - label += getDescriptionXHTML(); - if (propsReminder) - label += PROP_REMINDER_TEXT; - description.setValue(label); - } - - // Fix for #512 - public Label getDescription() { - return description; - } + private static final String PROP_REMINDER_TEXT = "" + + "

Note: Use Properties panel located at the top" + + " right corner to try out how different properties affect" + + " the presentation or functionality of currently selected component."; + + private boolean propsReminder = true; + + private OrderedLayout layout; + + private TabSheet ts; + + private boolean initialized = false; + + private static Resource sampleIcon; + + protected PropertyPanel propertyPanel; + + private Label javadoc; + + private Label description; + + /** Constuctor for the feature component */ + public Feature() { + layout = new OrderedLayout(OrderedLayout.ORIENTATION_VERTICAL); + setCompositionRoot(layout); + } + + /** + * Actual URL consists of "/doc/api/com/itmill/toolkit/"+url + * + * @param url + */ + public void setJavadocURL(String url) { + javadoc + .setValue(""); + } + + /** + * Feature component initialization is lazily done when the feature is + * attached to application + */ + public void attach() { + super.attach(); + + // Check if the feature is already initialized + if (initialized) { + return; + } + initialized = true; + + // Javadoc + javadoc = new Label(); + javadoc.setContentMode(Label.CONTENT_XHTML); + + // Demo + Component demo = getDemoComponent(); + if (demo != null) { + layout.addComponent(demo); + } + + ts = new TabSheet(); + + ts.setWidth(100); + ts.setWidthUnits(Sizeable.UNITS_PERCENTAGE); + ts.setHeight(100); + ts.setHeightUnits(Sizeable.UNITS_PERCENTAGE); + + // Description tab + String title = getTitle(); + if (getDescriptionXHTML() != null) { + OrderedLayout mainLayout = new OrderedLayout( + OrderedLayout.ORIENTATION_VERTICAL); + OrderedLayout layout = new OrderedLayout( + OrderedLayout.ORIENTATION_HORIZONTAL); + mainLayout.addComponent(layout); + if (getImage() != null) { + layout.addComponent(new Embedded("", new ClassResource( + getImage(), getApplication()))); + } + String label = ""; + label += getDescriptionXHTML(); + if (propsReminder) { + label += PROP_REMINDER_TEXT; + } + if (title != null) { + layout.addComponent(new Label("

" + title + "

", + Label.CONTENT_XHTML)); + } + description = new Label(label, Label.CONTENT_XHTML); + mainLayout.addComponent(description); + + ts.addTab(mainLayout, "Description", null); + } + + // Properties table tab + ts.addTab(getPropertyPanel().getAllProperties(), "Properties", null); + + // Javadoc tab + if (!javadoc.getValue().equals("")) { + ts.addTab(javadoc, "Javadoc", null); + } + + // Code Sample tab + String example = getExampleSrc(); + if (example != null) { + OrderedLayout l = new OrderedLayout(); + if (getTitle() != null) { + l.addComponent(new Label( + "// " + getTitle() + " example", + Label.CONTENT_XHTML)); + } + l.addComponent(new Label(example, Label.CONTENT_PREFORMATTED)); + ts.addTab(l, "Code Sample", null); + } + + } + + /** Get the desctiption of the feature as XHTML fragment */ + protected String getDescriptionXHTML() { + return "

Feature description is under construction

"; + } + + /** Get the title of the feature */ + protected String getTitle() { + return getClass().getName(); + } + + public TabSheet getTabSheet() { + return ts; + } + + /** Get the name of the image file that will be put on description page */ + protected String getImage() { + return null; + } + + /** Get the example application source code */ + protected String getExampleSrc() { + return null; + } + + /** Get the feature demo component */ + protected Component getDemoComponent() { + return null; + } + + /** Get sample icon resource */ + protected Resource getSampleIcon() { + if (sampleIcon == null) { + sampleIcon = new ClassResource("m.gif", getApplication()); + } + return sampleIcon; + } + + public PropertyPanel getPropertyPanel() { + return propertyPanel; + } + + public void setPropsReminder(boolean propsReminder) { + this.propsReminder = propsReminder; + } + + public void updateDescription() { + String label = ""; + label += getDescriptionXHTML(); + if (propsReminder) { + label += PROP_REMINDER_TEXT; + } + description.setValue(label); + } + + // Fix for #512 + public Label getDescription() { + return description; + } } \ No newline at end of file diff --git a/src/com/itmill/toolkit/tests/featurebrowser/FeatureBrowser.java b/src/com/itmill/toolkit/tests/featurebrowser/FeatureBrowser.java index 3247c6bd01..2aaefecc5a 100644 --- a/src/com/itmill/toolkit/tests/featurebrowser/FeatureBrowser.java +++ b/src/com/itmill/toolkit/tests/featurebrowser/FeatureBrowser.java @@ -31,313 +31,325 @@ package com.itmill.toolkit.tests.featurebrowser; import java.util.Iterator; import java.util.StringTokenizer; -import com.itmill.toolkit.data.*; -import com.itmill.toolkit.ui.*; +import com.itmill.toolkit.data.Property; +import com.itmill.toolkit.ui.AbstractComponent; +import com.itmill.toolkit.ui.Button; +import com.itmill.toolkit.ui.Component; +import com.itmill.toolkit.ui.ComponentContainer; +import com.itmill.toolkit.ui.CustomComponent; +import com.itmill.toolkit.ui.CustomLayout; +import com.itmill.toolkit.ui.Layout; +import com.itmill.toolkit.ui.Select; +import com.itmill.toolkit.ui.Tree; import com.itmill.toolkit.ui.Button.ClickEvent; import com.itmill.toolkit.ui.Button.ClickListener; public class FeatureBrowser extends CustomComponent implements - Property.ValueChangeListener, ClickListener, Layout { - - private Tree features; - - private Feature currentFeature = null; - - private CustomLayout mainlayout; - - private PropertyPanel properties; - - private boolean initialized = false; - - private Select themeSelector = new Select(); - - public void attach() { - - if (initialized) - return; - initialized = true; - - // Configure tree - features = new Tree(); - features.addContainerProperty("name", String.class, ""); - features.addContainerProperty("feature", Feature.class, null); - features.setItemCaptionPropertyId("name"); - features.addListener(this); - features.setImmediate(true); - features.setStyle("menu"); - - // Configure component layout - mainlayout = new CustomLayout("featurebrowser-mainlayout"); - setCompositionRoot(mainlayout); - mainlayout.addComponent(features, "tree"); - - // Theme selector - mainlayout.addComponent(themeSelector, "themes"); - themeSelector.addItem("tests-featurebrowser"); - - themeSelector.addListener(this); - themeSelector.select("tests-featurebrowser"); - themeSelector.setImmediate(true); - - // Restart button - Button close = new Button("restart", getApplication(), "close"); - close.setStyle("link"); - mainlayout.addComponent(close, "restart"); - - // Test component - registerFeature("/Welcome", new IntroWelcome()); - registerFeature("/UI Components", new IntroComponents()); - registerFeature("/UI Components/Basic", new IntroBasic()); - registerFeature("/UI Components/Basic/Text Field", - new FeatureTextField()); - registerFeature("/UI Components/Basic/Date Field", - new FeatureDateField()); - registerFeature("/UI Components/Basic/Button", new FeatureButton()); - registerFeature("/UI Components/Basic/Form", new FeatureForm()); - registerFeature("/UI Components/Basic/Label", new FeatureLabel()); - registerFeature("/UI Components/Basic/Link", new FeatureLink()); - registerFeature("/UI Components/Item Containers", - new IntroItemContainers()); - registerFeature("/UI Components/Item Containers/Select", - new FeatureSelect()); - registerFeature("/UI Components/Item Containers/Table", - new FeatureTable()); - registerFeature("/UI Components/Item Containers/Tree", - new FeatureTree()); - registerFeature("/UI Components/Layouts", new IntroLayouts()); - registerFeature("/UI Components/Layouts/Ordered Layout", - new FeatureOrderedLayout()); - registerFeature("/UI Components/Layouts/Grid Layout", - new FeatureGridLayout()); - registerFeature("/UI Components/Layouts/Custom Layout", - new FeatureCustomLayout()); - registerFeature("/UI Components/Layouts/Panel", new FeaturePanel()); - registerFeature("/UI Components/Layouts/Tab Sheet", - new FeatureTabSheet()); - registerFeature("/UI Components/Layouts/Window", new FeatureWindow()); - // Disabled for now - // registerFeature("/UI Components/Layouts/Frame Window", - // new FeatureFrameWindow()); - registerFeature("/UI Components/Data handling", new IntroDataHandling()); - registerFeature("/UI Components/Data handling/Embedded Objects", - new FeatureEmbedded()); - registerFeature("/UI Components/Data handling/Upload", - new FeatureUpload()); - registerFeature("/Data Model", new IntroDataModel()); - registerFeature("/Data Model/Properties", new FeatureProperties()); - registerFeature("/Data Model/Items", new FeatureItems()); - registerFeature("/Data Model/Containers", new FeatureContainers()); - registerFeature("/Data Model/Validators", new FeatureValidators()); - registerFeature("/Data Model/Buffering", new FeatureBuffering()); - // registerFeature("/Terminal", new IntroTerminal()); - // registerFeature("/Terminal/Parameters and URI Handling", - // new FeatureParameters()); - - // Pre-open all menus - for (Iterator i = features.getItemIds().iterator(); i.hasNext();) - features.expandItem(i.next()); - - // Add demo component and tabs - currentFeature = new IntroWelcome(); - mainlayout.addComponent(currentFeature, "demo"); - mainlayout.addComponent(currentFeature.getTabSheet(), "tabsheet"); - - // Add properties - properties = currentFeature.getPropertyPanel(); - mainlayout.addComponent(properties, "properties"); - } - - public void registerFeature(String path, Feature feature) { - StringTokenizer st = new StringTokenizer(path, "/"); - String id = ""; - String parentId = null; - while (st.hasMoreTokens()) { - String token = st.nextToken(); - id += "/" + token; - if (!features.containsId(id)) { - features.addItem(id); - features.setChildrenAllowed(id, false); - } - features.getContainerProperty(id, "name").setValue(token); - if (parentId != null) { - features.setChildrenAllowed(parentId, true); - features.setParent(id, parentId); - } - if (!st.hasMoreTokens()) - features.getContainerProperty(id, "feature").setValue(feature); - parentId = id; - } - } - - public void valueChange(Property.ValueChangeEvent event) { - - // FIXME: navigation statistics - try { - if ((event.getProperty().toString() == null) - && ((AbstractComponent) event.getProperty()).getTag() - .equals("tree")) { - // ignore tree initialization - } else { - FeatureUtil.debug(getApplication().getUser().toString(), - "valueChange " - + ((AbstractComponent) event.getProperty()) - .getTag() + ", " + event.getProperty()); - } - } catch (Exception e) { - // ignored, should never happen - } - - // Change feature - if (event.getProperty() == features) { - Object id = features.getValue(); - if (id != null) { - if (features.areChildrenAllowed(id)) - features.expandItem(id); - Property p = features.getContainerProperty(id, "feature"); - Feature feature = p != null ? ((Feature) p.getValue()) : null; - if (feature != null) { - mainlayout.removeComponent(currentFeature); - mainlayout.removeComponent(currentFeature.getTabSheet()); - mainlayout.addComponent(feature, "demo"); - mainlayout.addComponent(feature.getTabSheet(), "tabsheet"); - currentFeature = feature; - properties = feature.getPropertyPanel(); - if (properties != null) { - mainlayout.addComponent(properties, "properties"); - } - getWindow() - .setCaption( - "IT Mill Toolkit Features / " - + features.getContainerProperty(id, - "name")); - } - } - } else if (event.getProperty() == themeSelector) { - getApplication().setTheme(themeSelector.toString()); - } - } - - public void buttonClick(ClickEvent event) { - // FIXME: navigation statistics - try { - FeatureUtil.debug(getApplication().getUser().toString(), - "buttonClick " + event.getButton().getTag() + ", " - + event.getButton().getCaption() + ", " - + event.getButton().getValue()); - } catch (Exception e) { - // ignored, should never happen - } - - } - - public void addComponent(Component c) { - // TODO Auto-generated method stub - - } - - public void addListener(ComponentAttachListener listener) { - // TODO Auto-generated method stub - - } - - public void addListener(ComponentDetachListener listener) { - // TODO Auto-generated method stub - - } - - public Iterator getComponentIterator() { - // TODO Auto-generated method stub - return null; - } - - public void moveComponentsFrom(ComponentContainer source) { - // TODO Auto-generated method stub - - } - - public void removeAllComponents() { - // TODO Auto-generated method stub - - } - - public void removeComponent(Component c) { - // TODO Auto-generated method stub - - } - - public void removeListener(ComponentAttachListener listener) { - // TODO Auto-generated method stub - - } - - public void removeListener(ComponentDetachListener listener) { - // TODO Auto-generated method stub - - } - - public void replaceComponent(Component oldComponent, Component newComponent) { - // TODO Auto-generated method stub - - } - - public void setMargin(boolean enabled) { - // TODO Auto-generated method stub - - } - - public void setMargin(boolean top, boolean right, boolean bottom, - boolean left) { - // TODO Auto-generated method stub - - } - - public int getHeight() { - // TODO Auto-generated method stub - return 0; - } - - public int getHeightUnits() { - // TODO Auto-generated method stub - return 0; - } - - public int getWidth() { - // TODO Auto-generated method stub - return 0; - } + Property.ValueChangeListener, ClickListener, Layout { + + private Tree features; + + private Feature currentFeature = null; + + private CustomLayout mainlayout; + + private PropertyPanel properties; + + private boolean initialized = false; + + private Select themeSelector = new Select(); + + public void attach() { + + if (initialized) { + return; + } + initialized = true; + + // Configure tree + features = new Tree(); + features.addContainerProperty("name", String.class, ""); + features.addContainerProperty("feature", Feature.class, null); + features.setItemCaptionPropertyId("name"); + features.addListener(this); + features.setImmediate(true); + features.setStyle("menu"); + + // Configure component layout + mainlayout = new CustomLayout("featurebrowser-mainlayout"); + setCompositionRoot(mainlayout); + mainlayout.addComponent(features, "tree"); + + // Theme selector + mainlayout.addComponent(themeSelector, "themes"); + themeSelector.addItem("tests-featurebrowser"); + + themeSelector.addListener(this); + themeSelector.select("tests-featurebrowser"); + themeSelector.setImmediate(true); + + // Restart button + Button close = new Button("restart", getApplication(), "close"); + close.setStyle("link"); + mainlayout.addComponent(close, "restart"); + + // Test component + registerFeature("/Welcome", new IntroWelcome()); + registerFeature("/UI Components", new IntroComponents()); + registerFeature("/UI Components/Basic", new IntroBasic()); + registerFeature("/UI Components/Basic/Text Field", + new FeatureTextField()); + registerFeature("/UI Components/Basic/Date Field", + new FeatureDateField()); + registerFeature("/UI Components/Basic/Button", new FeatureButton()); + registerFeature("/UI Components/Basic/Form", new FeatureForm()); + registerFeature("/UI Components/Basic/Label", new FeatureLabel()); + registerFeature("/UI Components/Basic/Link", new FeatureLink()); + registerFeature("/UI Components/Item Containers", + new IntroItemContainers()); + registerFeature("/UI Components/Item Containers/Select", + new FeatureSelect()); + registerFeature("/UI Components/Item Containers/Table", + new FeatureTable()); + registerFeature("/UI Components/Item Containers/Tree", + new FeatureTree()); + registerFeature("/UI Components/Layouts", new IntroLayouts()); + registerFeature("/UI Components/Layouts/Ordered Layout", + new FeatureOrderedLayout()); + registerFeature("/UI Components/Layouts/Grid Layout", + new FeatureGridLayout()); + registerFeature("/UI Components/Layouts/Custom Layout", + new FeatureCustomLayout()); + registerFeature("/UI Components/Layouts/Panel", new FeaturePanel()); + registerFeature("/UI Components/Layouts/Tab Sheet", + new FeatureTabSheet()); + registerFeature("/UI Components/Layouts/Window", new FeatureWindow()); + // Disabled for now + // registerFeature("/UI Components/Layouts/Frame Window", + // new FeatureFrameWindow()); + registerFeature("/UI Components/Data handling", new IntroDataHandling()); + registerFeature("/UI Components/Data handling/Embedded Objects", + new FeatureEmbedded()); + registerFeature("/UI Components/Data handling/Upload", + new FeatureUpload()); + registerFeature("/Data Model", new IntroDataModel()); + registerFeature("/Data Model/Properties", new FeatureProperties()); + registerFeature("/Data Model/Items", new FeatureItems()); + registerFeature("/Data Model/Containers", new FeatureContainers()); + registerFeature("/Data Model/Validators", new FeatureValidators()); + registerFeature("/Data Model/Buffering", new FeatureBuffering()); + // registerFeature("/Terminal", new IntroTerminal()); + // registerFeature("/Terminal/Parameters and URI Handling", + // new FeatureParameters()); + + // Pre-open all menus + for (Iterator i = features.getItemIds().iterator(); i.hasNext();) { + features.expandItem(i.next()); + } + + // Add demo component and tabs + currentFeature = new IntroWelcome(); + mainlayout.addComponent(currentFeature, "demo"); + mainlayout.addComponent(currentFeature.getTabSheet(), "tabsheet"); + + // Add properties + properties = currentFeature.getPropertyPanel(); + mainlayout.addComponent(properties, "properties"); + } + + public void registerFeature(String path, Feature feature) { + StringTokenizer st = new StringTokenizer(path, "/"); + String id = ""; + String parentId = null; + while (st.hasMoreTokens()) { + String token = st.nextToken(); + id += "/" + token; + if (!features.containsId(id)) { + features.addItem(id); + features.setChildrenAllowed(id, false); + } + features.getContainerProperty(id, "name").setValue(token); + if (parentId != null) { + features.setChildrenAllowed(parentId, true); + features.setParent(id, parentId); + } + if (!st.hasMoreTokens()) { + features.getContainerProperty(id, "feature").setValue(feature); + } + parentId = id; + } + } + + public void valueChange(Property.ValueChangeEvent event) { + + // FIXME: navigation statistics + try { + if ((event.getProperty().toString() == null) + && ((AbstractComponent) event.getProperty()).getTag() + .equals("tree")) { + // ignore tree initialization + } else { + FeatureUtil.debug(getApplication().getUser().toString(), + "valueChange " + + ((AbstractComponent) event.getProperty()) + .getTag() + ", " + event.getProperty()); + } + } catch (Exception e) { + // ignored, should never happen + } + + // Change feature + if (event.getProperty() == features) { + Object id = features.getValue(); + if (id != null) { + if (features.areChildrenAllowed(id)) { + features.expandItem(id); + } + Property p = features.getContainerProperty(id, "feature"); + Feature feature = p != null ? ((Feature) p.getValue()) : null; + if (feature != null) { + mainlayout.removeComponent(currentFeature); + mainlayout.removeComponent(currentFeature.getTabSheet()); + mainlayout.addComponent(feature, "demo"); + mainlayout.addComponent(feature.getTabSheet(), "tabsheet"); + currentFeature = feature; + properties = feature.getPropertyPanel(); + if (properties != null) { + mainlayout.addComponent(properties, "properties"); + } + getWindow() + .setCaption( + "IT Mill Toolkit Features / " + + features.getContainerProperty(id, + "name")); + } + } + } else if (event.getProperty() == themeSelector) { + getApplication().setTheme(themeSelector.toString()); + } + } + + public void buttonClick(ClickEvent event) { + // FIXME: navigation statistics + try { + FeatureUtil.debug(getApplication().getUser().toString(), + "buttonClick " + event.getButton().getTag() + ", " + + event.getButton().getCaption() + ", " + + event.getButton().getValue()); + } catch (Exception e) { + // ignored, should never happen + } + + } + + public void addComponent(Component c) { + // TODO Auto-generated method stub + + } + + public void addListener(ComponentAttachListener listener) { + // TODO Auto-generated method stub + + } + + public void addListener(ComponentDetachListener listener) { + // TODO Auto-generated method stub + + } + + public Iterator getComponentIterator() { + // TODO Auto-generated method stub + return null; + } + + public void moveComponentsFrom(ComponentContainer source) { + // TODO Auto-generated method stub + + } + + public void removeAllComponents() { + // TODO Auto-generated method stub + + } + + public void removeComponent(Component c) { + // TODO Auto-generated method stub - public int getWidthUnits() { - // TODO Auto-generated method stub - return 0; - } + } - public void setHeight(int height) { - // TODO Auto-generated method stub - - } + public void removeListener(ComponentAttachListener listener) { + // TODO Auto-generated method stub - public void setHeightUnits(int units) { - // TODO Auto-generated method stub - - } + } - public void setSizeFull() { - // TODO Auto-generated method stub - - } + public void removeListener(ComponentDetachListener listener) { + // TODO Auto-generated method stub - public void setSizeUndefined() { - // TODO Auto-generated method stub - - } + } - public void setWidth(int width) { - // TODO Auto-generated method stub - - } + public void replaceComponent(Component oldComponent, Component newComponent) { + // TODO Auto-generated method stub - public void setWidthUnits(int units) { - // TODO Auto-generated method stub - - } + } + + public void setMargin(boolean enabled) { + // TODO Auto-generated method stub + + } + + public void setMargin(boolean top, boolean right, boolean bottom, + boolean left) { + // TODO Auto-generated method stub + + } + + public int getHeight() { + // TODO Auto-generated method stub + return 0; + } + + public int getHeightUnits() { + // TODO Auto-generated method stub + return 0; + } + + public int getWidth() { + // TODO Auto-generated method stub + return 0; + } + + public int getWidthUnits() { + // TODO Auto-generated method stub + return 0; + } + + public void setHeight(int height) { + // TODO Auto-generated method stub + + } + + public void setHeightUnits(int units) { + // TODO Auto-generated method stub + + } + + public void setSizeFull() { + // TODO Auto-generated method stub + + } + + public void setSizeUndefined() { + // TODO Auto-generated method stub + + } + + public void setWidth(int width) { + // TODO Auto-generated method stub + + } + + public void setWidthUnits(int units) { + // TODO Auto-generated method stub + + } } diff --git a/src/com/itmill/toolkit/tests/featurebrowser/FeatureBuffering.java b/src/com/itmill/toolkit/tests/featurebrowser/FeatureBuffering.java index a2e2ed8429..2711f7fd58 100644 --- a/src/com/itmill/toolkit/tests/featurebrowser/FeatureBuffering.java +++ b/src/com/itmill/toolkit/tests/featurebrowser/FeatureBuffering.java @@ -37,74 +37,74 @@ import com.itmill.toolkit.ui.Select; public class FeatureBuffering extends Feature { - private static final String INTRO_TEXT = "" - + "IT Mill Toolkit data model provides interface for implementing " - + "buffering in data components. The basic idea is that a component " - + "reading their state from data source can implement " - + "Buffered-interface, for storing the value internally. " - + "Buffering provides transactional access " - + "for setting data: data can be put to a component's buffer and " - + "afterwards committed to or discarded by re-reding it from the data source. " - + "The buffering can be used for creating interactive interfaces " - + "as well as caching the data for performance reasons." - + "

Buffered interface contains methods for committing and discarding " - + "changes to an object and support for controlling buffering mode " - + "with read-through and write-through modes. " - + "Read-through mode means that the value read from the buffered " - + "object is constantly up to date with the data source. " - + "Respectively the write-through mode means that all changes to the object are " - + "immediately updated to the data source."; - - public FeatureBuffering() { - super(); - } - - protected Component getDemoComponent() { - - OrderedLayout l = new OrderedLayout(); - Panel panel = new Panel(); - panel.setCaption("Buffering"); - l.addComponent(panel); - - Label label = new Label(); - panel.addComponent(label); - - label.setContentMode(Label.CONTENT_XHTML); - label.setValue(INTRO_TEXT); - - // Properties - propertyPanel = new PropertyPanel(panel); - Form ap = propertyPanel.createBeanPropertySet(new String[] { "width", - "height" }); - Select themes = (Select) propertyPanel.getField("style"); - themes.addItem("light").getItemProperty( - themes.getItemCaptionPropertyId()).setValue("light"); - themes.addItem("strong").getItemProperty( - themes.getItemCaptionPropertyId()).setValue("strong"); - propertyPanel.addProperties("Panel Properties", ap); - - setJavadocURL("data/Buffered.html"); - - return l; - } - - protected String getExampleSrc() { - return null; - } - - /** - * @see com.itmill.toolkit.tests.featurebrowser.Feature#getDescriptionXHTML() - */ - protected String getDescriptionXHTML() { - return null; - } - - protected String getImage() { - return null; - } - - protected String getTitle() { - return null; - } + private static final String INTRO_TEXT = "" + + "IT Mill Toolkit data model provides interface for implementing " + + "buffering in data components. The basic idea is that a component " + + "reading their state from data source can implement " + + "Buffered-interface, for storing the value internally. " + + "Buffering provides transactional access " + + "for setting data: data can be put to a component's buffer and " + + "afterwards committed to or discarded by re-reding it from the data source. " + + "The buffering can be used for creating interactive interfaces " + + "as well as caching the data for performance reasons." + + "

Buffered interface contains methods for committing and discarding " + + "changes to an object and support for controlling buffering mode " + + "with read-through and write-through modes. " + + "Read-through mode means that the value read from the buffered " + + "object is constantly up to date with the data source. " + + "Respectively the write-through mode means that all changes to the object are " + + "immediately updated to the data source."; + + public FeatureBuffering() { + super(); + } + + protected Component getDemoComponent() { + + OrderedLayout l = new OrderedLayout(); + Panel panel = new Panel(); + panel.setCaption("Buffering"); + l.addComponent(panel); + + Label label = new Label(); + panel.addComponent(label); + + label.setContentMode(Label.CONTENT_XHTML); + label.setValue(INTRO_TEXT); + + // Properties + propertyPanel = new PropertyPanel(panel); + Form ap = propertyPanel.createBeanPropertySet(new String[] { "width", + "height" }); + Select themes = (Select) propertyPanel.getField("style"); + themes.addItem("light").getItemProperty( + themes.getItemCaptionPropertyId()).setValue("light"); + themes.addItem("strong").getItemProperty( + themes.getItemCaptionPropertyId()).setValue("strong"); + propertyPanel.addProperties("Panel Properties", ap); + + setJavadocURL("data/Buffered.html"); + + return l; + } + + protected String getExampleSrc() { + return null; + } + + /** + * @see com.itmill.toolkit.tests.featurebrowser.Feature#getDescriptionXHTML() + */ + protected String getDescriptionXHTML() { + return null; + } + + protected String getImage() { + return null; + } + + protected String getTitle() { + return null; + } } diff --git a/src/com/itmill/toolkit/tests/featurebrowser/FeatureButton.java b/src/com/itmill/toolkit/tests/featurebrowser/FeatureButton.java index b572870be1..b3038a76ef 100644 --- a/src/com/itmill/toolkit/tests/featurebrowser/FeatureButton.java +++ b/src/com/itmill/toolkit/tests/featurebrowser/FeatureButton.java @@ -28,60 +28,64 @@ package com.itmill.toolkit.tests.featurebrowser; -import com.itmill.toolkit.ui.*; +import com.itmill.toolkit.ui.Button; +import com.itmill.toolkit.ui.Component; +import com.itmill.toolkit.ui.Form; +import com.itmill.toolkit.ui.OrderedLayout; +import com.itmill.toolkit.ui.Select; public class FeatureButton extends Feature { - public FeatureButton() { - super(); - } - - protected Component getDemoComponent() { - - OrderedLayout l = new OrderedLayout(); - - Button b = new Button("Caption"); - l.addComponent(b); - - // Properties - propertyPanel = new PropertyPanel(b); - Select themes = (Select) propertyPanel.getField("style"); - themes.addItem("link").getItemProperty( - themes.getItemCaptionPropertyId()).setValue("link"); - Form ap = propertyPanel - .createBeanPropertySet(new String[] { "switchMode" }); - propertyPanel.addProperties("Button Properties", ap); - - setJavadocURL("ui/Button.html"); - - return l; - } - - protected String getExampleSrc() { - return "Button b = new Button(\"Caption\");\n"; - - } - - /** - * @see com.itmill.toolkit.tests.featurebrowser.Feature#getDescriptionXHTML() - */ - protected String getDescriptionXHTML() { - return "In IT Mill Toolkit, boolean input values are represented by buttons. " - + "Buttons may function either as a push buttons or switches. (checkboxes)

" - + "Button can be directly connected to any method of an object, which " - + "is an easy way to trigger events: new Button(\"Play\", myPiano \"playIt\"). " - + "Or in checkbox-mode they can be bound to a boolean proterties and create " - + " simple selectors.

" - + "See the demo and try out how the different properties affect " - + "the presentation of the component."; - } - - protected String getImage() { - return "icon_demo.png"; - } - - protected String getTitle() { - return "Button"; - } + public FeatureButton() { + super(); + } + + protected Component getDemoComponent() { + + OrderedLayout l = new OrderedLayout(); + + Button b = new Button("Caption"); + l.addComponent(b); + + // Properties + propertyPanel = new PropertyPanel(b); + Select themes = (Select) propertyPanel.getField("style"); + themes.addItem("link").getItemProperty( + themes.getItemCaptionPropertyId()).setValue("link"); + Form ap = propertyPanel + .createBeanPropertySet(new String[] { "switchMode" }); + propertyPanel.addProperties("Button Properties", ap); + + setJavadocURL("ui/Button.html"); + + return l; + } + + protected String getExampleSrc() { + return "Button b = new Button(\"Caption\");\n"; + + } + + /** + * @see com.itmill.toolkit.tests.featurebrowser.Feature#getDescriptionXHTML() + */ + protected String getDescriptionXHTML() { + return "In IT Mill Toolkit, boolean input values are represented by buttons. " + + "Buttons may function either as a push buttons or switches. (checkboxes)

" + + "Button can be directly connected to any method of an object, which " + + "is an easy way to trigger events: new Button(\"Play\", myPiano \"playIt\"). " + + "Or in checkbox-mode they can be bound to a boolean proterties and create " + + " simple selectors.

" + + "See the demo and try out how the different properties affect " + + "the presentation of the component."; + } + + protected String getImage() { + return "icon_demo.png"; + } + + protected String getTitle() { + return "Button"; + } } diff --git a/src/com/itmill/toolkit/tests/featurebrowser/FeatureContainers.java b/src/com/itmill/toolkit/tests/featurebrowser/FeatureContainers.java index 4f02c5313b..62d2a5753f 100644 --- a/src/com/itmill/toolkit/tests/featurebrowser/FeatureContainers.java +++ b/src/com/itmill/toolkit/tests/featurebrowser/FeatureContainers.java @@ -37,77 +37,77 @@ import com.itmill.toolkit.ui.Select; public class FeatureContainers extends Feature { - private static final String INTRO_TEXT = "" - + "Container is the most advanced of the data " - + "model supported by IT Mill Toolkit. It provides a very flexible " - + "way of managing set of items that share common properties. Each " - + "item is identified by an item id. " - + "Properties can be requested from container with item " - + "and property ids. Other way of accessing properties is to first " - + "request an item from container and then request its properties " - + "from it." - + "

Container interface was designed with flexibility and " - + "efficiency in mind. It contains inner interfaces for ordering " - + "the items sequentially, indexing the items and accessing them " - + "hierarchically. Those ordering models provide basis for " - + "Table, Tree and Select UI components. As with other data " - + "models, the containers support events for notifying about the " - + "changes." - + "

Set of utilities for converting between container models by " - + "adding external indexing or hierarchy into existing containers. " - + "In memory containers implementing indexed and hierarchical " - + "models provide easy to use tools for setting up in memory data " - + "storages. There is even a hierarchical container for direct " - + "file system access."; - - public FeatureContainers() { - super(); - } - - protected Component getDemoComponent() { - - OrderedLayout l = new OrderedLayout(); - - Panel panel = new Panel(); - panel.setCaption("Containers"); - l.addComponent(panel); - - Label label = new Label(); - panel.addComponent(label); - - label.setContentMode(Label.CONTENT_XHTML); - label.setValue(INTRO_TEXT); - - // Properties - propertyPanel = new PropertyPanel(panel); - Form ap = propertyPanel.createBeanPropertySet(new String[] { "width", - "height" }); - Select themes = (Select) propertyPanel.getField("style"); - themes.addItem("light").getItemProperty( - themes.getItemCaptionPropertyId()).setValue("light"); - themes.addItem("strong").getItemProperty( - themes.getItemCaptionPropertyId()).setValue("strong"); - propertyPanel.addProperties("Panel Properties", ap); - - setJavadocURL("data/Container.html"); - - return l; - } - - protected String getExampleSrc() { - return null; - } - - protected String getDescriptionXHTML() { - return null; - } - - protected String getImage() { - return null; - } - - protected String getTitle() { - return null; - } + private static final String INTRO_TEXT = "" + + "Container is the most advanced of the data " + + "model supported by IT Mill Toolkit. It provides a very flexible " + + "way of managing set of items that share common properties. Each " + + "item is identified by an item id. " + + "Properties can be requested from container with item " + + "and property ids. Other way of accessing properties is to first " + + "request an item from container and then request its properties " + + "from it." + + "

Container interface was designed with flexibility and " + + "efficiency in mind. It contains inner interfaces for ordering " + + "the items sequentially, indexing the items and accessing them " + + "hierarchically. Those ordering models provide basis for " + + "Table, Tree and Select UI components. As with other data " + + "models, the containers support events for notifying about the " + + "changes." + + "

Set of utilities for converting between container models by " + + "adding external indexing or hierarchy into existing containers. " + + "In memory containers implementing indexed and hierarchical " + + "models provide easy to use tools for setting up in memory data " + + "storages. There is even a hierarchical container for direct " + + "file system access."; + + public FeatureContainers() { + super(); + } + + protected Component getDemoComponent() { + + OrderedLayout l = new OrderedLayout(); + + Panel panel = new Panel(); + panel.setCaption("Containers"); + l.addComponent(panel); + + Label label = new Label(); + panel.addComponent(label); + + label.setContentMode(Label.CONTENT_XHTML); + label.setValue(INTRO_TEXT); + + // Properties + propertyPanel = new PropertyPanel(panel); + Form ap = propertyPanel.createBeanPropertySet(new String[] { "width", + "height" }); + Select themes = (Select) propertyPanel.getField("style"); + themes.addItem("light").getItemProperty( + themes.getItemCaptionPropertyId()).setValue("light"); + themes.addItem("strong").getItemProperty( + themes.getItemCaptionPropertyId()).setValue("strong"); + propertyPanel.addProperties("Panel Properties", ap); + + setJavadocURL("data/Container.html"); + + return l; + } + + protected String getExampleSrc() { + return null; + } + + protected String getDescriptionXHTML() { + return null; + } + + protected String getImage() { + return null; + } + + protected String getTitle() { + return null; + } } diff --git a/src/com/itmill/toolkit/tests/featurebrowser/FeatureCustomLayout.java b/src/com/itmill/toolkit/tests/featurebrowser/FeatureCustomLayout.java index 979a8f0fdf..1cac66516b 100644 --- a/src/com/itmill/toolkit/tests/featurebrowser/FeatureCustomLayout.java +++ b/src/com/itmill/toolkit/tests/featurebrowser/FeatureCustomLayout.java @@ -28,69 +28,74 @@ package com.itmill.toolkit.tests.featurebrowser; -import com.itmill.toolkit.ui.*; +import com.itmill.toolkit.ui.Component; +import com.itmill.toolkit.ui.Form; +import com.itmill.toolkit.ui.Label; +import com.itmill.toolkit.ui.OrderedLayout; +import com.itmill.toolkit.ui.Panel; +import com.itmill.toolkit.ui.Select; public class FeatureCustomLayout extends Feature { - private static final String INTRO_TEXT = "" - + "A container component with freely designed layout and style. The " - + "container consists of items with textually represented locations. Each " - + "item contains one sub-component. The adapter and theme are resposible " - + "for rendering the layout with given style by placing the items on the " - + "screen in defined locations." - + "

The definition of locations is not fixed - the each style can define its " - + "locations in a way that is suitable for it. One typical example would be " - + "to create visual design for a website as a custom layout: the visual design " - + "could define locations for \"menu\", \"body\" and \"title\" for example. " - + "The layout would then be implemented e.g. as plain HTML file." - + "

The default theme handles the styles that are not defined by just drawing " - + "the subcomponents with flowlayout."; - - protected Component getDemoComponent() { - OrderedLayout l = new OrderedLayout(); - - Panel panel = new Panel(); - panel.setCaption("Custom Layout"); - l.addComponent(panel); - - Label label = new Label(); - panel.addComponent(label); - - label.setContentMode(Label.CONTENT_XHTML); - label.setValue(INTRO_TEXT); - - // Properties - propertyPanel = new PropertyPanel(panel); - Form ap = propertyPanel.createBeanPropertySet(new String[] { "width", - "height" }); - Select themes = (Select) propertyPanel.getField("style"); - themes.addItem("light").getItemProperty( - themes.getItemCaptionPropertyId()).setValue("light"); - themes.addItem("strong").getItemProperty( - themes.getItemCaptionPropertyId()).setValue("strong"); - propertyPanel.addProperties("Panel Properties", ap); - - setJavadocURL("ui/CustomLayout.html"); - - return l; - } - - protected String getDescriptionXHTML() { - return null; - } - - protected String getExampleSrc() { - return "CustomLayout c = new CustomLayout(\"mystyle\");\n" - + "c.addComponent(new Label(\"Example description\"),\"label1-location\");\n" - + "c.addComponent(new Button(\"Example action\"),\"example-action-location\");\n"; - } - - protected String getImage() { - return null; - } - - protected String getTitle() { - return "Custom Layout"; - } + private static final String INTRO_TEXT = "" + + "A container component with freely designed layout and style. The " + + "container consists of items with textually represented locations. Each " + + "item contains one sub-component. The adapter and theme are resposible " + + "for rendering the layout with given style by placing the items on the " + + "screen in defined locations." + + "

The definition of locations is not fixed - the each style can define its " + + "locations in a way that is suitable for it. One typical example would be " + + "to create visual design for a website as a custom layout: the visual design " + + "could define locations for \"menu\", \"body\" and \"title\" for example. " + + "The layout would then be implemented e.g. as plain HTML file." + + "

The default theme handles the styles that are not defined by just drawing " + + "the subcomponents with flowlayout."; + + protected Component getDemoComponent() { + OrderedLayout l = new OrderedLayout(); + + Panel panel = new Panel(); + panel.setCaption("Custom Layout"); + l.addComponent(panel); + + Label label = new Label(); + panel.addComponent(label); + + label.setContentMode(Label.CONTENT_XHTML); + label.setValue(INTRO_TEXT); + + // Properties + propertyPanel = new PropertyPanel(panel); + Form ap = propertyPanel.createBeanPropertySet(new String[] { "width", + "height" }); + Select themes = (Select) propertyPanel.getField("style"); + themes.addItem("light").getItemProperty( + themes.getItemCaptionPropertyId()).setValue("light"); + themes.addItem("strong").getItemProperty( + themes.getItemCaptionPropertyId()).setValue("strong"); + propertyPanel.addProperties("Panel Properties", ap); + + setJavadocURL("ui/CustomLayout.html"); + + return l; + } + + protected String getDescriptionXHTML() { + return null; + } + + protected String getExampleSrc() { + return "CustomLayout c = new CustomLayout(\"mystyle\");\n" + + "c.addComponent(new Label(\"Example description\"),\"label1-location\");\n" + + "c.addComponent(new Button(\"Example action\"),\"example-action-location\");\n"; + } + + protected String getImage() { + return null; + } + + protected String getTitle() { + return "Custom Layout"; + } } diff --git a/src/com/itmill/toolkit/tests/featurebrowser/FeatureDateField.java b/src/com/itmill/toolkit/tests/featurebrowser/FeatureDateField.java index 2b6317304b..28530ecca8 100644 --- a/src/com/itmill/toolkit/tests/featurebrowser/FeatureDateField.java +++ b/src/com/itmill/toolkit/tests/featurebrowser/FeatureDateField.java @@ -30,8 +30,6 @@ package com.itmill.toolkit.tests.featurebrowser; import java.util.Locale; -import com.itmill.toolkit.data.util.IndexedContainer; -import com.itmill.toolkit.data.util.MethodProperty; import com.itmill.toolkit.ui.Component; import com.itmill.toolkit.ui.DateField; import com.itmill.toolkit.ui.Form; @@ -41,86 +39,86 @@ import com.itmill.toolkit.ui.Select; public class FeatureDateField extends Feature { - static private String[] localeNames; - static { - Locale[] locales = Locale.getAvailableLocales(); - localeNames = new String[locales.length]; - for (int i = 0; i < locales.length; i++) - localeNames[i] = locales[i].getDisplayName(); - } - - public FeatureDateField() { - super(); - } - - protected Component getDemoComponent() { - - OrderedLayout l = new OrderedLayout(); - - l.addComponent(new Label("Your default locale is: " - + this.getApplication().getLocale().toString() - .replace('_', '-'))); - - DateField df = new DateField(); - df.setValue(new java.util.Date()); - l.addComponent(df); - - // Properties - propertyPanel = new PropertyPanel(df); - Form ap = propertyPanel.createBeanPropertySet(new String[] { - "resolution", "locale" }); - ap.replaceWithSelect("resolution", new Object[] { - new Integer(DateField.RESOLUTION_YEAR), - new Integer(DateField.RESOLUTION_MONTH), - new Integer(DateField.RESOLUTION_DAY), - new Integer(DateField.RESOLUTION_HOUR), - new Integer(DateField.RESOLUTION_MIN), - new Integer(DateField.RESOLUTION_SEC), - new Integer(DateField.RESOLUTION_MSEC) }, new Object[] { - "Year", "Month", "Day", "Hour", "Minute", "Second", - "Millisecond" }); - ap.replaceWithSelect("locale", Locale.getAvailableLocales(), - localeNames); - ap.getField("resolution").setValue( - new Integer(DateField.RESOLUTION_DAY)); - ap.getField("locale").setValue(Locale.getDefault()); - Select themes = (Select) propertyPanel.getField("style"); - themes.addItem("text").getItemProperty( - themes.getItemCaptionPropertyId()).setValue("text"); - themes.addItem("calendar").getItemProperty( - themes.getItemCaptionPropertyId()).setValue("calendar"); - propertyPanel.addProperties("DateField Properties", ap); - - setJavadocURL("ui/DateField.html"); - - return l; - } - - protected String getExampleSrc() { - return "DateField df = new DateField(\"Caption\");\n" - + "df.setValue(new java.util.Date());\n"; - } - - protected String getDescriptionXHTML() { - return "Representing Dates and times and providing a way to select " - + "or enter some specific date and/or time is an typical need in " - + "data-entry user interfaces (UI). IT Mill Toolkit provides a DateField " - + "component that is intuitive to use and yet controllable through " - + "its properties." - + "

The calendar-style allows point-and-click selection " - + "of dates while text-style shows only minimalistic user interface." - + " Validators may be bound to the component to check and " - + "validate the given input." - + "

On the demo tab you can try out how the different properties affect the " - + "presentation of the component."; - } - - protected String getImage() { - return "icon_demo.png"; - } - - protected String getTitle() { - return "DateField"; - } + static private String[] localeNames; + static { + Locale[] locales = Locale.getAvailableLocales(); + localeNames = new String[locales.length]; + for (int i = 0; i < locales.length; i++) { + localeNames[i] = locales[i].getDisplayName(); + } + } + + public FeatureDateField() { + super(); + } + + protected Component getDemoComponent() { + + OrderedLayout l = new OrderedLayout(); + + l.addComponent(new Label("Your default locale is: " + + getApplication().getLocale().toString().replace('_', '-'))); + + DateField df = new DateField(); + df.setValue(new java.util.Date()); + l.addComponent(df); + + // Properties + propertyPanel = new PropertyPanel(df); + Form ap = propertyPanel.createBeanPropertySet(new String[] { + "resolution", "locale" }); + ap.replaceWithSelect("resolution", new Object[] { + new Integer(DateField.RESOLUTION_YEAR), + new Integer(DateField.RESOLUTION_MONTH), + new Integer(DateField.RESOLUTION_DAY), + new Integer(DateField.RESOLUTION_HOUR), + new Integer(DateField.RESOLUTION_MIN), + new Integer(DateField.RESOLUTION_SEC), + new Integer(DateField.RESOLUTION_MSEC) }, new Object[] { + "Year", "Month", "Day", "Hour", "Minute", "Second", + "Millisecond" }); + ap.replaceWithSelect("locale", Locale.getAvailableLocales(), + localeNames); + ap.getField("resolution").setValue( + new Integer(DateField.RESOLUTION_DAY)); + ap.getField("locale").setValue(Locale.getDefault()); + Select themes = (Select) propertyPanel.getField("style"); + themes.addItem("text").getItemProperty( + themes.getItemCaptionPropertyId()).setValue("text"); + themes.addItem("calendar").getItemProperty( + themes.getItemCaptionPropertyId()).setValue("calendar"); + propertyPanel.addProperties("DateField Properties", ap); + + setJavadocURL("ui/DateField.html"); + + return l; + } + + protected String getExampleSrc() { + return "DateField df = new DateField(\"Caption\");\n" + + "df.setValue(new java.util.Date());\n"; + } + + protected String getDescriptionXHTML() { + return "Representing Dates and times and providing a way to select " + + "or enter some specific date and/or time is an typical need in " + + "data-entry user interfaces (UI). IT Mill Toolkit provides a DateField " + + "component that is intuitive to use and yet controllable through " + + "its properties." + + "

The calendar-style allows point-and-click selection " + + "of dates while text-style shows only minimalistic user interface." + + " Validators may be bound to the component to check and " + + "validate the given input." + + "

On the demo tab you can try out how the different properties affect the " + + "presentation of the component."; + } + + protected String getImage() { + return "icon_demo.png"; + } + + protected String getTitle() { + return "DateField"; + } } diff --git a/src/com/itmill/toolkit/tests/featurebrowser/FeatureEmbedded.java b/src/com/itmill/toolkit/tests/featurebrowser/FeatureEmbedded.java index 008e25531d..ba0f2eca3a 100644 --- a/src/com/itmill/toolkit/tests/featurebrowser/FeatureEmbedded.java +++ b/src/com/itmill/toolkit/tests/featurebrowser/FeatureEmbedded.java @@ -30,83 +30,86 @@ package com.itmill.toolkit.tests.featurebrowser; import com.itmill.toolkit.terminal.ClassResource; import com.itmill.toolkit.terminal.Sizeable; -import com.itmill.toolkit.ui.*; +import com.itmill.toolkit.ui.Component; +import com.itmill.toolkit.ui.Embedded; +import com.itmill.toolkit.ui.Form; +import com.itmill.toolkit.ui.OrderedLayout; public class FeatureEmbedded extends Feature { - public FeatureEmbedded() { - super(); - } - - protected Component getDemoComponent() { - - OrderedLayout l = new OrderedLayout(); - - ClassResource flashResource = new ClassResource("itmill_spin.swf", - getApplication()); - Embedded emb = new Embedded("Embedded Caption", flashResource); - emb.setType(Embedded.TYPE_OBJECT); - emb.setMimeType("application/x-shockwave-flash"); - emb.setWidth(250); - emb.setHeight(100); - l.addComponent(emb); - - // Properties - propertyPanel = new PropertyPanel(emb); - Form ap = propertyPanel.createBeanPropertySet(new String[] { "type", - "source", "width", "height", "widthUnits", "heightUnits", - "codebase", "codetype", "archive", "mimeType", "standby", - "classId" }); - ap.replaceWithSelect("type", new Object[] { - new Integer(Embedded.TYPE_IMAGE), - new Integer(Embedded.TYPE_OBJECT) }, new Object[] { "Image", - "Object" }); - Object[] units = new Object[Sizeable.UNIT_SYMBOLS.length]; - Object[] symbols = new Object[Sizeable.UNIT_SYMBOLS.length]; - for (int i = 0; i < units.length; i++) { - units[i] = new Integer(i); - symbols[i] = Sizeable.UNIT_SYMBOLS[i]; - } - ap.replaceWithSelect("heightUnits", units, symbols); - ap.replaceWithSelect("widthUnits", units, symbols); - ap.replaceWithSelect("source", new Object[] { flashResource }, - new Object[] { "itmill_spin.swf" }); - propertyPanel.addProperties("Embedded Properties", ap); - propertyPanel.getField("standby").setDescription( - "The text to display while loading the object."); - propertyPanel.getField("codebase").setDescription( - "root-path used to access resources with relative paths."); - propertyPanel.getField("codetype").setDescription( - "MIME-type of the code."); - propertyPanel - .getField("classId") - .setDescription( - "Unique object id. This can be used for example to identify windows components."); - - setJavadocURL("ui/Embedded.html"); - - return l; - } - - protected String getExampleSrc() { - return "// Load image from jpg-file, that is in the same package with the application\n" - + "Embedded e = new Embedded(\"Image title\",\n" - + " new ClassResource(\"image.jpg\", getApplication()));"; - } - - protected String getDescriptionXHTML() { - return "The embedding feature allows for adding images, multimedia and other non-specified " - + "content to your application. " - + "The feature has provisions for embedding both applets and Active X controls. " - + "Actual support for embedded media types is left to the terminal."; - } - - protected String getImage() { - return "icon_demo.png"; - } - - protected String getTitle() { - return "Embedded"; - } + public FeatureEmbedded() { + super(); + } + + protected Component getDemoComponent() { + + OrderedLayout l = new OrderedLayout(); + + ClassResource flashResource = new ClassResource("itmill_spin.swf", + getApplication()); + Embedded emb = new Embedded("Embedded Caption", flashResource); + emb.setType(Embedded.TYPE_OBJECT); + emb.setMimeType("application/x-shockwave-flash"); + emb.setWidth(250); + emb.setHeight(100); + l.addComponent(emb); + + // Properties + propertyPanel = new PropertyPanel(emb); + Form ap = propertyPanel.createBeanPropertySet(new String[] { "type", + "source", "width", "height", "widthUnits", "heightUnits", + "codebase", "codetype", "archive", "mimeType", "standby", + "classId" }); + ap.replaceWithSelect("type", new Object[] { + new Integer(Embedded.TYPE_IMAGE), + new Integer(Embedded.TYPE_OBJECT) }, new Object[] { "Image", + "Object" }); + Object[] units = new Object[Sizeable.UNIT_SYMBOLS.length]; + Object[] symbols = new Object[Sizeable.UNIT_SYMBOLS.length]; + for (int i = 0; i < units.length; i++) { + units[i] = new Integer(i); + symbols[i] = Sizeable.UNIT_SYMBOLS[i]; + } + ap.replaceWithSelect("heightUnits", units, symbols); + ap.replaceWithSelect("widthUnits", units, symbols); + ap.replaceWithSelect("source", new Object[] { flashResource }, + new Object[] { "itmill_spin.swf" }); + propertyPanel.addProperties("Embedded Properties", ap); + propertyPanel.getField("standby").setDescription( + "The text to display while loading the object."); + propertyPanel.getField("codebase").setDescription( + "root-path used to access resources with relative paths."); + propertyPanel.getField("codetype").setDescription( + "MIME-type of the code."); + propertyPanel + .getField("classId") + .setDescription( + "Unique object id. This can be used for example to identify windows components."); + + setJavadocURL("ui/Embedded.html"); + + return l; + } + + protected String getExampleSrc() { + return "// Load image from jpg-file, that is in the same package with the application\n" + + "Embedded e = new Embedded(\"Image title\",\n" + + " new ClassResource(\"image.jpg\", getApplication()));"; + } + + protected String getDescriptionXHTML() { + return "The embedding feature allows for adding images, multimedia and other non-specified " + + "content to your application. " + + "The feature has provisions for embedding both applets and Active X controls. " + + "Actual support for embedded media types is left to the terminal."; + } + + protected String getImage() { + return "icon_demo.png"; + } + + protected String getTitle() { + return "Embedded"; + } } diff --git a/src/com/itmill/toolkit/tests/featurebrowser/FeatureForm.java b/src/com/itmill/toolkit/tests/featurebrowser/FeatureForm.java index e84dfa22dd..7b18555248 100644 --- a/src/com/itmill/toolkit/tests/featurebrowser/FeatureForm.java +++ b/src/com/itmill/toolkit/tests/featurebrowser/FeatureForm.java @@ -31,161 +31,172 @@ package com.itmill.toolkit.tests.featurebrowser; import java.util.Date; import com.itmill.toolkit.data.Property; -import com.itmill.toolkit.ui.*; +import com.itmill.toolkit.ui.Component; +import com.itmill.toolkit.ui.DateField; +import com.itmill.toolkit.ui.Form; +import com.itmill.toolkit.ui.GridLayout; +import com.itmill.toolkit.ui.Layout; +import com.itmill.toolkit.ui.OrderedLayout; +import com.itmill.toolkit.ui.Select; +import com.itmill.toolkit.ui.TextField; public class FeatureForm extends Feature implements - Property.ValueChangeListener { + Property.ValueChangeListener { - OrderedLayout demo = null; - - Form test; - - Layout formLayout = null; - - Select addField = new Select("Add field"); - - Select resetLayout = new Select("Restart"); - - protected Component getDemoComponent() { - - if (demo == null) { - demo = new OrderedLayout(); - createDemo(); - } - - setJavadocURL("ui/Form.html"); - - return demo; - } - - private void createDemo() { - - demo.removeAllComponents(); - - // Test form - if (formLayout == null) - test = new Form(); - else - test = new Form(formLayout); - - demo.addComponent(test); - OrderedLayout actions = new OrderedLayout( - OrderedLayout.ORIENTATION_HORIZONTAL); - demo.addComponent(actions); - - // form adder - addField.setImmediate(true); - addField.addItem("Add field"); - addField.setNullSelectionItemId("Add field"); - addField.addItem("Text field"); - addField.addItem("Time"); - addField.addItem("Option group"); - addField.addItem("Calendar"); - addField.addListener(this); - actions.addComponent(addField); - - // Layout reset - resetLayout.setImmediate(true); - resetLayout.addItem("Select layout example"); - resetLayout.setNullSelectionItemId("Select layout example"); - resetLayout.addItem("Vertical form (OrderedLayout form-style)"); - resetLayout.addItem("Two columns (2x1 GridLayout)"); - resetLayout.addItem("Flow (OrderedLayout flow-orientation)"); - resetLayout.addListener(this); - actions.addComponent(resetLayout); - - // Properties - propertyPanel = new PropertyPanel(test); - propertyPanel.addProperties("Form special properties", new Form()); - } - - public void valueChange(Property.ValueChangeEvent event) { - - if (event.getProperty() == resetLayout) { - - String value = (String) resetLayout.getValue(); - - if (value != null) { - formLayout = null; - - if (value.equals("Two columns (2x1 GridLayout)")) - formLayout = new GridLayout(2, 1); - if (value.equals("Horizontal (OrderedLayout)")) - formLayout = new OrderedLayout( - OrderedLayout.ORIENTATION_HORIZONTAL); - - createDemo(); - resetLayout.setValue(null); - } - } - - if (event.getProperty() == addField) { - - String value = (String) addField.getValue(); - - if (value != null) { - if (value.equals("Text field")) - test.addField(new Object(), new TextField("Test field")); - if (value.equals("Time")) { - DateField d = new DateField("Time", new Date()); - d - .setDescription("This is a DateField-component with text-style"); - d.setResolution(DateField.RESOLUTION_MIN); - d.setStyle("text"); - test.addField(new Object(), d); - } - if (value.equals("Calendar")) { - DateField c = new DateField("Calendar", new Date()); - c - .setDescription("DateField-component with calendar-style and day-resolution"); - c.setStyle("calendar"); - c.setResolution(DateField.RESOLUTION_DAY); - test.addField(new Object(), c); - } - if (value.equals("Option group")) { - Select s = new Select("Options"); - s.setDescription("Select-component with optiongroup-style"); - s.addItem("Linux"); - s.addItem("Windows"); - s.addItem("Solaris"); - s.addItem("Symbian"); - s.setStyle("optiongroup"); - - test.addField(new Object(), s); - } - - addField.setValue(null); - } - } - } - - protected String getDescriptionXHTML() { - return "Form is a flexible, yet simple container for fields. " - + " It provides support for any layouts and provides buffering interface for" - + " easy connection of commit- and discard buttons. All the form" - + " fields can be customized by adding validators, setting captions and icons, " - + " setting immediateness, etc. Also direct mechanism for replacing existing" - + " fields with selections is given." - + "

Form provides customizable editor for classes implementing" - + " Item-interface. Also the form itself" - + " implements this interface for easier connectivity to other items." - + " To use the form as editor for an item, just connect the item to" - + " form.After the item has been connected to the form," - + " the automatically created fields can be customized and new fields can" - + " be added. If you need to connect a class that does not implement" - + " Item-interface, most properties of any" - + " class following bean pattern, can be accessed trough" - + " BeanItem." - + "

The best example of Form usage is the this feature browser itself; " - + " all the Property-panels in demos are composed of Form-components."; - } - - protected String getTitle() { - return "Form"; - } - - protected String getImage() { - return "icon_demo.png"; - } + OrderedLayout demo = null; + + Form test; + + Layout formLayout = null; + + Select addField = new Select("Add field"); + + Select resetLayout = new Select("Restart"); + + protected Component getDemoComponent() { + + if (demo == null) { + demo = new OrderedLayout(); + createDemo(); + } + + setJavadocURL("ui/Form.html"); + + return demo; + } + + private void createDemo() { + + demo.removeAllComponents(); + + // Test form + if (formLayout == null) { + test = new Form(); + } else { + test = new Form(formLayout); + } + + demo.addComponent(test); + OrderedLayout actions = new OrderedLayout( + OrderedLayout.ORIENTATION_HORIZONTAL); + demo.addComponent(actions); + + // form adder + addField.setImmediate(true); + addField.addItem("Add field"); + addField.setNullSelectionItemId("Add field"); + addField.addItem("Text field"); + addField.addItem("Time"); + addField.addItem("Option group"); + addField.addItem("Calendar"); + addField.addListener(this); + actions.addComponent(addField); + + // Layout reset + resetLayout.setImmediate(true); + resetLayout.addItem("Select layout example"); + resetLayout.setNullSelectionItemId("Select layout example"); + resetLayout.addItem("Vertical form (OrderedLayout form-style)"); + resetLayout.addItem("Two columns (2x1 GridLayout)"); + resetLayout.addItem("Flow (OrderedLayout flow-orientation)"); + resetLayout.addListener(this); + actions.addComponent(resetLayout); + + // Properties + propertyPanel = new PropertyPanel(test); + propertyPanel.addProperties("Form special properties", new Form()); + } + + public void valueChange(Property.ValueChangeEvent event) { + + if (event.getProperty() == resetLayout) { + + String value = (String) resetLayout.getValue(); + + if (value != null) { + formLayout = null; + + if (value.equals("Two columns (2x1 GridLayout)")) { + formLayout = new GridLayout(2, 1); + } + if (value.equals("Horizontal (OrderedLayout)")) { + formLayout = new OrderedLayout( + OrderedLayout.ORIENTATION_HORIZONTAL); + } + + createDemo(); + resetLayout.setValue(null); + } + } + + if (event.getProperty() == addField) { + + String value = (String) addField.getValue(); + + if (value != null) { + if (value.equals("Text field")) { + test.addField(new Object(), new TextField("Test field")); + } + if (value.equals("Time")) { + DateField d = new DateField("Time", new Date()); + d + .setDescription("This is a DateField-component with text-style"); + d.setResolution(DateField.RESOLUTION_MIN); + d.setStyle("text"); + test.addField(new Object(), d); + } + if (value.equals("Calendar")) { + DateField c = new DateField("Calendar", new Date()); + c + .setDescription("DateField-component with calendar-style and day-resolution"); + c.setStyle("calendar"); + c.setResolution(DateField.RESOLUTION_DAY); + test.addField(new Object(), c); + } + if (value.equals("Option group")) { + Select s = new Select("Options"); + s.setDescription("Select-component with optiongroup-style"); + s.addItem("Linux"); + s.addItem("Windows"); + s.addItem("Solaris"); + s.addItem("Symbian"); + s.setStyle("optiongroup"); + + test.addField(new Object(), s); + } + + addField.setValue(null); + } + } + } + + protected String getDescriptionXHTML() { + return "Form is a flexible, yet simple container for fields. " + + " It provides support for any layouts and provides buffering interface for" + + " easy connection of commit- and discard buttons. All the form" + + " fields can be customized by adding validators, setting captions and icons, " + + " setting immediateness, etc. Also direct mechanism for replacing existing" + + " fields with selections is given." + + "

Form provides customizable editor for classes implementing" + + " Item-interface. Also the form itself" + + " implements this interface for easier connectivity to other items." + + " To use the form as editor for an item, just connect the item to" + + " form.After the item has been connected to the form," + + " the automatically created fields can be customized and new fields can" + + " be added. If you need to connect a class that does not implement" + + " Item-interface, most properties of any" + + " class following bean pattern, can be accessed trough" + + " BeanItem." + + "

The best example of Form usage is the this feature browser itself; " + + " all the Property-panels in demos are composed of Form-components."; + } + + protected String getTitle() { + return "Form"; + } + + protected String getImage() { + return "icon_demo.png"; + } } diff --git a/src/com/itmill/toolkit/tests/featurebrowser/FeatureGridLayout.java b/src/com/itmill/toolkit/tests/featurebrowser/FeatureGridLayout.java index 0165f617d2..63b8235543 100644 --- a/src/com/itmill/toolkit/tests/featurebrowser/FeatureGridLayout.java +++ b/src/com/itmill/toolkit/tests/featurebrowser/FeatureGridLayout.java @@ -30,64 +30,71 @@ package com.itmill.toolkit.tests.featurebrowser; import java.util.Date; -import com.itmill.toolkit.ui.*; +import com.itmill.toolkit.ui.Button; +import com.itmill.toolkit.ui.Component; +import com.itmill.toolkit.ui.DateField; +import com.itmill.toolkit.ui.Form; +import com.itmill.toolkit.ui.GridLayout; +import com.itmill.toolkit.ui.OrderedLayout; +import com.itmill.toolkit.ui.TextField; public class FeatureGridLayout extends Feature { - public FeatureGridLayout() { - super(); - } - - protected Component getDemoComponent() { - - OrderedLayout l = new OrderedLayout(); - - GridLayout gl = new GridLayout(3, 3); - DateField cal = new DateField("Test component 1", new Date()); - cal.setStyle("calendar"); - gl.addComponent(cal, 1, 0, 2, 1); - for (int i = 2; i < 7; i++) - gl.addComponent(new TextField("Test component " + i)); - l.addComponent(gl); - - // Properties - propertyPanel = new PropertyPanel(gl); - Form ap = propertyPanel.createBeanPropertySet(new String[] { "width", - "height" }); - ap.addField("new line", new Button("New Line", gl, "newLine")); - ap.addField("space", new Button("Space", gl, "space")); - propertyPanel.addProperties("GridLayout Features", ap); - propertyPanel.getField("height").dependsOn( - propertyPanel.getField("add component")); - - setJavadocURL("ui/GridLayout.html"); - - return l; - } - - protected String getExampleSrc() { - return "GridLayout gl = new GridLayout(2,2);\n" - + "gl.addComponent(new Label(\"Label 1 in GridLayout\"));\n" - + "gl.addComponent(new Label(\"Label 2 in GridLayout\"));\n" - + "gl.addComponent(new Label(\"Label 3 in GridLayout\"));\n" - + "gl.addComponent(new Label(\"Label 4 in GridLayout\"));\n"; - } - - /** - * @see com.itmill.toolkit.tests.featurebrowser.Feature#getDescriptionXHTML() - */ - protected String getDescriptionXHTML() { - return "This feature provides a container that lays out components " - + "into a grid of given width and height." - + "

On the demo tab you can try out how the different " - + "properties affect the presentation of the component."; - } - - protected String getImage() { - return "icon_demo.png"; - } - - protected String getTitle() { - return "GridLayout"; - } + public FeatureGridLayout() { + super(); + } + + protected Component getDemoComponent() { + + OrderedLayout l = new OrderedLayout(); + + GridLayout gl = new GridLayout(3, 3); + DateField cal = new DateField("Test component 1", new Date()); + cal.setStyle("calendar"); + gl.addComponent(cal, 1, 0, 2, 1); + for (int i = 2; i < 7; i++) { + gl.addComponent(new TextField("Test component " + i)); + } + l.addComponent(gl); + + // Properties + propertyPanel = new PropertyPanel(gl); + Form ap = propertyPanel.createBeanPropertySet(new String[] { "width", + "height" }); + ap.addField("new line", new Button("New Line", gl, "newLine")); + ap.addField("space", new Button("Space", gl, "space")); + propertyPanel.addProperties("GridLayout Features", ap); + propertyPanel.getField("height").dependsOn( + propertyPanel.getField("add component")); + + setJavadocURL("ui/GridLayout.html"); + + return l; + } + + protected String getExampleSrc() { + return "GridLayout gl = new GridLayout(2,2);\n" + + "gl.addComponent(new Label(\"Label 1 in GridLayout\"));\n" + + "gl.addComponent(new Label(\"Label 2 in GridLayout\"));\n" + + "gl.addComponent(new Label(\"Label 3 in GridLayout\"));\n" + + "gl.addComponent(new Label(\"Label 4 in GridLayout\"));\n"; + } + + /** + * @see com.itmill.toolkit.tests.featurebrowser.Feature#getDescriptionXHTML() + */ + protected String getDescriptionXHTML() { + return "This feature provides a container that lays out components " + + "into a grid of given width and height." + + "

On the demo tab you can try out how the different " + + "properties affect the presentation of the component."; + } + + protected String getImage() { + return "icon_demo.png"; + } + + protected String getTitle() { + return "GridLayout"; + } } \ No newline at end of file diff --git a/src/com/itmill/toolkit/tests/featurebrowser/FeatureItems.java b/src/com/itmill/toolkit/tests/featurebrowser/FeatureItems.java index 45406d5584..a723b201f0 100644 --- a/src/com/itmill/toolkit/tests/featurebrowser/FeatureItems.java +++ b/src/com/itmill/toolkit/tests/featurebrowser/FeatureItems.java @@ -37,70 +37,70 @@ import com.itmill.toolkit.ui.Select; public class FeatureItems extends Feature { - private static final String INTRO_TEXT = "" - + "Item is an object, which contains a set of named " - + "properties. Each property is identified by an " - + "id and a reference to the property can be queried from the Item. " - + "Item defines inner-interfaces for maintaining the item property " - + "set and listening the item property set changes." - + "

Items generally represent objects in the object-oriented " - + "model, but with the exception that they are configurable " - + "and provide an event mechanism. The simplest way of utilizing " - + "Item interface is to use existing Item implementations. " - + "Provided utility classes include configurable property set," - + " bean to item adapter and Form UI component."; - - public FeatureItems() { - super(); - } - - protected Component getDemoComponent() { - - OrderedLayout l = new OrderedLayout(); - - Panel panel = new Panel(); - panel.setCaption("Items"); - l.addComponent(panel); - - Label label = new Label(); - panel.addComponent(label); - - label.setContentMode(Label.CONTENT_XHTML); - label.setValue(INTRO_TEXT); - - // Properties - propertyPanel = new PropertyPanel(panel); - Form ap = propertyPanel.createBeanPropertySet(new String[] { "width", - "height" }); - Select themes = (Select) propertyPanel.getField("style"); - themes.addItem("light").getItemProperty( - themes.getItemCaptionPropertyId()).setValue("light"); - themes.addItem("strong").getItemProperty( - themes.getItemCaptionPropertyId()).setValue("strong"); - propertyPanel.addProperties("Panel Properties", ap); - - setJavadocURL("data/Item.html"); - - return l; - } - - protected String getExampleSrc() { - return null; - } - - /** - * @see com.itmill.toolkit.tests.featurebrowser.Feature#getDescriptionXHTML() - */ - protected String getDescriptionXHTML() { - return null; - } - - protected String getImage() { - return "icon_demo.png"; - } - - protected String getTitle() { - return "Introduction of Data Model Item"; - } + private static final String INTRO_TEXT = "" + + "Item is an object, which contains a set of named " + + "properties. Each property is identified by an " + + "id and a reference to the property can be queried from the Item. " + + "Item defines inner-interfaces for maintaining the item property " + + "set and listening the item property set changes." + + "

Items generally represent objects in the object-oriented " + + "model, but with the exception that they are configurable " + + "and provide an event mechanism. The simplest way of utilizing " + + "Item interface is to use existing Item implementations. " + + "Provided utility classes include configurable property set," + + " bean to item adapter and Form UI component."; + + public FeatureItems() { + super(); + } + + protected Component getDemoComponent() { + + OrderedLayout l = new OrderedLayout(); + + Panel panel = new Panel(); + panel.setCaption("Items"); + l.addComponent(panel); + + Label label = new Label(); + panel.addComponent(label); + + label.setContentMode(Label.CONTENT_XHTML); + label.setValue(INTRO_TEXT); + + // Properties + propertyPanel = new PropertyPanel(panel); + Form ap = propertyPanel.createBeanPropertySet(new String[] { "width", + "height" }); + Select themes = (Select) propertyPanel.getField("style"); + themes.addItem("light").getItemProperty( + themes.getItemCaptionPropertyId()).setValue("light"); + themes.addItem("strong").getItemProperty( + themes.getItemCaptionPropertyId()).setValue("strong"); + propertyPanel.addProperties("Panel Properties", ap); + + setJavadocURL("data/Item.html"); + + return l; + } + + protected String getExampleSrc() { + return null; + } + + /** + * @see com.itmill.toolkit.tests.featurebrowser.Feature#getDescriptionXHTML() + */ + protected String getDescriptionXHTML() { + return null; + } + + protected String getImage() { + return "icon_demo.png"; + } + + protected String getTitle() { + return "Introduction of Data Model Item"; + } } diff --git a/src/com/itmill/toolkit/tests/featurebrowser/FeatureLabel.java b/src/com/itmill/toolkit/tests/featurebrowser/FeatureLabel.java index 7afb65604b..4f1febb783 100644 --- a/src/com/itmill/toolkit/tests/featurebrowser/FeatureLabel.java +++ b/src/com/itmill/toolkit/tests/featurebrowser/FeatureLabel.java @@ -28,68 +28,71 @@ package com.itmill.toolkit.tests.featurebrowser; -import com.itmill.toolkit.ui.*; +import com.itmill.toolkit.ui.Component; +import com.itmill.toolkit.ui.Form; +import com.itmill.toolkit.ui.Label; +import com.itmill.toolkit.ui.OrderedLayout; public class FeatureLabel extends Feature { - public FeatureLabel() { - super(); - } - - protected Component getDemoComponent() { - - OrderedLayout l = new OrderedLayout(); - - Label lab = new Label("Label text"); - l.addComponent(lab); - - // Properties - propertyPanel = new PropertyPanel(lab); - Form ap = propertyPanel.createBeanPropertySet(new String[] { - "contentMode", "value" }); - ap.replaceWithSelect("contentMode", new Object[] { - new Integer(Label.CONTENT_PREFORMATTED), - new Integer(Label.CONTENT_TEXT), - new Integer(Label.CONTENT_UIDL), - new Integer(Label.CONTENT_XHTML), - new Integer(Label.CONTENT_XML) }, - new Object[] { "Preformatted", "Text", "UIDL (Must be valid)", - "XHTML Fragment(Must be valid)", - "XML (Subtree with namespace)" }); - propertyPanel.addProperties("Label Properties", ap); - - setJavadocURL("ui/Label.html"); - - return l; - } - - protected String getExampleSrc() { - return "Label l = new Label(\"Caption\");\n"; - } - - /** - * @see com.itmill.toolkit.tests.featurebrowser.Feature#getDescriptionXHTML() - */ - protected String getDescriptionXHTML() { - return "Labels components are for captions and plain text. " - + "By default, it is a light-weight component for presenting " - + "text content in application, but it can be also used to present " - + "formatted information and even XML." - + "

" - + "Label can also be directly associated with data property to display " - + "information from different data sources automatically. This makes it " - + "trivial to present the current user in the corner of applications main window. " - + "

" - + "On the demo tab you can try out how the different properties affect " - + "the presentation of the component."; - } - - protected String getImage() { - return "icon_demo.png"; - } - - protected String getTitle() { - return "Label"; - } + public FeatureLabel() { + super(); + } + + protected Component getDemoComponent() { + + OrderedLayout l = new OrderedLayout(); + + Label lab = new Label("Label text"); + l.addComponent(lab); + + // Properties + propertyPanel = new PropertyPanel(lab); + Form ap = propertyPanel.createBeanPropertySet(new String[] { + "contentMode", "value" }); + ap.replaceWithSelect("contentMode", new Object[] { + new Integer(Label.CONTENT_PREFORMATTED), + new Integer(Label.CONTENT_TEXT), + new Integer(Label.CONTENT_UIDL), + new Integer(Label.CONTENT_XHTML), + new Integer(Label.CONTENT_XML) }, + new Object[] { "Preformatted", "Text", "UIDL (Must be valid)", + "XHTML Fragment(Must be valid)", + "XML (Subtree with namespace)" }); + propertyPanel.addProperties("Label Properties", ap); + + setJavadocURL("ui/Label.html"); + + return l; + } + + protected String getExampleSrc() { + return "Label l = new Label(\"Caption\");\n"; + } + + /** + * @see com.itmill.toolkit.tests.featurebrowser.Feature#getDescriptionXHTML() + */ + protected String getDescriptionXHTML() { + return "Labels components are for captions and plain text. " + + "By default, it is a light-weight component for presenting " + + "text content in application, but it can be also used to present " + + "formatted information and even XML." + + "

" + + "Label can also be directly associated with data property to display " + + "information from different data sources automatically. This makes it " + + "trivial to present the current user in the corner of applications main window. " + + "

" + + "On the demo tab you can try out how the different properties affect " + + "the presentation of the component."; + } + + protected String getImage() { + return "icon_demo.png"; + } + + protected String getTitle() { + return "Label"; + } } diff --git a/src/com/itmill/toolkit/tests/featurebrowser/FeatureLink.java b/src/com/itmill/toolkit/tests/featurebrowser/FeatureLink.java index 798df0b15e..3eb2434bfc 100644 --- a/src/com/itmill/toolkit/tests/featurebrowser/FeatureLink.java +++ b/src/com/itmill/toolkit/tests/featurebrowser/FeatureLink.java @@ -29,56 +29,59 @@ package com.itmill.toolkit.tests.featurebrowser; import com.itmill.toolkit.terminal.ExternalResource; -import com.itmill.toolkit.ui.*; +import com.itmill.toolkit.ui.Component; +import com.itmill.toolkit.ui.Form; +import com.itmill.toolkit.ui.Link; +import com.itmill.toolkit.ui.OrderedLayout; public class FeatureLink extends Feature { - public FeatureLink() { - super(); - } + public FeatureLink() { + super(); + } - protected Component getDemoComponent() { + protected Component getDemoComponent() { - OrderedLayout l = new OrderedLayout(); + OrderedLayout l = new OrderedLayout(); - Link lnk = new Link("Link caption", new ExternalResource( - "http://www.itmill.com")); - l.addComponent(lnk); + Link lnk = new Link("Link caption", new ExternalResource( + "http://www.itmill.com")); + l.addComponent(lnk); - // Properties - propertyPanel = new PropertyPanel(lnk); - Form ap = propertyPanel.createBeanPropertySet(new String[] { - "targetName", "targetWidth", "targetHeight", "targetBorder" }); - ap.replaceWithSelect("targetBorder", new Object[] { - new Integer(Link.TARGET_BORDER_DEFAULT), - new Integer(Link.TARGET_BORDER_MINIMAL), - new Integer(Link.TARGET_BORDER_NONE) }, new Object[] { - "Default", "Minimal", "None" }); - propertyPanel.addProperties("Link Properties", ap); + // Properties + propertyPanel = new PropertyPanel(lnk); + Form ap = propertyPanel.createBeanPropertySet(new String[] { + "targetName", "targetWidth", "targetHeight", "targetBorder" }); + ap.replaceWithSelect("targetBorder", new Object[] { + new Integer(Link.TARGET_BORDER_DEFAULT), + new Integer(Link.TARGET_BORDER_MINIMAL), + new Integer(Link.TARGET_BORDER_NONE) }, new Object[] { + "Default", "Minimal", "None" }); + propertyPanel.addProperties("Link Properties", ap); - setJavadocURL("ui/Link.html"); + setJavadocURL("ui/Link.html"); - return l; - } + return l; + } - protected String getExampleSrc() { - return "Link link = new Link(\"Link caption\",new ExternalResource(\"http://www.itmill.com\"));\n"; - } + protected String getExampleSrc() { + return "Link link = new Link(\"Link caption\",new ExternalResource(\"http://www.itmill.com\"));\n"; + } - protected String getDescriptionXHTML() { - return "The link feature allows for making refences to both internal and external resources. " - + "The link can open the new resource in a new window, allowing for control of the newly " - + "opened windows attributes, such as size and border. " - + "

" - + " For example you can create an application pop-up or create link to external resources."; + protected String getDescriptionXHTML() { + return "The link feature allows for making refences to both internal and external resources. " + + "The link can open the new resource in a new window, allowing for control of the newly " + + "opened windows attributes, such as size and border. " + + "

" + + " For example you can create an application pop-up or create link to external resources."; - } + } - protected String getImage() { - return "icon_demo.png"; - } + protected String getImage() { + return "icon_demo.png"; + } - protected String getTitle() { - return "Link"; - } + protected String getTitle() { + return "Link"; + } } diff --git a/src/com/itmill/toolkit/tests/featurebrowser/FeatureOrderedLayout.java b/src/com/itmill/toolkit/tests/featurebrowser/FeatureOrderedLayout.java index 5d18cd8870..4792baaed9 100644 --- a/src/com/itmill/toolkit/tests/featurebrowser/FeatureOrderedLayout.java +++ b/src/com/itmill/toolkit/tests/featurebrowser/FeatureOrderedLayout.java @@ -28,68 +28,73 @@ package com.itmill.toolkit.tests.featurebrowser; -import com.itmill.toolkit.ui.*; +import com.itmill.toolkit.ui.Component; +import com.itmill.toolkit.ui.Form; +import com.itmill.toolkit.ui.OrderedLayout; +import com.itmill.toolkit.ui.Select; +import com.itmill.toolkit.ui.TextField; public class FeatureOrderedLayout extends Feature { - public FeatureOrderedLayout() { - super(); - } - - protected Component getDemoComponent() { - - OrderedLayout l = new OrderedLayout(); - - OrderedLayout ol = new OrderedLayout(); - for (int i = 1; i < 5; i++) - ol.addComponent(new TextField("Test component " + i)); - l.addComponent(ol); - - // Properties - propertyPanel = new PropertyPanel(ol); - Form ap = propertyPanel - .createBeanPropertySet(new String[] { "orientation" }); - ap.replaceWithSelect("orientation", new Object[] { - new Integer(OrderedLayout.ORIENTATION_HORIZONTAL), - new Integer(OrderedLayout.ORIENTATION_VERTICAL) }, - new Object[] { "Horizontal", "Vertical" }); - Select themes = (Select) propertyPanel.getField("style"); - themes.addItem("form").getItemProperty( - themes.getItemCaptionPropertyId()).setValue("form"); - propertyPanel.addProperties("OrderedLayout Properties", ap); - - setJavadocURL("ui/OrderedLayout.html"); - - return l; - } - - protected String getExampleSrc() { - return "OrderedLayout ol = new OrderedLayout(OrderedLayout.ORIENTATION_FLOW);\n" - + "ol.addComponent(new TextField(\"Textfield caption\"));\n" - + "ol.addComponent(new Label(\"Label\"));\n"; - - } - - /** - * @see com.itmill.toolkit.tests.featurebrowser.Feature#getDescriptionXHTML() - */ - protected String getDescriptionXHTML() { - return "This feature provides a container for laying out components either " - + "vertically, horizontally or flowingly. The orientation may be changed " - + "during runtime. It also defines a special style for themes to implement called \"form\"" - + "that is used for input forms where the components are laid-out side-by-side " - + "with their captions." - + "

" - + "On the demo tab you can try out how the different properties " - + "affect the presentation of the component."; - } - - protected String getImage() { - return "icon_demo.png"; - } - - protected String getTitle() { - return "OrderedLayout"; - } + public FeatureOrderedLayout() { + super(); + } + + protected Component getDemoComponent() { + + OrderedLayout l = new OrderedLayout(); + + OrderedLayout ol = new OrderedLayout(); + for (int i = 1; i < 5; i++) { + ol.addComponent(new TextField("Test component " + i)); + } + l.addComponent(ol); + + // Properties + propertyPanel = new PropertyPanel(ol); + Form ap = propertyPanel + .createBeanPropertySet(new String[] { "orientation" }); + ap.replaceWithSelect("orientation", new Object[] { + new Integer(OrderedLayout.ORIENTATION_HORIZONTAL), + new Integer(OrderedLayout.ORIENTATION_VERTICAL) }, + new Object[] { "Horizontal", "Vertical" }); + Select themes = (Select) propertyPanel.getField("style"); + themes.addItem("form").getItemProperty( + themes.getItemCaptionPropertyId()).setValue("form"); + propertyPanel.addProperties("OrderedLayout Properties", ap); + + setJavadocURL("ui/OrderedLayout.html"); + + return l; + } + + protected String getExampleSrc() { + return "OrderedLayout ol = new OrderedLayout(OrderedLayout.ORIENTATION_FLOW);\n" + + "ol.addComponent(new TextField(\"Textfield caption\"));\n" + + "ol.addComponent(new Label(\"Label\"));\n"; + + } + + /** + * @see com.itmill.toolkit.tests.featurebrowser.Feature#getDescriptionXHTML() + */ + protected String getDescriptionXHTML() { + return "This feature provides a container for laying out components either " + + "vertically, horizontally or flowingly. The orientation may be changed " + + "during runtime. It also defines a special style for themes to implement called \"form\"" + + "that is used for input forms where the components are laid-out side-by-side " + + "with their captions." + + "

" + + "On the demo tab you can try out how the different properties " + + "affect the presentation of the component."; + } + + protected String getImage() { + return "icon_demo.png"; + } + + protected String getTitle() { + return "OrderedLayout"; + } } diff --git a/src/com/itmill/toolkit/tests/featurebrowser/FeaturePanel.java b/src/com/itmill/toolkit/tests/featurebrowser/FeaturePanel.java index efadad36c4..74cfa90ad1 100644 --- a/src/com/itmill/toolkit/tests/featurebrowser/FeaturePanel.java +++ b/src/com/itmill/toolkit/tests/featurebrowser/FeaturePanel.java @@ -28,60 +28,65 @@ package com.itmill.toolkit.tests.featurebrowser; -import com.itmill.toolkit.ui.*; +import com.itmill.toolkit.ui.Component; +import com.itmill.toolkit.ui.Form; +import com.itmill.toolkit.ui.Label; +import com.itmill.toolkit.ui.OrderedLayout; +import com.itmill.toolkit.ui.Panel; +import com.itmill.toolkit.ui.Select; public class FeaturePanel extends Feature { - public FeaturePanel() { - super(); - } - - protected Component getDemoComponent() { - - OrderedLayout l = new OrderedLayout(); - - // Example panel - Panel show = new Panel("Panel caption"); - show - .addComponent(new Label( - "This is an example Label component that is added into Panel.")); - l.addComponent(show); - - // Properties - propertyPanel = new PropertyPanel(show); - Form ap = propertyPanel.createBeanPropertySet(new String[] { "width", - "height" }); - Select themes = (Select) propertyPanel.getField("style"); - themes.addItem("light").getItemProperty( - themes.getItemCaptionPropertyId()).setValue("light"); - themes.addItem("strong").getItemProperty( - themes.getItemCaptionPropertyId()).setValue("strong"); - propertyPanel.addProperties("Panel Properties", ap); - - setJavadocURL("ui/Panel.html"); - - return l; - } - - protected String getExampleSrc() { - return "Panel show = new Panel(\"Panel caption\");\n" - + "show.addComponent(new Label(\"This is an example Label component that is added into Panel.\"));"; - - } - - protected String getDescriptionXHTML() { - return "Panel is a container for other components, by default it draws a frame around it's " - + "extremities and may have a caption to clarify the nature of the contained components' purpose." - + " Panel contains an layout where the actual contained components are added, " - + "this layout may be switched on the fly."; - } - - protected String getImage() { - return "icon_demo.png"; - } - - protected String getTitle() { - return "Panel"; - } + public FeaturePanel() { + super(); + } + + protected Component getDemoComponent() { + + OrderedLayout l = new OrderedLayout(); + + // Example panel + Panel show = new Panel("Panel caption"); + show + .addComponent(new Label( + "This is an example Label component that is added into Panel.")); + l.addComponent(show); + + // Properties + propertyPanel = new PropertyPanel(show); + Form ap = propertyPanel.createBeanPropertySet(new String[] { "width", + "height" }); + Select themes = (Select) propertyPanel.getField("style"); + themes.addItem("light").getItemProperty( + themes.getItemCaptionPropertyId()).setValue("light"); + themes.addItem("strong").getItemProperty( + themes.getItemCaptionPropertyId()).setValue("strong"); + propertyPanel.addProperties("Panel Properties", ap); + + setJavadocURL("ui/Panel.html"); + + return l; + } + + protected String getExampleSrc() { + return "Panel show = new Panel(\"Panel caption\");\n" + + "show.addComponent(new Label(\"This is an example Label component that is added into Panel.\"));"; + + } + + protected String getDescriptionXHTML() { + return "Panel is a container for other components, by default it draws a frame around it's " + + "extremities and may have a caption to clarify the nature of the contained components' purpose." + + " Panel contains an layout where the actual contained components are added, " + + "this layout may be switched on the fly."; + } + + protected String getImage() { + return "icon_demo.png"; + } + + protected String getTitle() { + return "Panel"; + } } diff --git a/src/com/itmill/toolkit/tests/featurebrowser/FeatureParameters.java b/src/com/itmill/toolkit/tests/featurebrowser/FeatureParameters.java index 18a2a9bef6..30f9194d06 100644 --- a/src/com/itmill/toolkit/tests/featurebrowser/FeatureParameters.java +++ b/src/com/itmill/toolkit/tests/featurebrowser/FeatureParameters.java @@ -36,142 +36,150 @@ import com.itmill.toolkit.terminal.DownloadStream; import com.itmill.toolkit.terminal.ExternalResource; import com.itmill.toolkit.terminal.ParameterHandler; import com.itmill.toolkit.terminal.URIHandler; -import com.itmill.toolkit.ui.*; +import com.itmill.toolkit.ui.Component; +import com.itmill.toolkit.ui.Form; +import com.itmill.toolkit.ui.Label; +import com.itmill.toolkit.ui.Link; +import com.itmill.toolkit.ui.OrderedLayout; +import com.itmill.toolkit.ui.Panel; +import com.itmill.toolkit.ui.Select; +import com.itmill.toolkit.ui.Table; public class FeatureParameters extends Feature implements URIHandler, - ParameterHandler { - - private Label context = new Label(); - - private Label relative = new Label(); - - private Table params = new Table(); - - public FeatureParameters() { - super(); - params.addContainerProperty("Values", String.class, ""); - } - - protected Component getDemoComponent() { - - OrderedLayout l = new OrderedLayout(); - - Label info = new Label("To test this feature, try to " - + "add some get parameters to URL. For example if you have " - + "the feature browser installed in your local host, try url: "); - info.setCaption("Usage info"); - l.addComponent(info); - try { - URL u1 = new URL(getApplication().getURL(), - "test/uri?test=1&test=2"); - URL u2 = new URL(getApplication().getURL(), - "foo/bar?mary=john&count=3"); - - l.addComponent(new Link(u1.toString(), new ExternalResource(u1))); - l.addComponent(new Label("Or this: ")); - l.addComponent(new Link(u2.toString(), new ExternalResource(u2))); - } catch (Exception e) { - System.out.println("Couldn't get hostname for this machine: " - + e.toString()); - e.printStackTrace(); - } - - // URI - Panel p1 = new Panel("URI Handler"); - context.setCaption("Last URI handler context"); - p1.addComponent(context); - relative.setCaption("Last relative URI"); - p1.addComponent(relative); - l.addComponent(p1); - - // Parameters - Panel p2 = new Panel("Parameter Handler"); - params.setCaption("Last parameters"); - params.setColumnHeaderMode(Table.COLUMN_HEADER_MODE_ID); - params.setRowHeaderMode(Table.ROW_HEADER_MODE_ID); - p2.addComponent(params); - l.addComponent(p2); - - // Properties - propertyPanel = new PropertyPanel(p1); - Form ap = propertyPanel.createBeanPropertySet(new String[] { "width", - "height" }); - Select themes = (Select) propertyPanel.getField("style"); - themes.addItem("light").getItemProperty( - themes.getItemCaptionPropertyId()).setValue("light"); - themes.addItem("strong").getItemProperty( - themes.getItemCaptionPropertyId()).setValue("strong"); - propertyPanel.addProperties("Panel Properties", ap); - - setJavadocURL("ui/Panel.html"); - - return l; - } - - protected String getDescriptionXHTML() { - return "This is a demonstration of how URL parameters can be recieved and handled." - + "Parameters and URL:s can be received trough the windows by registering " - + "URIHandler and ParameterHandler classes window."; - } - - protected String getImage() { - return "parameters.jpg"; - } - - protected String getTitle() { - return "Parameters"; - } - - /** - * Add URI and parametes handlers to window. - * - * @see com.itmill.toolkit.ui.Component#attach() - */ - public void attach() { - super.attach(); - getWindow().addURIHandler(this); - getWindow().addParameterHandler(this); - } - - /** - * Remove all handlers from window - * - * @see com.itmill.toolkit.ui.Component#detach() - */ - public void detach() { - super.detach(); - getWindow().removeURIHandler(this); - getWindow().removeParameterHandler(this); - } - - /** - * Update URI - * - * @see com.itmill.toolkit.terminal.URIHandler#handleURI(URL, String) - */ - public DownloadStream handleURI(URL context, String relativeUri) { - this.context.setValue(context.toString()); - this.relative.setValue(relativeUri); - return null; - } - - /** - * Update parameters table - * - * @see com.itmill.toolkit.terminal.ParameterHandler#handleParameters(Map) - */ - public void handleParameters(Map parameters) { - params.removeAllItems(); - for (Iterator i = parameters.keySet().iterator(); i.hasNext();) { - String name = (String) i.next(); - String[] values = (String[]) parameters.get(name); - String v = ""; - for (int j = 0; j < values.length; j++) { - if (v.length() > 0) - v += ", "; - v += "'" + values[j] + "'"; - } - params.addItem(new Object[] { v }, name); - } - } + ParameterHandler { + + private Label context = new Label(); + + private Label relative = new Label(); + + private Table params = new Table(); + + public FeatureParameters() { + super(); + params.addContainerProperty("Values", String.class, ""); + } + + protected Component getDemoComponent() { + + OrderedLayout l = new OrderedLayout(); + + Label info = new Label("To test this feature, try to " + + "add some get parameters to URL. For example if you have " + + "the feature browser installed in your local host, try url: "); + info.setCaption("Usage info"); + l.addComponent(info); + try { + URL u1 = new URL(getApplication().getURL(), + "test/uri?test=1&test=2"); + URL u2 = new URL(getApplication().getURL(), + "foo/bar?mary=john&count=3"); + + l.addComponent(new Link(u1.toString(), new ExternalResource(u1))); + l.addComponent(new Label("Or this: ")); + l.addComponent(new Link(u2.toString(), new ExternalResource(u2))); + } catch (Exception e) { + System.out.println("Couldn't get hostname for this machine: " + + e.toString()); + e.printStackTrace(); + } + + // URI + Panel p1 = new Panel("URI Handler"); + context.setCaption("Last URI handler context"); + p1.addComponent(context); + relative.setCaption("Last relative URI"); + p1.addComponent(relative); + l.addComponent(p1); + + // Parameters + Panel p2 = new Panel("Parameter Handler"); + params.setCaption("Last parameters"); + params.setColumnHeaderMode(Table.COLUMN_HEADER_MODE_ID); + params.setRowHeaderMode(Table.ROW_HEADER_MODE_ID); + p2.addComponent(params); + l.addComponent(p2); + + // Properties + propertyPanel = new PropertyPanel(p1); + Form ap = propertyPanel.createBeanPropertySet(new String[] { "width", + "height" }); + Select themes = (Select) propertyPanel.getField("style"); + themes.addItem("light").getItemProperty( + themes.getItemCaptionPropertyId()).setValue("light"); + themes.addItem("strong").getItemProperty( + themes.getItemCaptionPropertyId()).setValue("strong"); + propertyPanel.addProperties("Panel Properties", ap); + + setJavadocURL("ui/Panel.html"); + + return l; + } + + protected String getDescriptionXHTML() { + return "This is a demonstration of how URL parameters can be recieved and handled." + + "Parameters and URL:s can be received trough the windows by registering " + + "URIHandler and ParameterHandler classes window."; + } + + protected String getImage() { + return "parameters.jpg"; + } + + protected String getTitle() { + return "Parameters"; + } + + /** + * Add URI and parametes handlers to window. + * + * @see com.itmill.toolkit.ui.Component#attach() + */ + public void attach() { + super.attach(); + getWindow().addURIHandler(this); + getWindow().addParameterHandler(this); + } + + /** + * Remove all handlers from window + * + * @see com.itmill.toolkit.ui.Component#detach() + */ + public void detach() { + super.detach(); + getWindow().removeURIHandler(this); + getWindow().removeParameterHandler(this); + } + + /** + * Update URI + * + * @see com.itmill.toolkit.terminal.URIHandler#handleURI(URL, String) + */ + public DownloadStream handleURI(URL context, String relativeUri) { + this.context.setValue(context.toString()); + relative.setValue(relativeUri); + return null; + } + + /** + * Update parameters table + * + * @see com.itmill.toolkit.terminal.ParameterHandler#handleParameters(Map) + */ + public void handleParameters(Map parameters) { + params.removeAllItems(); + for (Iterator i = parameters.keySet().iterator(); i.hasNext();) { + String name = (String) i.next(); + String[] values = (String[]) parameters.get(name); + String v = ""; + for (int j = 0; j < values.length; j++) { + if (v.length() > 0) { + v += ", "; + } + v += "'" + values[j] + "'"; + } + params.addItem(new Object[] { v }, name); + } + } } diff --git a/src/com/itmill/toolkit/tests/featurebrowser/FeatureProperties.java b/src/com/itmill/toolkit/tests/featurebrowser/FeatureProperties.java index b3c8a55c67..8e2db9ed7d 100644 --- a/src/com/itmill/toolkit/tests/featurebrowser/FeatureProperties.java +++ b/src/com/itmill/toolkit/tests/featurebrowser/FeatureProperties.java @@ -37,75 +37,75 @@ import com.itmill.toolkit.ui.Select; public class FeatureProperties extends Feature { - private static final String INTRO_TEXT = "" - + "IT Mill Toolkit data model is one of the core concepts " - + "in the library and Property-interface is the base of that " - + "model. Property provides standardized API for a single data object " - + "that can be read (get) and written (set). A property is always typed, but can optionally " - + "support data type conversions. Optionally properties can provide " - + "value change events for following the state changes." - + "

The most important function of the Property as well as other " - + "data models is to connect classes implementing the interface directly to " - + "editor and viewer classes. Typically this is used to connect different " - + "data sources to UI components for editing and viewing their contents." - + "

Properties can be utilized either by implementing the interface " - + "or by using some of the existing property implementations. IT Mill Toolkit " - + "includes Property interface implementations for " - + "arbitrary function pairs or Bean-properties as well as simple object " - + "properties." - + "

Many of the UI components also implement Property interface and allow " - + "setting of other components as their data-source. These UI-components " - + "include TextField, DateField, Select, Table, Button, " - + "Label and Tree."; - - public FeatureProperties() { - super(); - } - - protected Component getDemoComponent() { - - OrderedLayout l = new OrderedLayout(); - - Panel panel = new Panel(); - panel.setCaption("Data Model"); - l.addComponent(panel); - - Label label = new Label(); - panel.addComponent(label); - - label.setContentMode(Label.CONTENT_XHTML); - label.setValue(INTRO_TEXT); - - // Properties - propertyPanel = new PropertyPanel(panel); - Form ap = propertyPanel.createBeanPropertySet(new String[] { "width", - "height" }); - Select themes = (Select) propertyPanel.getField("style"); - themes.addItem("light").getItemProperty( - themes.getItemCaptionPropertyId()).setValue("light"); - themes.addItem("strong").getItemProperty( - themes.getItemCaptionPropertyId()).setValue("strong"); - propertyPanel.addProperties("Panel Properties", ap); - - setJavadocURL("data/Property.html"); - - return l; - } - - protected String getExampleSrc() { - return null; - } - - protected String getDescriptionXHTML() { - return null; - } - - protected String getImage() { - return null; - } - - protected String getTitle() { - return null; - } + private static final String INTRO_TEXT = "" + + "IT Mill Toolkit data model is one of the core concepts " + + "in the library and Property-interface is the base of that " + + "model. Property provides standardized API for a single data object " + + "that can be read (get) and written (set). A property is always typed, but can optionally " + + "support data type conversions. Optionally properties can provide " + + "value change events for following the state changes." + + "

The most important function of the Property as well as other " + + "data models is to connect classes implementing the interface directly to " + + "editor and viewer classes. Typically this is used to connect different " + + "data sources to UI components for editing and viewing their contents." + + "

Properties can be utilized either by implementing the interface " + + "or by using some of the existing property implementations. IT Mill Toolkit " + + "includes Property interface implementations for " + + "arbitrary function pairs or Bean-properties as well as simple object " + + "properties." + + "

Many of the UI components also implement Property interface and allow " + + "setting of other components as their data-source. These UI-components " + + "include TextField, DateField, Select, Table, Button, " + + "Label and Tree."; + + public FeatureProperties() { + super(); + } + + protected Component getDemoComponent() { + + OrderedLayout l = new OrderedLayout(); + + Panel panel = new Panel(); + panel.setCaption("Data Model"); + l.addComponent(panel); + + Label label = new Label(); + panel.addComponent(label); + + label.setContentMode(Label.CONTENT_XHTML); + label.setValue(INTRO_TEXT); + + // Properties + propertyPanel = new PropertyPanel(panel); + Form ap = propertyPanel.createBeanPropertySet(new String[] { "width", + "height" }); + Select themes = (Select) propertyPanel.getField("style"); + themes.addItem("light").getItemProperty( + themes.getItemCaptionPropertyId()).setValue("light"); + themes.addItem("strong").getItemProperty( + themes.getItemCaptionPropertyId()).setValue("strong"); + propertyPanel.addProperties("Panel Properties", ap); + + setJavadocURL("data/Property.html"); + + return l; + } + + protected String getExampleSrc() { + return null; + } + + protected String getDescriptionXHTML() { + return null; + } + + protected String getImage() { + return null; + } + + protected String getTitle() { + return null; + } } diff --git a/src/com/itmill/toolkit/tests/featurebrowser/FeatureSelect.java b/src/com/itmill/toolkit/tests/featurebrowser/FeatureSelect.java index 0e8fd5400d..9d292093e4 100644 --- a/src/com/itmill/toolkit/tests/featurebrowser/FeatureSelect.java +++ b/src/com/itmill/toolkit/tests/featurebrowser/FeatureSelect.java @@ -28,79 +28,82 @@ package com.itmill.toolkit.tests.featurebrowser; -import com.itmill.toolkit.ui.*; +import com.itmill.toolkit.ui.Component; +import com.itmill.toolkit.ui.OrderedLayout; +import com.itmill.toolkit.ui.Select; public class FeatureSelect extends Feature { - private static final String[] firstnames = new String[] { "John", "Mary", - "Joe", "Sarah", "Jeff", "Jane", "Peter", "Marc", "Robert", "Paula", - "Lenny", "Kenny", "Nathan", "Nicole", "Laura", "Jos", "Josie", - "Linus" }; - - private static final String[] lastnames = new String[] { "Torvalds", - "Smith", "Adams", "Black", "Wilson", "Richards", "Thompson", - "McGoff", "Halas", "Jones", "Beck", "Sheridan", "Picard", "Hill", - "Fielding", "Einstein" }; - - public FeatureSelect() { - super(); - } - - protected Component getDemoComponent() { - - OrderedLayout l = new OrderedLayout(); - - Select s = new Select("Select employee"); - for (int i = 0; i < 50; i++) - s - .addItem(firstnames[(int) (Math.random() * (firstnames.length - 1))] - + " " - + lastnames[(int) (Math.random() * (lastnames.length - 1))]); - l.addComponent(s); - - // Properties - propertyPanel = new PropertyPanel(s); - Select themes = (Select) propertyPanel.getField("style"); - themes.addItem("optiongroup").getItemProperty( - themes.getItemCaptionPropertyId()).setValue("optiongroup"); - themes.addItem("twincol").getItemProperty( - themes.getItemCaptionPropertyId()).setValue("twincol"); - - setJavadocURL("ui/Select.html"); - - return l; - } - - protected String getExampleSrc() { - return "Select s = new Select(\"Select Car\");\n" - + "s.addItem(\"Audi\");\n" + "s.addItem(\"BMW\");\n" - + "s.addItem(\"Chrysler\");\n" + "s.addItem(\"Volvo\");\n"; - - } - - /** - * @see com.itmill.toolkit.tests.featurebrowser.Feature#getDescriptionXHTML() - */ - protected String getDescriptionXHTML() { - return "The select component combines two different modes of item selection. " - + "Firstly it presents the single selection mode, which is usually represented as " - + "either a drop-down menu or a radio-group of switches, secondly it " - + "allows for multiple item selection, this is usually represented as either a " - + "listbox of selectable items or as a group of checkboxes." - + "

" - + "Data source can be associated both with selected item and the list of selections. " - + "This way you can easily present a selection based on items specified elsewhere in application. " - + "

" - + "On the demo tab you can try out how the different properties affect the" - + " presentation of the component."; - } - - protected String getImage() { - return "icon_demo.png"; - } - - protected String getTitle() { - return "Select"; - } + private static final String[] firstnames = new String[] { "John", "Mary", + "Joe", "Sarah", "Jeff", "Jane", "Peter", "Marc", "Robert", "Paula", + "Lenny", "Kenny", "Nathan", "Nicole", "Laura", "Jos", "Josie", + "Linus" }; + + private static final String[] lastnames = new String[] { "Torvalds", + "Smith", "Adams", "Black", "Wilson", "Richards", "Thompson", + "McGoff", "Halas", "Jones", "Beck", "Sheridan", "Picard", "Hill", + "Fielding", "Einstein" }; + + public FeatureSelect() { + super(); + } + + protected Component getDemoComponent() { + + OrderedLayout l = new OrderedLayout(); + + Select s = new Select("Select employee"); + for (int i = 0; i < 50; i++) { + s + .addItem(firstnames[(int) (Math.random() * (firstnames.length - 1))] + + " " + + lastnames[(int) (Math.random() * (lastnames.length - 1))]); + } + l.addComponent(s); + + // Properties + propertyPanel = new PropertyPanel(s); + Select themes = (Select) propertyPanel.getField("style"); + themes.addItem("optiongroup").getItemProperty( + themes.getItemCaptionPropertyId()).setValue("optiongroup"); + themes.addItem("twincol").getItemProperty( + themes.getItemCaptionPropertyId()).setValue("twincol"); + + setJavadocURL("ui/Select.html"); + + return l; + } + + protected String getExampleSrc() { + return "Select s = new Select(\"Select Car\");\n" + + "s.addItem(\"Audi\");\n" + "s.addItem(\"BMW\");\n" + + "s.addItem(\"Chrysler\");\n" + "s.addItem(\"Volvo\");\n"; + + } + + /** + * @see com.itmill.toolkit.tests.featurebrowser.Feature#getDescriptionXHTML() + */ + protected String getDescriptionXHTML() { + return "The select component combines two different modes of item selection. " + + "Firstly it presents the single selection mode, which is usually represented as " + + "either a drop-down menu or a radio-group of switches, secondly it " + + "allows for multiple item selection, this is usually represented as either a " + + "listbox of selectable items or as a group of checkboxes." + + "

" + + "Data source can be associated both with selected item and the list of selections. " + + "This way you can easily present a selection based on items specified elsewhere in application. " + + "

" + + "On the demo tab you can try out how the different properties affect the" + + " presentation of the component."; + } + + protected String getImage() { + return "icon_demo.png"; + } + + protected String getTitle() { + return "Select"; + } } diff --git a/src/com/itmill/toolkit/tests/featurebrowser/FeatureTabSheet.java b/src/com/itmill/toolkit/tests/featurebrowser/FeatureTabSheet.java index 2059f37845..53fc4c5def 100644 --- a/src/com/itmill/toolkit/tests/featurebrowser/FeatureTabSheet.java +++ b/src/com/itmill/toolkit/tests/featurebrowser/FeatureTabSheet.java @@ -28,64 +28,67 @@ package com.itmill.toolkit.tests.featurebrowser; -import com.itmill.toolkit.ui.*; +import com.itmill.toolkit.ui.Component; +import com.itmill.toolkit.ui.Label; +import com.itmill.toolkit.ui.OrderedLayout; +import com.itmill.toolkit.ui.TabSheet; public class FeatureTabSheet extends Feature { - public FeatureTabSheet() { - super(); - } - - protected Component getDemoComponent() { - - OrderedLayout l = new OrderedLayout(); - - TabSheet ts = new TabSheet(); - ts - .addTab( - new Label( - "This is an example Label component that is added into Tab 1."), - "Tab 1 caption", null); - ts - .addTab( - new Label( - "This is an example Label component that is added into Tab 2."), - "Tab 2 caption", null); - ts - .addTab( - new Label( - "This is an example Label component that is added into Tab 3."), - "Tab 3 caption", null); - l.addComponent(ts); - - // Properties - propertyPanel = new PropertyPanel(ts); - - setJavadocURL("ui/TabSheet.html"); - - return l; - } - - protected String getExampleSrc() { - return "TabSheet ts = new TabSheet();\n" - + "ts.addTab(new Label(\"This is an example Label component that is added into Tab 1.\"),\"Tab 1 caption\",null);\n" - + "ts.addTab(new Label(\"This is an example Label component that is added into Tab 2.\"),\"Tab 2 caption\",null);\n" - + "ts.addTab(new Label(\"This is an example Label component that is added into Tab 3.\"),\"Tab 3 caption\",null);"; - } - - protected String getDescriptionXHTML() { - return "A multicomponent container with tabs for switching between them.
" - + "In the normal case, one would place a layout component on each tab.

" - + "On the demo tab you can try out how the different properties affect " - + "the presentation of the component."; - } - - protected String getImage() { - return "icon_demo.png"; - } - - protected String getTitle() { - return "TabSheet"; - } + public FeatureTabSheet() { + super(); + } + + protected Component getDemoComponent() { + + OrderedLayout l = new OrderedLayout(); + + TabSheet ts = new TabSheet(); + ts + .addTab( + new Label( + "This is an example Label component that is added into Tab 1."), + "Tab 1 caption", null); + ts + .addTab( + new Label( + "This is an example Label component that is added into Tab 2."), + "Tab 2 caption", null); + ts + .addTab( + new Label( + "This is an example Label component that is added into Tab 3."), + "Tab 3 caption", null); + l.addComponent(ts); + + // Properties + propertyPanel = new PropertyPanel(ts); + + setJavadocURL("ui/TabSheet.html"); + + return l; + } + + protected String getExampleSrc() { + return "TabSheet ts = new TabSheet();\n" + + "ts.addTab(new Label(\"This is an example Label component that is added into Tab 1.\"),\"Tab 1 caption\",null);\n" + + "ts.addTab(new Label(\"This is an example Label component that is added into Tab 2.\"),\"Tab 2 caption\",null);\n" + + "ts.addTab(new Label(\"This is an example Label component that is added into Tab 3.\"),\"Tab 3 caption\",null);"; + } + + protected String getDescriptionXHTML() { + return "A multicomponent container with tabs for switching between them.
" + + "In the normal case, one would place a layout component on each tab.

" + + "On the demo tab you can try out how the different properties affect " + + "the presentation of the component."; + } + + protected String getImage() { + return "icon_demo.png"; + } + + protected String getTitle() { + return "TabSheet"; + } } diff --git a/src/com/itmill/toolkit/tests/featurebrowser/FeatureTable.java b/src/com/itmill/toolkit/tests/featurebrowser/FeatureTable.java index c042614a79..37c9c18059 100644 --- a/src/com/itmill/toolkit/tests/featurebrowser/FeatureTable.java +++ b/src/com/itmill/toolkit/tests/featurebrowser/FeatureTable.java @@ -38,181 +38,182 @@ import com.itmill.toolkit.ui.Table; public class FeatureTable extends Feature implements Action.Handler { - private static final String[] firstnames = new String[] { "John", "Mary", - "Joe", "Sarah", "Jeff", "Jane", "Peter", "Marc", "Josie", "Linus" }; - - private static final String[] lastnames = new String[] { "Torvalds", - "Smith", "Jones", "Beck", "Sheridan", "Picard", "Hill", "Fielding", - "Einstein" }; - - private static final String[] title = new String[] { "Project Manager", - "Marketing Manager", "Sales Manager", "Trainer", "IT Support", - "Account Manager", "Customer Support", "Testing Engineer", - "Software Designer", "Programmer", "Consultant" }; - - private static final String[] unit = new String[] { "Tokyo", "Mexico City", - "Seoul", "New York", "Sao Paulo", "Bombay", "Delhi", "Shanghai", - "Los Angeles", "London", "Bangalore", "Hong Kong", "Madrid", - "Milano", "Beijing", "Paris", "Moscow", "Helsinki" }; - - private Table t; - - private boolean actionsActive = false; - - private Button actionHandlerSwitch = new Button("Activate actions", this, - "toggleActions"); - - public void toggleActions() { - if (actionsActive) { - t.removeActionHandler(this); - actionsActive = false; - actionHandlerSwitch.setCaption("Activate Actions"); - } else { - t.addActionHandler(this); - actionsActive = true; - actionHandlerSwitch.setCaption("Deactivate Actions"); - } - } - - protected Component getDemoComponent() { - - OrderedLayout l = new OrderedLayout(); - - // Sample table - t = new Table("Corporate Employees"); - t.setPageLength(10); - l.addComponent(t); - - // Add columns to table - t.addContainerProperty("Firstname", String.class, ""); - t.addContainerProperty("Lastname", String.class, ""); - t.addContainerProperty("Title", String.class, ""); - t.addContainerProperty("Unit", String.class, ""); - - // set alignments to demonstrate features - t.setColumnAlignment("Title", Table.ALIGN_CENTER); - t.setColumnAlignment("Unit", Table.ALIGN_RIGHT); - - // Add random rows to table - for (int j = 0; j < 300; j++) { - t - .addItem( - new Object[] { - firstnames[(int) (Math.random() * (firstnames.length - 1))], - lastnames[(int) (Math.random() * (lastnames.length - 1))], - title[(int) (Math.random() * title.length)], - unit[(int) (Math.random() * unit.length)] }, - new Integer(j)); - } - - // Actions - l.addComponent(this.actionHandlerSwitch); - - // Properties - propertyPanel = new PropertyPanel(t); - Form ap = propertyPanel.createBeanPropertySet(new String[] { - "pageLength", "rowHeaderMode", "selectable", - "columnHeaderMode", "columnCollapsingAllowed", - "columnReorderingAllowed", "width", "height" }); - ap.replaceWithSelect("columnHeaderMode", new Object[] { - new Integer(Table.COLUMN_HEADER_MODE_EXPLICIT), - new Integer(Table.COLUMN_HEADER_MODE_EXPLICIT_DEFAULTS_ID), - new Integer(Table.COLUMN_HEADER_MODE_HIDDEN), - new Integer(Table.COLUMN_HEADER_MODE_ID) }, new Object[] { - "Explicit", "Explicit defaults ID", "Hidden", "ID" }); - ap.replaceWithSelect("rowHeaderMode", new Object[] { - new Integer(Table.ROW_HEADER_MODE_EXPLICIT), - new Integer(Table.ROW_HEADER_MODE_EXPLICIT_DEFAULTS_ID), - new Integer(Table.ROW_HEADER_MODE_HIDDEN), - new Integer(Table.ROW_HEADER_MODE_ICON_ONLY), - new Integer(Table.ROW_HEADER_MODE_ID), - new Integer(Table.ROW_HEADER_MODE_INDEX), - new Integer(Table.ROW_HEADER_MODE_ITEM), - new Integer(Table.ROW_HEADER_MODE_PROPERTY) }, new Object[] { - "Explicit", "Explicit defaults ID", "Hidden", "Icon only", - "ID", "Index", "Item", "Property" }); - - Select themes = (Select) propertyPanel.getField("style"); - themes.addItem("list").getItemProperty( - themes.getItemCaptionPropertyId()).setValue("list"); - themes.addItem("paging").getItemProperty( - themes.getItemCaptionPropertyId()).setValue("paging"); - - propertyPanel.addProperties("Table Properties", ap); - - // Set first name as item caption propertyId in cas somebody selecs it - t.setItemCaptionPropertyId("Firstname"); - - // this overrides previous - t.setRowHeaderMode(Table.ROW_HEADER_MODE_INDEX); - t.setColumnHeaderMode(Table.COLUMN_HEADER_MODE_EXPLICIT_DEFAULTS_ID); - - t.setColumnCollapsingAllowed(true); - t.setColumnReorderingAllowed(true); - t.setSelectable(true); - - setJavadocURL("ui/Table.html"); - - return l; - } - - protected String getExampleSrc() { - return "// Sample table\n" - + "t = new Table(\"Corporate Employees\");\n" - + "t.setPageLength(10);\n\n" - + "// Add columns to table\n" - + "t.addContainerProperty(\"Firstname\", String.class, \"\");\n" - + "t.addContainerProperty(\"Lastname\", String.class, \"\");\n" - + "t.addContainerProperty(\"Age\", String.class, \"\");\n" - + "t.addContainerProperty(\"Title\", String.class, \"\");\n" - + "t.addContainerProperty(\"Unit\", String.class, \"\");\n\n" - + "// Add random rows to table\n" - + "for (int j = 0; j < 50; j++) {\n" + " t.addItem(\n" - + " new Object[] {\n" - + " firstnames[(int) (Math.random() * 9)],\n" - + " lastnames[(int) (Math.random() * 9)],\n" - + " title[(int) (Math.random() * title.length)],\n" - + " unit[(int) (Math.random() * unit.length)] },\n" - + " new Integer(j));\n" + "}\n"; - } - - protected String getDescriptionXHTML() { - - return "The Table component is designed for displaying large volumes of tabular data, " - + "in multiple pages whenever needed." - + "

Selection of the displayed data is supported both in selecting exclusively one row " - + "or multiple rows at the same time. For each row, there may be a set of actions associated, " - + "depending on the theme these actions may be displayed either as a drop-down " - + "menu for each row or a set of command buttons." - + "

Table may be connected to any datasource implementing the Container interface." - + "This way data found in external datasources can be directly presented in the table component." - + "

" - + "Table implements a number of features and you can test most of them in the table demo tab."; - } - - protected String getImage() { - return "icon_demo.png"; - } - - protected String getTitle() { - return "Table"; - } - - private Action ACTION1 = new Action("Action 1"); - - private Action ACTION2 = new Action("Action 2"); - - private Action ACTION3 = new Action("Action 3"); - - private Action[] actions = new Action[] { ACTION1, ACTION2, ACTION3 }; - - public Action[] getActions(Object target, Object sender) { - return actions; - } - - public void handleAction(Action action, Object sender, Object target) { - t.setDescription("Last action clicked was '" + action.getCaption() - + "' on item '" + t.getItem(target).toString() + "'"); - } + private static final String[] firstnames = new String[] { "John", "Mary", + "Joe", "Sarah", "Jeff", "Jane", "Peter", "Marc", "Josie", "Linus" }; + + private static final String[] lastnames = new String[] { "Torvalds", + "Smith", "Jones", "Beck", "Sheridan", "Picard", "Hill", "Fielding", + "Einstein" }; + + private static final String[] title = new String[] { "Project Manager", + "Marketing Manager", "Sales Manager", "Trainer", "IT Support", + "Account Manager", "Customer Support", "Testing Engineer", + "Software Designer", "Programmer", "Consultant" }; + + private static final String[] unit = new String[] { "Tokyo", "Mexico City", + "Seoul", "New York", "Sao Paulo", "Bombay", "Delhi", "Shanghai", + "Los Angeles", "London", "Bangalore", "Hong Kong", "Madrid", + "Milano", "Beijing", "Paris", "Moscow", "Helsinki" }; + + private Table t; + + private boolean actionsActive = false; + + private Button actionHandlerSwitch = new Button("Activate actions", this, + "toggleActions"); + + public void toggleActions() { + if (actionsActive) { + t.removeActionHandler(this); + actionsActive = false; + actionHandlerSwitch.setCaption("Activate Actions"); + } else { + t.addActionHandler(this); + actionsActive = true; + actionHandlerSwitch.setCaption("Deactivate Actions"); + } + } + + protected Component getDemoComponent() { + + OrderedLayout l = new OrderedLayout(); + + // Sample table + t = new Table("Corporate Employees"); + t.setPageLength(10); + l.addComponent(t); + + // Add columns to table + t.addContainerProperty("Firstname", String.class, ""); + t.addContainerProperty("Lastname", String.class, ""); + t.addContainerProperty("Title", String.class, ""); + t.addContainerProperty("Unit", String.class, ""); + + // set alignments to demonstrate features + t.setColumnAlignment("Title", Table.ALIGN_CENTER); + t.setColumnAlignment("Unit", Table.ALIGN_RIGHT); + + // Add random rows to table + for (int j = 0; j < 300; j++) { + t + .addItem( + new Object[] { + firstnames[(int) (Math.random() * (firstnames.length - 1))], + lastnames[(int) (Math.random() * (lastnames.length - 1))], + title[(int) (Math.random() * title.length)], + unit[(int) (Math.random() * unit.length)] }, + new Integer(j)); + } + + // Actions + l.addComponent(actionHandlerSwitch); + + // Properties + propertyPanel = new PropertyPanel(t); + Form ap = propertyPanel.createBeanPropertySet(new String[] { + "pageLength", "rowHeaderMode", "selectable", + "columnHeaderMode", "columnCollapsingAllowed", + "columnReorderingAllowed", "width", "height" }); + ap.replaceWithSelect("columnHeaderMode", new Object[] { + new Integer(Table.COLUMN_HEADER_MODE_EXPLICIT), + new Integer(Table.COLUMN_HEADER_MODE_EXPLICIT_DEFAULTS_ID), + new Integer(Table.COLUMN_HEADER_MODE_HIDDEN), + new Integer(Table.COLUMN_HEADER_MODE_ID) }, new Object[] { + "Explicit", "Explicit defaults ID", "Hidden", "ID" }); + ap.replaceWithSelect("rowHeaderMode", new Object[] { + new Integer(Table.ROW_HEADER_MODE_EXPLICIT), + new Integer(Table.ROW_HEADER_MODE_EXPLICIT_DEFAULTS_ID), + new Integer(Table.ROW_HEADER_MODE_HIDDEN), + new Integer(Table.ROW_HEADER_MODE_ICON_ONLY), + new Integer(Table.ROW_HEADER_MODE_ID), + new Integer(Table.ROW_HEADER_MODE_INDEX), + new Integer(Table.ROW_HEADER_MODE_ITEM), + new Integer(Table.ROW_HEADER_MODE_PROPERTY) }, new Object[] { + "Explicit", "Explicit defaults ID", "Hidden", "Icon only", + "ID", "Index", "Item", "Property" }); + + Select themes = (Select) propertyPanel.getField("style"); + themes.addItem("list").getItemProperty( + themes.getItemCaptionPropertyId()).setValue("list"); + themes.addItem("paging").getItemProperty( + themes.getItemCaptionPropertyId()).setValue("paging"); + + propertyPanel.addProperties("Table Properties", ap); + + // Set first name as item caption propertyId in cas somebody + // selecs it + t.setItemCaptionPropertyId("Firstname"); + + // this overrides previous + t.setRowHeaderMode(Table.ROW_HEADER_MODE_INDEX); + t.setColumnHeaderMode(Table.COLUMN_HEADER_MODE_EXPLICIT_DEFAULTS_ID); + + t.setColumnCollapsingAllowed(true); + t.setColumnReorderingAllowed(true); + t.setSelectable(true); + + setJavadocURL("ui/Table.html"); + + return l; + } + + protected String getExampleSrc() { + return "// Sample table\n" + + "t = new Table(\"Corporate Employees\");\n" + + "t.setPageLength(10);\n\n" + + "// Add columns to table\n" + + "t.addContainerProperty(\"Firstname\", String.class, \"\");\n" + + "t.addContainerProperty(\"Lastname\", String.class, \"\");\n" + + "t.addContainerProperty(\"Age\", String.class, \"\");\n" + + "t.addContainerProperty(\"Title\", String.class, \"\");\n" + + "t.addContainerProperty(\"Unit\", String.class, \"\");\n\n" + + "// Add random rows to table\n" + + "for (int j = 0; j < 50; j++) {\n" + " t.addItem(\n" + + " new Object[] {\n" + + " firstnames[(int) (Math.random() * 9)],\n" + + " lastnames[(int) (Math.random() * 9)],\n" + + " title[(int) (Math.random() * title.length)],\n" + + " unit[(int) (Math.random() * unit.length)] },\n" + + " new Integer(j));\n" + "}\n"; + } + + protected String getDescriptionXHTML() { + + return "The Table component is designed for displaying large volumes of tabular data, " + + "in multiple pages whenever needed." + + "

Selection of the displayed data is supported both in selecting exclusively one row " + + "or multiple rows at the same time. For each row, there may be a set of actions associated, " + + "depending on the theme these actions may be displayed either as a drop-down " + + "menu for each row or a set of command buttons." + + "

Table may be connected to any datasource implementing the Container interface." + + "This way data found in external datasources can be directly presented in the table component." + + "

" + + "Table implements a number of features and you can test most of them in the table demo tab."; + } + + protected String getImage() { + return "icon_demo.png"; + } + + protected String getTitle() { + return "Table"; + } + + private Action ACTION1 = new Action("Action 1"); + + private Action ACTION2 = new Action("Action 2"); + + private Action ACTION3 = new Action("Action 3"); + + private Action[] actions = new Action[] { ACTION1, ACTION2, ACTION3 }; + + public Action[] getActions(Object target, Object sender) { + return actions; + } + + public void handleAction(Action action, Object sender, Object target) { + t.setDescription("Last action clicked was '" + action.getCaption() + + "' on item '" + t.getItem(target).toString() + "'"); + } } diff --git a/src/com/itmill/toolkit/tests/featurebrowser/FeatureTextField.java b/src/com/itmill/toolkit/tests/featurebrowser/FeatureTextField.java index cc6ac13794..8bdcdd34f0 100644 --- a/src/com/itmill/toolkit/tests/featurebrowser/FeatureTextField.java +++ b/src/com/itmill/toolkit/tests/featurebrowser/FeatureTextField.java @@ -28,62 +28,65 @@ package com.itmill.toolkit.tests.featurebrowser; -import com.itmill.toolkit.ui.*; +import com.itmill.toolkit.ui.Component; +import com.itmill.toolkit.ui.Form; +import com.itmill.toolkit.ui.OrderedLayout; +import com.itmill.toolkit.ui.TextField; public class FeatureTextField extends Feature { - public FeatureTextField() { - super(); - } - - protected Component getDemoComponent() { - - OrderedLayout l = new OrderedLayout( - OrderedLayout.ORIENTATION_HORIZONTAL); - - // Test component - TextField tf = new TextField("Caption"); - l.addComponent(tf); - - // Properties - propertyPanel = new PropertyPanel(tf); - Form f = propertyPanel.createBeanPropertySet(new String[] { "columns", - "rows", "wordwrap", "writeThrough", "readThrough", - "nullRepresentation", "nullSettingAllowed", "secret" }); - propertyPanel.addProperties("Text field properties", f); - - setJavadocURL("ui/TextField.html"); - - return l; - } - - protected String getExampleSrc() { - return "TextField tf = new TextField(\"Caption\");\n" - + "tf.setValue(\"Contents\");"; - } - - /** - * @see com.itmill.toolkit.tests.featurebrowser.Feature#getDescriptionXHTML() - */ - protected String getDescriptionXHTML() { - return "TextField combines the logic of both the single line text-entry field and the multi-line " - + "text-area into one component. " - + "As with all Data-components of IT Mill Toolkit, the TextField can also be bound to an " - + "underlying data source, both directly or in a buffered (asynchronous) " - + "mode. In buffered mode its background color will change to indicate " - + "that the value has changed but is not committed." - + "

Furthermore a validators may be bound to the component to " - + "check and validate the given input before it is actually committed." - + "

On the demo tab you can try out how the different properties affect the " - + "presentation of the component."; - } - - protected String getImage() { - return "icon_demo.png"; - } - - protected String getTitle() { - return "TextField"; - } + public FeatureTextField() { + super(); + } + + protected Component getDemoComponent() { + + OrderedLayout l = new OrderedLayout( + OrderedLayout.ORIENTATION_HORIZONTAL); + + // Test component + TextField tf = new TextField("Caption"); + l.addComponent(tf); + + // Properties + propertyPanel = new PropertyPanel(tf); + Form f = propertyPanel.createBeanPropertySet(new String[] { "columns", + "rows", "wordwrap", "writeThrough", "readThrough", + "nullRepresentation", "nullSettingAllowed", "secret" }); + propertyPanel.addProperties("Text field properties", f); + + setJavadocURL("ui/TextField.html"); + + return l; + } + + protected String getExampleSrc() { + return "TextField tf = new TextField(\"Caption\");\n" + + "tf.setValue(\"Contents\");"; + } + + /** + * @see com.itmill.toolkit.tests.featurebrowser.Feature#getDescriptionXHTML() + */ + protected String getDescriptionXHTML() { + return "TextField combines the logic of both the single line text-entry field and the multi-line " + + "text-area into one component. " + + "As with all Data-components of IT Mill Toolkit, the TextField can also be bound to an " + + "underlying data source, both directly or in a buffered (asynchronous) " + + "mode. In buffered mode its background color will change to indicate " + + "that the value has changed but is not committed." + + "

Furthermore a validators may be bound to the component to " + + "check and validate the given input before it is actually committed." + + "

On the demo tab you can try out how the different properties affect the " + + "presentation of the component."; + } + + protected String getImage() { + return "icon_demo.png"; + } + + protected String getTitle() { + return "TextField"; + } } diff --git a/src/com/itmill/toolkit/tests/featurebrowser/FeatureTree.java b/src/com/itmill/toolkit/tests/featurebrowser/FeatureTree.java index 160fdfe6a4..cbe3781194 100644 --- a/src/com/itmill/toolkit/tests/featurebrowser/FeatureTree.java +++ b/src/com/itmill/toolkit/tests/featurebrowser/FeatureTree.java @@ -31,154 +31,163 @@ package com.itmill.toolkit.tests.featurebrowser; import java.util.Iterator; import com.itmill.toolkit.event.Action; -import com.itmill.toolkit.ui.*; +import com.itmill.toolkit.ui.Button; +import com.itmill.toolkit.ui.Component; +import com.itmill.toolkit.ui.Form; +import com.itmill.toolkit.ui.OrderedLayout; +import com.itmill.toolkit.ui.Select; +import com.itmill.toolkit.ui.Tree; public class FeatureTree extends Feature implements Action.Handler { - private static final String[] firstnames = new String[] { "John", "Mary", - "Joe", "Sarah", "Jeff", "Jane", "Peter", "Marc", "Josie", "Linus" }; - - private static final String[] lastnames = new String[] { "Torvalds", - "Smith", "Jones", "Beck", "Sheridan", "Picard", "Hill", "Fielding", - "Einstein" }; - - private Tree t; - - private boolean actionsActive = false; - - private Button actionHandlerSwitch = new Button("Activate actions", this, - "toggleActions"); - - public FeatureTree() { - super(); - } - - public void toggleActions() { - if (actionsActive) { - t.removeActionHandler(this); - actionsActive = false; - actionHandlerSwitch.setCaption("Activate Actions"); - } else { - t.addActionHandler(this); - actionsActive = true; - actionHandlerSwitch.setCaption("Deactivate Actions"); - } - } - - public void expandAll() { - for (Iterator i = t.rootItemIds().iterator(); i.hasNext();) { - t.expandItemsRecursively(i.next()); - } - } - - public void collapseAll() { - for (Iterator i = t.rootItemIds().iterator(); i.hasNext();) { - t.collapseItemsRecursively(i.next()); - } - } - - protected Component getDemoComponent() { - - OrderedLayout l = new OrderedLayout(); - - String[] names = new String[100]; - for (int i = 0; i < names.length; i++) - names[i] = firstnames[(int) (Math.random() * (firstnames.length - 1))] - + " " - + lastnames[(int) (Math.random() * (lastnames.length - 1))]; - - // Create tree - t = new Tree("Organization Structure"); - for (int i = 0; i < 100; i++) { - t.addItem(names[i]); - String parent = names[(int) (Math.random() * (names.length - 1))]; - if (t.containsId(parent)) - t.setParent(names[i], parent); - } - - // Forbid childless people to have children (makes them leaves) - for (int i = 0; i < 100; i++) - if (!t.hasChildren(names[i])) - t.setChildrenAllowed(names[i], false); - - l.addComponent(t); - - // Actions - l.addComponent(this.actionHandlerSwitch); - - // Expand and Collapse buttons - l.addComponent(new Button("Expand All", this, "expandAll")); - l.addComponent(new Button("Collapse All", this, "collapseAll")); - - // Properties - propertyPanel = new PropertyPanel(t); - Form ap = propertyPanel - .createBeanPropertySet(new String[] { "selectable" }); - Select themes = (Select) propertyPanel.getField("style"); - themes.addItem("menu").getItemProperty( - themes.getItemCaptionPropertyId()).setValue("menu"); - propertyPanel.addProperties("Tree Properties", ap); - - setJavadocURL("ui/Tree.html"); - - return l; - } - - protected String getExampleSrc() { - return "// Create tree\n" - + "t = new Tree(\"Organization Structure\");\n" - + "for (int i = 0; i < 100; i++) {\n" - + " t.addItem(names[i]);\n" - + " String parent = names[(int) (Math.random() * (names.length - 1))];\n" - + " if (t.containsId(parent)) \n" - + " t.setParent(names[i],parent);\n" - + "}\n\n" - + "// Forbid childless people to have children (makes them leaves)\n" - + "for (int i = 0; i < 100; i++)\n" - + " if (!t.hasChildren(names[i]))\n" - + " t.setChildrenAllowed(names[i], false);\n"; - } - - protected String getDescriptionXHTML() { - return "A tree is a natural way to represent datasets that have" - + " hierarchical relationships, such as filesystems, message " - + "threads or, as in this example, organization structure. IT Mill Toolkit features a versatile " - + "and powerful Tree component that works much like the tree components " - + "of most modern operating systems." - + "

The most prominent use of the Tree component is to " - + "use it for displaying a hierachical menu, like the " - + "menu on the left side of the screen for instance " - + "or to display filesystems or other hierarchical datasets." - + "

The tree component uses Container " - + "datasources much like the Table component, " - + "with the addition that it also utilizes the hierarchy " - + "information maintained by the container." - + "

On the demo tab you can try out how the different properties " - + "affect the presentation of the tree component."; - } - - protected String getImage() { - return "icon_demo.png"; - } - - protected String getTitle() { - return "Tree"; - } - - private Action ACTION1 = new Action("Action 1"); - - private Action ACTION2 = new Action("Action 2"); - - private Action ACTION3 = new Action("Action 3"); - - private Action[] actions = new Action[] { ACTION1, ACTION2, ACTION3 }; - - public Action[] getActions(Object target, Object sender) { - return actions; - } - - public void handleAction(Action action, Object sender, Object target) { - t.setDescription("Last action clicked was '" + action.getCaption() - + "' on item '" + target + "'"); - } + private static final String[] firstnames = new String[] { "John", "Mary", + "Joe", "Sarah", "Jeff", "Jane", "Peter", "Marc", "Josie", "Linus" }; + + private static final String[] lastnames = new String[] { "Torvalds", + "Smith", "Jones", "Beck", "Sheridan", "Picard", "Hill", "Fielding", + "Einstein" }; + + private Tree t; + + private boolean actionsActive = false; + + private Button actionHandlerSwitch = new Button("Activate actions", this, + "toggleActions"); + + public FeatureTree() { + super(); + } + + public void toggleActions() { + if (actionsActive) { + t.removeActionHandler(this); + actionsActive = false; + actionHandlerSwitch.setCaption("Activate Actions"); + } else { + t.addActionHandler(this); + actionsActive = true; + actionHandlerSwitch.setCaption("Deactivate Actions"); + } + } + + public void expandAll() { + for (Iterator i = t.rootItemIds().iterator(); i.hasNext();) { + t.expandItemsRecursively(i.next()); + } + } + + public void collapseAll() { + for (Iterator i = t.rootItemIds().iterator(); i.hasNext();) { + t.collapseItemsRecursively(i.next()); + } + } + + protected Component getDemoComponent() { + + OrderedLayout l = new OrderedLayout(); + + String[] names = new String[100]; + for (int i = 0; i < names.length; i++) { + names[i] = firstnames[(int) (Math.random() * (firstnames.length - 1))] + + " " + + lastnames[(int) (Math.random() * (lastnames.length - 1))]; + } + + // Create tree + t = new Tree("Organization Structure"); + for (int i = 0; i < 100; i++) { + t.addItem(names[i]); + String parent = names[(int) (Math.random() * (names.length - 1))]; + if (t.containsId(parent)) { + t.setParent(names[i], parent); + } + } + + // Forbid childless people to have children (makes them leaves) + for (int i = 0; i < 100; i++) { + if (!t.hasChildren(names[i])) { + t.setChildrenAllowed(names[i], false); + } + } + + l.addComponent(t); + + // Actions + l.addComponent(actionHandlerSwitch); + + // Expand and Collapse buttons + l.addComponent(new Button("Expand All", this, "expandAll")); + l.addComponent(new Button("Collapse All", this, "collapseAll")); + + // Properties + propertyPanel = new PropertyPanel(t); + Form ap = propertyPanel + .createBeanPropertySet(new String[] { "selectable" }); + Select themes = (Select) propertyPanel.getField("style"); + themes.addItem("menu").getItemProperty( + themes.getItemCaptionPropertyId()).setValue("menu"); + propertyPanel.addProperties("Tree Properties", ap); + + setJavadocURL("ui/Tree.html"); + + return l; + } + + protected String getExampleSrc() { + return "// Create tree\n" + + "t = new Tree(\"Organization Structure\");\n" + + "for (int i = 0; i < 100; i++) {\n" + + " t.addItem(names[i]);\n" + + " String parent = names[(int) (Math.random() * (names.length - 1))];\n" + + " if (t.containsId(parent)) \n" + + " t.setParent(names[i],parent);\n" + + "}\n\n" + + "// Forbid childless people to have children (makes them leaves)\n" + + "for (int i = 0; i < 100; i++)\n" + + " if (!t.hasChildren(names[i]))\n" + + " t.setChildrenAllowed(names[i], false);\n"; + } + + protected String getDescriptionXHTML() { + return "A tree is a natural way to represent datasets that have" + + " hierarchical relationships, such as filesystems, message " + + "threads or, as in this example, organization structure. IT Mill Toolkit features a versatile " + + "and powerful Tree component that works much like the tree components " + + "of most modern operating systems." + + "

The most prominent use of the Tree component is to " + + "use it for displaying a hierachical menu, like the " + + "menu on the left side of the screen for instance " + + "or to display filesystems or other hierarchical datasets." + + "

The tree component uses Container " + + "datasources much like the Table component, " + + "with the addition that it also utilizes the hierarchy " + + "information maintained by the container." + + "

On the demo tab you can try out how the different properties " + + "affect the presentation of the tree component."; + } + + protected String getImage() { + return "icon_demo.png"; + } + + protected String getTitle() { + return "Tree"; + } + + private Action ACTION1 = new Action("Action 1"); + + private Action ACTION2 = new Action("Action 2"); + + private Action ACTION3 = new Action("Action 3"); + + private Action[] actions = new Action[] { ACTION1, ACTION2, ACTION3 }; + + public Action[] getActions(Object target, Object sender) { + return actions; + } + + public void handleAction(Action action, Object sender, Object target) { + t.setDescription("Last action clicked was '" + action.getCaption() + + "' on item '" + target + "'"); + } } diff --git a/src/com/itmill/toolkit/tests/featurebrowser/FeatureUpload.java b/src/com/itmill/toolkit/tests/featurebrowser/FeatureUpload.java index b4178d55eb..4c5a418c94 100644 --- a/src/com/itmill/toolkit/tests/featurebrowser/FeatureUpload.java +++ b/src/com/itmill/toolkit/tests/featurebrowser/FeatureUpload.java @@ -43,126 +43,127 @@ import com.itmill.toolkit.ui.Upload; import com.itmill.toolkit.ui.Upload.FinishedEvent; public class FeatureUpload extends Feature implements Upload.FinishedListener { - Buffer buffer = new Buffer(); + Buffer buffer = new Buffer(); - Panel status = new Panel("Uploaded file:"); + Panel status = new Panel("Uploaded file:"); - public FeatureUpload() { - super(); - } - - protected Component getDemoComponent() { - - OrderedLayout l = new OrderedLayout(); - - Upload up = new Upload("Upload", buffer); - up.setImmediate(true); - up.addListener(this); - - status.setVisible(false); - - l.addComponent(up); - l.addComponent(status); - - // Properties - propertyPanel = new PropertyPanel(up); - - setJavadocURL("ui/Upload.html"); - - return l; - } - - protected String getExampleSrc() { - return "Upload u = new Upload(\"Upload a file:\", uploadReceiver);\n\n" - + "public class uploadReceiver \n" - + "implements Upload.receiver, Upload.FinishedListener { \n" - + "\n" + " java.io.File file;\n" - + " java.io.FileOutputStream fos;\n" - + " public uploadReceiver() {\n" + " }"; - - } - - protected String getDescriptionXHTML() { - return "This demonstrates the use of the Upload component together with the Link component. " - + "This implementation does not actually store the file to disk, it only keeps it in a buffer. " - + "The example given on the Code Sample-tab on the other hand stores the file to disk and binds the link to that file."; - } - - protected String getImage() { - return "icon_demo.png"; - } - - protected String getTitle() { - return "Upload"; - } - - public void uploadFinished(FinishedEvent event) { - status.removeAllComponents(); - if (buffer.getStream() == null) - status.addComponent(new Label( - "Upload finished, but output buffer is null!!")); - else { - status - .addComponent(new Label("Name: " - + event.getFilename(), Label.CONTENT_XHTML)); - status.addComponent(new Label("Mimetype: " - + event.getMIMEType(), Label.CONTENT_XHTML)); - status.addComponent(new Label("Size: " + event.getLength() - + " bytes.", Label.CONTENT_XHTML)); - - status.addComponent(new Link("Download " + buffer.getFileName(), - new StreamResource(buffer, buffer.getFileName(), - getApplication()))); - - status.setVisible(true); - } - } - - public class Buffer implements StreamResource.StreamSource, Upload.Receiver { - ByteArrayOutputStream outputBuffer = null; - - String mimeType; - - String fileName; - - public Buffer() { - - } - - public InputStream getStream() { - if (outputBuffer == null) - return null; - return new ByteArrayInputStream(outputBuffer.toByteArray()); - } - - /** - * @see com.itmill.toolkit.ui.Upload.Receiver#receiveUpload(String, - * String) - */ - public OutputStream receiveUpload(String filename, String MIMEType) { - fileName = filename; - mimeType = MIMEType; - outputBuffer = new ByteArrayOutputStream(); - return outputBuffer; - } - - /** - * Returns the fileName. - * - * @return String - */ - public String getFileName() { - return fileName; - } - - /** - * Returns the mimeType. - * - * @return String - */ - public String getMimeType() { - return mimeType; - } - - } + public FeatureUpload() { + super(); + } + + protected Component getDemoComponent() { + + OrderedLayout l = new OrderedLayout(); + + Upload up = new Upload("Upload", buffer); + up.setImmediate(true); + up.addListener(this); + + status.setVisible(false); + + l.addComponent(up); + l.addComponent(status); + + // Properties + propertyPanel = new PropertyPanel(up); + + setJavadocURL("ui/Upload.html"); + + return l; + } + + protected String getExampleSrc() { + return "Upload u = new Upload(\"Upload a file:\", uploadReceiver);\n\n" + + "public class uploadReceiver \n" + + "implements Upload.receiver, Upload.FinishedListener { \n" + + "\n" + " java.io.File file;\n" + + " java.io.FileOutputStream fos;\n" + + " public uploadReceiver() {\n" + " }"; + + } + + protected String getDescriptionXHTML() { + return "This demonstrates the use of the Upload component together with the Link component. " + + "This implementation does not actually store the file to disk, it only keeps it in a buffer. " + + "The example given on the Code Sample-tab on the other hand stores the file to disk and binds the link to that file."; + } + + protected String getImage() { + return "icon_demo.png"; + } + + protected String getTitle() { + return "Upload"; + } + + public void uploadFinished(FinishedEvent event) { + status.removeAllComponents(); + if (buffer.getStream() == null) { + status.addComponent(new Label( + "Upload finished, but output buffer is null!!")); + } else { + status + .addComponent(new Label("Name: " + + event.getFilename(), Label.CONTENT_XHTML)); + status.addComponent(new Label("Mimetype: " + + event.getMIMEType(), Label.CONTENT_XHTML)); + status.addComponent(new Label("Size: " + event.getLength() + + " bytes.", Label.CONTENT_XHTML)); + + status.addComponent(new Link("Download " + buffer.getFileName(), + new StreamResource(buffer, buffer.getFileName(), + getApplication()))); + + status.setVisible(true); + } + } + + public class Buffer implements StreamResource.StreamSource, Upload.Receiver { + ByteArrayOutputStream outputBuffer = null; + + String mimeType; + + String fileName; + + public Buffer() { + + } + + public InputStream getStream() { + if (outputBuffer == null) { + return null; + } + return new ByteArrayInputStream(outputBuffer.toByteArray()); + } + + /** + * @see com.itmill.toolkit.ui.Upload.Receiver#receiveUpload(String, + * String) + */ + public OutputStream receiveUpload(String filename, String MIMEType) { + fileName = filename; + mimeType = MIMEType; + outputBuffer = new ByteArrayOutputStream(); + return outputBuffer; + } + + /** + * Returns the fileName. + * + * @return String + */ + public String getFileName() { + return fileName; + } + + /** + * Returns the mimeType. + * + * @return String + */ + public String getMimeType() { + return mimeType; + } + + } } \ No newline at end of file diff --git a/src/com/itmill/toolkit/tests/featurebrowser/FeatureUtil.java b/src/com/itmill/toolkit/tests/featurebrowser/FeatureUtil.java index 14743c14d1..cf51e7756b 100644 --- a/src/com/itmill/toolkit/tests/featurebrowser/FeatureUtil.java +++ b/src/com/itmill/toolkit/tests/featurebrowser/FeatureUtil.java @@ -5,27 +5,29 @@ import java.util.Date; public class FeatureUtil { - private static boolean statistics = false; + private static boolean statistics = false; - public static final SimpleDateFormat format = new SimpleDateFormat( - "yyyyMMdd HHmmss"); + public static final SimpleDateFormat format = new SimpleDateFormat( + "yyyyMMdd HHmmss"); - public static void debug(String userIdentity, String msg) { - if (statistics) - System.out.println("[" + userIdentity + "] " + msg); - } + public static void debug(String userIdentity, String msg) { + if (statistics) { + System.out.println("[" + userIdentity + "] " + msg); + } + } - public static String getTimestamp() { - if (statistics) - try { - return format.format(new Date()); - } catch (Exception e) { - // ignored, should never happen - } - return ""; - } + public static String getTimestamp() { + if (statistics) { + try { + return format.format(new Date()); + } catch (Exception e) { + // ignored, should never happen + } + } + return ""; + } - public static void setStatistics(boolean statistics) { - FeatureUtil.statistics = statistics; - } + public static void setStatistics(boolean statistics) { + FeatureUtil.statistics = statistics; + } } diff --git a/src/com/itmill/toolkit/tests/featurebrowser/FeatureValidators.java b/src/com/itmill/toolkit/tests/featurebrowser/FeatureValidators.java index caa1c9b865..49b59f5289 100644 --- a/src/com/itmill/toolkit/tests/featurebrowser/FeatureValidators.java +++ b/src/com/itmill/toolkit/tests/featurebrowser/FeatureValidators.java @@ -37,70 +37,70 @@ import com.itmill.toolkit.ui.Select; public class FeatureValidators extends Feature { - private static final String INTRO_TEXT = "" - + "IT Mill Toolkit contains simple, yet powerful validation interface, " - + "that consists of two parts: Validator and Validatable. Validator is " - + "any class that can check validity of an Object. Validatable is " - + "a class with configurable validation. " - + "Validation errors are passed as special exceptions that implement " - + "ErrorMessage interface. This way the validation errors can be " - + "automatically added to components." - + "

Utilities for simple string and null validation are provided, as " - + "well as combinative validators. The validation interface can also " - + "be easily implemented by the applications for more complex " - + "validation needs."; - - public FeatureValidators() { - super(); - } - - protected Component getDemoComponent() { - - OrderedLayout l = new OrderedLayout(); - - Panel panel = new Panel(); - panel.setCaption("Validators"); - l.addComponent(panel); - - Label label = new Label(); - panel.addComponent(label); - - label.setContentMode(Label.CONTENT_XHTML); - label.setValue(INTRO_TEXT); - - // Properties - propertyPanel = new PropertyPanel(panel); - Form ap = propertyPanel.createBeanPropertySet(new String[] { "width", - "height" }); - Select themes = (Select) propertyPanel.getField("style"); - themes.addItem("light").getItemProperty( - themes.getItemCaptionPropertyId()).setValue("light"); - themes.addItem("strong").getItemProperty( - themes.getItemCaptionPropertyId()).setValue("strong"); - propertyPanel.addProperties("Panel Properties", ap); - - setJavadocURL("data/Validator.html"); - - return l; - } - - protected String getExampleSrc() { - return null; - } - - /** - * @see com.itmill.toolkit.tests.featurebrowser.Feature#getDescriptionXHTML() - */ - protected String getDescriptionXHTML() { - return null; - } - - protected String getImage() { - return null; - } - - protected String getTitle() { - return null; - } + private static final String INTRO_TEXT = "" + + "IT Mill Toolkit contains simple, yet powerful validation interface, " + + "that consists of two parts: Validator and Validatable. Validator is " + + "any class that can check validity of an Object. Validatable is " + + "a class with configurable validation. " + + "Validation errors are passed as special exceptions that implement " + + "ErrorMessage interface. This way the validation errors can be " + + "automatically added to components." + + "

Utilities for simple string and null validation are provided, as " + + "well as combinative validators. The validation interface can also " + + "be easily implemented by the applications for more complex " + + "validation needs."; + + public FeatureValidators() { + super(); + } + + protected Component getDemoComponent() { + + OrderedLayout l = new OrderedLayout(); + + Panel panel = new Panel(); + panel.setCaption("Validators"); + l.addComponent(panel); + + Label label = new Label(); + panel.addComponent(label); + + label.setContentMode(Label.CONTENT_XHTML); + label.setValue(INTRO_TEXT); + + // Properties + propertyPanel = new PropertyPanel(panel); + Form ap = propertyPanel.createBeanPropertySet(new String[] { "width", + "height" }); + Select themes = (Select) propertyPanel.getField("style"); + themes.addItem("light").getItemProperty( + themes.getItemCaptionPropertyId()).setValue("light"); + themes.addItem("strong").getItemProperty( + themes.getItemCaptionPropertyId()).setValue("strong"); + propertyPanel.addProperties("Panel Properties", ap); + + setJavadocURL("data/Validator.html"); + + return l; + } + + protected String getExampleSrc() { + return null; + } + + /** + * @see com.itmill.toolkit.tests.featurebrowser.Feature#getDescriptionXHTML() + */ + protected String getDescriptionXHTML() { + return null; + } + + protected String getImage() { + return null; + } + + protected String getTitle() { + return null; + } } diff --git a/src/com/itmill/toolkit/tests/featurebrowser/FeatureWindow.java b/src/com/itmill/toolkit/tests/featurebrowser/FeatureWindow.java index b3a6fa65c8..9784e6e1ce 100644 --- a/src/com/itmill/toolkit/tests/featurebrowser/FeatureWindow.java +++ b/src/com/itmill/toolkit/tests/featurebrowser/FeatureWindow.java @@ -28,132 +28,139 @@ package com.itmill.toolkit.tests.featurebrowser; -import com.itmill.toolkit.ui.*; +import com.itmill.toolkit.ui.Button; +import com.itmill.toolkit.ui.Component; +import com.itmill.toolkit.ui.Form; +import com.itmill.toolkit.ui.Label; +import com.itmill.toolkit.ui.OrderedLayout; +import com.itmill.toolkit.ui.Window; import com.itmill.toolkit.ui.Window.CloseEvent; public class FeatureWindow extends Feature implements Window.CloseListener { - private Button addButton = new Button("Add window", this, "addWin"); - - private Button removeButton = new Button("Remove window", this, "delWin"); - - private Window demoWindow; - - private Form windowProperties; - - public FeatureWindow() { - super(); - } - - protected Component getDemoComponent() { - - OrderedLayout layoutRoot = new OrderedLayout(); - OrderedLayout layoutUpper = new OrderedLayout(); - OrderedLayout layoutLower = new OrderedLayout(); - - demoWindow = new Window("Feature Test Window"); - demoWindow.addListener(this); - demoWindow.setWidth(400); - demoWindow.setHeight(200); - demoWindow.setTheme("default"); - - layoutUpper.addComponent(addButton); - layoutUpper.addComponent(removeButton); - - updateWinStatus(); - - // Properties - propertyPanel = new PropertyPanel(demoWindow); - propertyPanel.dependsOn(addButton); - propertyPanel.dependsOn(removeButton); - windowProperties = propertyPanel.createBeanPropertySet(new String[] { - "width", "height", "name", "theme", "border", "scrollable", }); - windowProperties.replaceWithSelect("border", new Object[] { - new Integer(Window.BORDER_DEFAULT), - new Integer(Window.BORDER_NONE), - new Integer(Window.BORDER_MINIMAL) }, new Object[] { "Default", - "None", "Minimal" }); - // Disabled, not applicable for default theme - windowProperties.getField("border").setEnabled(false); - windowProperties.getField("scrollable").setEnabled(false); - - propertyPanel.addProperties("Window Properties", windowProperties); - windowProperties.getField("width").setDescription( - "Minimum width is 100"); - windowProperties.getField("height").setDescription( - "Minimum height is 100"); - - setJavadocURL("ui/Window.html"); - - layoutRoot.addComponent(layoutUpper); - layoutRoot.addComponent(layoutLower); - return layoutRoot; - } - - protected String getExampleSrc() { - return "Window win = new Window();\n" - + "getApplication().addWindow(win);\n"; - - } - - protected String getDescriptionXHTML() { - return "The window support in IT Mill Toolkit allows for opening and closing windows, " - + "refreshing one window from another (for asynchronous terminals), " - + "resizing windows and scrolling window content. " - + "There are also a number of preset window border styles defined by " - + "this feature."; - } - - protected String getImage() { - return "icon_demo.png"; - } - - protected String getTitle() { - return "Window"; - } - - public void addWin() { - - propertyPanel.commit(); - - getApplication().getMainWindow().addWindow(demoWindow); - - demoWindow.removeAllComponents(); - - demoWindow - .addComponent(new Label( - "

This is a new window created by " - + "Add window" - + " button's event.

You may simply" - + " close this window or select " - + "Remove window from the Feature Browser window.", - Label.CONTENT_XHTML)); - // prevent user to change window name tag (after window is created) - windowProperties.getField("name").setEnabled(false); - windowProperties.getField("name").setReadOnly(true); - demoWindow.setVisible(true); - updateWinStatus(); - } - - public void delWin() { - getApplication().getMainWindow().removeWindow(demoWindow); - // allow user to change window name tag (before window is created) - windowProperties.getField("name").setEnabled(true); - windowProperties.getField("name").setReadOnly(false); - updateWinStatus(); - } - - private void updateWinStatus() { - if (demoWindow.getApplication() == null) { - addButton.setEnabled(true); - removeButton.setEnabled(false); - } else { - addButton.setEnabled(false); - removeButton.setEnabled(true); - } - } - - public void windowClose(CloseEvent e) { - delWin(); - } + private Button addButton = new Button("Add window", this, "addWin"); + + private Button removeButton = new Button("Remove window", this, "delWin"); + + private Window demoWindow; + + private Form windowProperties; + + public FeatureWindow() { + super(); + } + + protected Component getDemoComponent() { + + OrderedLayout layoutRoot = new OrderedLayout(); + OrderedLayout layoutUpper = new OrderedLayout(); + OrderedLayout layoutLower = new OrderedLayout(); + + demoWindow = new Window("Feature Test Window"); + demoWindow.addListener(this); + demoWindow.setWidth(400); + demoWindow.setHeight(200); + demoWindow.setTheme("default"); + + layoutUpper.addComponent(addButton); + layoutUpper.addComponent(removeButton); + + updateWinStatus(); + + // Properties + propertyPanel = new PropertyPanel(demoWindow); + propertyPanel.dependsOn(addButton); + propertyPanel.dependsOn(removeButton); + windowProperties = propertyPanel.createBeanPropertySet(new String[] { + "width", "height", "name", "theme", "border", "scrollable", }); + windowProperties.replaceWithSelect("border", new Object[] { + new Integer(Window.BORDER_DEFAULT), + new Integer(Window.BORDER_NONE), + new Integer(Window.BORDER_MINIMAL) }, new Object[] { "Default", + "None", "Minimal" }); + // Disabled, not applicable for default theme + windowProperties.getField("border").setEnabled(false); + windowProperties.getField("scrollable").setEnabled(false); + + propertyPanel.addProperties("Window Properties", windowProperties); + windowProperties.getField("width").setDescription( + "Minimum width is 100"); + windowProperties.getField("height").setDescription( + "Minimum height is 100"); + + setJavadocURL("ui/Window.html"); + + layoutRoot.addComponent(layoutUpper); + layoutRoot.addComponent(layoutLower); + return layoutRoot; + } + + protected String getExampleSrc() { + return "Window win = new Window();\n" + + "getApplication().addWindow(win);\n"; + + } + + protected String getDescriptionXHTML() { + return "The window support in IT Mill Toolkit allows for opening and closing windows, " + + "refreshing one window from another (for asynchronous terminals), " + + "resizing windows and scrolling window content. " + + "There are also a number of preset window border styles defined by " + + "this feature."; + } + + protected String getImage() { + return "icon_demo.png"; + } + + protected String getTitle() { + return "Window"; + } + + public void addWin() { + + propertyPanel.commit(); + + getApplication().getMainWindow().addWindow(demoWindow); + + demoWindow.removeAllComponents(); + + demoWindow + .addComponent(new Label( + "

This is a new window created by " + + "Add window" + + " button's event.

You may simply" + + " close this window or select " + + "Remove window from the Feature Browser window.", + Label.CONTENT_XHTML)); + // prevent user to change window name tag (after window is + // created) + windowProperties.getField("name").setEnabled(false); + windowProperties.getField("name").setReadOnly(true); + demoWindow.setVisible(true); + updateWinStatus(); + } + + public void delWin() { + getApplication().getMainWindow().removeWindow(demoWindow); + // allow user to change window name tag (before window is + // created) + windowProperties.getField("name").setEnabled(true); + windowProperties.getField("name").setReadOnly(false); + updateWinStatus(); + } + + private void updateWinStatus() { + if (demoWindow.getApplication() == null) { + addButton.setEnabled(true); + removeButton.setEnabled(false); + } else { + addButton.setEnabled(false); + removeButton.setEnabled(true); + } + } + + public void windowClose(CloseEvent e) { + delWin(); + } } diff --git a/src/com/itmill/toolkit/tests/featurebrowser/FeaturesApplication.java b/src/com/itmill/toolkit/tests/featurebrowser/FeaturesApplication.java index 335d583a6d..c27a2c1d60 100644 --- a/src/com/itmill/toolkit/tests/featurebrowser/FeaturesApplication.java +++ b/src/com/itmill/toolkit/tests/featurebrowser/FeaturesApplication.java @@ -28,29 +28,30 @@ package com.itmill.toolkit.tests.featurebrowser; -import com.itmill.toolkit.ui.*; +import com.itmill.toolkit.ui.Window; public class FeaturesApplication extends com.itmill.toolkit.Application { - public void init() { - if (getProperty("statistics") != null) - FeatureUtil.setStatistics(true); - setUser(new Long(System.currentTimeMillis()).toString()); - Window main = new Window("IT Mill Toolkit Features Tour"); - setMainWindow(main); - - main.setLayout(new FeatureBrowser()); - } - - /** - * ErrorEvents are printed to default error stream and not in GUI. - */ - public void terminalError( - com.itmill.toolkit.terminal.Terminal.ErrorEvent event) { - Throwable e = event.getThrowable(); - FeatureUtil.debug(getUser().toString(), "terminalError: " - + e.toString()); - e.printStackTrace(); - } + public void init() { + if (getProperty("statistics") != null) { + FeatureUtil.setStatistics(true); + } + setUser(new Long(System.currentTimeMillis()).toString()); + Window main = new Window("IT Mill Toolkit Features Tour"); + setMainWindow(main); + + main.setLayout(new FeatureBrowser()); + } + + /** + * ErrorEvents are printed to default error stream and not in GUI. + */ + public void terminalError( + com.itmill.toolkit.terminal.Terminal.ErrorEvent event) { + Throwable e = event.getThrowable(); + FeatureUtil.debug(getUser().toString(), "terminalError: " + + e.toString()); + e.printStackTrace(); + } } diff --git a/src/com/itmill/toolkit/tests/featurebrowser/IntroBasic.java b/src/com/itmill/toolkit/tests/featurebrowser/IntroBasic.java index fae31d029b..4d29a768df 100644 --- a/src/com/itmill/toolkit/tests/featurebrowser/IntroBasic.java +++ b/src/com/itmill/toolkit/tests/featurebrowser/IntroBasic.java @@ -37,62 +37,62 @@ import com.itmill.toolkit.ui.Select; public class IntroBasic extends Feature { - private static final String INTRO_TEXT = "" - + "Text Field, Date Field, Button, Form, Label and Link components are provided as samples" - + " for basic UI components." - + "

See the API documentation of respective components for more information."; - - public IntroBasic() { - super(); - } - - protected Component getDemoComponent() { - - OrderedLayout l = new OrderedLayout(); - - Panel panel = new Panel(); - panel.setCaption("Basic UI components"); - l.addComponent(panel); - - Label label = new Label(); - panel.addComponent(label); - - label.setContentMode(Label.CONTENT_XHTML); - label.setValue(INTRO_TEXT); - - // Properties - propertyPanel = new PropertyPanel(panel); - Form ap = propertyPanel.createBeanPropertySet(new String[] { "width", - "height" }); - Select themes = (Select) propertyPanel.getField("style"); - themes.addItem("light").getItemProperty( - themes.getItemCaptionPropertyId()).setValue("light"); - themes.addItem("strong").getItemProperty( - themes.getItemCaptionPropertyId()).setValue("strong"); - propertyPanel.addProperties("Panel Properties", ap); - - setJavadocURL("ui/package-summary.html"); - - return l; - } - - protected String getExampleSrc() { - return null; - } - - /** - * @see com.itmill.toolkit.tests.featurebrowser.Feature#getDescriptionXHTML() - */ - protected String getDescriptionXHTML() { - return null; - } - - protected String getImage() { - return null; - } - - protected String getTitle() { - return "Introduction of basic UI components"; - } + private static final String INTRO_TEXT = "" + + "Text Field, Date Field, Button, Form, Label and Link components are provided as samples" + + " for basic UI components." + + "

See the API documentation of respective components for more information."; + + public IntroBasic() { + super(); + } + + protected Component getDemoComponent() { + + OrderedLayout l = new OrderedLayout(); + + Panel panel = new Panel(); + panel.setCaption("Basic UI components"); + l.addComponent(panel); + + Label label = new Label(); + panel.addComponent(label); + + label.setContentMode(Label.CONTENT_XHTML); + label.setValue(INTRO_TEXT); + + // Properties + propertyPanel = new PropertyPanel(panel); + Form ap = propertyPanel.createBeanPropertySet(new String[] { "width", + "height" }); + Select themes = (Select) propertyPanel.getField("style"); + themes.addItem("light").getItemProperty( + themes.getItemCaptionPropertyId()).setValue("light"); + themes.addItem("strong").getItemProperty( + themes.getItemCaptionPropertyId()).setValue("strong"); + propertyPanel.addProperties("Panel Properties", ap); + + setJavadocURL("ui/package-summary.html"); + + return l; + } + + protected String getExampleSrc() { + return null; + } + + /** + * @see com.itmill.toolkit.tests.featurebrowser.Feature#getDescriptionXHTML() + */ + protected String getDescriptionXHTML() { + return null; + } + + protected String getImage() { + return null; + } + + protected String getTitle() { + return "Introduction of basic UI components"; + } } diff --git a/src/com/itmill/toolkit/tests/featurebrowser/IntroComponents.java b/src/com/itmill/toolkit/tests/featurebrowser/IntroComponents.java index 8f796a74fb..dd9d9773f3 100644 --- a/src/com/itmill/toolkit/tests/featurebrowser/IntroComponents.java +++ b/src/com/itmill/toolkit/tests/featurebrowser/IntroComponents.java @@ -39,64 +39,64 @@ import com.itmill.toolkit.ui.Select; public class IntroComponents extends Feature { - private static final String INTRO_TEXT = "" - + "This picture summarizes the relations between different user interface (UI) components." - + "

See API documentation below for more information."; + private static final String INTRO_TEXT = "" + + "This picture summarizes the relations between different user interface (UI) components." + + "

See API documentation below for more information."; - public IntroComponents() { - super(); - } + public IntroComponents() { + super(); + } - protected Component getDemoComponent() { + protected Component getDemoComponent() { - OrderedLayout l = new OrderedLayout(); + OrderedLayout l = new OrderedLayout(); - Panel panel = new Panel(); - panel.setCaption("UI component diagram"); - l.addComponent(panel); + Panel panel = new Panel(); + panel.setCaption("UI component diagram"); + l.addComponent(panel); - Label label = new Label(); - panel.addComponent(label); + Label label = new Label(); + panel.addComponent(label); - label.setContentMode(Label.CONTENT_XHTML); - label.setValue(INTRO_TEXT); + label.setContentMode(Label.CONTENT_XHTML); + label.setValue(INTRO_TEXT); - panel.addComponent(new Embedded("", new ClassResource("components.png", - this.getApplication()))); + panel.addComponent(new Embedded("", new ClassResource("components.png", + getApplication()))); - // Properties - propertyPanel = new PropertyPanel(panel); - Form ap = propertyPanel.createBeanPropertySet(new String[] { "width", - "height" }); - Select themes = (Select) propertyPanel.getField("style"); - themes.addItem("light").getItemProperty( - themes.getItemCaptionPropertyId()).setValue("light"); - themes.addItem("strong").getItemProperty( - themes.getItemCaptionPropertyId()).setValue("strong"); - propertyPanel.addProperties("Panel Properties", ap); + // Properties + propertyPanel = new PropertyPanel(panel); + Form ap = propertyPanel.createBeanPropertySet(new String[] { "width", + "height" }); + Select themes = (Select) propertyPanel.getField("style"); + themes.addItem("light").getItemProperty( + themes.getItemCaptionPropertyId()).setValue("light"); + themes.addItem("strong").getItemProperty( + themes.getItemCaptionPropertyId()).setValue("strong"); + propertyPanel.addProperties("Panel Properties", ap); - setJavadocURL("ui/package-summary.html"); + setJavadocURL("ui/package-summary.html"); - return l; - } + return l; + } - protected String getExampleSrc() { - return null; - } + protected String getExampleSrc() { + return null; + } - /** - * @see com.itmill.toolkit.tests.featurebrowser.Feature#getDescriptionXHTML() - */ - protected String getDescriptionXHTML() { - return null; - } + /** + * @see com.itmill.toolkit.tests.featurebrowser.Feature#getDescriptionXHTML() + */ + protected String getDescriptionXHTML() { + return null; + } - protected String getImage() { - return null; - } + protected String getImage() { + return null; + } - protected String getTitle() { - return null; - } + protected String getTitle() { + return null; + } } diff --git a/src/com/itmill/toolkit/tests/featurebrowser/IntroDataHandling.java b/src/com/itmill/toolkit/tests/featurebrowser/IntroDataHandling.java index b96c1c155c..2f0321884f 100644 --- a/src/com/itmill/toolkit/tests/featurebrowser/IntroDataHandling.java +++ b/src/com/itmill/toolkit/tests/featurebrowser/IntroDataHandling.java @@ -37,61 +37,61 @@ import com.itmill.toolkit.ui.Select; public class IntroDataHandling extends Feature { - private static final String INTRO_TEXT = "" - + "Embedded Objects and Upload components are provided as samples" - + " for data handling section." - + "

See the API documentation of respective components for more information."; - - public IntroDataHandling() { - super(); - } - - protected Component getDemoComponent() { - - OrderedLayout l = new OrderedLayout(); - - Panel panel = new Panel(); - panel.setCaption("Data Handling"); - l.addComponent(panel); - - Label label = new Label(); - panel.addComponent(label); - - label.setContentMode(Label.CONTENT_XHTML); - label.setValue(INTRO_TEXT); - - // Properties - propertyPanel = new PropertyPanel(panel); - Form ap = propertyPanel.createBeanPropertySet(new String[] { "width", - "height" }); - Select themes = (Select) propertyPanel.getField("style"); - themes.addItem("light").getItemProperty( - themes.getItemCaptionPropertyId()).setValue("light"); - themes.addItem("strong").getItemProperty( - themes.getItemCaptionPropertyId()).setValue("strong"); - propertyPanel.addProperties("Panel Properties", ap); - - return l; - } - - protected String getExampleSrc() { - return null; - } - - /** - * @see com.itmill.toolkit.tests.featurebrowser.Feature#getDescriptionXHTML() - */ - protected String getDescriptionXHTML() { - return "Please select Embedded Objects or Upload" - + " from the menu for more information."; - } - - protected String getImage() { - return null; - } - - protected String getTitle() { - return null; - } + private static final String INTRO_TEXT = "" + + "Embedded Objects and Upload components are provided as samples" + + " for data handling section." + + "

See the API documentation of respective components for more information."; + + public IntroDataHandling() { + super(); + } + + protected Component getDemoComponent() { + + OrderedLayout l = new OrderedLayout(); + + Panel panel = new Panel(); + panel.setCaption("Data Handling"); + l.addComponent(panel); + + Label label = new Label(); + panel.addComponent(label); + + label.setContentMode(Label.CONTENT_XHTML); + label.setValue(INTRO_TEXT); + + // Properties + propertyPanel = new PropertyPanel(panel); + Form ap = propertyPanel.createBeanPropertySet(new String[] { "width", + "height" }); + Select themes = (Select) propertyPanel.getField("style"); + themes.addItem("light").getItemProperty( + themes.getItemCaptionPropertyId()).setValue("light"); + themes.addItem("strong").getItemProperty( + themes.getItemCaptionPropertyId()).setValue("strong"); + propertyPanel.addProperties("Panel Properties", ap); + + return l; + } + + protected String getExampleSrc() { + return null; + } + + /** + * @see com.itmill.toolkit.tests.featurebrowser.Feature#getDescriptionXHTML() + */ + protected String getDescriptionXHTML() { + return "Please select Embedded Objects or Upload" + + " from the menu for more information."; + } + + protected String getImage() { + return null; + } + + protected String getTitle() { + return null; + } } diff --git a/src/com/itmill/toolkit/tests/featurebrowser/IntroDataModel.java b/src/com/itmill/toolkit/tests/featurebrowser/IntroDataModel.java index b46501f6c8..089ae73f76 100644 --- a/src/com/itmill/toolkit/tests/featurebrowser/IntroDataModel.java +++ b/src/com/itmill/toolkit/tests/featurebrowser/IntroDataModel.java @@ -37,63 +37,63 @@ import com.itmill.toolkit.ui.Select; public class IntroDataModel extends Feature { - private static final String INTRO_TEXT = "" - + "This section introduces main concepts of data model in IT Mill Toolkit." - + " It contains brief introduction to Properties, Items, Containers, Validators and" - + " Buffering classes." - + "

See the API documentation of respective area for more information."; - - public IntroDataModel() { - super(); - } - - protected Component getDemoComponent() { - - OrderedLayout l = new OrderedLayout(); - - Panel panel = new Panel(); - panel.setCaption("Data Model"); - l.addComponent(panel); - - Label label = new Label(); - panel.addComponent(label); - - label.setContentMode(Label.CONTENT_XHTML); - label.setValue(INTRO_TEXT); - - // Properties - propertyPanel = new PropertyPanel(panel); - Form ap = propertyPanel.createBeanPropertySet(new String[] { "width", - "height" }); - Select themes = (Select) propertyPanel.getField("style"); - themes.addItem("light").getItemProperty( - themes.getItemCaptionPropertyId()).setValue("light"); - themes.addItem("strong").getItemProperty( - themes.getItemCaptionPropertyId()).setValue("strong"); - propertyPanel.addProperties("Panel Properties", ap); - - setJavadocURL("data/package-summary.html"); - - return l; - } - - protected String getExampleSrc() { - return null; - } - - /** - * @see com.itmill.toolkit.tests.featurebrowser.Feature#getDescriptionXHTML() - */ - protected String getDescriptionXHTML() { - return null; - } - - protected String getImage() { - return null; - } - - protected String getTitle() { - return null; - } + private static final String INTRO_TEXT = "" + + "This section introduces main concepts of data model in IT Mill Toolkit." + + " It contains brief introduction to Properties, Items, Containers, Validators and" + + " Buffering classes." + + "

See the API documentation of respective area for more information."; + + public IntroDataModel() { + super(); + } + + protected Component getDemoComponent() { + + OrderedLayout l = new OrderedLayout(); + + Panel panel = new Panel(); + panel.setCaption("Data Model"); + l.addComponent(panel); + + Label label = new Label(); + panel.addComponent(label); + + label.setContentMode(Label.CONTENT_XHTML); + label.setValue(INTRO_TEXT); + + // Properties + propertyPanel = new PropertyPanel(panel); + Form ap = propertyPanel.createBeanPropertySet(new String[] { "width", + "height" }); + Select themes = (Select) propertyPanel.getField("style"); + themes.addItem("light").getItemProperty( + themes.getItemCaptionPropertyId()).setValue("light"); + themes.addItem("strong").getItemProperty( + themes.getItemCaptionPropertyId()).setValue("strong"); + propertyPanel.addProperties("Panel Properties", ap); + + setJavadocURL("data/package-summary.html"); + + return l; + } + + protected String getExampleSrc() { + return null; + } + + /** + * @see com.itmill.toolkit.tests.featurebrowser.Feature#getDescriptionXHTML() + */ + protected String getDescriptionXHTML() { + return null; + } + + protected String getImage() { + return null; + } + + protected String getTitle() { + return null; + } } diff --git a/src/com/itmill/toolkit/tests/featurebrowser/IntroItemContainers.java b/src/com/itmill/toolkit/tests/featurebrowser/IntroItemContainers.java index 97c17101b3..3e584120b7 100644 --- a/src/com/itmill/toolkit/tests/featurebrowser/IntroItemContainers.java +++ b/src/com/itmill/toolkit/tests/featurebrowser/IntroItemContainers.java @@ -37,62 +37,62 @@ import com.itmill.toolkit.ui.Select; public class IntroItemContainers extends Feature { - private static final String INTRO_TEXT = "" - + "Select, Table and Tree components are provided as samples" - + " for item containers section." - + "

See the API documentation of respective components for more information."; - - public IntroItemContainers() { - super(); - } - - protected Component getDemoComponent() { - - OrderedLayout l = new OrderedLayout(); - - Panel panel = new Panel(); - panel.setCaption("Item Containers"); - l.addComponent(panel); - - Label label = new Label(); - panel.addComponent(label); - - label.setContentMode(Label.CONTENT_XHTML); - label.setValue(INTRO_TEXT); - - // Properties - propertyPanel = new PropertyPanel(panel); - Form ap = propertyPanel.createBeanPropertySet(new String[] { "width", - "height" }); - Select themes = (Select) propertyPanel.getField("style"); - themes.addItem("light").getItemProperty( - themes.getItemCaptionPropertyId()).setValue("light"); - themes.addItem("strong").getItemProperty( - themes.getItemCaptionPropertyId()).setValue("strong"); - propertyPanel.addProperties("Panel Properties", ap); - - setJavadocURL("data/Container.html"); - - return l; - } - - protected String getExampleSrc() { - return null; - } - - /** - * @see com.itmill.toolkit.tests.featurebrowser.Feature#getDescriptionXHTML() - */ - protected String getDescriptionXHTML() { - return null; - } - - protected String getImage() { - return null; - } - - protected String getTitle() { - return null; - } + private static final String INTRO_TEXT = "" + + "Select, Table and Tree components are provided as samples" + + " for item containers section." + + "

See the API documentation of respective components for more information."; + + public IntroItemContainers() { + super(); + } + + protected Component getDemoComponent() { + + OrderedLayout l = new OrderedLayout(); + + Panel panel = new Panel(); + panel.setCaption("Item Containers"); + l.addComponent(panel); + + Label label = new Label(); + panel.addComponent(label); + + label.setContentMode(Label.CONTENT_XHTML); + label.setValue(INTRO_TEXT); + + // Properties + propertyPanel = new PropertyPanel(panel); + Form ap = propertyPanel.createBeanPropertySet(new String[] { "width", + "height" }); + Select themes = (Select) propertyPanel.getField("style"); + themes.addItem("light").getItemProperty( + themes.getItemCaptionPropertyId()).setValue("light"); + themes.addItem("strong").getItemProperty( + themes.getItemCaptionPropertyId()).setValue("strong"); + propertyPanel.addProperties("Panel Properties", ap); + + setJavadocURL("data/Container.html"); + + return l; + } + + protected String getExampleSrc() { + return null; + } + + /** + * @see com.itmill.toolkit.tests.featurebrowser.Feature#getDescriptionXHTML() + */ + protected String getDescriptionXHTML() { + return null; + } + + protected String getImage() { + return null; + } + + protected String getTitle() { + return null; + } } diff --git a/src/com/itmill/toolkit/tests/featurebrowser/IntroLayouts.java b/src/com/itmill/toolkit/tests/featurebrowser/IntroLayouts.java index 7c4a4b21bb..3c57a3c3e5 100644 --- a/src/com/itmill/toolkit/tests/featurebrowser/IntroLayouts.java +++ b/src/com/itmill/toolkit/tests/featurebrowser/IntroLayouts.java @@ -37,64 +37,64 @@ import com.itmill.toolkit.ui.Select; public class IntroLayouts extends Feature { - private static final String INTRO_TEXT = "" - + "Layouts are required to place components to specific place in the UI." - + " You can use plain Java to accomplish sophisticated component layouting." - + " Other option is to use Custom Layout and let the web page designers" - + " to take responsibility of component layouting using their own set of tools." - + "

See API documentation below for more information."; - - public IntroLayouts() { - super(); - } - - protected Component getDemoComponent() { - - OrderedLayout l = new OrderedLayout(); - - Panel panel = new Panel(); - panel.setCaption("Layouts"); - l.addComponent(panel); - - Label label = new Label(); - panel.addComponent(label); - - label.setContentMode(Label.CONTENT_XHTML); - label.setValue(INTRO_TEXT); - - // Properties - propertyPanel = new PropertyPanel(panel); - Form ap = propertyPanel.createBeanPropertySet(new String[] { "width", - "height" }); - Select themes = (Select) propertyPanel.getField("style"); - themes.addItem("light").getItemProperty( - themes.getItemCaptionPropertyId()).setValue("light"); - themes.addItem("strong").getItemProperty( - themes.getItemCaptionPropertyId()).setValue("strong"); - propertyPanel.addProperties("Panel Properties", ap); - - setJavadocURL("ui/Layout.html"); - - return l; - } - - protected String getExampleSrc() { - return null; - } - - /** - * @see com.itmill.toolkit.tests.featurebrowser.Feature#getDescriptionXHTML() - */ - protected String getDescriptionXHTML() { - return null; - } - - protected String getImage() { - return null; - } - - protected String getTitle() { - return null; - } + private static final String INTRO_TEXT = "" + + "Layouts are required to place components to specific place in the UI." + + " You can use plain Java to accomplish sophisticated component layouting." + + " Other option is to use Custom Layout and let the web page designers" + + " to take responsibility of component layouting using their own set of tools." + + "

See API documentation below for more information."; + + public IntroLayouts() { + super(); + } + + protected Component getDemoComponent() { + + OrderedLayout l = new OrderedLayout(); + + Panel panel = new Panel(); + panel.setCaption("Layouts"); + l.addComponent(panel); + + Label label = new Label(); + panel.addComponent(label); + + label.setContentMode(Label.CONTENT_XHTML); + label.setValue(INTRO_TEXT); + + // Properties + propertyPanel = new PropertyPanel(panel); + Form ap = propertyPanel.createBeanPropertySet(new String[] { "width", + "height" }); + Select themes = (Select) propertyPanel.getField("style"); + themes.addItem("light").getItemProperty( + themes.getItemCaptionPropertyId()).setValue("light"); + themes.addItem("strong").getItemProperty( + themes.getItemCaptionPropertyId()).setValue("strong"); + propertyPanel.addProperties("Panel Properties", ap); + + setJavadocURL("ui/Layout.html"); + + return l; + } + + protected String getExampleSrc() { + return null; + } + + /** + * @see com.itmill.toolkit.tests.featurebrowser.Feature#getDescriptionXHTML() + */ + protected String getDescriptionXHTML() { + return null; + } + + protected String getImage() { + return null; + } + + protected String getTitle() { + return null; + } } diff --git a/src/com/itmill/toolkit/tests/featurebrowser/IntroTerminal.java b/src/com/itmill/toolkit/tests/featurebrowser/IntroTerminal.java index 84ac477c9c..f7cad07245 100644 --- a/src/com/itmill/toolkit/tests/featurebrowser/IntroTerminal.java +++ b/src/com/itmill/toolkit/tests/featurebrowser/IntroTerminal.java @@ -34,41 +34,41 @@ import com.itmill.toolkit.ui.OrderedLayout; public class IntroTerminal extends Feature { - public IntroTerminal() { - super(); - } + public IntroTerminal() { + super(); + } - protected Component getDemoComponent() { + protected Component getDemoComponent() { - OrderedLayout l = new OrderedLayout(); + OrderedLayout l = new OrderedLayout(); - Label lab = new Label(); - lab.setStyle("featurebrowser-none"); - l.addComponent(lab); + Label lab = new Label(); + lab.setStyle("featurebrowser-none"); + l.addComponent(lab); - // Properties - propertyPanel = null; + // Properties + propertyPanel = null; - return l; - } + return l; + } - protected String getExampleSrc() { - return null; - } + protected String getExampleSrc() { + return null; + } - /** - * @see com.itmill.toolkit.tests.featurebrowser.Feature#getDescriptionXHTML() - */ - protected String getDescriptionXHTML() { - return ""; - } + /** + * @see com.itmill.toolkit.tests.featurebrowser.Feature#getDescriptionXHTML() + */ + protected String getDescriptionXHTML() { + return ""; + } - protected String getImage() { - return null; - } + protected String getImage() { + return null; + } - protected String getTitle() { - return "Introduction for terminals (TODO)"; - } + protected String getTitle() { + return "Introduction for terminals (TODO)"; + } } diff --git a/src/com/itmill/toolkit/tests/featurebrowser/IntroWelcome.java b/src/com/itmill/toolkit/tests/featurebrowser/IntroWelcome.java index 79b9705e7f..5421f9dc57 100644 --- a/src/com/itmill/toolkit/tests/featurebrowser/IntroWelcome.java +++ b/src/com/itmill/toolkit/tests/featurebrowser/IntroWelcome.java @@ -34,8 +34,6 @@ import java.util.Iterator; import java.util.Map; import com.itmill.toolkit.terminal.DownloadStream; -import com.itmill.toolkit.terminal.PaintException; -import com.itmill.toolkit.terminal.PaintTarget; import com.itmill.toolkit.terminal.ParameterHandler; import com.itmill.toolkit.terminal.URIHandler; import com.itmill.toolkit.terminal.gwt.server.ApplicationServlet; @@ -48,150 +46,150 @@ import com.itmill.toolkit.ui.Panel; import com.itmill.toolkit.ui.Select; public class IntroWelcome extends Feature implements URIHandler, - ParameterHandler { - - private WebBrowser webBrowser = null; - - Panel panel = new Panel(); - - private static final String WELCOME_TEXT_UPPER = "" - + "This application lets you view and play with some features of " - + "IT Mill Toolkit. Use menu on the left to select component." - + "

Note the Properties selection on the top " - + "right corner. Click it open to access component properties and" - + " feel free to edit properties at any time." - + "

The area that you are now reading is the component" - + " demo area. Lower area from here contains component description, API" - + " documentation and optional code sample. Note that not all selections" - + " contain demo, only description and API documentation is shown." - + "

You may also change application's theme from below the menu." - + " This example application is designed to work best with" - + " Demo theme, other themes are for demonstration purposes only." - + "

IT Mill Toolkit enables you to construct complex Web" - + " applications using plain Java, no knowledge of other Web technologies" - + " such as XML, HTML, DOM, JavaScript or browser differences is required." - + "

For more information, point your browser to" - + " www.itmill.com."; - - private static final String WELCOME_TEXT_LOWER = "" - + "This area contains the selected component's description, list of properties, javadoc" - + " and optional code sample. " - + "Start your tour now by selecting features from the list" - + " on the left and remember to experiment with the Properties panel" - + " located at the top right corner area."; - - // TODO Add browser agent string - private String description = WELCOME_TEXT_LOWER - + "

IT Mill Toolkit version: " - + ApplicationServlet.VERSION; - - public IntroWelcome() { - super(); - } - - protected Component getDemoComponent() { - - OrderedLayout l = new OrderedLayout(); - - panel.setCaption("Welcome to the IT Mill Toolkit feature tour!"); - l.addComponent(panel); - - Label label = new Label(); - panel.addComponent(label); - - label.setContentMode(Label.CONTENT_XHTML); - label.setValue(WELCOME_TEXT_UPPER); - - propertyPanel = new PropertyPanel(panel); - Form ap = propertyPanel.createBeanPropertySet(new String[] { "width", - "height" }); - Select themes = (Select) propertyPanel.getField("style"); - themes.addItem("light").getItemProperty( - themes.getItemCaptionPropertyId()).setValue("light"); - themes.addItem("strong").getItemProperty( - themes.getItemCaptionPropertyId()).setValue("strong"); - propertyPanel.addProperties("Panel Properties", ap); - - setJavadocURL("package-summary.html"); - - setPropsReminder(false); - - return l; - } - - protected String getExampleSrc() { - return "" - + "package com.itmill.toolkit.demo;\n" - + "import com.itmill.toolkit.ui.*;\n\n" - + "public class HelloWorld extends com.itmill.toolkit.Application {\n" - + " public void init() {\n" - + " Window main = new Window(\"Hello window\");\n" - + " setMainWindow(main);\n" - + " main.addComponent(new Label(\"Hello World!\"));\n" - + " }\n" + "}\n"; - } - - // not ready yet to give description, see paint instead - protected String getDescriptionXHTML() { - return description; - } - - protected String getImage() { - return "icon_intro.png"; - } - - protected String getTitle() { - return "Welcome"; - } - - /** - * Add URI and parametes handlers to window. - * - * @see com.itmill.toolkit.ui.Component#attach() - */ - public void attach() { - super.attach(); - getWindow().addURIHandler(this); - getWindow().addParameterHandler(this); - } - - /** - * Remove all handlers from window - * - * @see com.itmill.toolkit.ui.Component#detach() - */ - public void detach() { - super.detach(); - getWindow().removeURIHandler(this); - getWindow().removeParameterHandler(this); - } - - /** - * Update URI - * - * @see com.itmill.toolkit.terminal.URIHandler#handleURI(URL, String) - */ - public DownloadStream handleURI(URL context, String relativeUri) { - return null; - } - - /** - * Show system status if systemStatus is given on URL - * - * @see com.itmill.toolkit.terminal.ParameterHandler#handleParameters(Map) - */ - public void handleParameters(Map parameters) { - for (Iterator i = parameters.keySet().iterator(); i.hasNext();) { - String name = (String) i.next(); - if (name.equals("systemStatus")) { - String status = ""; - status += "timestamp=" + new Date() + " "; - status += "free=" + Runtime.getRuntime().freeMemory() + ", "; - status += "total=" + Runtime.getRuntime().totalMemory() + ", "; - status += "max=" + Runtime.getRuntime().maxMemory() + "\n"; - System.out.println(status); - } - } - } + ParameterHandler { + + private WebBrowser webBrowser = null; + + Panel panel = new Panel(); + + private static final String WELCOME_TEXT_UPPER = "" + + "This application lets you view and play with some features of " + + "IT Mill Toolkit. Use menu on the left to select component." + + "

Note the Properties selection on the top " + + "right corner. Click it open to access component properties and" + + " feel free to edit properties at any time." + + "

The area that you are now reading is the component" + + " demo area. Lower area from here contains component description, API" + + " documentation and optional code sample. Note that not all selections" + + " contain demo, only description and API documentation is shown." + + "

You may also change application's theme from below the menu." + + " This example application is designed to work best with" + + " Demo theme, other themes are for demonstration purposes only." + + "

IT Mill Toolkit enables you to construct complex Web" + + " applications using plain Java, no knowledge of other Web technologies" + + " such as XML, HTML, DOM, JavaScript or browser differences is required." + + "

For more information, point your browser to" + + " www.itmill.com."; + + private static final String WELCOME_TEXT_LOWER = "" + + "This area contains the selected component's description, list of properties, javadoc" + + " and optional code sample. " + + "Start your tour now by selecting features from the list" + + " on the left and remember to experiment with the Properties panel" + + " located at the top right corner area."; + + // TODO Add browser agent string + private String description = WELCOME_TEXT_LOWER + + "

IT Mill Toolkit version: " + + ApplicationServlet.VERSION; + + public IntroWelcome() { + super(); + } + + protected Component getDemoComponent() { + + OrderedLayout l = new OrderedLayout(); + + panel.setCaption("Welcome to the IT Mill Toolkit feature tour!"); + l.addComponent(panel); + + Label label = new Label(); + panel.addComponent(label); + + label.setContentMode(Label.CONTENT_XHTML); + label.setValue(WELCOME_TEXT_UPPER); + + propertyPanel = new PropertyPanel(panel); + Form ap = propertyPanel.createBeanPropertySet(new String[] { "width", + "height" }); + Select themes = (Select) propertyPanel.getField("style"); + themes.addItem("light").getItemProperty( + themes.getItemCaptionPropertyId()).setValue("light"); + themes.addItem("strong").getItemProperty( + themes.getItemCaptionPropertyId()).setValue("strong"); + propertyPanel.addProperties("Panel Properties", ap); + + setJavadocURL("package-summary.html"); + + setPropsReminder(false); + + return l; + } + + protected String getExampleSrc() { + return "" + + "package com.itmill.toolkit.demo;\n" + + "import com.itmill.toolkit.ui.*;\n\n" + + "public class HelloWorld extends com.itmill.toolkit.Application {\n" + + " public void init() {\n" + + " Window main = new Window(\"Hello window\");\n" + + " setMainWindow(main);\n" + + " main.addComponent(new Label(\"Hello World!\"));\n" + + " }\n" + "}\n"; + } + + // not ready yet to give description, see paint instead + protected String getDescriptionXHTML() { + return description; + } + + protected String getImage() { + return "icon_intro.png"; + } + + protected String getTitle() { + return "Welcome"; + } + + /** + * Add URI and parametes handlers to window. + * + * @see com.itmill.toolkit.ui.Component#attach() + */ + public void attach() { + super.attach(); + getWindow().addURIHandler(this); + getWindow().addParameterHandler(this); + } + + /** + * Remove all handlers from window + * + * @see com.itmill.toolkit.ui.Component#detach() + */ + public void detach() { + super.detach(); + getWindow().removeURIHandler(this); + getWindow().removeParameterHandler(this); + } + + /** + * Update URI + * + * @see com.itmill.toolkit.terminal.URIHandler#handleURI(URL, String) + */ + public DownloadStream handleURI(URL context, String relativeUri) { + return null; + } + + /** + * Show system status if systemStatus is given on URL + * + * @see com.itmill.toolkit.terminal.ParameterHandler#handleParameters(Map) + */ + public void handleParameters(Map parameters) { + for (Iterator i = parameters.keySet().iterator(); i.hasNext();) { + String name = (String) i.next(); + if (name.equals("systemStatus")) { + String status = ""; + status += "timestamp=" + new Date() + " "; + status += "free=" + Runtime.getRuntime().freeMemory() + ", "; + status += "total=" + Runtime.getRuntime().totalMemory() + ", "; + status += "max=" + Runtime.getRuntime().maxMemory() + "\n"; + System.out.println(status); + } + } + } } diff --git a/src/com/itmill/toolkit/tests/featurebrowser/PropertyPanel.java b/src/com/itmill/toolkit/tests/featurebrowser/PropertyPanel.java index b574563653..cbe9bc5be0 100644 --- a/src/com/itmill/toolkit/tests/featurebrowser/PropertyPanel.java +++ b/src/com/itmill/toolkit/tests/featurebrowser/PropertyPanel.java @@ -37,480 +37,506 @@ import java.util.HashSet; import java.util.Iterator; import java.util.LinkedList; -import com.itmill.toolkit.data.*; -import com.itmill.toolkit.data.Property.ValueChangeListener; -import com.itmill.toolkit.data.util.*; -import com.itmill.toolkit.terminal.*; -import com.itmill.toolkit.ui.*; +import com.itmill.toolkit.data.Property; +import com.itmill.toolkit.data.util.BeanItem; +import com.itmill.toolkit.terminal.ErrorMessage; +import com.itmill.toolkit.terminal.SystemError; +import com.itmill.toolkit.terminal.ThemeResource; +import com.itmill.toolkit.terminal.UserError; +import com.itmill.toolkit.ui.AbstractComponent; +import com.itmill.toolkit.ui.AbstractComponentContainer; +import com.itmill.toolkit.ui.AbstractField; +import com.itmill.toolkit.ui.Button; +import com.itmill.toolkit.ui.Component; +import com.itmill.toolkit.ui.DateField; +import com.itmill.toolkit.ui.Field; +import com.itmill.toolkit.ui.Form; +import com.itmill.toolkit.ui.GridLayout; +import com.itmill.toolkit.ui.OrderedLayout; +import com.itmill.toolkit.ui.Panel; +import com.itmill.toolkit.ui.Select; +import com.itmill.toolkit.ui.Table; +import com.itmill.toolkit.ui.TextField; +import com.itmill.toolkit.ui.Tree; +import com.itmill.toolkit.ui.Window; public class PropertyPanel extends Panel implements Button.ClickListener, - Property.ValueChangeListener { - - private Select addComponent; - - private OrderedLayout formsLayout = new OrderedLayout(); - - private LinkedList forms = new LinkedList(); - - private Button setButton = new Button("Set", this); - - private Button discardButton = new Button("Discard changes", this); - - private Table allProperties = new Table(); - - private Object objectToConfigure; - - private BeanItem config; - - protected static final int COLUMNS = 3; - - /** Contruct new property panel for configuring given object. */ - public PropertyPanel(Object objectToConfigure) { - super(); - getLayout().setMargin(false); - - // Layout - setCaption("Properties"); - addComponent(formsLayout); - - setWidth(100); - setWidthUnits(Table.UNITS_PERCENTAGE); - setHeight(100); - setHeightUnits(Table.UNITS_PERCENTAGE); - - // Target object - this.objectToConfigure = objectToConfigure; - config = new BeanItem(objectToConfigure); - - // Control buttons - OrderedLayout buttons = new OrderedLayout( - OrderedLayout.ORIENTATION_HORIZONTAL); - buttons.setMargin(false, true, true, true); - buttons.addComponent(setButton); - buttons.addComponent(discardButton); - addComponent(buttons); - - // Add default properties - addBasicComponentProperties(); - if (objectToConfigure instanceof Select) - addSelectProperties(); - if (objectToConfigure instanceof AbstractField - && !(objectToConfigure instanceof Table || objectToConfigure instanceof Tree)) - addFieldProperties(); - if ((objectToConfigure instanceof AbstractComponentContainer)) - addComponentContainerProperties(); - - // The list of all properties - allProperties.addContainerProperty("Name", String.class, ""); - allProperties.addContainerProperty("Type", String.class, ""); - allProperties.addContainerProperty("R/W", String.class, ""); - allProperties.addContainerProperty("Demo", String.class, ""); - allProperties.setColumnAlignments(new String[] { Table.ALIGN_LEFT, - Table.ALIGN_LEFT, Table.ALIGN_CENTER, Table.ALIGN_CENTER }); - allProperties.setColumnHeaderMode(Table.COLUMN_HEADER_MODE_ID); - allProperties.setPageLength(0); - allProperties.setWidth(100); - allProperties.setWidthUnits(Table.UNITS_PERCENTAGE); - allProperties.setHeight(100); - allProperties.setHeightUnits(Table.UNITS_PERCENTAGE); - updatePropertyList(); - - } - - /** Add a formful of properties to property panel */ - public void addProperties(String propertySetCaption, Form properties) { - - // Create new panel containing the form - Panel p = new Panel(); - p.setCaption(propertySetCaption); - p.setStyle("light"); - p.addComponent(properties); - formsLayout.addComponent(p); - - // Setup buffering - setButton.dependsOn(properties); - discardButton.dependsOn(properties); - properties.setWriteThrough(false); - // TODO change this to false, and test it is suitable for FeatureBrowser - // demo - properties.setReadThrough(true); - - // Maintain property lists - forms.add(properties); - updatePropertyList(); - } - - /** Recreate property list contents */ - public void updatePropertyList() { - - allProperties.removeAllItems(); - - // Collect demoed properties - HashSet listed = new HashSet(); - for (Iterator i = forms.iterator(); i.hasNext();) - listed.addAll(((Form) i.next()).getItemPropertyIds()); - - // Resolve all properties - BeanInfo info; - try { - info = Introspector.getBeanInfo(objectToConfigure.getClass()); - } catch (IntrospectionException e) { - throw new RuntimeException(e.toString()); - } - PropertyDescriptor[] pd = info.getPropertyDescriptors(); - - // Fill the table - for (int i = 0; i < pd.length; i++) { - allProperties.addItem(new Object[] { pd[i].getName(), - pd[i].getPropertyType().getName(), - (pd[i].getWriteMethod() == null ? "R" : "R/W"), - (listed.contains(pd[i].getName()) ? "x" : "") }, pd[i]); - } - } - - /** Add basic properties implemented most often by abstract component */ - private void addBasicComponentProperties() { - - // Set of properties - Form set = createBeanPropertySet(new String[] { "caption", "icon", - "componentError", "description", "enabled", "visible", "style", - "readOnly", "immediate" }); - - // Icon - set.replaceWithSelect("icon", new Object[] { null, - new ThemeResource("icon/files/file.gif") }, new Object[] { - "No icon", "Sample icon" }); - - // Component error - Throwable sampleException; - try { - throw new NullPointerException("sample exception"); - } catch (NullPointerException e) { - sampleException = e; - } - set - .replaceWithSelect( - "componentError", - new Object[] { - null, - new UserError("Sample text error message."), - new UserError( - "

Error message formatting

Error messages can " - + "contain any UIDL formatting, like:

  • Bold" - + "
  • Italic

", - UserError.CONTENT_UIDL, - ErrorMessage.INFORMATION), - new SystemError( - "This is an example of exception error reposting", - sampleException) }, - new Object[] { "No error", "Sample text error", - "Sample Formatted error", "Sample System Error" }); - - // Style - String currentStyle = ((Component) objectToConfigure).getStyleName(); - if (currentStyle == null) - set.replaceWithSelect("style", new Object[] { null }, - new Object[] { "Default" }).setNewItemsAllowed(true); - else - set.replaceWithSelect("style", new Object[] { null, currentStyle }, - new Object[] { "Default", currentStyle }) - .setNewItemsAllowed(true); - - // Set up descriptions - set - .getField("caption") - .setDescription( - "Component caption is the title of the component. Usage of the caption is optional and the " - + "exact behavior of the propery is defined by the component. Setting caption null " - + "or empty disables the caption."); - set - .getField("enabled") - .setDescription( - "Enabled property controls the usage of the component. If the component is disabled (enabled=false)," - + " it can not receive any events from the terminal. In most cases it makes the usage" - + " of the component easier, if the component visually looks disbled (for example is grayed), " - + "when it can not be used."); - set - .getField("icon") - .setDescription( - "Icon of the component selects the main icon of the component. The usage of the icon is identical " - + "to caption and in most components caption and icon are kept together. Icons can be " - + "loaded from any resources (see Terminal/Resources for more information). Some components " - + "contain more than just the captions icon. Those icons are controlled through their " - + "own properties."); - set - .getField("visible") - .setDescription( - "Visibility property says if the component is renreded or not. Invisible components are implicitly " - + "disabled, as there is no visible user interface to send event."); - set - .getField("description") - .setDescription( - "Description is designed to allow easy addition of short tooltips, like this. Like the caption," - + " setting description null or empty disables the description."); - set - .getField("readOnly") - .setDescription( - "Those components that have internal state that can be written are settable to readOnly-mode," - + " where the object can only be read, not written."); - set - .getField("componentError") - .setDescription( - "IT Mill Toolkit supports extensive error reporting. One part of the error reporting are component" - + " errors that can be controlled by the programmer. This example only contains couple of " - + "sample errors; to get the full picture, read browse ErrorMessage-interface implementors " - + "API documentation."); - set - .getField("immediate") - .setDescription( - "Not all terminals can send the events immediately to server from all action. Web is the most " - + "typical environment where many events (like textfield changed) are not sent to server, " - + "before they are explicitly submitted. Setting immediate property true (by default this " - + "is false for most components), the programmer can assure that the application is" - + " notified as soon as possible about the value change in this component."); - set - .getField("style") - .setDescription( - "Themes specify the overall looks of the user interface. In addition component can have a set of " - + "styles, that can be visually very different (like datefield calendar- and text-styles), " - + "but contain the same logical functionality. As a rule of thumb, theme specifies if a " - + "component is blue or yellow and style determines how the component is used."); - - // Add created fields to property panel - addProperties("Component Basics", set); - - // Customization for Window component - if (objectToConfigure instanceof Window) { - disableField(set.getField("enabled"), new Boolean(true)); - disableField(set.getField("visible"), new Boolean(true)); - disableField(set.getField("componentError")); - disableField(set.getField("icon")); - } - } - - /** Add properties for selecting */ - private void addSelectProperties() { - Form set = createBeanPropertySet(new String[] { "newItemsAllowed", - "lazyLoading", "multiSelect" }); - addProperties("Select Properties", set); - - set.getField("multiSelect").setDescription( - "Specified if multiple items can be selected at once."); - set - .getField("newItemsAllowed") - .setDescription( - "Select component (but not Tree or Table) can allow the user to directly " - + "add new items to set of options. The new items are constrained to be " - + "strings and thus feature only applies to simple lists."); - /*Button ll = (Button) set.getField("lazyLoading"); - ll - .setDescription("In Ajax rendering mode select supports lazy loading and filtering of options."); - ll.addListener((ValueChangeListener) this); - ll.setImmediate(true); - if (((Boolean) ll.getValue()).booleanValue()) { - set.getField("multiSelect").setVisible(false); - set.getField("newItemsAllowed").setVisible(false); - }*/ - if (objectToConfigure instanceof Tree - || objectToConfigure instanceof Table) { - set.removeItemProperty("newItemsAllowed"); - set.removeItemProperty("lazyLoading"); - } - } - - /** Field special properties */ - private void addFieldProperties() { - // TODO bug #211 states that setFocus works only for Button and - // Textfield UI components - Form set = new Form(new GridLayout(COLUMNS, 1)); - set.addField("focus", new Button("Focus", objectToConfigure, "focus")); - set.getField("focus").setDescription( - "Focus the cursor to this field. Not all " - + "components and/or terminals support this feature."); - addProperties("Field Features", set); - } - - /** - * Add and remove some miscellaneous example component to/from component - * container - */ - private void addComponentContainerProperties() { - Form set = new Form(new OrderedLayout( - OrderedLayout.ORIENTATION_VERTICAL)); - - addComponent = new Select(); - addComponent.setImmediate(true); - addComponent.addItem("Add component to container"); - addComponent.setNullSelectionItemId("Add component to container"); - addComponent.addItem("Text field"); - addComponent.addItem("Option group"); - addComponent.addListener(this); - - set.addField("component adder", addComponent); - set.addField("remove all components", new Button( - "Remove all components", objectToConfigure, - "removeAllComponents")); - - addProperties("ComponentContainer Features", set); - } - - /** Value change listener for listening selections */ - public void valueChange(Property.ValueChangeEvent event) { - - // FIXME: navigation statistics - try { - FeatureUtil.debug(getApplication().getUser().toString(), - "valueChange " - + ((AbstractComponent) event.getProperty()) - .getTag() + ", " + event.getProperty()); - } catch (Exception e) { - // ignored, should never happen - } - - // Adding components to component container - if (event.getProperty() == addComponent) { - String value = (String) addComponent.getValue(); - - if (value != null) { - // TextField component - if (value.equals("Text field")) - ((AbstractComponentContainer) objectToConfigure) - .addComponent(new TextField("Test field")); - - // DateField time style - if (value.equals("Time")) { - DateField d = new DateField("Time", new Date()); - d - .setDescription("This is a DateField-component with text-style"); - d.setResolution(DateField.RESOLUTION_MIN); - d.setStyle("text"); - ((AbstractComponentContainer) objectToConfigure) - .addComponent(d); - } - - // Date field calendar style - if (value.equals("Calendar")) { - DateField c = new DateField("Calendar", new Date()); - c - .setDescription("DateField-component with calendar-style and day-resolution"); - c.setStyle("calendar"); - c.setResolution(DateField.RESOLUTION_DAY); - ((AbstractComponentContainer) objectToConfigure) - .addComponent(c); - } - - // Select option group style - if (value.equals("Option group")) { - Select s = new Select("Options"); - s.setDescription("Select-component with optiongroup-style"); - s.addItem("Linux"); - s.addItem("Windows"); - s.addItem("Solaris"); - s.addItem("Symbian"); - s.setStyle("optiongroup"); - - ((AbstractComponentContainer) objectToConfigure) - .addComponent(s); - } - - addComponent.setValue(null); - } - } else if (event.getProperty() == getField("lazyLoading")) { - boolean newValue = ((Boolean) event.getProperty().getValue()) - .booleanValue(); - Field multiselect = getField("multiSelect"); - Field newitems = getField("newItemsAllowed"); - if (newValue) { - newitems.setValue(Boolean.FALSE); - newitems.setVisible(false); - multiselect.setValue(Boolean.FALSE); - multiselect.setVisible(false); - } else { - newitems.setVisible(true); - multiselect.setVisible(true); - } - } - } - - /** Handle all button clicks for this panel */ - public void buttonClick(Button.ClickEvent event) { - // FIXME: navigation statistics - try { - FeatureUtil.debug(getApplication().getUser().toString(), - "buttonClick " + event.getButton().getTag() + ", " - + event.getButton().getCaption() + ", " - + event.getButton().getValue()); - } catch (Exception e) { - // ignored, should never happen - } - // Commit all changed on all forms - if (event.getButton() == setButton) { - commit(); - } - - // Discard all changed on all forms - if (event.getButton() == discardButton) { - for (Iterator i = forms.iterator(); i.hasNext();) - ((Form) i.next()).discard(); - } - - } - - /** - * Helper function for creating forms from array of propety names. - */ - protected Form createBeanPropertySet(String names[]) { - - Form set = new Form(new OrderedLayout( - OrderedLayout.ORIENTATION_VERTICAL)); - - for (int i = 0; i < names.length; i++) { - Property p = config.getItemProperty(names[i]); - if (p != null) { - set.addItemProperty(names[i], p); - Field f = set.getField(names[i]); - if (f instanceof TextField) { - if (Integer.class.equals(p.getType())) - ((TextField) f).setColumns(4); - else { - ((TextField) f).setNullSettingAllowed(true); - ((TextField) f).setColumns(24); - } - } - } - } - - return set; - } - - /** Find a field from all forms */ - public Field getField(Object propertyId) { - for (Iterator i = forms.iterator(); i.hasNext();) { - Form f = (Form) i.next(); - Field af = f.getField(propertyId); - if (af != null) - return af; - } - return null; - } - - public Table getAllProperties() { - return allProperties; - } - - protected void commit() { - for (Iterator i = forms.iterator(); i.hasNext();) - ((Form) i.next()).commit(); - } - - private void disableField(Field field) { - field.setEnabled(false); - field.setReadOnly(true); - } - - private void disableField(Field field, Object value) { - field.setValue(value); - disableField(field); - } + Property.ValueChangeListener { + + private Select addComponent; + + private OrderedLayout formsLayout = new OrderedLayout(); + + private LinkedList forms = new LinkedList(); + + private Button setButton = new Button("Set", this); + + private Button discardButton = new Button("Discard changes", this); + + private Table allProperties = new Table(); + + private Object objectToConfigure; + + private BeanItem config; + + protected static final int COLUMNS = 3; + + /** Contruct new property panel for configuring given object. */ + public PropertyPanel(Object objectToConfigure) { + super(); + getLayout().setMargin(false); + + // Layout + setCaption("Properties"); + addComponent(formsLayout); + + setWidth(100); + setWidthUnits(Table.UNITS_PERCENTAGE); + setHeight(100); + setHeightUnits(Table.UNITS_PERCENTAGE); + + // Target object + this.objectToConfigure = objectToConfigure; + config = new BeanItem(objectToConfigure); + + // Control buttons + OrderedLayout buttons = new OrderedLayout( + OrderedLayout.ORIENTATION_HORIZONTAL); + buttons.setMargin(false, true, true, true); + buttons.addComponent(setButton); + buttons.addComponent(discardButton); + addComponent(buttons); + + // Add default properties + addBasicComponentProperties(); + if (objectToConfigure instanceof Select) { + addSelectProperties(); + } + if (objectToConfigure instanceof AbstractField + && !(objectToConfigure instanceof Table || objectToConfigure instanceof Tree)) { + addFieldProperties(); + } + if ((objectToConfigure instanceof AbstractComponentContainer)) { + addComponentContainerProperties(); + } + + // The list of all properties + allProperties.addContainerProperty("Name", String.class, ""); + allProperties.addContainerProperty("Type", String.class, ""); + allProperties.addContainerProperty("R/W", String.class, ""); + allProperties.addContainerProperty("Demo", String.class, ""); + allProperties.setColumnAlignments(new String[] { Table.ALIGN_LEFT, + Table.ALIGN_LEFT, Table.ALIGN_CENTER, Table.ALIGN_CENTER }); + allProperties.setColumnHeaderMode(Table.COLUMN_HEADER_MODE_ID); + allProperties.setPageLength(0); + allProperties.setWidth(100); + allProperties.setWidthUnits(Table.UNITS_PERCENTAGE); + allProperties.setHeight(100); + allProperties.setHeightUnits(Table.UNITS_PERCENTAGE); + updatePropertyList(); + + } + + /** Add a formful of properties to property panel */ + public void addProperties(String propertySetCaption, Form properties) { + + // Create new panel containing the form + Panel p = new Panel(); + p.setCaption(propertySetCaption); + p.setStyle("light"); + p.addComponent(properties); + formsLayout.addComponent(p); + + // Setup buffering + setButton.dependsOn(properties); + discardButton.dependsOn(properties); + properties.setWriteThrough(false); + // TODO change this to false, and test it is suitable for FeatureBrowser + // demo + properties.setReadThrough(true); + + // Maintain property lists + forms.add(properties); + updatePropertyList(); + } + + /** Recreate property list contents */ + public void updatePropertyList() { + + allProperties.removeAllItems(); + + // Collect demoed properties + HashSet listed = new HashSet(); + for (Iterator i = forms.iterator(); i.hasNext();) { + listed.addAll(((Form) i.next()).getItemPropertyIds()); + } + + // Resolve all properties + BeanInfo info; + try { + info = Introspector.getBeanInfo(objectToConfigure.getClass()); + } catch (IntrospectionException e) { + throw new RuntimeException(e.toString()); + } + PropertyDescriptor[] pd = info.getPropertyDescriptors(); + + // Fill the table + for (int i = 0; i < pd.length; i++) { + allProperties.addItem(new Object[] { pd[i].getName(), + pd[i].getPropertyType().getName(), + (pd[i].getWriteMethod() == null ? "R" : "R/W"), + (listed.contains(pd[i].getName()) ? "x" : "") }, pd[i]); + } + } + + /** Add basic properties implemented most often by abstract component */ + private void addBasicComponentProperties() { + + // Set of properties + Form set = createBeanPropertySet(new String[] { "caption", "icon", + "componentError", "description", "enabled", "visible", "style", + "readOnly", "immediate" }); + + // Icon + set.replaceWithSelect("icon", new Object[] { null, + new ThemeResource("icon/files/file.gif") }, new Object[] { + "No icon", "Sample icon" }); + + // Component error + Throwable sampleException; + try { + throw new NullPointerException("sample exception"); + } catch (NullPointerException e) { + sampleException = e; + } + set + .replaceWithSelect( + "componentError", + new Object[] { + null, + new UserError("Sample text error message."), + new UserError( + "

Error message formatting

Error messages can " + + "contain any UIDL formatting, like:

  • Bold" + + "
  • Italic

", + UserError.CONTENT_UIDL, + ErrorMessage.INFORMATION), + new SystemError( + "This is an example of exception error reposting", + sampleException) }, + new Object[] { "No error", "Sample text error", + "Sample Formatted error", "Sample System Error" }); + + // Style + String currentStyle = ((Component) objectToConfigure).getStyleName(); + if (currentStyle == null) { + set.replaceWithSelect("style", new Object[] { null }, + new Object[] { "Default" }).setNewItemsAllowed(true); + } else { + set.replaceWithSelect("style", new Object[] { null, currentStyle }, + new Object[] { "Default", currentStyle }) + .setNewItemsAllowed(true); + } + + // Set up descriptions + set + .getField("caption") + .setDescription( + "Component caption is the title of the component. Usage of the caption is optional and the " + + "exact behavior of the propery is defined by the component. Setting caption null " + + "or empty disables the caption."); + set + .getField("enabled") + .setDescription( + "Enabled property controls the usage of the component. If the component is disabled (enabled=false)," + + " it can not receive any events from the terminal. In most cases it makes the usage" + + " of the component easier, if the component visually looks disbled (for example is grayed), " + + "when it can not be used."); + set + .getField("icon") + .setDescription( + "Icon of the component selects the main icon of the component. The usage of the icon is identical " + + "to caption and in most components caption and icon are kept together. Icons can be " + + "loaded from any resources (see Terminal/Resources for more information). Some components " + + "contain more than just the captions icon. Those icons are controlled through their " + + "own properties."); + set + .getField("visible") + .setDescription( + "Visibility property says if the component is renreded or not. Invisible components are implicitly " + + "disabled, as there is no visible user interface to send event."); + set + .getField("description") + .setDescription( + "Description is designed to allow easy addition of short tooltips, like this. Like the caption," + + " setting description null or empty disables the description."); + set + .getField("readOnly") + .setDescription( + "Those components that have internal state that can be written are settable to readOnly-mode," + + " where the object can only be read, not written."); + set + .getField("componentError") + .setDescription( + "IT Mill Toolkit supports extensive error reporting. One part of the error reporting are component" + + " errors that can be controlled by the programmer. This example only contains couple of " + + "sample errors; to get the full picture, read browse ErrorMessage-interface implementors " + + "API documentation."); + set + .getField("immediate") + .setDescription( + "Not all terminals can send the events immediately to server from all action. Web is the most " + + "typical environment where many events (like textfield changed) are not sent to server, " + + "before they are explicitly submitted. Setting immediate property true (by default this " + + "is false for most components), the programmer can assure that the application is" + + " notified as soon as possible about the value change in this component."); + set + .getField("style") + .setDescription( + "Themes specify the overall looks of the user interface. In addition component can have a set of " + + "styles, that can be visually very different (like datefield calendar- and text-styles), " + + "but contain the same logical functionality. As a rule of thumb, theme specifies if a " + + "component is blue or yellow and style determines how the component is used."); + + // Add created fields to property panel + addProperties("Component Basics", set); + + // Customization for Window component + if (objectToConfigure instanceof Window) { + disableField(set.getField("enabled"), new Boolean(true)); + disableField(set.getField("visible"), new Boolean(true)); + disableField(set.getField("componentError")); + disableField(set.getField("icon")); + } + } + + /** Add properties for selecting */ + private void addSelectProperties() { + Form set = createBeanPropertySet(new String[] { "newItemsAllowed", + "lazyLoading", "multiSelect" }); + addProperties("Select Properties", set); + + set.getField("multiSelect").setDescription( + "Specified if multiple items can be selected at once."); + set + .getField("newItemsAllowed") + .setDescription( + "Select component (but not Tree or Table) can allow the user to directly " + + "add new items to set of options. The new items are constrained to be " + + "strings and thus feature only applies to simple lists."); + /* + * Button ll = (Button) set.getField("lazyLoading"); ll + * .setDescription("In Ajax rendering mode select supports lazy loading + * and filtering of options."); ll.addListener((ValueChangeListener) + * this); ll.setImmediate(true); if (((Boolean) + * ll.getValue()).booleanValue()) { + * set.getField("multiSelect").setVisible(false); + * set.getField("newItemsAllowed").setVisible(false); } + */ + if (objectToConfigure instanceof Tree + || objectToConfigure instanceof Table) { + set.removeItemProperty("newItemsAllowed"); + set.removeItemProperty("lazyLoading"); + } + } + + /** Field special properties */ + private void addFieldProperties() { + // TODO bug #211 states that setFocus works only for Button and + // Textfield UI components + Form set = new Form(new GridLayout(COLUMNS, 1)); + set.addField("focus", new Button("Focus", objectToConfigure, "focus")); + set.getField("focus").setDescription( + "Focus the cursor to this field. Not all " + + "components and/or terminals support this feature."); + addProperties("Field Features", set); + } + + /** + * Add and remove some miscellaneous example component to/from component + * container + */ + private void addComponentContainerProperties() { + Form set = new Form(new OrderedLayout( + OrderedLayout.ORIENTATION_VERTICAL)); + + addComponent = new Select(); + addComponent.setImmediate(true); + addComponent.addItem("Add component to container"); + addComponent.setNullSelectionItemId("Add component to container"); + addComponent.addItem("Text field"); + addComponent.addItem("Option group"); + addComponent.addListener(this); + + set.addField("component adder", addComponent); + set.addField("remove all components", new Button( + "Remove all components", objectToConfigure, + "removeAllComponents")); + + addProperties("ComponentContainer Features", set); + } + + /** Value change listener for listening selections */ + public void valueChange(Property.ValueChangeEvent event) { + + // FIXME: navigation statistics + try { + FeatureUtil.debug(getApplication().getUser().toString(), + "valueChange " + + ((AbstractComponent) event.getProperty()) + .getTag() + ", " + event.getProperty()); + } catch (Exception e) { + // ignored, should never happen + } + + // Adding components to component container + if (event.getProperty() == addComponent) { + String value = (String) addComponent.getValue(); + + if (value != null) { + // TextField component + if (value.equals("Text field")) { + ((AbstractComponentContainer) objectToConfigure) + .addComponent(new TextField("Test field")); + } + + // DateField time style + if (value.equals("Time")) { + DateField d = new DateField("Time", new Date()); + d + .setDescription("This is a DateField-component with text-style"); + d.setResolution(DateField.RESOLUTION_MIN); + d.setStyle("text"); + ((AbstractComponentContainer) objectToConfigure) + .addComponent(d); + } + + // Date field calendar style + if (value.equals("Calendar")) { + DateField c = new DateField("Calendar", new Date()); + c + .setDescription("DateField-component with calendar-style and day-resolution"); + c.setStyle("calendar"); + c.setResolution(DateField.RESOLUTION_DAY); + ((AbstractComponentContainer) objectToConfigure) + .addComponent(c); + } + + // Select option group style + if (value.equals("Option group")) { + Select s = new Select("Options"); + s.setDescription("Select-component with optiongroup-style"); + s.addItem("Linux"); + s.addItem("Windows"); + s.addItem("Solaris"); + s.addItem("Symbian"); + s.setStyle("optiongroup"); + + ((AbstractComponentContainer) objectToConfigure) + .addComponent(s); + } + + addComponent.setValue(null); + } + } else if (event.getProperty() == getField("lazyLoading")) { + boolean newValue = ((Boolean) event.getProperty().getValue()) + .booleanValue(); + Field multiselect = getField("multiSelect"); + Field newitems = getField("newItemsAllowed"); + if (newValue) { + newitems.setValue(Boolean.FALSE); + newitems.setVisible(false); + multiselect.setValue(Boolean.FALSE); + multiselect.setVisible(false); + } else { + newitems.setVisible(true); + multiselect.setVisible(true); + } + } + } + + /** Handle all button clicks for this panel */ + public void buttonClick(Button.ClickEvent event) { + // FIXME: navigation statistics + try { + FeatureUtil.debug(getApplication().getUser().toString(), + "buttonClick " + event.getButton().getTag() + ", " + + event.getButton().getCaption() + ", " + + event.getButton().getValue()); + } catch (Exception e) { + // ignored, should never happen + } + // Commit all changed on all forms + if (event.getButton() == setButton) { + commit(); + } + + // Discard all changed on all forms + if (event.getButton() == discardButton) { + for (Iterator i = forms.iterator(); i.hasNext();) { + ((Form) i.next()).discard(); + } + } + + } + + /** + * Helper function for creating forms from array of propety names. + */ + protected Form createBeanPropertySet(String names[]) { + + Form set = new Form(new OrderedLayout( + OrderedLayout.ORIENTATION_VERTICAL)); + + for (int i = 0; i < names.length; i++) { + Property p = config.getItemProperty(names[i]); + if (p != null) { + set.addItemProperty(names[i], p); + Field f = set.getField(names[i]); + if (f instanceof TextField) { + if (Integer.class.equals(p.getType())) { + ((TextField) f).setColumns(4); + } else { + ((TextField) f).setNullSettingAllowed(true); + ((TextField) f).setColumns(24); + } + } + } + } + + return set; + } + + /** Find a field from all forms */ + public Field getField(Object propertyId) { + for (Iterator i = forms.iterator(); i.hasNext();) { + Form f = (Form) i.next(); + Field af = f.getField(propertyId); + if (af != null) { + return af; + } + } + return null; + } + + public Table getAllProperties() { + return allProperties; + } + + protected void commit() { + for (Iterator i = forms.iterator(); i.hasNext();) { + ((Form) i.next()).commit(); + } + } + + private void disableField(Field field) { + field.setEnabled(false); + field.setReadOnly(true); + } + + private void disableField(Field field, Object value) { + field.setValue(value); + disableField(field); + } } diff --git a/src/com/itmill/toolkit/tests/magi/DefaultButtonExample.java b/src/com/itmill/toolkit/tests/magi/DefaultButtonExample.java index 991264d206..a91493eb79 100644 --- a/src/com/itmill/toolkit/tests/magi/DefaultButtonExample.java +++ b/src/com/itmill/toolkit/tests/magi/DefaultButtonExample.java @@ -1,84 +1,97 @@ package com.itmill.toolkit.tests.magi; + import com.itmill.toolkit.event.Action; import com.itmill.toolkit.event.ShortcutAction; import com.itmill.toolkit.event.Action.Handler; -import com.itmill.toolkit.ui.*; +import com.itmill.toolkit.ui.Button; +import com.itmill.toolkit.ui.CustomComponent; +import com.itmill.toolkit.ui.Label; +import com.itmill.toolkit.ui.OrderedLayout; +import com.itmill.toolkit.ui.Panel; +import com.itmill.toolkit.ui.TextField; public class DefaultButtonExample extends CustomComponent implements Handler { - // Define and create user interface components - Panel panel = new Panel("Login"); - OrderedLayout formlayout = new OrderedLayout(OrderedLayout.ORIENTATION_VERTICAL); - TextField username = new TextField("Username"); - TextField password = new TextField("Password"); - OrderedLayout buttons = new OrderedLayout(OrderedLayout.ORIENTATION_HORIZONTAL); - - // Create buttons and define their listener methods. Here we use parameterless - // methods so that we can use same methods for both click events and keyboard - // actions. - Button ok = new Button("OK", this, "okHandler"); - Button cancel = new Button("Cancel", this, "cancelHandler"); + // Define and create user interface components + Panel panel = new Panel("Login"); + OrderedLayout formlayout = new OrderedLayout( + OrderedLayout.ORIENTATION_VERTICAL); + TextField username = new TextField("Username"); + TextField password = new TextField("Password"); + OrderedLayout buttons = new OrderedLayout( + OrderedLayout.ORIENTATION_HORIZONTAL); + + // Create buttons and define their listener methods. Here we use + // parameterless + // methods so that we can use same methods for both click events and + // keyboard + // actions. + Button ok = new Button("OK", this, "okHandler"); + Button cancel = new Button("Cancel", this, "cancelHandler"); + + public DefaultButtonExample() { + // Set up the user interface + setCompositionRoot(panel); + panel.addComponent(formlayout); + formlayout.addComponent(username); + formlayout.addComponent(password); + formlayout.setStyle("form"); + formlayout.addComponent(buttons); + buttons.addComponent(ok); + buttons.addComponent(cancel); + + // Set focus to username + username.focus(); - public DefaultButtonExample() { - // Set up the user interface - setCompositionRoot(panel); - panel.addComponent(formlayout); - formlayout.addComponent(username); - formlayout.addComponent(password); - formlayout.setStyle("form"); - formlayout.addComponent(buttons); - buttons.addComponent(ok); - buttons.addComponent(cancel); - - // Set focus to username - username.focus(); - - // Set this object as the action handler for actions related to the Ok - // and Cancel buttons. - // @TODO - //ok.addActionHandler(this); - //cancel.addActionHandler(this); - } + // Set this object as the action handler for actions related to the Ok + // and Cancel buttons. + // @TODO + // ok.addActionHandler(this); + // cancel.addActionHandler(this); + } - /** - * Retrieve actions for a specific component. This method will be called for each - * object that has a handler; in this example the Ok and Cancel buttons. - **/ - public Action[] getActions(Object target, Object sender) { - Action[] actions = new Action[1]; + /** + * Retrieve actions for a specific component. This method will be called for + * each object that has a handler; in this example the Ok and Cancel + * buttons. + */ + public Action[] getActions(Object target, Object sender) { + Action[] actions = new Action[1]; - // Set the action for the requested component + // Set the action for the requested component if (sender == ok) { - // Bind the unmodified Enter key to the Ok button. + // Bind the unmodified Enter key to the Ok button. actions[0] = new ShortcutAction("Default key", - ShortcutAction.KeyCode.ENTER, null); + ShortcutAction.KeyCode.ENTER, null); } else if (sender == cancel) { - // Bind "C" key modified with Alt to the Cancel button. - actions[0] = new ShortcutAction("Alt+C", - ShortcutAction.KeyCode.C, new int[] { - ShortcutAction.ModifierKey.ALT}); - } else - return null; - return actions; - } + // Bind "C" key modified with Alt to the Cancel button. + actions[0] = new ShortcutAction("Alt+C", ShortcutAction.KeyCode.C, + new int[] { ShortcutAction.ModifierKey.ALT }); + } else { + return null; + } + return actions; + } - /** - * Handle actions received from keyboard. This simply directs the actions to - * the same listener methods that are called with ButtonClick events. - **/ - public void handleAction(Action action, Object sender, Object target) { - if (target == ok) - this.okHandler(); - if (target == cancel) - this.cancelHandler(); - } + /** + * Handle actions received from keyboard. This simply directs the actions to + * the same listener methods that are called with ButtonClick events. + */ + public void handleAction(Action action, Object sender, Object target) { + if (target == ok) { + okHandler(); + } + if (target == cancel) { + cancelHandler(); + } + } - public void okHandler() { - // Do something: report the click - formlayout.addComponent(new Label("OK clicked")); - } + public void okHandler() { + // Do something: report the click + formlayout.addComponent(new Label("OK clicked")); + } - public void cancelHandler() { - // Do something: report the click - formlayout.addComponent(new Label("Cancel clicked")); - } + public void cancelHandler() { + // Do something: report the click + formlayout.addComponent(new Label("Cancel clicked")); + } } diff --git a/src/com/itmill/toolkit/tests/magi/EmbeddedButton.java b/src/com/itmill/toolkit/tests/magi/EmbeddedButton.java index d447f2ba64..0f32304331 100644 --- a/src/com/itmill/toolkit/tests/magi/EmbeddedButton.java +++ b/src/com/itmill/toolkit/tests/magi/EmbeddedButton.java @@ -1,30 +1,35 @@ package com.itmill.toolkit.tests.magi; -import com.itmill.toolkit.ui.*; -import com.itmill.toolkit.terminal.*; - -public class EmbeddedButton extends CustomComponent implements Button.ClickListener { - Button thebutton; - - public EmbeddedButton(Resource icon) { - /* Create a Button without a caption. */ - thebutton = new Button (); - - /* Set the icon of the button from a resource. */ - thebutton.setIcon(icon); - - /* Set the style to link; this leaves out the button frame so you - * just have the image in the link. */ - thebutton.setStyle("link"); - - /* Listen for ClickEvents. */ - thebutton.addListener(this); - - setCompositionRoot(thebutton); - } - - /** Handle button click events from the button. */ - public void buttonClick (Button.ClickEvent event) { - thebutton.setIcon(null); - thebutton.setCaption ("You successfully clicked on the icon"); - } + +import com.itmill.toolkit.terminal.Resource; +import com.itmill.toolkit.ui.Button; +import com.itmill.toolkit.ui.CustomComponent; + +public class EmbeddedButton extends CustomComponent implements + Button.ClickListener { + Button thebutton; + + public EmbeddedButton(Resource icon) { + /* Create a Button without a caption. */ + thebutton = new Button(); + + /* Set the icon of the button from a resource. */ + thebutton.setIcon(icon); + + /* + * Set the style to link; this leaves out the button frame so you just + * have the image in the link. + */ + thebutton.setStyle("link"); + + /* Listen for ClickEvents. */ + thebutton.addListener(this); + + setCompositionRoot(thebutton); + } + + /** Handle button click events from the button. */ + public void buttonClick(Button.ClickEvent event) { + thebutton.setIcon(null); + thebutton.setCaption("You successfully clicked on the icon"); + } } diff --git a/src/com/itmill/toolkit/tests/magi/MyUploader.java b/src/com/itmill/toolkit/tests/magi/MyUploader.java index a55ef4791b..ef8efa8d5f 100644 --- a/src/com/itmill/toolkit/tests/magi/MyUploader.java +++ b/src/com/itmill/toolkit/tests/magi/MyUploader.java @@ -12,69 +12,69 @@ import com.itmill.toolkit.ui.Panel; import com.itmill.toolkit.ui.Upload; public class MyUploader extends CustomComponent implements - Upload.FinishedListener { - MyUploadReceiver uploadReceiver; /* Upload receiver object. */ - Panel root; /* Root element for contained components. */ - Panel imagePanel; /* Panel that contains the uploaded image. */ + Upload.FinishedListener { + MyUploadReceiver uploadReceiver; /* Upload receiver object. */ + Panel root; /* Root element for contained components. */ + Panel imagePanel; /* Panel that contains the uploaded image. */ - /* Custom upload receiver that has to be implemented for Upload. */ - class MyUploadReceiver implements Upload.Receiver { - java.io.File file; /* File to write to. */ - java.io.FileOutputStream fos; /* Output stream to write to. */ + /* Custom upload receiver that has to be implemented for Upload. */ + class MyUploadReceiver implements Upload.Receiver { + java.io.File file; /* File to write to. */ + java.io.FileOutputStream fos; /* Output stream to write to. */ - public OutputStream receiveUpload(String filename, String MIMEType) { - file = new File("/tmp/uploads/" + filename); - try { - /* Open the file for writing. */ - fos = new FileOutputStream(file); - } catch (java.io.FileNotFoundException e) { - return null; /* - * Error while opening the file. Not reported - * here. - */ - } + public OutputStream receiveUpload(String filename, String MIMEType) { + file = new File("/tmp/uploads/" + filename); + try { + /* Open the file for writing. */ + fos = new FileOutputStream(file); + } catch (java.io.FileNotFoundException e) { + return null; /* + * Error while opening the file. Not reported + * here. + */ + } - return fos; /* Return the output stream. */ - } + return fos; /* Return the output stream. */ + } - public File getFile() { - return file; - } - } + public File getFile() { + return file; + } + } - MyUploader() { - root = new Panel("My Upload Component"); - setCompositionRoot(root); + MyUploader() { + root = new Panel("My Upload Component"); + setCompositionRoot(root); - /* Create the upload receiver required by Upload. */ - uploadReceiver = new MyUploadReceiver(); + /* Create the upload receiver required by Upload. */ + uploadReceiver = new MyUploadReceiver(); - /* Create the Upload component. */ - Upload upload = new Upload("Upload", uploadReceiver); + /* Create the Upload component. */ + Upload upload = new Upload("Upload", uploadReceiver); - /* Listen for Upload.FinishedEvent events. */ - upload.addListener(this); + /* Listen for Upload.FinishedEvent events. */ + upload.addListener(this); - root.addComponent(upload); - root.addComponent(new Label( - "Click 'Browse' to select a file and then click 'Upload'.")); + root.addComponent(upload); + root.addComponent(new Label( + "Click 'Browse' to select a file and then click 'Upload'.")); - /* Create a panel for displaying the uploaded file (image). */ - imagePanel = new Panel("Uploaded image"); - imagePanel.addComponent(new Label("No image uploaded yet")); - root.addComponent(imagePanel); - } + /* Create a panel for displaying the uploaded file (image). */ + imagePanel = new Panel("Uploaded image"); + imagePanel.addComponent(new Label("No image uploaded yet")); + root.addComponent(imagePanel); + } - /* This is called when the upload is finished. */ - public void uploadFinished(Upload.FinishedEvent event) { - /* Log the upload on screen. */ - root.addComponent(new Label("File " + event.getFilename() - + " of type '" + event.getMIMEType() + "' uploaded.")); + /* This is called when the upload is finished. */ + public void uploadFinished(Upload.FinishedEvent event) { + /* Log the upload on screen. */ + root.addComponent(new Label("File " + event.getFilename() + + " of type '" + event.getMIMEType() + "' uploaded.")); - /* Display the uploaded file in the image panel. */ - FileResource imageResource = new FileResource(uploadReceiver.getFile(), - getApplication()); - imagePanel.removeAllComponents(); - imagePanel.addComponent(new Embedded("", imageResource)); - } + /* Display the uploaded file in the image panel. */ + FileResource imageResource = new FileResource(uploadReceiver.getFile(), + getApplication()); + imagePanel.removeAllComponents(); + imagePanel.addComponent(new Embedded("", imageResource)); + } } diff --git a/src/com/itmill/toolkit/tests/magi/SSNField.java b/src/com/itmill/toolkit/tests/magi/SSNField.java index f513e6b97d..9333abf369 100644 --- a/src/com/itmill/toolkit/tests/magi/SSNField.java +++ b/src/com/itmill/toolkit/tests/magi/SSNField.java @@ -12,88 +12,88 @@ import com.itmill.toolkit.ui.TextField; /* Finnish Social Security Number input field that validates the value. */ public class SSNField extends CustomComponent implements - Property.ValueChangeListener { - OrderedLayout layout = new OrderedLayout( - OrderedLayout.ORIENTATION_HORIZONTAL); - TextField myfield; - Label myerror; - - /** Validator for Finnish Social Security Number. */ - class SSNValidator implements Validator { - - /** The isValid() is simply a wrapper for the validate() method. */ - public boolean isValid(Object value) { - try { - validate(value); - } catch (InvalidValueException e) { - return false; - } - return true; - } - - /** Validate the given SSN. */ - public void validate(Object value) throws InvalidValueException { - String ssn = (String) value; - if (ssn.length() != 11) { - throw new InvalidValueException("Invalid SSN length"); - } - - String numbers = ssn.substring(0, 6) + ssn.substring(7, 10); - int checksum = new Integer(numbers).intValue() % 31; - if (!ssn.substring(10).equals( - "0123456789ABCDEFHJKLMNPRSTUVWXY".substring(checksum, - checksum + 1))) { - throw new InvalidValueException("Invalid SSN checksum"); - } - } - } - - SSNField() { - setCompositionRoot(layout); - layout.setStyle("form"); - - /* Create the text field for the SSN. */ - myfield = new TextField("Social Security Number"); - myfield.setColumns(11); - myfield.setFormat(new MessageFormat("{0,number,##}")); - - /* Create and set the validator object for the field. */ - SSNValidator ssnvalidator = new SSNValidator(); - myfield.addValidator(ssnvalidator); - - /* - * ValueChageEvent will be generated immediately when the component - * loses focus. - */ - myfield.setImmediate(true); - - /* Listen for ValueChangeEvent events. */ - myfield.addListener(this); - - layout.addComponent(myfield); - - /* The field will have an error label, normally invisible. */ - myerror = new Label(); - layout.addComponent(myerror); - } - - public void valueChange(ValueChangeEvent event) { - try { - /* Validate the field value. */ - myfield.validate(); - - /* The value was correct. */ - myerror.setValue("Ok"); - myfield.setStyle(""); - } catch (Validator.InvalidValueException e) { - /* Report the error message to the user. */ - myerror.setValue(e.getMessage()); - - /* - * The CSS defines that text field with the "error" class will be - * colored red. - */ - myfield.setStyle("error"); - } - } + Property.ValueChangeListener { + OrderedLayout layout = new OrderedLayout( + OrderedLayout.ORIENTATION_HORIZONTAL); + TextField myfield; + Label myerror; + + /** Validator for Finnish Social Security Number. */ + class SSNValidator implements Validator { + + /** The isValid() is simply a wrapper for the validate() method. */ + public boolean isValid(Object value) { + try { + validate(value); + } catch (InvalidValueException e) { + return false; + } + return true; + } + + /** Validate the given SSN. */ + public void validate(Object value) throws InvalidValueException { + String ssn = (String) value; + if (ssn.length() != 11) { + throw new InvalidValueException("Invalid SSN length"); + } + + String numbers = ssn.substring(0, 6) + ssn.substring(7, 10); + int checksum = new Integer(numbers).intValue() % 31; + if (!ssn.substring(10).equals( + "0123456789ABCDEFHJKLMNPRSTUVWXY".substring(checksum, + checksum + 1))) { + throw new InvalidValueException("Invalid SSN checksum"); + } + } + } + + SSNField() { + setCompositionRoot(layout); + layout.setStyle("form"); + + /* Create the text field for the SSN. */ + myfield = new TextField("Social Security Number"); + myfield.setColumns(11); + myfield.setFormat(new MessageFormat("{0,number,##}")); + + /* Create and set the validator object for the field. */ + SSNValidator ssnvalidator = new SSNValidator(); + myfield.addValidator(ssnvalidator); + + /* + * ValueChageEvent will be generated immediately when the component + * loses focus. + */ + myfield.setImmediate(true); + + /* Listen for ValueChangeEvent events. */ + myfield.addListener(this); + + layout.addComponent(myfield); + + /* The field will have an error label, normally invisible. */ + myerror = new Label(); + layout.addComponent(myerror); + } + + public void valueChange(ValueChangeEvent event) { + try { + /* Validate the field value. */ + myfield.validate(); + + /* The value was correct. */ + myerror.setValue("Ok"); + myfield.setStyle(""); + } catch (Validator.InvalidValueException e) { + /* Report the error message to the user. */ + myerror.setValue(e.getMessage()); + + /* + * The CSS defines that text field with the "error" class will be + * colored red. + */ + myfield.setStyle("error"); + } + } } diff --git a/src/com/itmill/toolkit/tests/magi/SelectExample.java b/src/com/itmill/toolkit/tests/magi/SelectExample.java index e972c19ab8..112f1c9c77 100644 --- a/src/com/itmill/toolkit/tests/magi/SelectExample.java +++ b/src/com/itmill/toolkit/tests/magi/SelectExample.java @@ -2,101 +2,113 @@ package com.itmill.toolkit.tests.magi; import com.itmill.toolkit.Application; import com.itmill.toolkit.data.Property; -import com.itmill.toolkit.ui.*; +import com.itmill.toolkit.ui.AbstractSelect; +import com.itmill.toolkit.ui.CustomComponent; +import com.itmill.toolkit.ui.Label; +import com.itmill.toolkit.ui.NativeSelect; +import com.itmill.toolkit.ui.OptionGroup; +import com.itmill.toolkit.ui.OrderedLayout; +import com.itmill.toolkit.ui.Select; +import com.itmill.toolkit.ui.TwinColSelect; /* Let us add an implementation of the ValueChangeListener interface. */ -public class SelectExample extends CustomComponent implements Property.ValueChangeListener { - - class Planet extends Object { - String planetName; - - Planet(String name) { - planetName = name; - } - - public String toString() { - return "The Planet " + planetName; - } - } - - /* Create the Select object with a caption. */ - AbstractSelect select; - - OrderedLayout layout = new OrderedLayout(OrderedLayout.ORIENTATION_VERTICAL); - Label status = new Label(""); - - SelectExample(Application application, String param, String caption, boolean multiselect) { - if (param.equals("optiongroup")) { - select = new OptionGroup(caption); - select.setMultiSelect(multiselect); - } else if (param.equals("twincol")) { - select = new TwinColSelect(caption); - } else if (param.equals("native")) { - select = new NativeSelect(caption); - } else if (param.equals("filter")) { - select = new Select(caption); - ((Select)select).setFilteringMode(AbstractSelect.Filtering.FILTERINGMODE_CONTAINS); - } else { - select = new Select(caption); - select.setMultiSelect(multiselect); - } - - layout.addComponent(select); - setCompositionRoot(layout); - - /* Fill the component with some items. */ - final String[] planets = new String[] {"Mercury", "Venus", "Earth", - "Mars", "Jupiter", "Saturn", "Uranus", "Neptune" }; - - for (int i = 0; i < planets.length; i++) { - select.addItem(planets[i]); - - /* Create an item with an Integer as the Item ID. */ - // select.addItem(i); - // select.addItem(new Planet(planets[i])); - /* Set the visible caption of the item. */ - // select.setItemCaption(i, planets[i]); - /* - * ClassResource icon = new ClassResource - * ("images/"+planets[i]+"_symbol.png", application); - * layout.addComponent(new Embedded ("Icon", icon)); - * select.setItemIcon(i, icon); - */ - } - - /* By default, the change event is not triggered immediately when the - * selection changes. This enables it. */ - select.setImmediate(true); - - /* Listen for changes in the selection. */ - select.addListener(this); - - //select.setStyle("twincol"); - //select.setMultiSelect(true); - //select.setNewItemsAllowed(true); - // int a=1; - - // select.setItemCaptionMode(Select.ITEM_CAPTION_MODE_ICON_ONLY); - //select.setNullSelectionItemId("-- select somethingd --"); - //select.setNullSelectionAllowed(false); - - layout.addComponent(status); - } - - /* Respond to change in the selection. */ - public void valueChange(Property.ValueChangeEvent event) { - /* - * The event.getProperty() returns the component. The currently selected - * item is the property of the component, retrievable with getValue(). - */ - if (false) { - status.setValue("Currently selected item ID: " - + event.getProperty().getValue() + "
" - + "Class of the Item ID: " - + event.getProperty().getValue().getClass().getName() - + "
" + "Caption: " - + select.getItemCaption(event.getProperty().getValue())); - status.setContentMode(Label.CONTENT_XHTML); - } - } +public class SelectExample extends CustomComponent implements + Property.ValueChangeListener { + + class Planet extends Object { + String planetName; + + Planet(String name) { + planetName = name; + } + + public String toString() { + return "The Planet " + planetName; + } + } + + /* Create the Select object with a caption. */ + AbstractSelect select; + + OrderedLayout layout = new OrderedLayout(OrderedLayout.ORIENTATION_VERTICAL); + Label status = new Label(""); + + SelectExample(Application application, String param, String caption, + boolean multiselect) { + if (param.equals("optiongroup")) { + select = new OptionGroup(caption); + select.setMultiSelect(multiselect); + } else if (param.equals("twincol")) { + select = new TwinColSelect(caption); + } else if (param.equals("native")) { + select = new NativeSelect(caption); + } else if (param.equals("filter")) { + select = new Select(caption); + ((Select) select) + .setFilteringMode(AbstractSelect.Filtering.FILTERINGMODE_CONTAINS); + } else { + select = new Select(caption); + select.setMultiSelect(multiselect); + } + + layout.addComponent(select); + setCompositionRoot(layout); + + /* Fill the component with some items. */ + final String[] planets = new String[] { "Mercury", "Venus", "Earth", + "Mars", "Jupiter", "Saturn", "Uranus", "Neptune" }; + + for (int i = 0; i < planets.length; i++) { + select.addItem(planets[i]); + + /* Create an item with an Integer as the Item ID. */ + // select.addItem(i); + // select.addItem(new Planet(planets[i])); + /* Set the visible caption of the item. */ + // select.setItemCaption(i, planets[i]); + /* + * ClassResource icon = new ClassResource + * ("images/"+planets[i]+"_symbol.png", application); + * layout.addComponent(new Embedded ("Icon", icon)); + * select.setItemIcon(i, icon); + */ + } + + /* + * By default, the change event is not triggered immediately when the + * selection changes. This enables it. + */ + select.setImmediate(true); + + /* Listen for changes in the selection. */ + select.addListener(this); + + // select.setStyle("twincol"); + // select.setMultiSelect(true); + // select.setNewItemsAllowed(true); + // int a=1; + + // select.setItemCaptionMode(Select.ITEM_CAPTION_MODE_ICON_ONLY); + // select.setNullSelectionItemId("-- select somethingd --"); + // select.setNullSelectionAllowed(false); + + layout.addComponent(status); + } + + /* Respond to change in the selection. */ + public void valueChange(Property.ValueChangeEvent event) { + /* + * The event.getProperty() returns the component. The currently selected + * item is the property of the component, retrievable with getValue(). + */ + if (false) { + status.setValue("Currently selected item ID: " + + event.getProperty().getValue() + "
" + + "Class of the Item ID: " + + event.getProperty().getValue().getClass().getName() + + "
" + "Caption: " + + select.getItemCaption(event.getProperty().getValue())); + status.setContentMode(Label.CONTENT_XHTML); + } + } } diff --git a/src/com/itmill/toolkit/tests/magi/TableExample.java b/src/com/itmill/toolkit/tests/magi/TableExample.java index e9431d0015..989fc863cc 100644 --- a/src/com/itmill/toolkit/tests/magi/TableExample.java +++ b/src/com/itmill/toolkit/tests/magi/TableExample.java @@ -5,46 +5,46 @@ import com.itmill.toolkit.ui.OrderedLayout; import com.itmill.toolkit.ui.Table; public class TableExample extends CustomComponent { - /* Create the table with a caption. */ - Table table = new Table("This is a Table"); - - /* A layout needed for the example. */ - OrderedLayout layout = new OrderedLayout(OrderedLayout.ORIENTATION_VERTICAL); - - TableExample() { - setCompositionRoot(layout); - layout.addComponent(table); - - /* Define the names, data types, and default values of columns. */ - table.addContainerProperty("First Name", String.class, - "(no first name)"); - table.addContainerProperty("Last Name", String.class, "(no last name)"); - table.addContainerProperty("Year", Integer.class, null); - - /* We use these entries to generate random items in a table. */ - final String[] firstnames = new String[] { "Donald", "Patty", "Sally", - "Douglas" }; - final String[] lastnames = new String[] { "Smith", "Jones", "Adams", - "Knuth" }; - - /* Add some items in the table and assign them an Item ID (IID). */ - for (int i = 0; i < 500; i++) { - /* Add a randomly generated item in the Table. */ - table - .addItem( - new Object[] { - firstnames[(int) (Math.random() * (firstnames.length - 0.01))], - lastnames[(int) (Math.random() * (lastnames.length - 0.01))], - new Integer( - (int) (1900 + Math.random() * 100)) }, - new Integer(i)); - } - - /* Set the number of items visible in the table. */ - table.setPageLength(10); - - table.setStyle("twincol"); - table.setColumnReorderingAllowed(true); - table.setColumnCollapsingAllowed(true); - } + /* Create the table with a caption. */ + Table table = new Table("This is a Table"); + + /* A layout needed for the example. */ + OrderedLayout layout = new OrderedLayout(OrderedLayout.ORIENTATION_VERTICAL); + + TableExample() { + setCompositionRoot(layout); + layout.addComponent(table); + + /* Define the names, data types, and default values of columns. */ + table.addContainerProperty("First Name", String.class, + "(no first name)"); + table.addContainerProperty("Last Name", String.class, "(no last name)"); + table.addContainerProperty("Year", Integer.class, null); + + /* We use these entries to generate random items in a table. */ + final String[] firstnames = new String[] { "Donald", "Patty", "Sally", + "Douglas" }; + final String[] lastnames = new String[] { "Smith", "Jones", "Adams", + "Knuth" }; + + /* Add some items in the table and assign them an Item ID (IID). */ + for (int i = 0; i < 500; i++) { + /* Add a randomly generated item in the Table. */ + table + .addItem( + new Object[] { + firstnames[(int) (Math.random() * (firstnames.length - 0.01))], + lastnames[(int) (Math.random() * (lastnames.length - 0.01))], + new Integer( + (int) (1900 + Math.random() * 100)) }, + new Integer(i)); + } + + /* Set the number of items visible in the table. */ + table.setPageLength(10); + + table.setStyle("twincol"); + table.setColumnReorderingAllowed(true); + table.setColumnCollapsingAllowed(true); + } } diff --git a/src/com/itmill/toolkit/tests/magi/TheButton.java b/src/com/itmill/toolkit/tests/magi/TheButton.java index d480a503aa..4f41e2ddde 100644 --- a/src/com/itmill/toolkit/tests/magi/TheButton.java +++ b/src/com/itmill/toolkit/tests/magi/TheButton.java @@ -1,21 +1,23 @@ package com.itmill.toolkit.tests.magi; -import com.itmill.toolkit.ui.*; + +import com.itmill.toolkit.ui.Button; +import com.itmill.toolkit.ui.CustomComponent; public class TheButton extends CustomComponent implements Button.ClickListener { - Button thebutton; + Button thebutton; + + public TheButton() { + /* Create a Button with the given caption. */ + thebutton = new Button("Do not push this button"); + + /* Listen for ClickEvents. */ + thebutton.addListener(this); - public TheButton() { - /* Create a Button with the given caption. */ - thebutton = new Button ("Do not push this button"); - - /* Listen for ClickEvents. */ - thebutton.addListener(this); + setCompositionRoot(thebutton); + } - setCompositionRoot(thebutton); - } - - /** Handle button click events from the button. */ - public void buttonClick (Button.ClickEvent event) { - thebutton.setCaption ("Do not push this button again"); - } + /** Handle button click events from the button. */ + public void buttonClick(Button.ClickEvent event) { + thebutton.setCaption("Do not push this button again"); + } } diff --git a/src/com/itmill/toolkit/tests/magi/TheButtons.java b/src/com/itmill/toolkit/tests/magi/TheButtons.java index 32eb646452..64962b2260 100644 --- a/src/com/itmill/toolkit/tests/magi/TheButtons.java +++ b/src/com/itmill/toolkit/tests/magi/TheButtons.java @@ -1,26 +1,29 @@ package com.itmill.toolkit.tests.magi; -import com.itmill.toolkit.ui.*; + +import com.itmill.toolkit.ui.AbstractComponentContainer; +import com.itmill.toolkit.ui.Button; public class TheButtons implements Button.ClickListener { - Button thebutton; - Button secondbutton; + Button thebutton; + Button secondbutton; + + /** Creates two buttons into given container. */ + public TheButtons(AbstractComponentContainer container) { + thebutton = new Button("Do not push this button"); + thebutton.addListener(this); + container.addComponent(thebutton); + + secondbutton = new Button("I am a button too"); + secondbutton.addListener(this); + container.addComponent(secondbutton); + } - /** Creates two buttons into given container. */ - public TheButtons(AbstractComponentContainer container) { - thebutton = new Button ("Do not push this button"); - thebutton.addListener(this); - container.addComponent(thebutton); - - secondbutton = new Button ("I am a button too"); - secondbutton.addListener(this); - container.addComponent (secondbutton); - } - - /** Handle button click events from the two buttons. */ - public void buttonClick (Button.ClickEvent event) { - if (event.getButton() == thebutton) - thebutton.setCaption ("Do not push this button again"); - else if (event.getButton() == secondbutton) - secondbutton.setCaption ("I am not a number"); - } + /** Handle button click events from the two buttons. */ + public void buttonClick(Button.ClickEvent event) { + if (event.getButton() == thebutton) { + thebutton.setCaption("Do not push this button again"); + } else if (event.getButton() == secondbutton) { + secondbutton.setCaption("I am not a number"); + } + } } diff --git a/src/com/itmill/toolkit/tests/magi/TheButtons2.java b/src/com/itmill/toolkit/tests/magi/TheButtons2.java index ffe84d92bb..b4604df873 100644 --- a/src/com/itmill/toolkit/tests/magi/TheButtons2.java +++ b/src/com/itmill/toolkit/tests/magi/TheButtons2.java @@ -1,26 +1,29 @@ package com.itmill.toolkit.tests.magi; -import com.itmill.toolkit.ui.*; + +import com.itmill.toolkit.ui.AbstractComponentContainer; +import com.itmill.toolkit.ui.Button; public class TheButtons2 { - Button thebutton; - Button secondbutton; + Button thebutton; + Button secondbutton; + + /** Creates two buttons in given container. */ + public TheButtons2(AbstractComponentContainer container) { + thebutton = new Button("Do not push this button"); + thebutton.addListener(Button.ClickEvent.class, this, "theButtonClick"); + container.addComponent(thebutton); + + secondbutton = new Button("I am a button too"); + secondbutton.addListener(Button.ClickEvent.class, this, + "secondButtonClick"); + container.addComponent(secondbutton); + } - /** Creates two buttons in given container. */ - public TheButtons2(AbstractComponentContainer container) { - thebutton = new Button ("Do not push this button"); - thebutton.addListener(Button.ClickEvent.class, this, "theButtonClick"); - container.addComponent(thebutton); - - secondbutton = new Button ("I am a button too"); - secondbutton.addListener(Button.ClickEvent.class, this, "secondButtonClick"); - container.addComponent (secondbutton); - } - - public void theButtonClick (Button.ClickEvent event) { - thebutton.setCaption ("Do not push this button again"); - } + public void theButtonClick(Button.ClickEvent event) { + thebutton.setCaption("Do not push this button again"); + } - public void secondButtonClick (Button.ClickEvent event) { - secondbutton.setCaption ("I am not a number!"); - } + public void secondButtonClick(Button.ClickEvent event) { + secondbutton.setCaption("I am not a number!"); + } } diff --git a/src/com/itmill/toolkit/tests/magi/TheButtons3.java b/src/com/itmill/toolkit/tests/magi/TheButtons3.java index 1d257afd93..a5280efb7f 100644 --- a/src/com/itmill/toolkit/tests/magi/TheButtons3.java +++ b/src/com/itmill/toolkit/tests/magi/TheButtons3.java @@ -1,31 +1,39 @@ package com.itmill.toolkit.tests.magi; -import com.itmill.toolkit.ui.*; + +import com.itmill.toolkit.ui.AbstractComponentContainer; +import com.itmill.toolkit.ui.Button; import com.itmill.toolkit.ui.Button.ClickEvent; /** This example demonstrates the use of inline classes for event listeners. */ public class TheButtons3 { - Button thebutton; /* This component is stored as a member variable. */ - - /** Creates two buttons in given container. */ - public TheButtons3(AbstractComponentContainer container) { - thebutton = new Button ("Do not push this button"); - thebutton.addListener(new Button.ClickListener() { - /* Define the method in the local class to handle the click. */ - public void buttonClick(ClickEvent event) { - thebutton.setCaption ("Do not push this button again"); - } - }); - container.addComponent(thebutton); - - /* Have the second button as a local variable in the constructor. - * Only "final" local variables can be accessed from an anonymous class. */ - final Button secondbutton = new Button ("I am a button too"); - secondbutton.addListener(new Button.ClickListener() { - /* Define the method in the local class to handle the click. */ - public void buttonClick(ClickEvent event) { - secondbutton.setCaption ("I am not a number!"); - } - }); - container.addComponent (secondbutton); - } + Button thebutton; /* This component is stored as a member variable. */ + + /** Creates two buttons in given container. */ + public TheButtons3(AbstractComponentContainer container) { + thebutton = new Button("Do not push this button"); + thebutton.addListener(new Button.ClickListener() { + /* + * Define the method in the local class to handle the click. + */ + public void buttonClick(ClickEvent event) { + thebutton.setCaption("Do not push this button again"); + } + }); + container.addComponent(thebutton); + + /* + * Have the second button as a local variable in the constructor. Only + * "final" local variables can be accessed from an anonymous class. + */ + final Button secondbutton = new Button("I am a button too"); + secondbutton.addListener(new Button.ClickListener() { + /* + * Define the method in the local class to handle the click. + */ + public void buttonClick(ClickEvent event) { + secondbutton.setCaption("I am not a number!"); + } + }); + container.addComponent(secondbutton); + } } diff --git a/src/com/itmill/toolkit/tests/magi/WindowOpener.java b/src/com/itmill/toolkit/tests/magi/WindowOpener.java index d8d0f290aa..c38dbfc9a6 100644 --- a/src/com/itmill/toolkit/tests/magi/WindowOpener.java +++ b/src/com/itmill/toolkit/tests/magi/WindowOpener.java @@ -1,63 +1,70 @@ package com.itmill.toolkit.tests.magi; -import com.itmill.toolkit.ui.*; + +import com.itmill.toolkit.ui.Button; +import com.itmill.toolkit.ui.CustomComponent; +import com.itmill.toolkit.ui.Label; +import com.itmill.toolkit.ui.OrderedLayout; +import com.itmill.toolkit.ui.Window; import com.itmill.toolkit.ui.Window.CloseEvent; /** Component contains a button that allows opening a window. */ -public class WindowOpener extends CustomComponent implements Window.CloseListener { - Window mainwindow; // Reference to main window - Window mywindow; // The window to be opened - Button openbutton; // Button for opening the window - Button closebutton; // A button in the window - Label explanation; // A descriptive text - - public WindowOpener(String label, Window main) { - mainwindow = main; - - /* The component consists of a button that opens the window. */ - OrderedLayout layout = new OrderedLayout (); - layout.addComponent (openbutton = new Button ("Open Window", this, "openButtonClick")); - layout.addComponent (explanation = new Label ("Explanation")); - setCompositionRoot (layout); - } - - /** Handle the clicks for the two buttons. */ - public void openButtonClick (Button.ClickEvent event) { - /* Create a new window. */ - mywindow = new Window("My Dialog"); - - /* Listen for close events for the window. */ - mywindow.addListener((Window.CloseListener) this); - - /* Add components in the window. */ - mywindow.addComponent(new Label("A text label in the window.")); - closebutton = new Button("Close", this, "closeButtonClick"); - mywindow.addComponent(closebutton); - - /* Add the window inside the main window. */ - mainwindow.addWindow(mywindow); - - /* Allow opening only one window at a time. */ - openbutton.setEnabled(false); - - explanation.setValue("Window opened"); - } - - /** Handle Close button click and close the window. */ - public void closeButtonClick (Button.ClickEvent event) { - /* Windows are managed by the application object. */ - mainwindow.removeWindow (mywindow); - - /* Return to initial state. */ - openbutton.setEnabled(true); - - explanation.setValue("Closed with button"); - } - - /** In case the window is closed otherwise. */ - public void windowClose(CloseEvent e) { - /* Return to initial state. */ - openbutton.setEnabled(true); - - explanation.setValue("Closed with window controls"); - } +public class WindowOpener extends CustomComponent implements + Window.CloseListener { + Window mainwindow; // Reference to main window + Window mywindow; // The window to be opened + Button openbutton; // Button for opening the window + Button closebutton; // A button in the window + Label explanation; // A descriptive text + + public WindowOpener(String label, Window main) { + mainwindow = main; + + /* The component consists of a button that opens the window. */ + OrderedLayout layout = new OrderedLayout(); + layout.addComponent(openbutton = new Button("Open Window", this, + "openButtonClick")); + layout.addComponent(explanation = new Label("Explanation")); + setCompositionRoot(layout); + } + + /** Handle the clicks for the two buttons. */ + public void openButtonClick(Button.ClickEvent event) { + /* Create a new window. */ + mywindow = new Window("My Dialog"); + + /* Listen for close events for the window. */ + mywindow.addListener(this); + + /* Add components in the window. */ + mywindow.addComponent(new Label("A text label in the window.")); + closebutton = new Button("Close", this, "closeButtonClick"); + mywindow.addComponent(closebutton); + + /* Add the window inside the main window. */ + mainwindow.addWindow(mywindow); + + /* Allow opening only one window at a time. */ + openbutton.setEnabled(false); + + explanation.setValue("Window opened"); + } + + /** Handle Close button click and close the window. */ + public void closeButtonClick(Button.ClickEvent event) { + /* Windows are managed by the application object. */ + mainwindow.removeWindow(mywindow); + + /* Return to initial state. */ + openbutton.setEnabled(true); + + explanation.setValue("Closed with button"); + } + + /** In case the window is closed otherwise. */ + public void windowClose(CloseEvent e) { + /* Return to initial state. */ + openbutton.setEnabled(true); + + explanation.setValue("Closed with window controls"); + } } diff --git a/src/com/itmill/toolkit/ui/AbstractComponent.java b/src/com/itmill/toolkit/ui/AbstractComponent.java index b0b8181e14..08d447640f 100644 --- a/src/com/itmill/toolkit/ui/AbstractComponent.java +++ b/src/com/itmill/toolkit/ui/AbstractComponent.java @@ -59,904 +59,938 @@ import com.itmill.toolkit.terminal.VariableOwner; */ public abstract class AbstractComponent implements Component, MethodEventSource { - /* Private members ************************************************* */ - - /** - * Style names. - */ - private ArrayList styles; - - /** - * Caption text. - */ - private String caption; - - /** - * Application specific data object. - */ - private Object applicationData; - - /** - * Icon to be shown together with caption. - */ - private Resource icon; - - /** - * Is the component enable (its normal usage is allowed). - */ - private boolean enabled = true; - - /** - * Is the component visible (it is rendered). - */ - private boolean visible = true; - - /** - * Is the component read-only ? - */ - private boolean readOnly = false; - - /** - * Description of the usage (XML). - */ - private String description = null; - - /** - * The container this component resides in. - */ - private Component parent = null; - - /** - * The EventRouter used for the event model. - */ - private EventRouter eventRouter = null; - - /** - * The internal error message of the component. - */ - private ErrorMessage componentError = null; - - /** - * Immediate mode: if true, all variable changes are required to be sent - * from the terminal immediately. - */ - private boolean immediate = false; - - /** - * Locale of this component. - */ - private Locale locale; - - /** - * List of repaint request listeners or null if not listened at all. - */ - private LinkedList repaintRequestListeners = null; - - /** - * Are all the repaint listeners notified about recent changes ? - */ - private boolean repaintRequestListenersNotified = false; - - /* Constructor ***************************************************** */ - - /** - * Constructs a new Component. - */ - public AbstractComponent() { - } - - /* Get/Set component properties ************************************ */ - - /** - * Gets the UIDL tag corresponding to the component. - * - * @return the component's UIDL tag as String - */ - public abstract String getTag(); - - /** - * Gets style for component. Multiple styles are joined with spaces. - * - * @return the component's styleValue of property style. - * @deprecated Use getStyleName() instead; renamed for consistency and to - * indicate that "style" should not be used to switch client - * side implementation, only to style the component. - */ - public String getStyle() { - return getStyleName(); - } - - /** - * Sets and replaces all previous style names of the component. This method - * will trigger a - * {@link com.itmill.toolkit.terminal.Paintable.RepaintRequestEvent RepaintRequestEvent}. - * - * @param style - * the new style of the component. - * @deprecated Use setStyleName() instead; renamed for consistency and to - * indicate that "style" should not be used to switch client - * side implementation, only to style the component. - */ - public void setStyle(String style) { - setStyleName(style); - } - - /* - * Gets the component's style. Don't add a JavaDoc comment here, we use the - * default documentation from implemented interface. - */ - public String getStyleName() { - String s = ""; - if (styles != null) { - for (Iterator it = styles.iterator(); it.hasNext();) { - s += (String) it.next(); - if (it.hasNext()) - s += " "; - } - } - return s; - } - - /* - * Sets the component's style. Don't add a JavaDoc comment here, we use the - * default documentation from implemented interface. - */ - public void setStyleName(String style) { - if (style == null || "".equals(style)) { - styles = null; - requestRepaint(); - return; - } - if (this.styles == null) { - styles = new ArrayList(); - } - styles.clear(); - styles.add(style); - requestRepaint(); - } - - public void addStyleName(String style) { - if (style == null || "".equals(style)) - return; - if (this.styles == null) { - styles = new ArrayList(); - } - if (!styles.contains(style)) { - this.styles.add(style); - requestRepaint(); - } - } - - public void removeStyleName(String style) { - styles.remove(style); - requestRepaint(); - } - - /* - * Get's the component's caption. Don't add a JavaDoc comment here, we use - * the default documentation from implemented interface. - */ - public String getCaption() { - return this.caption; - } - - /** - * Sets the component's caption String. Caption is the - * visible name of the component. This method will trigger a - * {@link com.itmill.toolkit.terminal.Paintable.RepaintRequestEvent RepaintRequestEvent}. - * - * @param caption - * the new caption String for the component. - */ - public void setCaption(String caption) { - this.caption = caption; - requestRepaint(); - } - - /* - * Don't add a JavaDoc comment here, we use the default documentation from - * implemented interface. - */ - public Locale getLocale() { - if (this.locale != null) - return this.locale; - if (this.parent != null) - return parent.getLocale(); - Application app = this.getApplication(); - if (app != null) - return app.getLocale(); - return null; - } - - /** - * Sets the locale of this component. - * - * @param locale - * the locale to become this component's locale. - */ - public void setLocale(Locale locale) { - this.locale = locale; - } - - /* - * Gets the component's icon resource. Don't add a JavaDoc comment here, we - * use the default documentation from implemented interface. - */ - public Resource getIcon() { - return this.icon; - } - - /** - * Sets the component's icon. This method will trigger a - * {@link com.itmill.toolkit.terminal.Paintable.RepaintRequestEvent RepaintRequestEvent}. - * - * @param icon - * the icon to be shown with the component's caption. - */ - public void setIcon(Resource icon) { - this.icon = icon; - requestRepaint(); - } - - /* - * Tests if the component is enabled or not. Don't add a JavaDoc comment - * here, we use the default documentation from implemented interface. - */ - public boolean isEnabled() { - return this.enabled && isVisible(); - } - - /* - * Enables or disables the component. Don't add a JavaDoc comment here, we - * use the default documentation from implemented interface. - */ - public void setEnabled(boolean enabled) { - if (this.enabled != enabled) { - this.enabled = enabled; - requestRepaint(); - } - } - - /* - * Tests if the component is in the immediate mode. Don't add a JavaDoc - * comment here, we use the default documentation from implemented - * interface. - */ - public boolean isImmediate() { - return immediate; - } - - /** - * Sets the component's immediate mode to the specified status. This method - * will trigger a - * {@link com.itmill.toolkit.terminal.Paintable.RepaintRequestEvent RepaintRequestEvent}. - * - * @param immediate - * the boolean value specifying if the component should be in the - * immediate mode after the call. - * @see Component#isImmediate() - */ - public void setImmediate(boolean immediate) { - this.immediate = immediate; - requestRepaint(); - } - - /* - * Tests if the component is visible. Don't add a JavaDoc comment here, we - * use the default documentation from implemented interface. - */ - public boolean isVisible() { - return this.visible; - } - - /* - * Sets the components visibility. Don't add a JavaDoc comment here, we use - * the default documentation from implemented interface. - */ - public void setVisible(boolean visible) { - - if (this.visible != visible) { - this.visible = visible; - // Instead of requesting repaint normally we - // fire the event directly to assure that the - // event goes through event in the component might - // now be invisible - fireRequestRepaintEvent(null); - } - } - - /** - *

- * Gets the component's description. The description can be used to briefly - * describe the state of the component to the user. The description string - * may contain certain XML tags: - *

- * - *

- * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - *
TagDescriptionExample
<b>boldbold text
<i>italicitalic text
<u>underlinedunderlined text
<br>linebreakN/A
<ul>
- * <li>item1
- * <li>item1
- * </ul>
item list - *
    - *
  • item1 - *
  • item2 - *
- *
- *

- * - *

- * These tags may be nested. - *

- * - * @return component's description String - */ - public String getDescription() { - return this.description; - } - - /** - * Sets the component's description. See {@link #getDescription()} for more - * information on what the description is. This method will trigger a - * {@link com.itmill.toolkit.terminal.Paintable.RepaintRequestEvent RepaintRequestEvent}. - * - * @param description - * the new description string for the component. - */ - public void setDescription(String description) { - this.description = description; - requestRepaint(); - } - - /* - * Gets the component's parent component. Don't add a JavaDoc comment here, - * we use the default documentation from implemented interface. - */ - public Component getParent() { - return this.parent; - } - - /* - * Sets the parent component. Don't add a JavaDoc comment here, we use the - * default documentation from implemented interface. - */ - public void setParent(Component parent) { - - // If the parent is not changed, dont do nothing - if (parent == this.parent) - return; - - // Send detach event if the component have been connected to a window - if (getApplication() != null) { - detach(); - this.parent = null; - } - - // Connect to new parent - this.parent = parent; - - // Send attach event if connected to a window - if (getApplication() != null) - attach(); - } - - /** - * Gets the error message for this component. - * - * @return ErrorMessage containing the description of the error state of the - * component or null, if the component contains no errors. Extending - * classes should override this method if they support other error - * message types such as validation errors or buffering errors. The - * returned error message contains information about all the errors. - */ - public ErrorMessage getErrorMessage() { - return this.componentError; - } - - /** - * Gets the component's error message. - * - * @link Terminal.ErrorMessage#ErrorMessage(String, int) - * - * @return the component's error message. - */ - public ErrorMessage getComponentError() { - return this.componentError; - } - - /** - * Sets the component's error message. The message may contain certain XML - * tags, for more information see - * - * @link Component.ErrorMessage#ErrorMessage(String, int) - * - * @param componentError - * the new ErrorMessage of the component. - */ - public void setComponentError(ErrorMessage componentError) { - this.componentError = componentError; - fireComponentErrorEvent(); - requestRepaint(); - } - - /* - * Tests if the component is in read-only mode. Don't add a JavaDoc comment - * here, we use the default documentation from implemented interface. - */ - public boolean isReadOnly() { - return readOnly; - } - - /* - * Sets the component's read-only mode. Don't add a JavaDoc comment here, we - * use the default documentation from implemented interface. - */ - public void setReadOnly(boolean readOnly) { - this.readOnly = readOnly; - requestRepaint(); - } - - /* - * Gets the parent window of the component. Don't add a JavaDoc comment - * here, we use the default documentation from implemented interface. - */ - public Window getWindow() { - if (parent == null) - return null; - else - return parent.getWindow(); - } - - /* - * Notify the component that it's attached to a window. Don't add a JavaDoc - * comment here, we use the default documentation from implemented - * interface. - */ - public void attach() { - requestRepaint(); - } - - /* - * Detach the component from application. Don't add a JavaDoc comment here, - * we use the default documentation from implemented interface. - */ - public void detach() { - } - - /* - * Gets the parent application of the component. Don't add a JavaDoc comment - * here, we use the default documentation from implemented interface. - */ - public Application getApplication() { - if (parent == null) - return null; - else - return parent.getApplication(); - } - - /* Component painting ********************************************** */ - - /* Documented in super interface */ - public void requestRepaintRequests() { - repaintRequestListenersNotified = false; - } - - /* - * Paints the component into a UIDL stream. Don't add a JavaDoc comment - * here, we use the default documentation from implemented interface. - */ - public final void paint(PaintTarget target) throws PaintException { - - if (!target.startTag(this, this.getTag()) - || repaintRequestListenersNotified) { - - // Paint the contents of the component - - if (styles != null && styles.size() > 0) - target.addAttribute("style", getStyle()); - if (isReadOnly()) - target.addAttribute("readonly", true); - if (!isVisible()) - target.addAttribute("invisible", true); - if (isImmediate()) - target.addAttribute("immediate", true); - if (!isEnabled()) - target.addAttribute("disabled", true); - if (getCaption() != null) - target.addAttribute("caption", getCaption()); - if (getIcon() != null) - target.addAttribute("icon", getIcon()); - - // Only paint content of visible components. - if (isVisible()) { - String desc = getDescription(); - if (desc != null && description.length() > 0) { - target.addAttribute("description", getDescription()); - } - - paintContent(target); - - ErrorMessage error = getErrorMessage(); - if (error != null) - error.paint(target); - } - } else { - - // Contents have not changed, only cached presentation can be used - target.addAttribute("cached", true); - } - target.endTag(this.getTag()); - - repaintRequestListenersNotified = false; - } - - /** - * Paints any needed component-specific things to the given UIDL stream. The - * more general {@link #paint(PaintTarget)} method handles all general - * attributes common to all components, and it calls this method to paint - * any component-specific attributes to the UIDL stream. - * - * @param target - * the target UIDL stream where the component should paint itself - * to - * @throws PaintException - * if the paint operation failed. - */ - public void paintContent(PaintTarget target) throws PaintException { - - } - - /* Documentation copied from interface */ - public void requestRepaint() { - - // The effect of the repaint request is identical to case where a - // child requests repaint - childRequestedRepaint(null); - } - - /* Documentation copied from interface */ - public void childRequestedRepaint(Collection alreadyNotified) { - - // Invisible components do not need repaints - if (!isVisible()) - return; - - fireRequestRepaintEvent(alreadyNotified); - } - - /** - * Fires the repaint request event. - * - * @param alreadyNotified - */ - private void fireRequestRepaintEvent(Collection alreadyNotified) { - - // Notify listeners only once - if (!repaintRequestListenersNotified) { - - // Notify the listeners - if (repaintRequestListeners != null - && !repaintRequestListeners.isEmpty()) { - Object[] listeners = repaintRequestListeners.toArray(); - RepaintRequestEvent event = new RepaintRequestEvent(this); - for (int i = 0; i < listeners.length; i++) { - if (alreadyNotified == null) - alreadyNotified = new LinkedList(); - if (!alreadyNotified.contains(listeners[i])) { - ((RepaintRequestListener) listeners[i]) - .repaintRequested(event); - alreadyNotified.add(listeners[i]); - repaintRequestListenersNotified = true; - } - } - } - - // Notify the parent - Component parent = getParent(); - if (parent != null) - parent.childRequestedRepaint(alreadyNotified); - } - } - - /* Documentation copied from interface */ - public void addListener(RepaintRequestListener listener) { - if (repaintRequestListeners == null) - repaintRequestListeners = new LinkedList(); - if (!repaintRequestListeners.contains(listener)) { - repaintRequestListeners.add(listener); - } - } - - /* Documentation copied from interface */ - public void removeListener(RepaintRequestListener listener) { - if (repaintRequestListeners != null) { - repaintRequestListeners.remove(listener); - if (repaintRequestListeners.isEmpty()) - repaintRequestListeners = null; - } - } - - /* Component variable changes ************************************** */ - - /* - * Invoked when the value of a variable has changed. Don't add a JavaDoc - * comment here, we use the default documentation from implemented - * interface. - */ - public void changeVariables(Object source, Map variables) { - - } - - /* Dependency -framework is deprecated */ - public void dependsOn(VariableOwner depended) {} - public void removeDirectDependency(VariableOwner depended) {} - public Set getDirectDependencies() { - return null; - } - - /* General event framework *************************************** */ - - private static final Method COMPONENT_EVENT_METHOD; - - static { - try { - COMPONENT_EVENT_METHOD = Component.Listener.class - .getDeclaredMethod("componentEvent", - new Class[] { Component.Event.class }); - } catch (java.lang.NoSuchMethodException e) { - // This should never happen - e.printStackTrace(); - throw new java.lang.RuntimeException(); - } - } - - /** - *

- * Registers a new listener with the specified activation method to listen - * events generated by this component. If the activation method does not - * have any arguments the event object will not be passed to it when it's - * called. - *

- * - *

- * For more information on the inheritable event mechanism see the - * {@link com.itmill.toolkit.event com.itmill.toolkit.event package documentation}. - *

- * - * @param eventType - * the type of the listened event. Events of this type or its - * subclasses activate the listener. - * @param object - * the object instance who owns the activation method. - * @param method - * the activation method. - */ - public void addListener(Class eventType, Object object, Method method) { - if (eventRouter == null) - eventRouter = new EventRouter(); - eventRouter.addListener(eventType, object, method); - } - - /** - *

- * Registers a new listener with the specified activation method to listen - * events generated by this component. If the activation method does not - * have any arguments the event object will not be passed to it when it's - * called. - *

- * - *

- * This version of addListener gets the name of the - * activation method as a parameter. The actual method is reflected from - * object, and unless exactly one match is found, - * java.lang.IllegalArgumentException is thrown. - *

- * - *

- * For more information on the inheritable event mechanism see the - * {@link com.itmill.toolkit.event com.itmill.toolkit.event package documentation}. - *

- * - * @param eventType - * the type of the listened event. Events of this type or its - * subclasses activate the listener. - * @param object - * the object instance who owns the activation method. - * @param methodName - * the name of the activation method. - */ - public void addListener(Class eventType, Object object, String methodName) { - if (eventRouter == null) - eventRouter = new EventRouter(); - eventRouter.addListener(eventType, object, methodName); - } - - /** - * Removes all registered listeners matching the given parameters. Since - * this method receives the event type and the listener object as - * parameters, it will unregister all object's methods that - * are registered to listen to events of type eventType - * generated by this component. - * - *

- * For more information on the inheritable event mechanism see the - * {@link com.itmill.toolkit.event com.itmill.toolkit.event package documentation}. - *

- * - * @param eventType - * the exact event type the object listens to. - * @param target - * the target object that has registered to listen to events of - * type eventType with one or more methods. - */ - public void removeListener(Class eventType, Object target) { - if (eventRouter != null) - eventRouter.removeListener(eventType, target); - } - - /** - * Removes one registered listener method. The given method owned by the - * given object will no longer be called when the specified events are - * generated by this component. - * - *

- * For more information on the inheritable event mechanism see the - * {@link com.itmill.toolkit.event com.itmill.toolkit.event package documentation}. - *

- * - * @param eventType - * the exact event type the object listens to. - * @param target - * target object that has registered to listen to events of type - * eventType with one or more methods. - * @param method - * the method owned by target that's registered to - * listen to events of type eventType. - */ - public void removeListener(Class eventType, Object target, Method method) { - if (eventRouter != null) - eventRouter.removeListener(eventType, target, method); - } - - /** - *

- * Removes one registered listener method. The given method owned by the - * given object will no longer be called when the specified events are - * generated by this component. - *

- * - *

- * This version of removeListener gets the name of the - * activation method as a parameter. The actual method is reflected from - * target, and unless exactly one match is found, - * java.lang.IllegalArgumentException is thrown. - *

- * - *

- * For more information on the inheritable event mechanism see the - * {@link com.itmill.toolkit.event com.itmill.toolkit.event package documentation}. - *

- * - * @param eventType - * the exact event type the object listens to. - * @param target - * the target object that has registered to listen to events of - * type eventType with one or more methods. - * @param methodName - * the name of the method owned by target that's - * registered to listen to events of type eventType. - */ - public void removeListener(Class eventType, Object target, String methodName) { - if (eventRouter != null) - eventRouter.removeListener(eventType, target, methodName); - } - - /** - * Sends the event to all listeners. - * - * @param event - * the Event to be sent to all listeners. - */ - protected void fireEvent(Component.Event event) { - - if (eventRouter != null) - eventRouter.fireEvent(event); - - } - - /* Component event framework *************************************** */ - - /* - * Registers a new listener to listen events generated by this component. - * Don't add a JavaDoc comment here, we use the default documentation from - * implemented interface. - */ - public void addListener(Component.Listener listener) { - - if (eventRouter == null) - eventRouter = new EventRouter(); - - eventRouter.addListener(Component.Event.class, listener, - COMPONENT_EVENT_METHOD); - } - - /* - * Removes a previously registered listener from this component. Don't add a - * JavaDoc comment here, we use the default documentation from implemented - * interface. - */ - public void removeListener(Component.Listener listener) { - - if (eventRouter != null) { - eventRouter.removeListener(Component.Event.class, listener, - COMPONENT_EVENT_METHOD); - } - } - - /** - * Emits the component event. It is transmitted to all registered listeners - * interested in such events. - */ - protected void fireComponentEvent() { - fireEvent(new Component.Event(this)); - } - - /** - * Emits the component error event. It is transmitted to all registered - * listeners interested in such events. - */ - protected void fireComponentErrorEvent() { - fireEvent(new Component.ErrorEvent(this.getComponentError(), this)); - } - - /** - * Sets the application specific data object. - * - * @param data - * the Application specific data. - * @since 3.1 - */ - public void setData(Object data) { - this.applicationData = data; - } - - /** - * Gets the application specific data. - * - * @return the Application specific data set with setData function. - * @since 3.1 - */ - public Object getData() { - return this.applicationData; - } + /* Private members ************************************************* */ + + /** + * Style names. + */ + private ArrayList styles; + + /** + * Caption text. + */ + private String caption; + + /** + * Application specific data object. + */ + private Object applicationData; + + /** + * Icon to be shown together with caption. + */ + private Resource icon; + + /** + * Is the component enable (its normal usage is allowed). + */ + private boolean enabled = true; + + /** + * Is the component visible (it is rendered). + */ + private boolean visible = true; + + /** + * Is the component read-only ? + */ + private boolean readOnly = false; + + /** + * Description of the usage (XML). + */ + private String description = null; + + /** + * The container this component resides in. + */ + private Component parent = null; + + /** + * The EventRouter used for the event model. + */ + private EventRouter eventRouter = null; + + /** + * The internal error message of the component. + */ + private ErrorMessage componentError = null; + + /** + * Immediate mode: if true, all variable changes are required to be sent + * from the terminal immediately. + */ + private boolean immediate = false; + + /** + * Locale of this component. + */ + private Locale locale; + + /** + * List of repaint request listeners or null if not listened at all. + */ + private LinkedList repaintRequestListeners = null; + + /** + * Are all the repaint listeners notified about recent changes ? + */ + private boolean repaintRequestListenersNotified = false; + + /* Constructor ***************************************************** */ + + /** + * Constructs a new Component. + */ + public AbstractComponent() { + } + + /* Get/Set component properties ************************************ */ + + /** + * Gets the UIDL tag corresponding to the component. + * + * @return the component's UIDL tag as String + */ + public abstract String getTag(); + + /** + * Gets style for component. Multiple styles are joined with spaces. + * + * @return the component's styleValue of property style. + * @deprecated Use getStyleName() instead; renamed for consistency and to + * indicate that "style" should not be used to switch client + * side implementation, only to style the component. + */ + public String getStyle() { + return getStyleName(); + } + + /** + * Sets and replaces all previous style names of the component. This method + * will trigger a + * {@link com.itmill.toolkit.terminal.Paintable.RepaintRequestEvent RepaintRequestEvent}. + * + * @param style + * the new style of the component. + * @deprecated Use setStyleName() instead; renamed for consistency and to + * indicate that "style" should not be used to switch client + * side implementation, only to style the component. + */ + public void setStyle(String style) { + setStyleName(style); + } + + /* + * Gets the component's style. Don't add a JavaDoc comment here, we use the + * default documentation from implemented interface. + */ + public String getStyleName() { + String s = ""; + if (styles != null) { + for (Iterator it = styles.iterator(); it.hasNext();) { + s += (String) it.next(); + if (it.hasNext()) { + s += " "; + } + } + } + return s; + } + + /* + * Sets the component's style. Don't add a JavaDoc comment here, we use the + * default documentation from implemented interface. + */ + public void setStyleName(String style) { + if (style == null || "".equals(style)) { + styles = null; + requestRepaint(); + return; + } + if (styles == null) { + styles = new ArrayList(); + } + styles.clear(); + styles.add(style); + requestRepaint(); + } + + public void addStyleName(String style) { + if (style == null || "".equals(style)) { + return; + } + if (styles == null) { + styles = new ArrayList(); + } + if (!styles.contains(style)) { + styles.add(style); + requestRepaint(); + } + } + + public void removeStyleName(String style) { + styles.remove(style); + requestRepaint(); + } + + /* + * Get's the component's caption. Don't add a JavaDoc comment here, we use + * the default documentation from implemented interface. + */ + public String getCaption() { + return caption; + } + + /** + * Sets the component's caption String. Caption is the + * visible name of the component. This method will trigger a + * {@link com.itmill.toolkit.terminal.Paintable.RepaintRequestEvent RepaintRequestEvent}. + * + * @param caption + * the new caption String for the component. + */ + public void setCaption(String caption) { + this.caption = caption; + requestRepaint(); + } + + /* + * Don't add a JavaDoc comment here, we use the default documentation from + * implemented interface. + */ + public Locale getLocale() { + if (locale != null) { + return locale; + } + if (parent != null) { + return parent.getLocale(); + } + Application app = getApplication(); + if (app != null) { + return app.getLocale(); + } + return null; + } + + /** + * Sets the locale of this component. + * + * @param locale + * the locale to become this component's locale. + */ + public void setLocale(Locale locale) { + this.locale = locale; + } + + /* + * Gets the component's icon resource. Don't add a JavaDoc comment here, we + * use the default documentation from implemented interface. + */ + public Resource getIcon() { + return icon; + } + + /** + * Sets the component's icon. This method will trigger a + * {@link com.itmill.toolkit.terminal.Paintable.RepaintRequestEvent RepaintRequestEvent}. + * + * @param icon + * the icon to be shown with the component's caption. + */ + public void setIcon(Resource icon) { + this.icon = icon; + requestRepaint(); + } + + /* + * Tests if the component is enabled or not. Don't add a JavaDoc comment + * here, we use the default documentation from implemented interface. + */ + public boolean isEnabled() { + return enabled && isVisible(); + } + + /* + * Enables or disables the component. Don't add a JavaDoc comment here, we + * use the default documentation from implemented interface. + */ + public void setEnabled(boolean enabled) { + if (this.enabled != enabled) { + this.enabled = enabled; + requestRepaint(); + } + } + + /* + * Tests if the component is in the immediate mode. Don't add a JavaDoc + * comment here, we use the default documentation from implemented + * interface. + */ + public boolean isImmediate() { + return immediate; + } + + /** + * Sets the component's immediate mode to the specified status. This method + * will trigger a + * {@link com.itmill.toolkit.terminal.Paintable.RepaintRequestEvent RepaintRequestEvent}. + * + * @param immediate + * the boolean value specifying if the component should be in + * the immediate mode after the call. + * @see Component#isImmediate() + */ + public void setImmediate(boolean immediate) { + this.immediate = immediate; + requestRepaint(); + } + + /* + * Tests if the component is visible. Don't add a JavaDoc comment here, we + * use the default documentation from implemented interface. + */ + public boolean isVisible() { + return visible; + } + + /* + * Sets the components visibility. Don't add a JavaDoc comment here, we use + * the default documentation from implemented interface. + */ + public void setVisible(boolean visible) { + + if (this.visible != visible) { + this.visible = visible; + // Instead of requesting repaint normally we + // fire the event directly to assure that the + // event goes through event in the component might + // now be invisible + fireRequestRepaintEvent(null); + } + } + + /** + *

+ * Gets the component's description. The description can be used to briefly + * describe the state of the component to the user. The description string + * may contain certain XML tags: + *

+ * + *

+ * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
TagDescriptionExample
<b>boldbold text
<i>italicitalic text
<u>underlinedunderlined text
<br>linebreakN/A
<ul>
+ * <li>item1
+ * <li>item1
+ * </ul>
item list + *
    + *
  • item1 + *
  • item2 + *
+ *
+ *

+ * + *

+ * These tags may be nested. + *

+ * + * @return component's description String + */ + public String getDescription() { + return description; + } + + /** + * Sets the component's description. See {@link #getDescription()} for more + * information on what the description is. This method will trigger a + * {@link com.itmill.toolkit.terminal.Paintable.RepaintRequestEvent RepaintRequestEvent}. + * + * @param description + * the new description string for the component. + */ + public void setDescription(String description) { + this.description = description; + requestRepaint(); + } + + /* + * Gets the component's parent component. Don't add a JavaDoc comment here, + * we use the default documentation from implemented interface. + */ + public Component getParent() { + return parent; + } + + /* + * Sets the parent component. Don't add a JavaDoc comment here, we use the + * default documentation from implemented interface. + */ + public void setParent(Component parent) { + + // If the parent is not changed, dont do nothing + if (parent == this.parent) { + return; + } + + // Send detach event if the component have been connected to a window + if (getApplication() != null) { + detach(); + this.parent = null; + } + + // Connect to new parent + this.parent = parent; + + // Send attach event if connected to a window + if (getApplication() != null) { + attach(); + } + } + + /** + * Gets the error message for this component. + * + * @return ErrorMessage containing the description of the error state of the + * component or null, if the component contains no errors. Extending + * classes should override this method if they support other error + * message types such as validation errors or buffering errors. The + * returned error message contains information about all the errors. + */ + public ErrorMessage getErrorMessage() { + return componentError; + } + + /** + * Gets the component's error message. + * + * @link Terminal.ErrorMessage#ErrorMessage(String, int) + * + * @return the component's error message. + */ + public ErrorMessage getComponentError() { + return componentError; + } + + /** + * Sets the component's error message. The message may contain certain XML + * tags, for more information see + * + * @link Component.ErrorMessage#ErrorMessage(String, int) + * + * @param componentError + * the new ErrorMessage of the component. + */ + public void setComponentError(ErrorMessage componentError) { + this.componentError = componentError; + fireComponentErrorEvent(); + requestRepaint(); + } + + /* + * Tests if the component is in read-only mode. Don't add a JavaDoc comment + * here, we use the default documentation from implemented interface. + */ + public boolean isReadOnly() { + return readOnly; + } + + /* + * Sets the component's read-only mode. Don't add a JavaDoc comment here, we + * use the default documentation from implemented interface. + */ + public void setReadOnly(boolean readOnly) { + this.readOnly = readOnly; + requestRepaint(); + } + + /* + * Gets the parent window of the component. Don't add a JavaDoc comment + * here, we use the default documentation from implemented interface. + */ + public Window getWindow() { + if (parent == null) { + return null; + } else { + return parent.getWindow(); + } + } + + /* + * Notify the component that it's attached to a window. Don't add a JavaDoc + * comment here, we use the default documentation from implemented + * interface. + */ + public void attach() { + requestRepaint(); + } + + /* + * Detach the component from application. Don't add a JavaDoc comment here, + * we use the default documentation from implemented interface. + */ + public void detach() { + } + + /* + * Gets the parent application of the component. Don't add a JavaDoc comment + * here, we use the default documentation from implemented interface. + */ + public Application getApplication() { + if (parent == null) { + return null; + } else { + return parent.getApplication(); + } + } + + /* Component painting ********************************************** */ + + /* Documented in super interface */ + public void requestRepaintRequests() { + repaintRequestListenersNotified = false; + } + + /* + * Paints the component into a UIDL stream. Don't add a JavaDoc comment + * here, we use the default documentation from implemented interface. + */ + public final void paint(PaintTarget target) throws PaintException { + + if (!target.startTag(this, getTag()) || repaintRequestListenersNotified) { + + // Paint the contents of the component + + if (styles != null && styles.size() > 0) { + target.addAttribute("style", getStyle()); + } + if (isReadOnly()) { + target.addAttribute("readonly", true); + } + if (!isVisible()) { + target.addAttribute("invisible", true); + } + if (isImmediate()) { + target.addAttribute("immediate", true); + } + if (!isEnabled()) { + target.addAttribute("disabled", true); + } + if (getCaption() != null) { + target.addAttribute("caption", getCaption()); + } + if (getIcon() != null) { + target.addAttribute("icon", getIcon()); + } + + // Only paint content of visible components. + if (isVisible()) { + String desc = getDescription(); + if (desc != null && description.length() > 0) { + target.addAttribute("description", getDescription()); + } + + paintContent(target); + + ErrorMessage error = getErrorMessage(); + if (error != null) { + error.paint(target); + } + } + } else { + + // Contents have not changed, only cached presentation can be used + target.addAttribute("cached", true); + } + target.endTag(getTag()); + + repaintRequestListenersNotified = false; + } + + /** + * Paints any needed component-specific things to the given UIDL stream. The + * more general {@link #paint(PaintTarget)} method handles all general + * attributes common to all components, and it calls this method to paint + * any component-specific attributes to the UIDL stream. + * + * @param target + * the target UIDL stream where the component should paint + * itself to + * @throws PaintException + * if the paint operation failed. + */ + public void paintContent(PaintTarget target) throws PaintException { + + } + + /* Documentation copied from interface */ + public void requestRepaint() { + + // The effect of the repaint request is identical to case where a + // child requests repaint + childRequestedRepaint(null); + } + + /* Documentation copied from interface */ + public void childRequestedRepaint(Collection alreadyNotified) { + + // Invisible components do not need repaints + if (!isVisible()) { + return; + } + + fireRequestRepaintEvent(alreadyNotified); + } + + /** + * Fires the repaint request event. + * + * @param alreadyNotified + */ + private void fireRequestRepaintEvent(Collection alreadyNotified) { + + // Notify listeners only once + if (!repaintRequestListenersNotified) { + + // Notify the listeners + if (repaintRequestListeners != null + && !repaintRequestListeners.isEmpty()) { + Object[] listeners = repaintRequestListeners.toArray(); + RepaintRequestEvent event = new RepaintRequestEvent(this); + for (int i = 0; i < listeners.length; i++) { + if (alreadyNotified == null) { + alreadyNotified = new LinkedList(); + } + if (!alreadyNotified.contains(listeners[i])) { + ((RepaintRequestListener) listeners[i]) + .repaintRequested(event); + alreadyNotified.add(listeners[i]); + repaintRequestListenersNotified = true; + } + } + } + + // Notify the parent + Component parent = getParent(); + if (parent != null) { + parent.childRequestedRepaint(alreadyNotified); + } + } + } + + /* Documentation copied from interface */ + public void addListener(RepaintRequestListener listener) { + if (repaintRequestListeners == null) { + repaintRequestListeners = new LinkedList(); + } + if (!repaintRequestListeners.contains(listener)) { + repaintRequestListeners.add(listener); + } + } + + /* Documentation copied from interface */ + public void removeListener(RepaintRequestListener listener) { + if (repaintRequestListeners != null) { + repaintRequestListeners.remove(listener); + if (repaintRequestListeners.isEmpty()) { + repaintRequestListeners = null; + } + } + } + + /* Component variable changes ************************************** */ + + /* + * Invoked when the value of a variable has changed. Don't add a JavaDoc + * comment here, we use the default documentation from implemented + * interface. + */ + public void changeVariables(Object source, Map variables) { + + } + + /* Dependency -framework is deprecated */ + public void dependsOn(VariableOwner depended) { + } + + public void removeDirectDependency(VariableOwner depended) { + } + + public Set getDirectDependencies() { + return null; + } + + /* General event framework *************************************** */ + + private static final Method COMPONENT_EVENT_METHOD; + + static { + try { + COMPONENT_EVENT_METHOD = Component.Listener.class + .getDeclaredMethod("componentEvent", + new Class[] { Component.Event.class }); + } catch (java.lang.NoSuchMethodException e) { + // This should never happen + e.printStackTrace(); + throw new java.lang.RuntimeException(); + } + } + + /** + *

+ * Registers a new listener with the specified activation method to listen + * events generated by this component. If the activation method does not + * have any arguments the event object will not be passed to it when it's + * called. + *

+ * + *

+ * For more information on the inheritable event mechanism see the + * {@link com.itmill.toolkit.event com.itmill.toolkit.event package documentation}. + *

+ * + * @param eventType + * the type of the listened event. Events of this type or its + * subclasses activate the listener. + * @param object + * the object instance who owns the activation method. + * @param method + * the activation method. + */ + public void addListener(Class eventType, Object object, Method method) { + if (eventRouter == null) { + eventRouter = new EventRouter(); + } + eventRouter.addListener(eventType, object, method); + } + + /** + *

+ * Registers a new listener with the specified activation method to listen + * events generated by this component. If the activation method does not + * have any arguments the event object will not be passed to it when it's + * called. + *

+ * + *

+ * This version of addListener gets the name of the + * activation method as a parameter. The actual method is reflected from + * object, and unless exactly one match is found, + * java.lang.IllegalArgumentException is thrown. + *

+ * + *

+ * For more information on the inheritable event mechanism see the + * {@link com.itmill.toolkit.event com.itmill.toolkit.event package documentation}. + *

+ * + * @param eventType + * the type of the listened event. Events of this type or its + * subclasses activate the listener. + * @param object + * the object instance who owns the activation method. + * @param methodName + * the name of the activation method. + */ + public void addListener(Class eventType, Object object, String methodName) { + if (eventRouter == null) { + eventRouter = new EventRouter(); + } + eventRouter.addListener(eventType, object, methodName); + } + + /** + * Removes all registered listeners matching the given parameters. Since + * this method receives the event type and the listener object as + * parameters, it will unregister all object's methods that + * are registered to listen to events of type eventType + * generated by this component. + * + *

+ * For more information on the inheritable event mechanism see the + * {@link com.itmill.toolkit.event com.itmill.toolkit.event package documentation}. + *

+ * + * @param eventType + * the exact event type the object listens to. + * @param target + * the target object that has registered to listen to events + * of type eventType with one or more methods. + */ + public void removeListener(Class eventType, Object target) { + if (eventRouter != null) { + eventRouter.removeListener(eventType, target); + } + } + + /** + * Removes one registered listener method. The given method owned by the + * given object will no longer be called when the specified events are + * generated by this component. + * + *

+ * For more information on the inheritable event mechanism see the + * {@link com.itmill.toolkit.event com.itmill.toolkit.event package documentation}. + *

+ * + * @param eventType + * the exact event type the object listens to. + * @param target + * target object that has registered to listen to events of + * type eventType with one or more methods. + * @param method + * the method owned by target that's + * registered to listen to events of type + * eventType. + */ + public void removeListener(Class eventType, Object target, Method method) { + if (eventRouter != null) { + eventRouter.removeListener(eventType, target, method); + } + } + + /** + *

+ * Removes one registered listener method. The given method owned by the + * given object will no longer be called when the specified events are + * generated by this component. + *

+ * + *

+ * This version of removeListener gets the name of the + * activation method as a parameter. The actual method is reflected from + * target, and unless exactly one match is found, + * java.lang.IllegalArgumentException is thrown. + *

+ * + *

+ * For more information on the inheritable event mechanism see the + * {@link com.itmill.toolkit.event com.itmill.toolkit.event package documentation}. + *

+ * + * @param eventType + * the exact event type the object listens to. + * @param target + * the target object that has registered to listen to events + * of type eventType with one or more methods. + * @param methodName + * the name of the method owned by target + * that's registered to listen to events of type + * eventType. + */ + public void removeListener(Class eventType, Object target, String methodName) { + if (eventRouter != null) { + eventRouter.removeListener(eventType, target, methodName); + } + } + + /** + * Sends the event to all listeners. + * + * @param event + * the Event to be sent to all listeners. + */ + protected void fireEvent(Component.Event event) { + + if (eventRouter != null) { + eventRouter.fireEvent(event); + } + + } + + /* Component event framework *************************************** */ + + /* + * Registers a new listener to listen events generated by this component. + * Don't add a JavaDoc comment here, we use the default documentation from + * implemented interface. + */ + public void addListener(Component.Listener listener) { + + if (eventRouter == null) { + eventRouter = new EventRouter(); + } + + eventRouter.addListener(Component.Event.class, listener, + COMPONENT_EVENT_METHOD); + } + + /* + * Removes a previously registered listener from this component. Don't add a + * JavaDoc comment here, we use the default documentation from implemented + * interface. + */ + public void removeListener(Component.Listener listener) { + + if (eventRouter != null) { + eventRouter.removeListener(Component.Event.class, listener, + COMPONENT_EVENT_METHOD); + } + } + + /** + * Emits the component event. It is transmitted to all registered listeners + * interested in such events. + */ + protected void fireComponentEvent() { + fireEvent(new Component.Event(this)); + } + + /** + * Emits the component error event. It is transmitted to all registered + * listeners interested in such events. + */ + protected void fireComponentErrorEvent() { + fireEvent(new Component.ErrorEvent(getComponentError(), this)); + } + + /** + * Sets the application specific data object. + * + * @param data + * the Application specific data. + * @since 3.1 + */ + public void setData(Object data) { + applicationData = data; + } + + /** + * Gets the application specific data. + * + * @return the Application specific data set with setData function. + * @since 3.1 + */ + public Object getData() { + return applicationData; + } } \ No newline at end of file diff --git a/src/com/itmill/toolkit/ui/AbstractComponentContainer.java b/src/com/itmill/toolkit/ui/AbstractComponentContainer.java index 6c2e45d562..9f4fcb45a1 100644 --- a/src/com/itmill/toolkit/ui/AbstractComponentContainer.java +++ b/src/com/itmill/toolkit/ui/AbstractComponentContainer.java @@ -44,166 +44,171 @@ import java.util.LinkedList; * @since 3.0 */ public abstract class AbstractComponentContainer extends AbstractComponent - implements ComponentContainer { - - /** - * Constructs a new component container. - */ - public AbstractComponentContainer() { - super(); - } - - /** - * Removes all components from the container. This should probably be - * reimplemented in extending classes for a more powerfull implementation. - */ - public void removeAllComponents() { - LinkedList l = new LinkedList(); - - // Adds all components - for (Iterator i = getComponentIterator(); i.hasNext();) - l.add(i.next()); - - // Removes all component - for (Iterator i = l.iterator(); i.hasNext();) - removeComponent((Component) i.next()); - } - - /* - * Moves all components from an another container into this container. Don't - * add a JavaDoc comment here, we use the default documentation from - * implemented interface. - */ - public void moveComponentsFrom(ComponentContainer source) { - LinkedList components = new LinkedList(); - for (Iterator i = source.getComponentIterator(); i.hasNext();) - components.add(i.next()); - - for (Iterator i = components.iterator(); i.hasNext();) { - Component c = (Component) i.next(); - source.removeComponent(c); - addComponent(c); - } - } - - /** - * Notifies all contained components that the container is attached to a - * window. - * - * @see com.itmill.toolkit.ui.Component#attach() - */ - public void attach() { - super.attach(); - - for (Iterator i = getComponentIterator(); i.hasNext();) - ((Component) i.next()).attach(); - } - - /** - * Notifies all contained components that the container is detached from a - * window. - * - * @see com.itmill.toolkit.ui.Component#detach() - */ - public void detach() { - super.detach(); - - for (Iterator i = getComponentIterator(); i.hasNext();) - ((Component) i.next()).detach(); - } - - /* Events ************************************************************ */ - - private static final Method COMPONENT_ATTACHED_METHOD; - - private static final Method COMPONENT_DETACHED_METHOD; - - static { - try { - COMPONENT_ATTACHED_METHOD = ComponentAttachListener.class - .getDeclaredMethod("componentAttachedToContainer", - new Class[] { ComponentAttachEvent.class }); - COMPONENT_DETACHED_METHOD = ComponentDetachListener.class - .getDeclaredMethod("componentDetachedFromContainer", - new Class[] { ComponentDetachEvent.class }); - } catch (java.lang.NoSuchMethodException e) { - // This should never happen - throw new java.lang.RuntimeException(); - } - } - - /* documented in interface */ - public void addListener(ComponentAttachListener listener) { - addListener(ComponentContainer.ComponentAttachEvent.class, listener, - COMPONENT_ATTACHED_METHOD); - } - - /* documented in interface */ - public void addListener(ComponentDetachListener listener) { - addListener(ComponentContainer.ComponentDetachEvent.class, listener, - COMPONENT_DETACHED_METHOD); - } - - /* documented in interface */ - public void removeListener(ComponentAttachListener listener) { - removeListener(ComponentContainer.ComponentAttachEvent.class, listener, - COMPONENT_ATTACHED_METHOD); - } - - /* documented in interface */ - public void removeListener(ComponentDetachListener listener) { - removeListener(ComponentContainer.ComponentDetachEvent.class, listener, - COMPONENT_DETACHED_METHOD); - } - - /** - * Fires the component attached event. This should be called by the - * addComponent methods after the component have been added to this - * container. - * - * @param component - * the component that has been added to this container. - */ - protected void fireComponentAttachEvent(Component component) { - fireEvent(new ComponentAttachEvent(this, component)); - } - - /** - * Fires the component detached event. This should be called by the - * removeComponent methods after the component have been removed from this - * container. - * - * @param component - * the component that has been removed from this container. - */ - protected void fireComponentDetachEvent(Component component) { - fireEvent(new ComponentDetachEvent(this, component)); - } - - /** - * This only implements the events and component parent calls. The extending - * classes must implement component list maintenance and call this method - * after component list maintenance. - * - * @see com.itmill.toolkit.ui.ComponentContainer#addComponent(Component) - */ - public void addComponent(Component c) { - c.setParent(this); - fireComponentAttachEvent(c); - } - - /** - * This only implements the events and component parent calls. The extending - * classes must implement component list maintenance and call this method - * before component list maintenance. - * - * @see com.itmill.toolkit.ui.ComponentContainer#removeComponent(Component) - */ - public void removeComponent(Component c) { - if (c.getParent() == this) { - c.setParent(null); - fireComponentDetachEvent(c); - } - } + implements ComponentContainer { + + /** + * Constructs a new component container. + */ + public AbstractComponentContainer() { + super(); + } + + /** + * Removes all components from the container. This should probably be + * reimplemented in extending classes for a more powerfull implementation. + */ + public void removeAllComponents() { + LinkedList l = new LinkedList(); + + // Adds all components + for (Iterator i = getComponentIterator(); i.hasNext();) { + l.add(i.next()); + } + + // Removes all component + for (Iterator i = l.iterator(); i.hasNext();) { + removeComponent((Component) i.next()); + } + } + + /* + * Moves all components from an another container into this container. Don't + * add a JavaDoc comment here, we use the default documentation from + * implemented interface. + */ + public void moveComponentsFrom(ComponentContainer source) { + LinkedList components = new LinkedList(); + for (Iterator i = source.getComponentIterator(); i.hasNext();) { + components.add(i.next()); + } + + for (Iterator i = components.iterator(); i.hasNext();) { + Component c = (Component) i.next(); + source.removeComponent(c); + addComponent(c); + } + } + + /** + * Notifies all contained components that the container is attached to a + * window. + * + * @see com.itmill.toolkit.ui.Component#attach() + */ + public void attach() { + super.attach(); + + for (Iterator i = getComponentIterator(); i.hasNext();) { + ((Component) i.next()).attach(); + } + } + + /** + * Notifies all contained components that the container is detached from a + * window. + * + * @see com.itmill.toolkit.ui.Component#detach() + */ + public void detach() { + super.detach(); + + for (Iterator i = getComponentIterator(); i.hasNext();) { + ((Component) i.next()).detach(); + } + } + + /* Events ************************************************************ */ + + private static final Method COMPONENT_ATTACHED_METHOD; + + private static final Method COMPONENT_DETACHED_METHOD; + + static { + try { + COMPONENT_ATTACHED_METHOD = ComponentAttachListener.class + .getDeclaredMethod("componentAttachedToContainer", + new Class[] { ComponentAttachEvent.class }); + COMPONENT_DETACHED_METHOD = ComponentDetachListener.class + .getDeclaredMethod("componentDetachedFromContainer", + new Class[] { ComponentDetachEvent.class }); + } catch (java.lang.NoSuchMethodException e) { + // This should never happen + throw new java.lang.RuntimeException(); + } + } + + /* documented in interface */ + public void addListener(ComponentAttachListener listener) { + addListener(ComponentContainer.ComponentAttachEvent.class, listener, + COMPONENT_ATTACHED_METHOD); + } + + /* documented in interface */ + public void addListener(ComponentDetachListener listener) { + addListener(ComponentContainer.ComponentDetachEvent.class, listener, + COMPONENT_DETACHED_METHOD); + } + + /* documented in interface */ + public void removeListener(ComponentAttachListener listener) { + removeListener(ComponentContainer.ComponentAttachEvent.class, listener, + COMPONENT_ATTACHED_METHOD); + } + + /* documented in interface */ + public void removeListener(ComponentDetachListener listener) { + removeListener(ComponentContainer.ComponentDetachEvent.class, listener, + COMPONENT_DETACHED_METHOD); + } + + /** + * Fires the component attached event. This should be called by the + * addComponent methods after the component have been added to this + * container. + * + * @param component + * the component that has been added to this container. + */ + protected void fireComponentAttachEvent(Component component) { + fireEvent(new ComponentAttachEvent(this, component)); + } + + /** + * Fires the component detached event. This should be called by the + * removeComponent methods after the component have been removed from this + * container. + * + * @param component + * the component that has been removed from this container. + */ + protected void fireComponentDetachEvent(Component component) { + fireEvent(new ComponentDetachEvent(this, component)); + } + + /** + * This only implements the events and component parent calls. The extending + * classes must implement component list maintenance and call this method + * after component list maintenance. + * + * @see com.itmill.toolkit.ui.ComponentContainer#addComponent(Component) + */ + public void addComponent(Component c) { + c.setParent(this); + fireComponentAttachEvent(c); + } + + /** + * This only implements the events and component parent calls. The extending + * classes must implement component list maintenance and call this method + * before component list maintenance. + * + * @see com.itmill.toolkit.ui.ComponentContainer#removeComponent(Component) + */ + public void removeComponent(Component c) { + if (c.getParent() == this) { + c.setParent(null); + fireComponentDetachEvent(c); + } + } } diff --git a/src/com/itmill/toolkit/ui/AbstractField.java b/src/com/itmill/toolkit/ui/AbstractField.java index 877920273d..3b398a13d5 100644 --- a/src/com/itmill/toolkit/ui/AbstractField.java +++ b/src/com/itmill/toolkit/ui/AbstractField.java @@ -70,916 +70,948 @@ import com.itmill.toolkit.terminal.PaintTarget; * @since 3.0 */ public abstract class AbstractField extends AbstractComponent implements Field, - Property.ReadOnlyStatusChangeNotifier { - - /* Private members ************************************************* */ - - private boolean delayedFocus; - - /** - * Value of the datafield. - */ - private Object value; - - /** - * Connected data-source. - */ - private Property dataSource = null; - - /** - * The list of validators. - */ - private LinkedList validators = null; - - /** - * Auto commit mode. - */ - private boolean writeTroughMode = true; - - /** - * Reads the value from data-source, when it is not modified. - */ - private boolean readTroughMode = true; - - /** - * Is the field modified but not committed. - */ - private boolean modified = false; - - /** - * Current source exception. - */ - private Buffered.SourceException currentBufferedSourceException = null; - - /** - * Are the invalid values alloved in fields ? - */ - private boolean invalidAllowed = true; - - /** - * Are the invalid values committed ? - */ - private boolean invalidCommitted = false; - - /** - * The tab order number of this field. - */ - private int tabIndex = 0; - - /** - * Unique focusable id. - */ - private long focusableId = -1; - - /** - * Required field. - */ - private boolean required = false; - - /* Component basics ************************************************ */ - - public AbstractField() { - this.focusableId = Window.getNewFocusableId(this); - } - - /* - * Paints the field. Don't add a JavaDoc comment here, we use the default - * documentation from the implemented interface. - */ - public void paintContent(PaintTarget target) throws PaintException { - - // Focus control id - if (this.focusableId > 0) { - target.addAttribute("focusid", this.focusableId); - } - - // The tab ordering number - if (this.tabIndex > 0) - target.addAttribute("tabindex", this.tabIndex); - - // If the field is modified, but not committed, set modified attribute - if (isModified()) - target.addAttribute("modified", true); - - // Adds the required attribute - if (isRequired()) - target.addAttribute("required", true); - - } - - /* - * Gets the field type Don't add a JavaDoc comment here, we use the default - * documentation from the implemented interface. - */ - public abstract Class getType(); - - /** - * The abstract field is read only also if the data source is in readonly - * mode. - */ - public boolean isReadOnly() { - return super.isReadOnly() - || (dataSource != null && dataSource.isReadOnly()); - } - - /** - * Changes the readonly state and throw read-only status change events. - * - * @see com.itmill.toolkit.ui.Component#setReadOnly(boolean) - */ - public void setReadOnly(boolean readOnly) { - super.setReadOnly(readOnly); - fireReadOnlyStatusChange(); - } - - /** - * Tests if the invalid data is committed to datasource. - * - * @see com.itmill.toolkit.data.BufferedValidatable#isInvalidCommitted() - */ - public boolean isInvalidCommitted() { - return invalidCommitted; - } - - /** - * Sets if the invalid data should be committed to datasource. - * - * @see com.itmill.toolkit.data.BufferedValidatable#setInvalidCommitted(boolean) - */ - public void setInvalidCommitted(boolean isCommitted) { - this.invalidCommitted = isCommitted; - } - - /* - * Saves the current value to the data source Don't add a JavaDoc comment - * here, we use the default documentation from the implemented interface. - */ - public void commit() throws Buffered.SourceException { - if (dataSource != null && (isInvalidCommitted() || isValid()) - && !dataSource.isReadOnly()) { - Object newValue = getValue(); - try { - - // Commits the value to datasource. - dataSource.setValue(newValue); - - } catch (Throwable e) { - - // Sets the buffering state. - currentBufferedSourceException = new Buffered.SourceException( - this, e); - requestRepaint(); - - // Throws the source exception. - throw currentBufferedSourceException; - } - } - - boolean repaintNeeded = false; - - // The abstract field is not modified anymore - if (modified) { - modified = false; - repaintNeeded = true; - } - - // If successful, remove set the buffering state to be ok - if (currentBufferedSourceException != null) { - currentBufferedSourceException = null; - repaintNeeded = true; - } - - if (repaintNeeded) - requestRepaint(); - } - - /* - * Updates the value from the data source. Don't add a JavaDoc comment here, - * we use the default documentation from the implemented interface. - */ - public void discard() throws Buffered.SourceException { - if (dataSource != null) { - - // Gets the correct value from datasource - Object newValue; - try { - - // Discards buffer by overwriting from datasource - newValue = dataSource.getValue(); - - // If successful, remove set the buffering state to be ok - if (currentBufferedSourceException != null) { - currentBufferedSourceException = null; - requestRepaint(); - } - } catch (Throwable e) { - - // Sets the buffering state - currentBufferedSourceException = new Buffered.SourceException( - this, e); - requestRepaint(); - - // Throws the source exception - throw currentBufferedSourceException; - } - - boolean wasModified = isModified(); - modified = false; - - // If the new value differs from the previous one - if ((newValue == null && value != null) - || (newValue != null && !newValue.equals(value))) { - setInternalValue(newValue); - fireValueChange(false); - } - - // If the value did not change, but the modification status did - else if (wasModified) { - requestRepaint(); - } - } - } - - /* - * Has the field been modified since the last commit()? Don't add a JavaDoc - * comment here, we use the default documentation from the implemented - * interface. - */ - public boolean isModified() { - return modified; - } - - /* - * Tests if the field is in write-through mode. Don't add a JavaDoc comment - * here, we use the default documentation from the implemented interface. - */ - public boolean isWriteThrough() { - return writeTroughMode; - } - - /* - * Sets the field's write-through mode to the specified status Don't add a - * JavaDoc comment here, we use the default documentation from the - * implemented interface. - */ - public void setWriteThrough(boolean writeTrough) - throws Buffered.SourceException { - if (writeTroughMode == writeTrough) - return; - writeTroughMode = writeTrough; - if (writeTroughMode) - commit(); - } - - /* - * Tests if the field is in read-through mode. Don't add a JavaDoc comment - * here, we use the default documentation from the implemented interface. - */ - public boolean isReadThrough() { - return readTroughMode; - } - - /* - * Sets the field's read-through mode to the specified status Don't add a - * JavaDoc comment here, we use the default documentation from the - * implemented interface. - */ - public void setReadThrough(boolean readTrough) - throws Buffered.SourceException { - if (readTroughMode == readTrough) - return; - readTroughMode = readTrough; - if (!isModified() && readTroughMode && dataSource != null) { - setInternalValue(dataSource.getValue()); - fireValueChange(false); - } - } - - /* Property interface implementation ******************************* */ - - /** - * Returns the value of the Property in human readable textual format. - * - * @see java.lang.Object#toString() - */ - public String toString() { - Object value = getValue(); - if (value == null) - return null; - return getValue().toString(); - } - - /** - * Gets the current value of the field. This is the visible, modified and - * possible invalid value the user have entered to the field. In the - * read-through mode, the abstract buffer is also updated and validation is - * performed. - * - * @return the current value of the field. - */ - public Object getValue() { - - // Give the value from abstract buffers if the field if possible - if (dataSource == null || !isReadThrough() || isModified()) - return value; - - Object newValue = dataSource.getValue(); - if ((newValue == null && value != null) - || (newValue != null && !newValue.equals(value))) { - setInternalValue(newValue); - fireValueChange(false); - } - - return newValue; - } - - /** - * Sets the value of the field. - * - * @param newValue - * the New value of the field. - * @throws Property.ReadOnlyException - * @throws Property.ConversionException - */ - public void setValue(Object newValue) throws Property.ReadOnlyException, - Property.ConversionException { - setValue(newValue, false); - } - - /** - * Sets the value of the field. - * - * @param newValue - * the New value of the field. - * @param repaintIsNotNeeded - * True iff caller is sure that repaint is not needed. - * @throws Property.ReadOnlyException - * @throws Property.ConversionException - */ - protected void setValue(Object newValue, boolean repaintIsNotNeeded) - throws Property.ReadOnlyException, Property.ConversionException { - - if ((newValue == null && value != null) - || (newValue != null && !newValue.equals(value))) { - - // Read only fields can not be changed - if (isReadOnly()) - throw new Property.ReadOnlyException(); - - // If invalid values are not allowed, the value must be checked - if (!isInvalidAllowed()) { - Collection v = getValidators(); - if (v != null) - for (Iterator i = v.iterator(); i.hasNext();) - ((Validator) i.next()).validate(newValue); - } - - // Changes the value - setInternalValue(newValue); - modified = dataSource != null; - - // In write trough mode , try to commit - if (isWriteThrough() && dataSource != null - && (isInvalidCommitted() || isValid())) { - try { - - // Commits the value to datasource - dataSource.setValue(newValue); - - // The buffer is now unmodified - modified = false; - - } catch (Throwable e) { - - // Sets the buffering state - currentBufferedSourceException = new Buffered.SourceException( - this, e); - requestRepaint(); - - // Throws the source exception - throw currentBufferedSourceException; - } - } - - // If successful, remove set the buffering state to be ok - if (currentBufferedSourceException != null) { - currentBufferedSourceException = null; - requestRepaint(); - } - - // Fires the value change - fireValueChange(repaintIsNotNeeded); - } - } - - /* External data source ******************************************** */ - - /** - * Gets the current data source of the field, if any. - * - * @return the current data source as a Property, or null if - * none defined. - */ - public Property getPropertyDataSource() { - return dataSource; - } - - /** - *

- * Sets the specified Property as the data source for the field. All - * uncommitted changes to the field are discarded and the value is refreshed - * from the new data source. - *

- * - *

- * If the datasource has any validators, the same validators are added to - * the field. Because the default behavior of the field is to allow invalid - * values, but not to allow committing them, this only adds visual error - * messages to fields and do not allow committing them as long as the value - * is invalid. After the value is valid, the error message is not shown and - * the commit can be done normally. - *

- * - * @param newDataSource - * the new data source Property. - */ - public void setPropertyDataSource(Property newDataSource) { - - // Saves the old value - Object oldValue = value; - - // Discards all changes to old datasource - try { - discard(); - } catch (Buffered.SourceException ignored) { - } - - // Stops listening the old data source changes - if (dataSource != null - && Property.ValueChangeNotifier.class - .isAssignableFrom(dataSource.getClass())) - ((Property.ValueChangeNotifier) dataSource).removeListener(this); - - // Sets the new data source - dataSource = newDataSource; - - // Gets the value from source - try { - if (dataSource != null) - setInternalValue(dataSource.getValue()); - modified = false; - } catch (Throwable e) { - currentBufferedSourceException = new Buffered.SourceException(this, - e); - modified = true; - } - - // Listens the new data source if possible - if (dataSource instanceof Property.ValueChangeNotifier) - ((Property.ValueChangeNotifier) dataSource).addListener(this); - - // Copy the validators from the data source - if (dataSource instanceof Validatable) { - Collection validators = ((Validatable) dataSource).getValidators(); - if (validators != null) - for (Iterator i = validators.iterator(); i.hasNext();) - addValidator((Validator) i.next()); - } - - // Fires value change if the value has changed - if ((value != oldValue) - && ((value != null && !value.equals(oldValue)) || value == null)) - fireValueChange(false); - } - - /* Validation ****************************************************** */ - - /** - * Adds a new validator for the field's value. All validators added to a - * field are checked each time the its value changes. - * - * @param validator - * the new validator to be added. - */ - public void addValidator(Validator validator) { - if (validators == null) - validators = new LinkedList(); - validators.add(validator); - } - - /** - * Gets the validators of the field. - * - * @return the Unmodifiable collection that holds all validators for the - * field. - */ - public Collection getValidators() { - if (validators == null || validators.isEmpty()) - return null; - return Collections.unmodifiableCollection(validators); - } - - /** - * Removes the validator from the field. - * - * @param validator - * the validator to remove. - */ - public void removeValidator(Validator validator) { - if (validators != null) - validators.remove(validator); - } - - /** - * Tests the current value against all registered validators. - * - * @return true if all registered validators claim that the - * current value is valid, false otherwise. - */ - public boolean isValid() { - - if (validators == null) - return true; - - Object value = getValue(); - for (Iterator i = validators.iterator(); i.hasNext();) - if (!((Validator) i.next()).isValid(value)) - return false; - - return true; - } - - /** - * Checks the validity of the validatable - * - * @see com.itmill.toolkit.data.Validatable#validate() - */ - public void validate() throws Validator.InvalidValueException { - - // If there is no validator, there can not be any errors - if (validators == null) - return; - - // Initialize temps - Validator.InvalidValueException firstError = null; - LinkedList errors = null; - Object value = getValue(); - - // Gets all the validation errors - for (Iterator i = validators.iterator(); i.hasNext();) - try { - ((Validator) i.next()).validate(value); - } catch (Validator.InvalidValueException e) { - if (firstError == null) - firstError = e; - else { - if (errors == null) { - errors = new LinkedList(); - errors.add(firstError); - } - errors.add(e); - } - } - - // If there were no error - if (firstError == null) - return; - - // If only one error occurred, throw it forwards - if (errors == null) - throw firstError; - - // Creates composite validator - Validator.InvalidValueException[] exceptions = new Validator.InvalidValueException[errors - .size()]; - int index = 0; - for (Iterator i = errors.iterator(); i.hasNext();) - exceptions[index++] = (Validator.InvalidValueException) i.next(); - - throw new Validator.InvalidValueException(null, exceptions); - } - - /** - * Fields allow invalid values by default. In most cases this is wanted, - * because the field otherwise visually forget the user input immediately. - * - * @return true iff the invalid values are allowed. - * @see com.itmill.toolkit.data.Validatable#isInvalidAllowed() - */ - public boolean isInvalidAllowed() { - return invalidAllowed; - } - - /** - * Fields allow invalid values by default. In most cases this is wanted, - * because the field otherwise visually forget the user input immediately. - *

- * In common setting where the user wants to assure the correctness of the - * datasource, but allow temporarily invalid contents in the field, the user - * should add the validators to datasource, that should not allow invalid - * values. The validators are automatically copied to the field when the - * datasource is set. - *

- * - * @see com.itmill.toolkit.data.Validatable#setInvalidAllowed(boolean) - */ - public void setInvalidAllowed(boolean invalidAllowed) - throws UnsupportedOperationException { - this.invalidAllowed = invalidAllowed; - } - - /** - * Error messages shown by the fields are composites of the error message - * thrown by the superclasses (that is the component error message), - * validation errors and buffered source errors. - * - * @see com.itmill.toolkit.ui.AbstractComponent#getErrorMessage() - */ - public ErrorMessage getErrorMessage() { - ErrorMessage superError = super.getErrorMessage(); - return superError; - /* - * TODO: Check the logic of this ErrorMessage validationError = null; - * try { validate(); } catch (Validator.InvalidValueException e) { - * validationError = e; } - * - * if (superError == null && validationError == null && - * currentBufferedSourceException == null) return null; // Throw - * combination of the error types return new CompositeErrorMessage( new - * ErrorMessage[] { superError, validationError, - * currentBufferedSourceException }); - */ - - } - - /* Value change events ****************************************** */ - - private static final Method VALUE_CHANGE_METHOD; - - static { - try { - VALUE_CHANGE_METHOD = Property.ValueChangeListener.class - .getDeclaredMethod("valueChange", - new Class[] { Property.ValueChangeEvent.class }); - } catch (java.lang.NoSuchMethodException e) { - // This should never happen - throw new java.lang.RuntimeException(); - } - } - - /* - * Adds a value change listener for the field. Don't add a JavaDoc comment - * here, we use the default documentation from the implemented interface. - */ - public void addListener(Property.ValueChangeListener listener) { - addListener(AbstractField.ValueChangeEvent.class, listener, - VALUE_CHANGE_METHOD); - } - - /* - * Removes a value change listener from the field. Don't add a JavaDoc - * comment here, we use the default documentation from the implemented - * interface. - */ - public void removeListener(Property.ValueChangeListener listener) { - removeListener(AbstractField.ValueChangeEvent.class, listener, - VALUE_CHANGE_METHOD); - } - - /** - * Emits the value change event. The value contained in the field is - * validated before the event is created. - */ - protected void fireValueChange(boolean repaintIsNotNeeded) { - fireEvent(new AbstractField.ValueChangeEvent(this)); - if (!repaintIsNotNeeded) - requestRepaint(); - } - - /* Read-only status change events *************************************** */ - - private static final Method READ_ONLY_STATUS_CHANGE_METHOD; - - static { - try { - READ_ONLY_STATUS_CHANGE_METHOD = Property.ReadOnlyStatusChangeListener.class - .getDeclaredMethod( - "readOnlyStatusChange", - new Class[] { Property.ReadOnlyStatusChangeEvent.class }); - } catch (java.lang.NoSuchMethodException e) { - // This should never happen - throw new java.lang.RuntimeException(); - } - } - - /** - * An Event object specifying the Property whose read-only - * status has changed. - * - * @author IT Mill Ltd. - * @version - * @VERSION@ - * @since 3.0 - */ - public class ReadOnlyStatusChangeEvent extends Component.Event implements - Property.ReadOnlyStatusChangeEvent { - - /** - * Serial generated by eclipse. - */ - private static final long serialVersionUID = 3258688823264161846L; - - /** - * New instance of text change event. - * - * @param source - * the Source of the event. - */ - public ReadOnlyStatusChangeEvent(AbstractField source) { - super(source); - } - - /** - * Property where the event occurred. - * - * @return the Source of the event. - */ - public Property getProperty() { - return (Property) getSource(); - } - } - - /* - * Adds a read-only status change listener for the field. Don't add a - * JavaDoc comment here, we use the default documentation from the - * implemented interface. - */ - public void addListener(Property.ReadOnlyStatusChangeListener listener) { - addListener(Property.ReadOnlyStatusChangeEvent.class, listener, - READ_ONLY_STATUS_CHANGE_METHOD); - } - - /* - * Removes a read-only status change listener from the field. Don't add a - * JavaDoc comment here, we use the default documentation from the - * implemented interface. - */ - public void removeListener(Property.ReadOnlyStatusChangeListener listener) { - removeListener(Property.ReadOnlyStatusChangeEvent.class, listener, - READ_ONLY_STATUS_CHANGE_METHOD); - } - - /** - * Emits the read-only status change event. The value contained in the field - * is validated before the event is created. - */ - protected void fireReadOnlyStatusChange() { - fireEvent(new AbstractField.ReadOnlyStatusChangeEvent(this)); - } - - /** - * This method listens to data source value changes and passes the changes - * forwards. - * - * @param event - * the value change event telling the data source contents have - * changed. - */ - public void valueChange(Property.ValueChangeEvent event) { - if (isReadThrough() || !isModified()) - fireValueChange(false); - } - - /** - * Asks the terminal to place the cursor to this field. - */ - public void focus() { - Window w = getWindow(); - if (w != null) { - w.setFocusedComponent(this); - } else { - this.delayedFocus = true; - } - } - - /** - * Creates abstract field by the type of the property. - * - *

- * This returns most suitable field type for editing property of given type. - *

- * - * @param propertyType - * the Type of the property, that needs to be edited. - */ - public static AbstractField constructField(Class propertyType) { - - // Null typed properties can not be edited - if (propertyType == null) - return null; - - // Date field - if (Date.class.isAssignableFrom(propertyType)) { - return new DateField(); - } - - // Boolean field - if (Boolean.class.isAssignableFrom(propertyType)) { - Button button = new Button(""); - button.setSwitchMode(true); - button.setImmediate(false); - return button; - } - - // Text field is used by default - return new TextField(); - } - - /** - * Gets the tab index of this field. The tab index property is used to - * specify the natural tab ordering of fields. - * - * @return the Tab index of this field. Negative value means unspecified. - */ - public int getTabIndex() { - return tabIndex; - } - - /** - * Gets the tab index of this field. The tab index property is used to - * specify the natural tab ordering of fields. - * - * @param tabIndex - * the tab order of this component. Negative value means - * unspecified. - */ - public void setTabIndex(int tabIndex) { - this.tabIndex = tabIndex; - } - - /** - * Sets the internal field value. This is purely used by AbstractField to - * change the internal Field value. It does not trigger any events. It can - * be overriden by the inheriting classes to update all dependent variables. - * - * @param newValue - * the new value to be set. - */ - protected void setInternalValue(Object newValue) { - this.value = newValue; - } - - /** - * Gets the unique ID of focusable - * - * @see com.itmill.toolkit.ui.Component.Focusable#getFocusableId() - */ - public long getFocusableId() { - return this.focusableId; - } - - /** - * Notifies the component that it is connected to an application. - * - * @see com.itmill.toolkit.ui.Component#attach() - */ - public void attach() { - super.attach(); - if (this.delayedFocus) { - this.delayedFocus = false; - this.focus(); - } - } - - /** - * Is this field required. Required fields must filled by the user. - * - * @return true if the field is required .otherwise - * false. - */ - public boolean isRequired() { - return required; - } - - /** - * Sets the field required. Required fields must filled by the user. - * - * @param required - * Is the field required. - */ - public void setRequired(boolean required) { - this.required = required; - } - - /** - * Free used resources. - * - * @see java.lang.Object#finalize() - */ - public void finalize() throws Throwable { - if (focusableId > -1) { - Window.removeFocusableId(focusableId); - } - super.finalize(); - } + Property.ReadOnlyStatusChangeNotifier { + + /* Private members ************************************************* */ + + private boolean delayedFocus; + + /** + * Value of the datafield. + */ + private Object value; + + /** + * Connected data-source. + */ + private Property dataSource = null; + + /** + * The list of validators. + */ + private LinkedList validators = null; + + /** + * Auto commit mode. + */ + private boolean writeTroughMode = true; + + /** + * Reads the value from data-source, when it is not modified. + */ + private boolean readTroughMode = true; + + /** + * Is the field modified but not committed. + */ + private boolean modified = false; + + /** + * Current source exception. + */ + private Buffered.SourceException currentBufferedSourceException = null; + + /** + * Are the invalid values alloved in fields ? + */ + private boolean invalidAllowed = true; + + /** + * Are the invalid values committed ? + */ + private boolean invalidCommitted = false; + + /** + * The tab order number of this field. + */ + private int tabIndex = 0; + + /** + * Unique focusable id. + */ + private long focusableId = -1; + + /** + * Required field. + */ + private boolean required = false; + + /* Component basics ************************************************ */ + + public AbstractField() { + focusableId = Window.getNewFocusableId(this); + } + + /* + * Paints the field. Don't add a JavaDoc comment here, we use the default + * documentation from the implemented interface. + */ + public void paintContent(PaintTarget target) throws PaintException { + + // Focus control id + if (focusableId > 0) { + target.addAttribute("focusid", focusableId); + } + + // The tab ordering number + if (tabIndex > 0) { + target.addAttribute("tabindex", tabIndex); + } + + // If the field is modified, but not committed, set modified attribute + if (isModified()) { + target.addAttribute("modified", true); + } + + // Adds the required attribute + if (isRequired()) { + target.addAttribute("required", true); + } + + } + + /* + * Gets the field type Don't add a JavaDoc comment here, we use the default + * documentation from the implemented interface. + */ + public abstract Class getType(); + + /** + * The abstract field is read only also if the data source is in readonly + * mode. + */ + public boolean isReadOnly() { + return super.isReadOnly() + || (dataSource != null && dataSource.isReadOnly()); + } + + /** + * Changes the readonly state and throw read-only status change events. + * + * @see com.itmill.toolkit.ui.Component#setReadOnly(boolean) + */ + public void setReadOnly(boolean readOnly) { + super.setReadOnly(readOnly); + fireReadOnlyStatusChange(); + } + + /** + * Tests if the invalid data is committed to datasource. + * + * @see com.itmill.toolkit.data.BufferedValidatable#isInvalidCommitted() + */ + public boolean isInvalidCommitted() { + return invalidCommitted; + } + + /** + * Sets if the invalid data should be committed to datasource. + * + * @see com.itmill.toolkit.data.BufferedValidatable#setInvalidCommitted(boolean) + */ + public void setInvalidCommitted(boolean isCommitted) { + invalidCommitted = isCommitted; + } + + /* + * Saves the current value to the data source Don't add a JavaDoc comment + * here, we use the default documentation from the implemented interface. + */ + public void commit() throws Buffered.SourceException { + if (dataSource != null && (isInvalidCommitted() || isValid()) + && !dataSource.isReadOnly()) { + Object newValue = getValue(); + try { + + // Commits the value to datasource. + dataSource.setValue(newValue); + + } catch (Throwable e) { + + // Sets the buffering state. + currentBufferedSourceException = new Buffered.SourceException( + this, e); + requestRepaint(); + + // Throws the source exception. + throw currentBufferedSourceException; + } + } + + boolean repaintNeeded = false; + + // The abstract field is not modified anymore + if (modified) { + modified = false; + repaintNeeded = true; + } + + // If successful, remove set the buffering state to be ok + if (currentBufferedSourceException != null) { + currentBufferedSourceException = null; + repaintNeeded = true; + } + + if (repaintNeeded) { + requestRepaint(); + } + } + + /* + * Updates the value from the data source. Don't add a JavaDoc comment here, + * we use the default documentation from the implemented interface. + */ + public void discard() throws Buffered.SourceException { + if (dataSource != null) { + + // Gets the correct value from datasource + Object newValue; + try { + + // Discards buffer by overwriting from datasource + newValue = dataSource.getValue(); + + // If successful, remove set the buffering state to be ok + if (currentBufferedSourceException != null) { + currentBufferedSourceException = null; + requestRepaint(); + } + } catch (Throwable e) { + + // Sets the buffering state + currentBufferedSourceException = new Buffered.SourceException( + this, e); + requestRepaint(); + + // Throws the source exception + throw currentBufferedSourceException; + } + + boolean wasModified = isModified(); + modified = false; + + // If the new value differs from the previous one + if ((newValue == null && value != null) + || (newValue != null && !newValue.equals(value))) { + setInternalValue(newValue); + fireValueChange(false); + } + + // If the value did not change, but the modification status did + else if (wasModified) { + requestRepaint(); + } + } + } + + /* + * Has the field been modified since the last commit()? Don't add a JavaDoc + * comment here, we use the default documentation from the implemented + * interface. + */ + public boolean isModified() { + return modified; + } + + /* + * Tests if the field is in write-through mode. Don't add a JavaDoc comment + * here, we use the default documentation from the implemented interface. + */ + public boolean isWriteThrough() { + return writeTroughMode; + } + + /* + * Sets the field's write-through mode to the specified status Don't add a + * JavaDoc comment here, we use the default documentation from the + * implemented interface. + */ + public void setWriteThrough(boolean writeTrough) + throws Buffered.SourceException { + if (writeTroughMode == writeTrough) { + return; + } + writeTroughMode = writeTrough; + if (writeTroughMode) { + commit(); + } + } + + /* + * Tests if the field is in read-through mode. Don't add a JavaDoc comment + * here, we use the default documentation from the implemented interface. + */ + public boolean isReadThrough() { + return readTroughMode; + } + + /* + * Sets the field's read-through mode to the specified status Don't add a + * JavaDoc comment here, we use the default documentation from the + * implemented interface. + */ + public void setReadThrough(boolean readTrough) + throws Buffered.SourceException { + if (readTroughMode == readTrough) { + return; + } + readTroughMode = readTrough; + if (!isModified() && readTroughMode && dataSource != null) { + setInternalValue(dataSource.getValue()); + fireValueChange(false); + } + } + + /* Property interface implementation ******************************* */ + + /** + * Returns the value of the Property in human readable textual format. + * + * @see java.lang.Object#toString() + */ + public String toString() { + Object value = getValue(); + if (value == null) { + return null; + } + return getValue().toString(); + } + + /** + * Gets the current value of the field. This is the visible, modified and + * possible invalid value the user have entered to the field. In the + * read-through mode, the abstract buffer is also updated and validation is + * performed. + * + * @return the current value of the field. + */ + public Object getValue() { + + // Give the value from abstract buffers if the field if possible + if (dataSource == null || !isReadThrough() || isModified()) { + return value; + } + + Object newValue = dataSource.getValue(); + if ((newValue == null && value != null) + || (newValue != null && !newValue.equals(value))) { + setInternalValue(newValue); + fireValueChange(false); + } + + return newValue; + } + + /** + * Sets the value of the field. + * + * @param newValue + * the New value of the field. + * @throws Property.ReadOnlyException + * @throws Property.ConversionException + */ + public void setValue(Object newValue) throws Property.ReadOnlyException, + Property.ConversionException { + setValue(newValue, false); + } + + /** + * Sets the value of the field. + * + * @param newValue + * the New value of the field. + * @param repaintIsNotNeeded + * True iff caller is sure that repaint is not needed. + * @throws Property.ReadOnlyException + * @throws Property.ConversionException + */ + protected void setValue(Object newValue, boolean repaintIsNotNeeded) + throws Property.ReadOnlyException, Property.ConversionException { + + if ((newValue == null && value != null) + || (newValue != null && !newValue.equals(value))) { + + // Read only fields can not be changed + if (isReadOnly()) { + throw new Property.ReadOnlyException(); + } + + // If invalid values are not allowed, the value must be checked + if (!isInvalidAllowed()) { + Collection v = getValidators(); + if (v != null) { + for (Iterator i = v.iterator(); i.hasNext();) { + ((Validator) i.next()).validate(newValue); + } + } + } + + // Changes the value + setInternalValue(newValue); + modified = dataSource != null; + + // In write trough mode , try to commit + if (isWriteThrough() && dataSource != null + && (isInvalidCommitted() || isValid())) { + try { + + // Commits the value to datasource + dataSource.setValue(newValue); + + // The buffer is now unmodified + modified = false; + + } catch (Throwable e) { + + // Sets the buffering state + currentBufferedSourceException = new Buffered.SourceException( + this, e); + requestRepaint(); + + // Throws the source exception + throw currentBufferedSourceException; + } + } + + // If successful, remove set the buffering state to be ok + if (currentBufferedSourceException != null) { + currentBufferedSourceException = null; + requestRepaint(); + } + + // Fires the value change + fireValueChange(repaintIsNotNeeded); + } + } + + /* External data source ******************************************** */ + + /** + * Gets the current data source of the field, if any. + * + * @return the current data source as a Property, or null if + * none defined. + */ + public Property getPropertyDataSource() { + return dataSource; + } + + /** + *

+ * Sets the specified Property as the data source for the field. All + * uncommitted changes to the field are discarded and the value is refreshed + * from the new data source. + *

+ * + *

+ * If the datasource has any validators, the same validators are added to + * the field. Because the default behavior of the field is to allow invalid + * values, but not to allow committing them, this only adds visual error + * messages to fields and do not allow committing them as long as the value + * is invalid. After the value is valid, the error message is not shown and + * the commit can be done normally. + *

+ * + * @param newDataSource + * the new data source Property. + */ + public void setPropertyDataSource(Property newDataSource) { + + // Saves the old value + Object oldValue = value; + + // Discards all changes to old datasource + try { + discard(); + } catch (Buffered.SourceException ignored) { + } + + // Stops listening the old data source changes + if (dataSource != null + && Property.ValueChangeNotifier.class + .isAssignableFrom(dataSource.getClass())) { + ((Property.ValueChangeNotifier) dataSource).removeListener(this); + } + + // Sets the new data source + dataSource = newDataSource; + + // Gets the value from source + try { + if (dataSource != null) { + setInternalValue(dataSource.getValue()); + } + modified = false; + } catch (Throwable e) { + currentBufferedSourceException = new Buffered.SourceException(this, + e); + modified = true; + } + + // Listens the new data source if possible + if (dataSource instanceof Property.ValueChangeNotifier) { + ((Property.ValueChangeNotifier) dataSource).addListener(this); + } + + // Copy the validators from the data source + if (dataSource instanceof Validatable) { + Collection validators = ((Validatable) dataSource).getValidators(); + if (validators != null) { + for (Iterator i = validators.iterator(); i.hasNext();) { + addValidator((Validator) i.next()); + } + } + } + + // Fires value change if the value has changed + if ((value != oldValue) + && ((value != null && !value.equals(oldValue)) || value == null)) { + fireValueChange(false); + } + } + + /* Validation ****************************************************** */ + + /** + * Adds a new validator for the field's value. All validators added to a + * field are checked each time the its value changes. + * + * @param validator + * the new validator to be added. + */ + public void addValidator(Validator validator) { + if (validators == null) { + validators = new LinkedList(); + } + validators.add(validator); + } + + /** + * Gets the validators of the field. + * + * @return the Unmodifiable collection that holds all validators for the + * field. + */ + public Collection getValidators() { + if (validators == null || validators.isEmpty()) { + return null; + } + return Collections.unmodifiableCollection(validators); + } + + /** + * Removes the validator from the field. + * + * @param validator + * the validator to remove. + */ + public void removeValidator(Validator validator) { + if (validators != null) { + validators.remove(validator); + } + } + + /** + * Tests the current value against all registered validators. + * + * @return true if all registered validators claim that the + * current value is valid, false otherwise. + */ + public boolean isValid() { + + if (validators == null) { + return true; + } + + Object value = getValue(); + for (Iterator i = validators.iterator(); i.hasNext();) { + if (!((Validator) i.next()).isValid(value)) { + return false; + } + } + + return true; + } + + /** + * Checks the validity of the validatable + * + * @see com.itmill.toolkit.data.Validatable#validate() + */ + public void validate() throws Validator.InvalidValueException { + + // If there is no validator, there can not be any errors + if (validators == null) { + return; + } + + // Initialize temps + Validator.InvalidValueException firstError = null; + LinkedList errors = null; + Object value = getValue(); + + // Gets all the validation errors + for (Iterator i = validators.iterator(); i.hasNext();) { + try { + ((Validator) i.next()).validate(value); + } catch (Validator.InvalidValueException e) { + if (firstError == null) { + firstError = e; + } else { + if (errors == null) { + errors = new LinkedList(); + errors.add(firstError); + } + errors.add(e); + } + } + } + + // If there were no error + if (firstError == null) { + return; + } + + // If only one error occurred, throw it forwards + if (errors == null) { + throw firstError; + } + + // Creates composite validator + Validator.InvalidValueException[] exceptions = new Validator.InvalidValueException[errors + .size()]; + int index = 0; + for (Iterator i = errors.iterator(); i.hasNext();) { + exceptions[index++] = (Validator.InvalidValueException) i.next(); + } + + throw new Validator.InvalidValueException(null, exceptions); + } + + /** + * Fields allow invalid values by default. In most cases this is wanted, + * because the field otherwise visually forget the user input immediately. + * + * @return true iff the invalid values are allowed. + * @see com.itmill.toolkit.data.Validatable#isInvalidAllowed() + */ + public boolean isInvalidAllowed() { + return invalidAllowed; + } + + /** + * Fields allow invalid values by default. In most cases this is wanted, + * because the field otherwise visually forget the user input immediately. + *

+ * In common setting where the user wants to assure the correctness of the + * datasource, but allow temporarily invalid contents in the field, the user + * should add the validators to datasource, that should not allow invalid + * values. The validators are automatically copied to the field when the + * datasource is set. + *

+ * + * @see com.itmill.toolkit.data.Validatable#setInvalidAllowed(boolean) + */ + public void setInvalidAllowed(boolean invalidAllowed) + throws UnsupportedOperationException { + this.invalidAllowed = invalidAllowed; + } + + /** + * Error messages shown by the fields are composites of the error message + * thrown by the superclasses (that is the component error message), + * validation errors and buffered source errors. + * + * @see com.itmill.toolkit.ui.AbstractComponent#getErrorMessage() + */ + public ErrorMessage getErrorMessage() { + ErrorMessage superError = super.getErrorMessage(); + return superError; + /* + * TODO: Check the logic of this ErrorMessage validationError = null; + * try { validate(); } catch (Validator.InvalidValueException e) { + * validationError = e; } + * + * if (superError == null && validationError == null && + * currentBufferedSourceException == null) return null; // Throw + * combination of the error types return new CompositeErrorMessage( new + * ErrorMessage[] { superError, validationError, + * currentBufferedSourceException }); + */ + + } + + /* Value change events ****************************************** */ + + private static final Method VALUE_CHANGE_METHOD; + + static { + try { + VALUE_CHANGE_METHOD = Property.ValueChangeListener.class + .getDeclaredMethod("valueChange", + new Class[] { Property.ValueChangeEvent.class }); + } catch (java.lang.NoSuchMethodException e) { + // This should never happen + throw new java.lang.RuntimeException(); + } + } + + /* + * Adds a value change listener for the field. Don't add a JavaDoc comment + * here, we use the default documentation from the implemented interface. + */ + public void addListener(Property.ValueChangeListener listener) { + addListener(AbstractField.ValueChangeEvent.class, listener, + VALUE_CHANGE_METHOD); + } + + /* + * Removes a value change listener from the field. Don't add a JavaDoc + * comment here, we use the default documentation from the implemented + * interface. + */ + public void removeListener(Property.ValueChangeListener listener) { + removeListener(AbstractField.ValueChangeEvent.class, listener, + VALUE_CHANGE_METHOD); + } + + /** + * Emits the value change event. The value contained in the field is + * validated before the event is created. + */ + protected void fireValueChange(boolean repaintIsNotNeeded) { + fireEvent(new AbstractField.ValueChangeEvent(this)); + if (!repaintIsNotNeeded) { + requestRepaint(); + } + } + + /* Read-only status change events *************************************** */ + + private static final Method READ_ONLY_STATUS_CHANGE_METHOD; + + static { + try { + READ_ONLY_STATUS_CHANGE_METHOD = Property.ReadOnlyStatusChangeListener.class + .getDeclaredMethod( + "readOnlyStatusChange", + new Class[] { Property.ReadOnlyStatusChangeEvent.class }); + } catch (java.lang.NoSuchMethodException e) { + // This should never happen + throw new java.lang.RuntimeException(); + } + } + + /** + * An Event object specifying the Property whose read-only + * status has changed. + * + * @author IT Mill Ltd. + * @version + * @VERSION@ + * @since 3.0 + */ + public class ReadOnlyStatusChangeEvent extends Component.Event implements + Property.ReadOnlyStatusChangeEvent { + + /** + * Serial generated by eclipse. + */ + private static final long serialVersionUID = 3258688823264161846L; + + /** + * New instance of text change event. + * + * @param source + * the Source of the event. + */ + public ReadOnlyStatusChangeEvent(AbstractField source) { + super(source); + } + + /** + * Property where the event occurred. + * + * @return the Source of the event. + */ + public Property getProperty() { + return (Property) getSource(); + } + } + + /* + * Adds a read-only status change listener for the field. Don't add a + * JavaDoc comment here, we use the default documentation from the + * implemented interface. + */ + public void addListener(Property.ReadOnlyStatusChangeListener listener) { + addListener(Property.ReadOnlyStatusChangeEvent.class, listener, + READ_ONLY_STATUS_CHANGE_METHOD); + } + + /* + * Removes a read-only status change listener from the field. Don't add a + * JavaDoc comment here, we use the default documentation from the + * implemented interface. + */ + public void removeListener(Property.ReadOnlyStatusChangeListener listener) { + removeListener(Property.ReadOnlyStatusChangeEvent.class, listener, + READ_ONLY_STATUS_CHANGE_METHOD); + } + + /** + * Emits the read-only status change event. The value contained in the field + * is validated before the event is created. + */ + protected void fireReadOnlyStatusChange() { + fireEvent(new AbstractField.ReadOnlyStatusChangeEvent(this)); + } + + /** + * This method listens to data source value changes and passes the changes + * forwards. + * + * @param event + * the value change event telling the data source contents + * have changed. + */ + public void valueChange(Property.ValueChangeEvent event) { + if (isReadThrough() || !isModified()) { + fireValueChange(false); + } + } + + /** + * Asks the terminal to place the cursor to this field. + */ + public void focus() { + Window w = getWindow(); + if (w != null) { + w.setFocusedComponent(this); + } else { + delayedFocus = true; + } + } + + /** + * Creates abstract field by the type of the property. + * + *

+ * This returns most suitable field type for editing property of given type. + *

+ * + * @param propertyType + * the Type of the property, that needs to be edited. + */ + public static AbstractField constructField(Class propertyType) { + + // Null typed properties can not be edited + if (propertyType == null) { + return null; + } + + // Date field + if (Date.class.isAssignableFrom(propertyType)) { + return new DateField(); + } + + // Boolean field + if (Boolean.class.isAssignableFrom(propertyType)) { + Button button = new Button(""); + button.setSwitchMode(true); + button.setImmediate(false); + return button; + } + + // Text field is used by default + return new TextField(); + } + + /** + * Gets the tab index of this field. The tab index property is used to + * specify the natural tab ordering of fields. + * + * @return the Tab index of this field. Negative value means unspecified. + */ + public int getTabIndex() { + return tabIndex; + } + + /** + * Gets the tab index of this field. The tab index property is used to + * specify the natural tab ordering of fields. + * + * @param tabIndex + * the tab order of this component. Negative value means + * unspecified. + */ + public void setTabIndex(int tabIndex) { + this.tabIndex = tabIndex; + } + + /** + * Sets the internal field value. This is purely used by AbstractField to + * change the internal Field value. It does not trigger any events. It can + * be overriden by the inheriting classes to update all dependent variables. + * + * @param newValue + * the new value to be set. + */ + protected void setInternalValue(Object newValue) { + value = newValue; + } + + /** + * Gets the unique ID of focusable + * + * @see com.itmill.toolkit.ui.Component.Focusable#getFocusableId() + */ + public long getFocusableId() { + return focusableId; + } + + /** + * Notifies the component that it is connected to an application. + * + * @see com.itmill.toolkit.ui.Component#attach() + */ + public void attach() { + super.attach(); + if (delayedFocus) { + delayedFocus = false; + focus(); + } + } + + /** + * Is this field required. Required fields must filled by the user. + * + * @return true if the field is required .otherwise + * false. + */ + public boolean isRequired() { + return required; + } + + /** + * Sets the field required. Required fields must filled by the user. + * + * @param required + * Is the field required. + */ + public void setRequired(boolean required) { + this.required = required; + } + + /** + * Free used resources. + * + * @see java.lang.Object#finalize() + */ + public void finalize() throws Throwable { + if (focusableId > -1) { + Window.removeFocusableId(focusableId); + } + super.finalize(); + } } \ No newline at end of file diff --git a/src/com/itmill/toolkit/ui/AbstractLayout.java b/src/com/itmill/toolkit/ui/AbstractLayout.java index 6e7049bacc..c862c0a48b 100644 --- a/src/com/itmill/toolkit/ui/AbstractLayout.java +++ b/src/com/itmill/toolkit/ui/AbstractLayout.java @@ -15,182 +15,186 @@ import com.itmill.toolkit.terminal.gwt.client.ui.MarginInfo; * @since 5.0 */ public abstract class AbstractLayout extends AbstractComponentContainer - implements Layout { - - protected MarginInfo margins = new MarginInfo(false,false,false,false); - - /** - * Height of the layout. Set to -1 for undefined height. - */ - private int height = -1; - - /** - * Height unit. - * - * @see com.itmill.toolkit.terminal.Sizeable.UNIT_SYMBOLS; - */ - private int heightUnit = UNITS_PIXELS; - - /** - * Width of the layout. Set to -1 for undefined width. - */ - private int width = -1; - - /** - * Width unit. - * - * @see com.itmill.toolkit.terminal.Sizeable.UNIT_SYMBOLS; - */ - private int widthUnit = UNITS_PIXELS; - - /* - * (non-Javadoc) - * - * @see com.itmill.toolkit.ui.AbstractComponent#getTag() - */ - public abstract String getTag(); - - /* - * (non-Javadoc) - * - * @see com.itmill.toolkit.ui.Layout#setMargin(boolean) - */ - public void setMargin(boolean enabled) { - margins.setMargins(enabled); - requestRepaint(); - } - - /* - * (non-Javadoc) - * - * @see com.itmill.toolkit.ui.Layout#setMargin(boolean, boolean, boolean, - * boolean) - */ - public void setMargin(boolean topEnabled, boolean rightEnabled, - boolean bottomEnabled, boolean leftEnabled) { - margins.setMargins(topEnabled, rightEnabled, bottomEnabled, leftEnabled); - requestRepaint(); - } - - /* - * (non-Javadoc) - * - * @see com.itmill.toolkit.terminal.Sizeable#getHeight() - */ - public int getHeight() { - return height; - } - - /* - * (non-Javadoc) - * - * @see com.itmill.toolkit.terminal.Sizeable#getHeightUnits() - */ - public int getHeightUnits() { - return heightUnit; - } - - /* - * (non-Javadoc) - * - * @see com.itmill.toolkit.terminal.Sizeable#getWidth() - */ - public int getWidth() { - return width; - } - - /* - * (non-Javadoc) - * - * @see com.itmill.toolkit.terminal.Sizeable#getWidthUnits() - */ - public int getWidthUnits() { - return widthUnit; - } - - /* - * (non-Javadoc) - * - * @see com.itmill.toolkit.terminal.Sizeable#setHeight(int) - */ - public void setHeight(int height) { - this.height = height; - requestRepaint(); - } - - /* - * (non-Javadoc) - * - * @see com.itmill.toolkit.terminal.Sizeable#setHeightUnits(int) - */ - public void setHeightUnits(int units) { - this.heightUnit = units; - requestRepaint(); - } - - /* - * (non-Javadoc) - * - * @see com.itmill.toolkit.terminal.Sizeable#setSizeFull() - */ - public void setSizeFull() { - height = 100; - width = 100; - heightUnit = UNITS_PERCENTAGE; - widthUnit = UNITS_PERCENTAGE; - requestRepaint(); - } - - /* - * (non-Javadoc) - * - * @see com.itmill.toolkit.terminal.Sizeable#setSizeUndefined() - */ - public void setSizeUndefined() { - height = -1; - width = -1; - heightUnit = UNITS_PIXELS; - widthUnit = UNITS_PIXELS; - requestRepaint(); - } - - /* - * (non-Javadoc) - * - * @see com.itmill.toolkit.terminal.Sizeable#setWidth(int) - */ - public void setWidth(int width) { - this.width = width; - requestRepaint(); - } - - /* - * (non-Javadoc) - * - * @see com.itmill.toolkit.terminal.Sizeable#setWidthUnits(int) - */ - public void setWidthUnits(int units) { - this.widthUnit = units; - requestRepaint(); - } - - /* - * (non-Javadoc) - * - * @see com.itmill.toolkit.ui.AbstractComponent#paintContent(com.itmill.toolkit.terminal.PaintTarget) - */ - public void paintContent(PaintTarget target) throws PaintException { - - // Add margin info. Defaults to false. - target.addAttribute("margins", margins.getBitMask()); - - // Size - if (getHeight() >= 0) - target.addAttribute("height", "" + getHeight() - + Sizeable.UNIT_SYMBOLS[getHeightUnits()]); - if (getWidth() >= 0) - target.addAttribute("width", "" + getWidth() - + Sizeable.UNIT_SYMBOLS[getWidthUnits()]); - } + implements Layout { + + protected MarginInfo margins = new MarginInfo(false, false, false, false); + + /** + * Height of the layout. Set to -1 for undefined height. + */ + private int height = -1; + + /** + * Height unit. + * + * @see com.itmill.toolkit.terminal.Sizeable.UNIT_SYMBOLS; + */ + private int heightUnit = UNITS_PIXELS; + + /** + * Width of the layout. Set to -1 for undefined width. + */ + private int width = -1; + + /** + * Width unit. + * + * @see com.itmill.toolkit.terminal.Sizeable.UNIT_SYMBOLS; + */ + private int widthUnit = UNITS_PIXELS; + + /* + * (non-Javadoc) + * + * @see com.itmill.toolkit.ui.AbstractComponent#getTag() + */ + public abstract String getTag(); + + /* + * (non-Javadoc) + * + * @see com.itmill.toolkit.ui.Layout#setMargin(boolean) + */ + public void setMargin(boolean enabled) { + margins.setMargins(enabled); + requestRepaint(); + } + + /* + * (non-Javadoc) + * + * @see com.itmill.toolkit.ui.Layout#setMargin(boolean, boolean, boolean, + * boolean) + */ + public void setMargin(boolean topEnabled, boolean rightEnabled, + boolean bottomEnabled, boolean leftEnabled) { + margins + .setMargins(topEnabled, rightEnabled, bottomEnabled, + leftEnabled); + requestRepaint(); + } + + /* + * (non-Javadoc) + * + * @see com.itmill.toolkit.terminal.Sizeable#getHeight() + */ + public int getHeight() { + return height; + } + + /* + * (non-Javadoc) + * + * @see com.itmill.toolkit.terminal.Sizeable#getHeightUnits() + */ + public int getHeightUnits() { + return heightUnit; + } + + /* + * (non-Javadoc) + * + * @see com.itmill.toolkit.terminal.Sizeable#getWidth() + */ + public int getWidth() { + return width; + } + + /* + * (non-Javadoc) + * + * @see com.itmill.toolkit.terminal.Sizeable#getWidthUnits() + */ + public int getWidthUnits() { + return widthUnit; + } + + /* + * (non-Javadoc) + * + * @see com.itmill.toolkit.terminal.Sizeable#setHeight(int) + */ + public void setHeight(int height) { + this.height = height; + requestRepaint(); + } + + /* + * (non-Javadoc) + * + * @see com.itmill.toolkit.terminal.Sizeable#setHeightUnits(int) + */ + public void setHeightUnits(int units) { + heightUnit = units; + requestRepaint(); + } + + /* + * (non-Javadoc) + * + * @see com.itmill.toolkit.terminal.Sizeable#setSizeFull() + */ + public void setSizeFull() { + height = 100; + width = 100; + heightUnit = UNITS_PERCENTAGE; + widthUnit = UNITS_PERCENTAGE; + requestRepaint(); + } + + /* + * (non-Javadoc) + * + * @see com.itmill.toolkit.terminal.Sizeable#setSizeUndefined() + */ + public void setSizeUndefined() { + height = -1; + width = -1; + heightUnit = UNITS_PIXELS; + widthUnit = UNITS_PIXELS; + requestRepaint(); + } + + /* + * (non-Javadoc) + * + * @see com.itmill.toolkit.terminal.Sizeable#setWidth(int) + */ + public void setWidth(int width) { + this.width = width; + requestRepaint(); + } + + /* + * (non-Javadoc) + * + * @see com.itmill.toolkit.terminal.Sizeable#setWidthUnits(int) + */ + public void setWidthUnits(int units) { + widthUnit = units; + requestRepaint(); + } + + /* + * (non-Javadoc) + * + * @see com.itmill.toolkit.ui.AbstractComponent#paintContent(com.itmill.toolkit.terminal.PaintTarget) + */ + public void paintContent(PaintTarget target) throws PaintException { + + // Add margin info. Defaults to false. + target.addAttribute("margins", margins.getBitMask()); + + // Size + if (getHeight() >= 0) { + target.addAttribute("height", "" + getHeight() + + Sizeable.UNIT_SYMBOLS[getHeightUnits()]); + } + if (getWidth() >= 0) { + target.addAttribute("width", "" + getWidth() + + Sizeable.UNIT_SYMBOLS[getWidthUnits()]); + } + } } diff --git a/src/com/itmill/toolkit/ui/BaseFieldFactory.java b/src/com/itmill/toolkit/ui/BaseFieldFactory.java index c9881e6854..e5d6af12e6 100644 --- a/src/com/itmill/toolkit/ui/BaseFieldFactory.java +++ b/src/com/itmill/toolkit/ui/BaseFieldFactory.java @@ -50,82 +50,86 @@ import com.itmill.toolkit.data.Property; public class BaseFieldFactory implements FieldFactory { - /** - * Creates the field based on type of data. - * - * - * @param type - * the type of data presented in field. - * @param uiContext - * the context where the Field is presented. - * - * @see com.itmill.toolkit.ui.FieldFactory#createField(Class, Component) - */ - public Field createField(Class type, Component uiContext) { - // Null typed properties can not be edited - if (type == null) - return null; - - // Item field - if (Item.class.isAssignableFrom(type)) { - return new Form(); - } - - // Date field - if (Date.class.isAssignableFrom(type)) { - DateField df = new DateField(); - df.setResolution(DateField.RESOLUTION_DAY); - return df; - } - - // Boolean field - if (Boolean.class.isAssignableFrom(type)) { - Button button = new Button(); - button.setSwitchMode(true); - button.setImmediate(false); - return button; - } - - // Nested form is used by default - return new TextField(); - } - - /** - * Creates the field based on the datasource property. - * - * @see com.itmill.toolkit.ui.FieldFactory#createField(Property, Component) - */ - public Field createField(Property property, Component uiContext) { - if (property != null) - return createField(property.getType(), uiContext); - else - return null; - } - - /** - * Creates the field based on the item and property id. - * - * @see com.itmill.toolkit.ui.FieldFactory#createField(Item, Object, - * Component) - */ - public Field createField(Item item, Object propertyId, Component uiContext) { - if (item != null && propertyId != null) { - Field f = createField(item.getItemProperty(propertyId), uiContext); - if (f instanceof AbstractComponent) - ((AbstractComponent) f).setCaption(propertyId.toString()); - return f; - } else - return null; - } - - /** - * @see com.itmill.toolkit.ui.FieldFactory#createField(com.itmill.toolkit.data.Container, - * java.lang.Object, java.lang.Object, com.itmill.toolkit.ui.Component) - */ - public Field createField(Container container, Object itemId, - Object propertyId, Component uiContext) { - return createField(container.getContainerProperty(itemId, propertyId), - uiContext); - } + /** + * Creates the field based on type of data. + * + * + * @param type + * the type of data presented in field. + * @param uiContext + * the context where the Field is presented. + * + * @see com.itmill.toolkit.ui.FieldFactory#createField(Class, Component) + */ + public Field createField(Class type, Component uiContext) { + // Null typed properties can not be edited + if (type == null) { + return null; + } + + // Item field + if (Item.class.isAssignableFrom(type)) { + return new Form(); + } + + // Date field + if (Date.class.isAssignableFrom(type)) { + DateField df = new DateField(); + df.setResolution(DateField.RESOLUTION_DAY); + return df; + } + + // Boolean field + if (Boolean.class.isAssignableFrom(type)) { + Button button = new Button(); + button.setSwitchMode(true); + button.setImmediate(false); + return button; + } + + // Nested form is used by default + return new TextField(); + } + + /** + * Creates the field based on the datasource property. + * + * @see com.itmill.toolkit.ui.FieldFactory#createField(Property, Component) + */ + public Field createField(Property property, Component uiContext) { + if (property != null) { + return createField(property.getType(), uiContext); + } else { + return null; + } + } + + /** + * Creates the field based on the item and property id. + * + * @see com.itmill.toolkit.ui.FieldFactory#createField(Item, Object, + * Component) + */ + public Field createField(Item item, Object propertyId, Component uiContext) { + if (item != null && propertyId != null) { + Field f = createField(item.getItemProperty(propertyId), uiContext); + if (f instanceof AbstractComponent) { + ((AbstractComponent) f).setCaption(propertyId.toString()); + } + return f; + } else { + return null; + } + } + + /** + * @see com.itmill.toolkit.ui.FieldFactory#createField(com.itmill.toolkit.data.Container, + * java.lang.Object, java.lang.Object, com.itmill.toolkit.ui.Component) + */ + public Field createField(Container container, Object itemId, + Object propertyId, Component uiContext) { + return createField(container.getContainerProperty(itemId, propertyId), + uiContext); + } } diff --git a/src/com/itmill/toolkit/ui/Button.java b/src/com/itmill/toolkit/ui/Button.java index 08a90527e3..b9daa511c2 100644 --- a/src/com/itmill/toolkit/ui/Button.java +++ b/src/com/itmill/toolkit/ui/Button.java @@ -46,294 +46,297 @@ import com.itmill.toolkit.terminal.PaintTarget; */ public class Button extends AbstractField { - /* Private members ************************************************* */ - - boolean switchMode = false; - - /** - * Creates a new push button. The value of the push button is allways false - * and they are immediate by default. - * - */ - public Button() { - setSwitchMode(false); - } - - /** - * Creates a new push button. - * - * The value of the push button is allways false and they are immediate by - * default. - * - * @param caption - * the Button caption. - */ - public Button(String caption) { - setCaption(caption); - setSwitchMode(false); - } - - /** - * Creates a new push button with click listener. - * - * @param caption - * the Button caption. - * @param listener - * the Button click listener. - */ - public Button(String caption, ClickListener listener) { - this(caption); - addListener(listener); - } - - /** - * Creates a new push button with a method listening button clicks. The - * method must have either no parameters, or only one parameter of - * Button.ClickEvent type. - * - * @param caption - * the Button caption. - * @param target - * the Object having the method for listening button clicks. - * @param methodName - * the name of the method in target object, that receives button - * click events. - */ - public Button(String caption, Object target, String methodName) { - this(caption); - addListener(ClickEvent.class, target, methodName); - } - - /** - * Creates a new switch button with initial value. - * - * @param state - * the Initial state of the switch-button. - * @param initialState - */ - public Button(String caption, boolean initialState) { - setCaption(caption); - setValue(new Boolean(initialState)); - setSwitchMode(true); - } - - /** - * Creates a new switch button that is connected to a boolean property. - * - * @param state - * the Initial state of the switch-button. - * @param dataSource - */ - public Button(String caption, Property dataSource) { - setCaption(caption); - setSwitchMode(true); - setPropertyDataSource(dataSource); - } - - /** - * Gets component UIDL tag. - * - * @return the Component UIDL tag as string. - */ - public String getTag() { - return "button"; - } - - /** - * Paints the content of this component. - * - * @param event - * the PaintEvent. - * @throws IOException - * if the writing failed due to input/output error. - * @throws PaintException - * if the paint operation failed. - */ - public void paintContent(PaintTarget target) throws PaintException { - super.paintContent(target); - - if (isSwitchMode()) - target.addAttribute("type", "switch"); - boolean state; - try { - state = ((Boolean) getValue()).booleanValue(); - } catch (NullPointerException e) { - state = false; - } - target.addVariable(this, "state", state); - - } - - /** - * Invoked when the value of a variable has changed. Button listeners are - * notified if the button is clicked. - * - * @param source - * @param variables - */ - public void changeVariables(Object source, Map variables) { - if (variables.containsKey("state")) { - // Gets the new and old button states - Boolean newValue = (Boolean) variables.get("state"); - Boolean oldValue = (Boolean) getValue(); - - if (isSwitchMode()) { - - // For switch button, the event is only sent if the - // switch state is changed - if (newValue != null && !newValue.equals(oldValue) - && !isReadOnly()) { - setValue(newValue); - fireClick(); - } - } else { - - // Only send click event if the button is pushed - if (newValue.booleanValue()) - fireClick(); - - // If the button is true for some reason, release it - if (oldValue.booleanValue()) - setValue(new Boolean(false)); - } - } - } - - /** - * Checks if it is switchMode. - * - * @return true if it is in Switch Mode, otherwise - * false. - */ - public boolean isSwitchMode() { - return switchMode; - } - - /** - * Sets the switchMode. - * - * @param switchMode - * The switchMode to set. - */ - public void setSwitchMode(boolean switchMode) { - this.switchMode = switchMode; - if (!switchMode) { - setImmediate(true); - setValue(new Boolean(false)); - } - } - - /** - * Sets immediate mode. Push buttons can not be set in non-immediate mode. - * - * @see com.itmill.toolkit.ui.AbstractComponent#setImmediate(boolean) - */ - public void setImmediate(boolean immediate) { - // Push buttons are allways immediate - super.setImmediate(!isSwitchMode() || immediate); - } - - /** - * The type of the button as a property. - * - * @see com.itmill.toolkit.data.Property#getType() - */ - public Class getType() { - return Boolean.class; - } - - /* Click event ************************************************ */ - - private static final Method BUTTON_CLICK_METHOD; - static { - try { - BUTTON_CLICK_METHOD = ClickListener.class.getDeclaredMethod( - "buttonClick", new Class[] { ClickEvent.class }); - } catch (java.lang.NoSuchMethodException e) { - // This should never happen - throw new java.lang.RuntimeException(); - } - } - - /** - * Click event. This event is thrown, when the button is clicked. - * - * @author IT Mill Ltd. - * @version - * @VERSION@ - * @since 3.0 - */ - public class ClickEvent extends Component.Event { - - /** - * Serial generated by eclipse. - */ - private static final long serialVersionUID = 3546647602931118393L; - - /** - * New instance of text change event. - * - * @param source - * the Source of the event. - */ - public ClickEvent(Component source) { - super(source); - } - - /** - * Gets the Button where the event occurred. - * - * @return the Source of the event. - */ - public Button getButton() { - return (Button) getSource(); - } - } - - /** - * Button click listener - * - * @author IT Mill Ltd. - * @version - * @VERSION@ - * @since 3.0 - */ - public interface ClickListener { - - /** - * Button has been pressed. - * - * @param event - * Button click event. - */ - public void buttonClick(ClickEvent event); - } - - /** - * Adds the button click listener. - * - * @param listener - * the Listener to be added. - */ - public void addListener(ClickListener listener) { - addListener(ClickEvent.class, listener, BUTTON_CLICK_METHOD); - } - - /** - * Removes the button click listener. - * - * @param listener - * the Listener to be removed. - */ - public void removeListener(ClickListener listener) { - removeListener(ClickEvent.class, listener, BUTTON_CLICK_METHOD); - } - - /** - * Emits the options change event. - */ - protected void fireClick() { - fireEvent(new Button.ClickEvent(this)); - } + /* Private members ************************************************* */ + + boolean switchMode = false; + + /** + * Creates a new push button. The value of the push button is allways false + * and they are immediate by default. + * + */ + public Button() { + setSwitchMode(false); + } + + /** + * Creates a new push button. + * + * The value of the push button is allways false and they are immediate by + * default. + * + * @param caption + * the Button caption. + */ + public Button(String caption) { + setCaption(caption); + setSwitchMode(false); + } + + /** + * Creates a new push button with click listener. + * + * @param caption + * the Button caption. + * @param listener + * the Button click listener. + */ + public Button(String caption, ClickListener listener) { + this(caption); + addListener(listener); + } + + /** + * Creates a new push button with a method listening button clicks. The + * method must have either no parameters, or only one parameter of + * Button.ClickEvent type. + * + * @param caption + * the Button caption. + * @param target + * the Object having the method for listening button clicks. + * @param methodName + * the name of the method in target object, that receives + * button click events. + */ + public Button(String caption, Object target, String methodName) { + this(caption); + addListener(ClickEvent.class, target, methodName); + } + + /** + * Creates a new switch button with initial value. + * + * @param state + * the Initial state of the switch-button. + * @param initialState + */ + public Button(String caption, boolean initialState) { + setCaption(caption); + setValue(new Boolean(initialState)); + setSwitchMode(true); + } + + /** + * Creates a new switch button that is connected to a boolean property. + * + * @param state + * the Initial state of the switch-button. + * @param dataSource + */ + public Button(String caption, Property dataSource) { + setCaption(caption); + setSwitchMode(true); + setPropertyDataSource(dataSource); + } + + /** + * Gets component UIDL tag. + * + * @return the Component UIDL tag as string. + */ + public String getTag() { + return "button"; + } + + /** + * Paints the content of this component. + * + * @param event + * the PaintEvent. + * @throws IOException + * if the writing failed due to input/output error. + * @throws PaintException + * if the paint operation failed. + */ + public void paintContent(PaintTarget target) throws PaintException { + super.paintContent(target); + + if (isSwitchMode()) { + target.addAttribute("type", "switch"); + } + boolean state; + try { + state = ((Boolean) getValue()).booleanValue(); + } catch (NullPointerException e) { + state = false; + } + target.addVariable(this, "state", state); + + } + + /** + * Invoked when the value of a variable has changed. Button listeners are + * notified if the button is clicked. + * + * @param source + * @param variables + */ + public void changeVariables(Object source, Map variables) { + if (variables.containsKey("state")) { + // Gets the new and old button states + Boolean newValue = (Boolean) variables.get("state"); + Boolean oldValue = (Boolean) getValue(); + + if (isSwitchMode()) { + + // For switch button, the event is only sent if the + // switch state is changed + if (newValue != null && !newValue.equals(oldValue) + && !isReadOnly()) { + setValue(newValue); + fireClick(); + } + } else { + + // Only send click event if the button is pushed + if (newValue.booleanValue()) { + fireClick(); + } + + // If the button is true for some reason, release it + if (oldValue.booleanValue()) { + setValue(new Boolean(false)); + } + } + } + } + + /** + * Checks if it is switchMode. + * + * @return true if it is in Switch Mode, otherwise + * false. + */ + public boolean isSwitchMode() { + return switchMode; + } + + /** + * Sets the switchMode. + * + * @param switchMode + * The switchMode to set. + */ + public void setSwitchMode(boolean switchMode) { + this.switchMode = switchMode; + if (!switchMode) { + setImmediate(true); + setValue(new Boolean(false)); + } + } + + /** + * Sets immediate mode. Push buttons can not be set in non-immediate mode. + * + * @see com.itmill.toolkit.ui.AbstractComponent#setImmediate(boolean) + */ + public void setImmediate(boolean immediate) { + // Push buttons are allways immediate + super.setImmediate(!isSwitchMode() || immediate); + } + + /** + * The type of the button as a property. + * + * @see com.itmill.toolkit.data.Property#getType() + */ + public Class getType() { + return Boolean.class; + } + + /* Click event ************************************************ */ + + private static final Method BUTTON_CLICK_METHOD; + static { + try { + BUTTON_CLICK_METHOD = ClickListener.class.getDeclaredMethod( + "buttonClick", new Class[] { ClickEvent.class }); + } catch (java.lang.NoSuchMethodException e) { + // This should never happen + throw new java.lang.RuntimeException(); + } + } + + /** + * Click event. This event is thrown, when the button is clicked. + * + * @author IT Mill Ltd. + * @version + * @VERSION@ + * @since 3.0 + */ + public class ClickEvent extends Component.Event { + + /** + * Serial generated by eclipse. + */ + private static final long serialVersionUID = 3546647602931118393L; + + /** + * New instance of text change event. + * + * @param source + * the Source of the event. + */ + public ClickEvent(Component source) { + super(source); + } + + /** + * Gets the Button where the event occurred. + * + * @return the Source of the event. + */ + public Button getButton() { + return (Button) getSource(); + } + } + + /** + * Button click listener + * + * @author IT Mill Ltd. + * @version + * @VERSION@ + * @since 3.0 + */ + public interface ClickListener { + + /** + * Button has been pressed. + * + * @param event + * Button click event. + */ + public void buttonClick(ClickEvent event); + } + + /** + * Adds the button click listener. + * + * @param listener + * the Listener to be added. + */ + public void addListener(ClickListener listener) { + addListener(ClickEvent.class, listener, BUTTON_CLICK_METHOD); + } + + /** + * Removes the button click listener. + * + * @param listener + * the Listener to be removed. + */ + public void removeListener(ClickListener listener) { + removeListener(ClickEvent.class, listener, BUTTON_CLICK_METHOD); + } + + /** + * Emits the options change event. + */ + protected void fireClick() { + fireEvent(new Button.ClickEvent(this)); + } } diff --git a/src/com/itmill/toolkit/ui/Component.java b/src/com/itmill/toolkit/ui/Component.java index eefa6ff11d..fd5d78840e 100644 --- a/src/com/itmill/toolkit/ui/Component.java +++ b/src/com/itmill/toolkit/ui/Component.java @@ -28,17 +28,17 @@ package com.itmill.toolkit.ui; +import java.util.Collection; +import java.util.EventListener; +import java.util.EventObject; +import java.util.Locale; + import com.itmill.toolkit.Application; import com.itmill.toolkit.terminal.ErrorMessage; import com.itmill.toolkit.terminal.Paintable; import com.itmill.toolkit.terminal.Resource; import com.itmill.toolkit.terminal.VariableOwner; -import java.util.Collection; -import java.util.EventListener; -import java.util.EventObject; -import java.util.Locale; - /** * The top-level component interface which must be implemented by all UI * components that use IT Mill Toolkit. @@ -50,371 +50,371 @@ import java.util.Locale; */ public interface Component extends Paintable, VariableOwner { - /** - * Gets style for component. Multiple styles are joined with spaces. - * - * @return the component's styleValue of property style. - */ - public String getStyleName(); - - /** - * Sets and replaces all previous style names of the component. This method - * will trigger a - * {@link com.itmill.toolkit.terminal.Paintable.RepaintRequestEvent RepaintRequestEvent}. - * - * @param style - * the new style of the component. - */ - public void setStyleName(String style); - - /** - * Adds style name to component. Handling additional style names is terminal - * specific, but in web browser environment they will most likely become CSS - * classes as given on server side. - * - * This method will trigger a - * {@link com.itmill.toolkit.terminal.Paintable.RepaintRequestEvent RepaintRequestEvent}. - * - * @param style - * the new style to be added to the component - */ - public void addStyleName(String style); - - /** - * Removes given style name from component. - * - * @param style - * the style to be removed - */ - public void removeStyleName(String style); - - /** - *

- * Tests if the component is enabled or not. All the variable change events - * are blocked from disabled components. Also the component should visually - * indicate that it is disabled (by shading the component for example). All - * hidden (isVisible() == false) components must return false. - *

- * - *

- * Components should be enabled by default. - *

- * - * @return true if the component is enabled, - * false if not. - * @see VariableOwner#isEnabled() - */ - public boolean isEnabled(); - - /** - * Enables or disables the component. Being enabled means that the component - * can be edited. This method will trigger a - * {@link com.itmill.toolkit.terminal.Paintable.RepaintRequestEvent RepaintRequestEvent}. - * - * @param enabled - * the boolean value specifying if the component should be - * enabled after the call or not - */ - public void setEnabled(boolean enabled); - - /** - * Tests if the component is visible or not. Visibility defines if the - * component is shown in the UI or not. Default is true. - * - * @return true if the component is visible in the UI, - * false if not - */ - public boolean isVisible(); - - /** - * Sets the components visibility status. Visibility defines if the - * component is shown in the UI or not. - * - * @param visible - * the Boolean value specifying if the component should be - * visible after the call or not. - */ - public void setVisible(boolean visible); - - /** - * Gets the visual parent of the component. The components can be nested but - * one component can have only one parent. - * - * @return the parent component. - */ - public Component getParent(); - - /** - * Sets the component's parent component. - * - *

- * This method calls automatically {@link #attach()} if the parent is - * attached to a window (or is itself a window}, and {@link #detach()} if - * parent is set null, but the component was - * in the application. - *

- * - *

- * This method is rarely called directly. Instead the - * {@link ComponentContainer#addComponent(Component)} method is used to add - * components to container, which call this method implicitly. - * - * @param parent - * the new parent component. - */ - public void setParent(Component parent); - - /** - * Tests if the component is in read-only mode. - * - * @return true if the component is in read-only mode, - * false if not. - */ - public boolean isReadOnly(); - - /** - * Sets the component's to read-only mode to the specified state. This - * method will trigger a - * {@link com.itmill.toolkit.terminal.Paintable.RepaintRequestEvent RepaintRequestEvent}. - * - * @param readOnly - * the boolean value specifying if the component should be in - * read-only mode after the call or not. - */ - public void setReadOnly(boolean readOnly); - - /** - * Gets the caption of the component. Caption is the visible name of the - * component. - * - * @return the component's caption String. - */ - public String getCaption(); - - /** - * Gets the component's icon. A component may have a graphical icon - * associated with it, this method retrieves it if it is defined. - * - * @return the component's icon or null if it not defined. - */ - public Resource getIcon(); - - /** - * Gets the component's parent window. If the component does not yet belong - * to a window null is returned. - * - * @return the parent window of the component or null. - */ - public Window getWindow(); - - /** - * Gets the component's parent application. If the component does not yet - * belong to a application null is returned. - * - * @return the parent application of the component or null. - */ - public Application getApplication(); - - /** - *

- * Notifies the component that it is connected to an application. This - * method is always called before the component is first time painted and is - * suitable to be extended. The getApplication and - * getWindow methods might return null before - * this method is called. - *

- * - *

- * The caller of this method is {@link #setParent(Component)} if the parent - * is already in the application. If the parent is not in the application, - * it must call the {@link #attach()} for all its children when it will be - * added to the application. - *

- */ - public void attach(); - - /** - * Notifies the component that it is detached from the application. - *

- * The {@link #getApplication()} and {@link #getWindow()} methods might - * return null after this method is called. - *

- * - *

- * The caller of this method is {@link #setParent(Component)} if the parent - * is in the application. When the parent is detached from the application - * it is its response to call {@link #detach()} for all the children and to - * detach itself from the terminal. - *

- */ - public void detach(); - - /** - * Gets the locale of this component. - * - * @return This component's locale. If this component does not have a - * locale, the locale of its parent is returned. Eventually locale - * of application is returned. If application does not have its own - * locale the locale is determined by - * Locale.getDefautlt. Returns null if the component - * does not have its own locale and has not yet been added to a - * containment hierarchy such that the locale can be determined from - * the containing parent. - */ - public Locale getLocale(); - - /** - * The children must call this method when they need repainting. The call - * must be made event in the case the children sent the repaint request - * themselves. - * - * @param alreadyNotified - * the collection of repaint request listeners that have been - * already notified by the child. This component should not - * renotify the listed listeners again. The container given as - * parameter must be modifiable as the component might modify it - * and pass it forwards. Null parameter is interpreted as empty - * collection. - */ - public void childRequestedRepaint(Collection alreadyNotified); - - /* Component event framework *************************************** */ - - /** - * Superclass of all component originated Events. - */ - public class Event extends EventObject { - - /** - * Serial generated by eclipse. - */ - private static final long serialVersionUID = 4048791277653274933L; - - /** - * Constructs a new event with a specified source component. - * - * @param source - * the source component of the event. - */ - public Event(Component source) { - super(source); - } - } - - /** - * Listener interface for receiving Component.Events. - */ - public interface Listener extends EventListener { - - /** - * Notifies the listener of a component event. - * - * @param event - * the event that has occured. - */ - public void componentEvent(Component.Event event); - } - - /** - * Registers a new component event listener for this component. - * - * @param listener - * the new Listener to be registered. - */ - public void addListener(Component.Listener listener); - - /** - * Removes a previously registered component event listener from this - * component. - * - * @param listener - * the listener to be removed. - */ - public void removeListener(Component.Listener listener); - - /** - * Class of all component originated ErrorEvents. - */ - public class ErrorEvent extends Event { - - /** - * Serial generated by eclipse. - */ - private static final long serialVersionUID = 4051323457293857333L; - - private ErrorMessage message; - - /** - * Constructs a new event with a specified source component. - * - * @param message - * the error message. - * @param component - * the source component. - */ - public ErrorEvent(ErrorMessage message, Component component) { - super(component); - this.message = message; - } - - /** - * Gets the error message. - * - * @return the error message. - */ - public ErrorMessage getErrorMessage() { - return this.message; - } - } - - /** - * Listener interface for receiving Component.Errorss. - */ - public interface ErrorListener extends EventListener { - - /** - * Notifies the listener of a component error. - * - * @param event - * the event that has occured. - */ - public void componentError(Component.ErrorEvent event); - } - - /** - * Interface implemented by components which can obtain input focus. - */ - public interface Focusable { - - /** - * Sets the focus to this component. - */ - public void focus(); - - /** - * Gets the Tabulator index of this Focusable component. - * - * @return the Positive tab order of this focusable. Negative of zero - * means unspecified tab order. - */ - public int getTabIndex(); - - /** - * Sets the Tabulator index of this Focusable component. - * - * @param tabIndex - * the Positive tab order of this focusable. Negative of zero - * means unspecified tab order. - */ - public void setTabIndex(int tabIndex); - - /** - * Gets the unique ID of focusable. This will be used to move input - * focus directly to this component. - * - * @return the Unique id of focusable. - */ - public long getFocusableId(); - - } + /** + * Gets style for component. Multiple styles are joined with spaces. + * + * @return the component's styleValue of property style. + */ + public String getStyleName(); + + /** + * Sets and replaces all previous style names of the component. This method + * will trigger a + * {@link com.itmill.toolkit.terminal.Paintable.RepaintRequestEvent RepaintRequestEvent}. + * + * @param style + * the new style of the component. + */ + public void setStyleName(String style); + + /** + * Adds style name to component. Handling additional style names is terminal + * specific, but in web browser environment they will most likely become CSS + * classes as given on server side. + * + * This method will trigger a + * {@link com.itmill.toolkit.terminal.Paintable.RepaintRequestEvent RepaintRequestEvent}. + * + * @param style + * the new style to be added to the component + */ + public void addStyleName(String style); + + /** + * Removes given style name from component. + * + * @param style + * the style to be removed + */ + public void removeStyleName(String style); + + /** + *

+ * Tests if the component is enabled or not. All the variable change events + * are blocked from disabled components. Also the component should visually + * indicate that it is disabled (by shading the component for example). All + * hidden (isVisible() == false) components must return false. + *

+ * + *

+ * Components should be enabled by default. + *

+ * + * @return true if the component is enabled, + * false if not. + * @see VariableOwner#isEnabled() + */ + public boolean isEnabled(); + + /** + * Enables or disables the component. Being enabled means that the component + * can be edited. This method will trigger a + * {@link com.itmill.toolkit.terminal.Paintable.RepaintRequestEvent RepaintRequestEvent}. + * + * @param enabled + * the boolean value specifying if the component should be + * enabled after the call or not + */ + public void setEnabled(boolean enabled); + + /** + * Tests if the component is visible or not. Visibility defines if the + * component is shown in the UI or not. Default is true. + * + * @return true if the component is visible in the UI, + * false if not + */ + public boolean isVisible(); + + /** + * Sets the components visibility status. Visibility defines if the + * component is shown in the UI or not. + * + * @param visible + * the Boolean value specifying if the component should be + * visible after the call or not. + */ + public void setVisible(boolean visible); + + /** + * Gets the visual parent of the component. The components can be nested but + * one component can have only one parent. + * + * @return the parent component. + */ + public Component getParent(); + + /** + * Sets the component's parent component. + * + *

+ * This method calls automatically {@link #attach()} if the parent is + * attached to a window (or is itself a window}, and {@link #detach()} if + * parent is set null, but the component was + * in the application. + *

+ * + *

+ * This method is rarely called directly. Instead the + * {@link ComponentContainer#addComponent(Component)} method is used to add + * components to container, which call this method implicitly. + * + * @param parent + * the new parent component. + */ + public void setParent(Component parent); + + /** + * Tests if the component is in read-only mode. + * + * @return true if the component is in read-only mode, + * false if not. + */ + public boolean isReadOnly(); + + /** + * Sets the component's to read-only mode to the specified state. This + * method will trigger a + * {@link com.itmill.toolkit.terminal.Paintable.RepaintRequestEvent RepaintRequestEvent}. + * + * @param readOnly + * the boolean value specifying if the component should be in + * read-only mode after the call or not. + */ + public void setReadOnly(boolean readOnly); + + /** + * Gets the caption of the component. Caption is the visible name of the + * component. + * + * @return the component's caption String. + */ + public String getCaption(); + + /** + * Gets the component's icon. A component may have a graphical icon + * associated with it, this method retrieves it if it is defined. + * + * @return the component's icon or null if it not defined. + */ + public Resource getIcon(); + + /** + * Gets the component's parent window. If the component does not yet belong + * to a window null is returned. + * + * @return the parent window of the component or null. + */ + public Window getWindow(); + + /** + * Gets the component's parent application. If the component does not yet + * belong to a application null is returned. + * + * @return the parent application of the component or null. + */ + public Application getApplication(); + + /** + *

+ * Notifies the component that it is connected to an application. This + * method is always called before the component is first time painted and is + * suitable to be extended. The getApplication and + * getWindow methods might return null before + * this method is called. + *

+ * + *

+ * The caller of this method is {@link #setParent(Component)} if the parent + * is already in the application. If the parent is not in the application, + * it must call the {@link #attach()} for all its children when it will be + * added to the application. + *

+ */ + public void attach(); + + /** + * Notifies the component that it is detached from the application. + *

+ * The {@link #getApplication()} and {@link #getWindow()} methods might + * return null after this method is called. + *

+ * + *

+ * The caller of this method is {@link #setParent(Component)} if the parent + * is in the application. When the parent is detached from the application + * it is its response to call {@link #detach()} for all the children and to + * detach itself from the terminal. + *

+ */ + public void detach(); + + /** + * Gets the locale of this component. + * + * @return This component's locale. If this component does not have a + * locale, the locale of its parent is returned. Eventually locale + * of application is returned. If application does not have its own + * locale the locale is determined by + * Locale.getDefautlt. Returns null if the component + * does not have its own locale and has not yet been added to a + * containment hierarchy such that the locale can be determined from + * the containing parent. + */ + public Locale getLocale(); + + /** + * The children must call this method when they need repainting. The call + * must be made event in the case the children sent the repaint request + * themselves. + * + * @param alreadyNotified + * the collection of repaint request listeners that have been + * already notified by the child. This component should not + * renotify the listed listeners again. The container given + * as parameter must be modifiable as the component might + * modify it and pass it forwards. Null parameter is + * interpreted as empty collection. + */ + public void childRequestedRepaint(Collection alreadyNotified); + + /* Component event framework *************************************** */ + + /** + * Superclass of all component originated Events. + */ + public class Event extends EventObject { + + /** + * Serial generated by eclipse. + */ + private static final long serialVersionUID = 4048791277653274933L; + + /** + * Constructs a new event with a specified source component. + * + * @param source + * the source component of the event. + */ + public Event(Component source) { + super(source); + } + } + + /** + * Listener interface for receiving Component.Events. + */ + public interface Listener extends EventListener { + + /** + * Notifies the listener of a component event. + * + * @param event + * the event that has occured. + */ + public void componentEvent(Component.Event event); + } + + /** + * Registers a new component event listener for this component. + * + * @param listener + * the new Listener to be registered. + */ + public void addListener(Component.Listener listener); + + /** + * Removes a previously registered component event listener from this + * component. + * + * @param listener + * the listener to be removed. + */ + public void removeListener(Component.Listener listener); + + /** + * Class of all component originated ErrorEvents. + */ + public class ErrorEvent extends Event { + + /** + * Serial generated by eclipse. + */ + private static final long serialVersionUID = 4051323457293857333L; + + private ErrorMessage message; + + /** + * Constructs a new event with a specified source component. + * + * @param message + * the error message. + * @param component + * the source component. + */ + public ErrorEvent(ErrorMessage message, Component component) { + super(component); + this.message = message; + } + + /** + * Gets the error message. + * + * @return the error message. + */ + public ErrorMessage getErrorMessage() { + return message; + } + } + + /** + * Listener interface for receiving Component.Errorss. + */ + public interface ErrorListener extends EventListener { + + /** + * Notifies the listener of a component error. + * + * @param event + * the event that has occured. + */ + public void componentError(Component.ErrorEvent event); + } + + /** + * Interface implemented by components which can obtain input focus. + */ + public interface Focusable { + + /** + * Sets the focus to this component. + */ + public void focus(); + + /** + * Gets the Tabulator index of this Focusable component. + * + * @return the Positive tab order of this focusable. Negative of zero + * means unspecified tab order. + */ + public int getTabIndex(); + + /** + * Sets the Tabulator index of this Focusable component. + * + * @param tabIndex + * the Positive tab order of this focusable. Negative of + * zero means unspecified tab order. + */ + public void setTabIndex(int tabIndex); + + /** + * Gets the unique ID of focusable. This will be used to move input + * focus directly to this component. + * + * @return the Unique id of focusable. + */ + public long getFocusableId(); + + } } diff --git a/src/com/itmill/toolkit/ui/ComponentContainer.java b/src/com/itmill/toolkit/ui/ComponentContainer.java index 5010becf10..fae3670d05 100644 --- a/src/com/itmill/toolkit/ui/ComponentContainer.java +++ b/src/com/itmill/toolkit/ui/ComponentContainer.java @@ -42,213 +42,213 @@ import java.util.Iterator; */ public interface ComponentContainer extends Component { - /** - * Adds the component into this container. - * - * @param c - * the component to be added. - */ - public void addComponent(Component c); - - /** - * Removes the component from this container. - * - * @param c - * the component to be added. - */ - public void removeComponent(Component c); - - /** - * Removes all components from this container. - */ - public void removeAllComponents(); - - /** - * Replaces the component in the container with another one without changing - * position. - * - *

- * This method replaces component with another one is such way that the new - * component overtakes the position of the old component. If the old - * component is not in the container, the new component is added to the - * container. If the both component are already in the container, their - * positions are swapped. Component attach and detach events should be taken - * care as with add and remove. - *

- * - * @param oldComponent - * the old component that will be replaced. - * @param newComponent - * the new component to be replaced. - */ - public void replaceComponent(Component oldComponent, Component newComponent); - - /** - * Gets an iterator to the collection of contained components. Using this - * iterator it is possible to step through all components contained in this - * container. - * - * @return the component iterator. - */ - public Iterator getComponentIterator(); - - /** - * Moves all components from an another container into this container. The - * components are removed from source. - * - * @param source - * the container which contains the components that are to be - * moved to this container. - */ - public void moveComponentsFrom(ComponentContainer source); - - /** - * Listens the component attach events. - * - * @param listener - * the listener to add. - */ - public void addListener(ComponentAttachListener listener); - - /** - * Stops the listening component attach events. - * - * @param listener - * the listener to removed. - */ - public void removeListener(ComponentAttachListener listener); - - /** - * Listens the component detach events. - */ - public void addListener(ComponentDetachListener listener); - - /** - * Stops the listening component detach events. - */ - public void removeListener(ComponentDetachListener listener); - - /** - * Component attach listener interface. - */ - public interface ComponentAttachListener { - - /** - * A new component is attached to container. - * - * @param event - * the component attach event. - */ - public void componentAttachedToContainer(ComponentAttachEvent event); - } - - /** - * Component detach listener interface. - */ - public interface ComponentDetachListener { - - /** - * A component has been detached from container. - * - * @param event - * the component detach event. - */ - public void componentDetachedFromContainer(ComponentDetachEvent event); - } - - /** - * Component attach event sent when a component is attached to container. - */ - public class ComponentAttachEvent extends Component.Event { - - /** - * Serial generated by eclipse. - */ - private static final long serialVersionUID = 3257285812184692019L; - - private Component component; - - /** - * Creates a new attach event. - * - * @param container - * the component container the component has been detached - * to. - * @param attachedComponent - * the component that has been attached. - */ - public ComponentAttachEvent(ComponentContainer container, - Component attachedComponent) { - super(container); - this.component = attachedComponent; - } - - /** - * Gets the component container. - * - * @param the - * component container. - */ - public ComponentContainer getContainer() { - return (ComponentContainer) getSource(); - } - - /** - * Gets the attached component. - * - * @param the - * attach component. - */ - public Component getAttachedComponent() { - return component; - } - } - - /** - * Component detach event sent when a component is detached from container. - */ - public class ComponentDetachEvent extends Component.Event { - - /** - * Serial generated by eclipse. - */ - private static final long serialVersionUID = 3618140052337930290L; - - private Component component; - - /** - * Creates a new detach event. - * - * @param container - * the component container the component has been detached - * from. - * @param detachedComponent - * the component that has been detached. - */ - public ComponentDetachEvent(ComponentContainer container, - Component detachedComponent) { - super(container); - this.component = detachedComponent; - } - - /** - * Gets the component container. - * - * @param the - * component container. - */ - public ComponentContainer getContainer() { - return (ComponentContainer) getSource(); - } - - /** - * Gets the detached component. - * - * @return the detached component. - */ - public Component getDetachedComponent() { - return component; - } - } + /** + * Adds the component into this container. + * + * @param c + * the component to be added. + */ + public void addComponent(Component c); + + /** + * Removes the component from this container. + * + * @param c + * the component to be added. + */ + public void removeComponent(Component c); + + /** + * Removes all components from this container. + */ + public void removeAllComponents(); + + /** + * Replaces the component in the container with another one without changing + * position. + * + *

+ * This method replaces component with another one is such way that the new + * component overtakes the position of the old component. If the old + * component is not in the container, the new component is added to the + * container. If the both component are already in the container, their + * positions are swapped. Component attach and detach events should be taken + * care as with add and remove. + *

+ * + * @param oldComponent + * the old component that will be replaced. + * @param newComponent + * the new component to be replaced. + */ + public void replaceComponent(Component oldComponent, Component newComponent); + + /** + * Gets an iterator to the collection of contained components. Using this + * iterator it is possible to step through all components contained in this + * container. + * + * @return the component iterator. + */ + public Iterator getComponentIterator(); + + /** + * Moves all components from an another container into this container. The + * components are removed from source. + * + * @param source + * the container which contains the components that are to be + * moved to this container. + */ + public void moveComponentsFrom(ComponentContainer source); + + /** + * Listens the component attach events. + * + * @param listener + * the listener to add. + */ + public void addListener(ComponentAttachListener listener); + + /** + * Stops the listening component attach events. + * + * @param listener + * the listener to removed. + */ + public void removeListener(ComponentAttachListener listener); + + /** + * Listens the component detach events. + */ + public void addListener(ComponentDetachListener listener); + + /** + * Stops the listening component detach events. + */ + public void removeListener(ComponentDetachListener listener); + + /** + * Component attach listener interface. + */ + public interface ComponentAttachListener { + + /** + * A new component is attached to container. + * + * @param event + * the component attach event. + */ + public void componentAttachedToContainer(ComponentAttachEvent event); + } + + /** + * Component detach listener interface. + */ + public interface ComponentDetachListener { + + /** + * A component has been detached from container. + * + * @param event + * the component detach event. + */ + public void componentDetachedFromContainer(ComponentDetachEvent event); + } + + /** + * Component attach event sent when a component is attached to container. + */ + public class ComponentAttachEvent extends Component.Event { + + /** + * Serial generated by eclipse. + */ + private static final long serialVersionUID = 3257285812184692019L; + + private Component component; + + /** + * Creates a new attach event. + * + * @param container + * the component container the component has been + * detached to. + * @param attachedComponent + * the component that has been attached. + */ + public ComponentAttachEvent(ComponentContainer container, + Component attachedComponent) { + super(container); + component = attachedComponent; + } + + /** + * Gets the component container. + * + * @param the + * component container. + */ + public ComponentContainer getContainer() { + return (ComponentContainer) getSource(); + } + + /** + * Gets the attached component. + * + * @param the + * attach component. + */ + public Component getAttachedComponent() { + return component; + } + } + + /** + * Component detach event sent when a component is detached from container. + */ + public class ComponentDetachEvent extends Component.Event { + + /** + * Serial generated by eclipse. + */ + private static final long serialVersionUID = 3618140052337930290L; + + private Component component; + + /** + * Creates a new detach event. + * + * @param container + * the component container the component has been + * detached from. + * @param detachedComponent + * the component that has been detached. + */ + public ComponentDetachEvent(ComponentContainer container, + Component detachedComponent) { + super(container); + component = detachedComponent; + } + + /** + * Gets the component container. + * + * @param the + * component container. + */ + public ComponentContainer getContainer() { + return (ComponentContainer) getSource(); + } + + /** + * Gets the detached component. + * + * @return the detached component. + */ + public Component getDetachedComponent() { + return component; + } + } } diff --git a/src/com/itmill/toolkit/ui/CustomComponent.java b/src/com/itmill/toolkit/ui/CustomComponent.java index 786fdae539..3f63ff4806 100644 --- a/src/com/itmill/toolkit/ui/CustomComponent.java +++ b/src/com/itmill/toolkit/ui/CustomComponent.java @@ -29,7 +29,6 @@ package com.itmill.toolkit.ui; import java.util.Collection; -import java.util.HashSet; import java.util.LinkedList; import java.util.Locale; import java.util.Map; @@ -57,454 +56,470 @@ import com.itmill.toolkit.terminal.VariableOwner; */ public class CustomComponent implements Component { - /** - * The root component implementing the custom component. - */ - private Component root = null; - - /** - * The visibility of the component. - */ - private boolean visible = true; - - /** - * The parent of the component. - */ - private Component parent = null; - - /** - * Type of the component. - */ - private String componentType = null; - - /** - * List of repaint request listeners or null if not listened at all. - */ - private LinkedList repaintRequestListeners = null; - - /** - * Are all the repaint listeners notified about recent changes ? - */ - private boolean repaintRequestListenersNotified = false; - - /** - * Constructs a new custom component. - * - *

- * The component is implemented by wrapping the methods of the composition - * root component given as parameter. The composition root must be set - * before the component can be used. - *

- */ - public CustomComponent() { - } - - /** - * Constructs a new custom component. - * - *

- * The component is implemented by wrapping the methods of the composition - * root component given as parameter. The composition root must not be null - * and can not be changed after the composition. - *

- * - * @param compositionRoot - * the root of the composition component tree. - */ - public CustomComponent(Component compositionRoot) { - setCompositionRoot(compositionRoot); - } - - /** - * Returns the composition root. - * - * @return the Component Composition root. - */ - protected final Component getCompositionRoot() { - return root; - } - - /** - * Sets the compositions root. - *

- * The composition root must be set to non-null value before the component - * can be used. The composition root can only be set once. - *

- * - * @param compositionRoot - * the root of the composition component tree. - */ - protected final void setCompositionRoot(Component compositionRoot) { - if (compositionRoot != root && root != null) - root.setParent(null); - this.root = compositionRoot; - if (root != null) - root.setParent(this); - } - - /* Basic component features ------------------------------------------ */ - - /** - * Notifies the component that it is connected to an application. - * - * @see com.itmill.toolkit.ui.Component#attach() - */ - public void attach() { - if (root != null) { - root.attach(); - requestRepaint(); - } - } - - /** - * Notifies the component that it is detached from the application. - * - * @see com.itmill.toolkit.ui.Component#detach() - */ - public void detach() { - if (root != null) - root.detach(); - } - - /** - * Gets the component's parent application - * - * @see com.itmill.toolkit.ui.Component#getApplication() - */ - public Application getApplication() { - if (parent == null) - return null; - return parent.getApplication(); - } - - /** - * The caption of the custom component is by default the caption of the root - * component, or null if the root is not set. - * - * @see com.itmill.toolkit.ui.Component#getCaption() - */ - public String getCaption() { - if (root == null) - return null; - return root.getCaption(); - } - - /** - * The icon of the custom component is by default the icon of the root - * component, or null if the root is not set. - * - * @see com.itmill.toolkit.ui.Component#getIcon() - */ - public Resource getIcon() { - if (root == null) - return null; - return root.getIcon(); - } - - /** - * The icon of the custom component is by default the locale of the parent - * or null if the parent is not set. - * - * @see com.itmill.toolkit.ui.Component#getLocale() - */ - public Locale getLocale() { - if (parent == null) - return null; - return parent.getLocale(); - } - - /** - * Gets the visual parent of the component. - * - * @see com.itmill.toolkit.ui.Component#getParent() - */ - public Component getParent() { - return parent; - } - - /** - * Custom component does not implement custom styles by default and this - * function returns null. - * - * @see com.itmill.toolkit.ui.Component#getStyle() - */ - public String getStyleName() { - return null; - } - - /** - * Gets the component's parent window. - * - * @see com.itmill.toolkit.ui.Component#getWindow() - */ - public Window getWindow() { - if (parent == null) - return null; - return parent.getWindow(); - } - - /** - * Custom component is always enabled by default. - * - * @see com.itmill.toolkit.ui.Component#isEnabled() - */ - public boolean isEnabled() { - return true; - } - - /** - * Custom component is by default in the non-immediate mode. The - * immediateness of the custom component is defined by the components it is - * composed of. - * - * @see com.itmill.toolkit.terminal.VariableOwner#isImmediate() - */ - public boolean isImmediate() { - return false; - } - - /** - * The custom components are not readonly by default. - * - * @see com.itmill.toolkit.ui.Component#isReadOnly() - */ - public boolean isReadOnly() { - return false; - } - - /** - * Tests if the component is visible or not. - * - * @see com.itmill.toolkit.ui.Component#isVisible() - */ - public boolean isVisible() { - return visible; - } - - /* Documentation copied from interface */ - public void requestRepaint() { - - // The effect of the repaint request is identical to case where a - // child requests repaint - childRequestedRepaint(null); - } - - /* Documentation copied from interface */ - public void childRequestedRepaint(Collection alreadyNotified) { - - // Notify listeners only once - if (!repaintRequestListenersNotified) { - - // Notify the listeners - if (repaintRequestListeners != null - && !repaintRequestListeners.isEmpty()) { - Object[] listeners = repaintRequestListeners.toArray(); - RepaintRequestEvent event = new RepaintRequestEvent(this); - for (int i = 0; i < listeners.length; i++) { - if (alreadyNotified == null) - alreadyNotified = new LinkedList(); - if (!alreadyNotified.contains(listeners[i])) { - ((RepaintRequestListener) listeners[i]) - .repaintRequested(event); - alreadyNotified.add(listeners[i]); - } - } - } - - repaintRequestListenersNotified = true; - - // Notify the parent - Component parent = getParent(); - if (parent != null) - parent.childRequestedRepaint(alreadyNotified); - - } - } - - /* Documentation copied from interface */ - public void addListener(RepaintRequestListener listener) { - if (repaintRequestListeners == null) - repaintRequestListeners = new LinkedList(); - if (!repaintRequestListeners.contains(listener)) { - repaintRequestListeners.add(listener); - } - } - - /* Documentation copied from interface */ - public void removeListener(RepaintRequestListener listener) { - if (repaintRequestListeners != null) { - repaintRequestListeners.remove(listener); - if (repaintRequestListeners.isEmpty()) - repaintRequestListeners = null; - } - } - - /** - * The custom component is allways enabled by default. - */ - public void setEnabled(boolean enabled) { - } - - /** - * Sets the component's parent component. - * - * @see com.itmill.toolkit.ui.Component#setParent(com.itmill.toolkit.ui.Component) - */ - public void setParent(Component parent) { - - // If the parent is not changed, dont do nothing - if (parent == this.parent) - return; - - // Sends the detach event if the component have been connected to a - // window - if (getApplication() != null) { - detach(); - this.parent = null; - } - - // Connects to new parent - this.parent = parent; - - // Sends the attach event if connected to a window - if (getApplication() != null) - attach(); - } - - /** - * Sets the component's to read-only mode to the specified state. - * - * @see com.itmill.toolkit.ui.Component#setReadOnly(boolean) - */ - public void setReadOnly(boolean readOnly) { - } - - /** - * Custom component does not implement custom styles by default. - * - * @see com.itmill.toolkit.ui.Component#setStyle(java.lang.String) - */ - public void setStyleName(String style) { - } - - /** - * Sets the components visibility status. - * - * @see com.itmill.toolkit.ui.Component#setVisible(boolean) - */ - public void setVisible(boolean visible) { - this.visible = visible; - } - - /* Documented in super interface */ - public void requestRepaintRequests() { - repaintRequestListenersNotified = false; - } - - /* Documented in super interface */ - public void paint(PaintTarget target) throws PaintException { - if (root == null) - throw new IllegalStateException("Composition root must be set to" - + " non-null value before the " + getClass().getName() - + " can be painted"); - - if (isVisible()) { - String type = getComponentType(); - if (type != null) { - if (!target.startTag(this, "component")) { - target.addAttribute("type", type); - root.paint(target); - } - target.endTag("component"); - } else - root.paint(target); - } - repaintRequestListenersNotified = false; - } - - /** - * Called when one or more variables handled by the implementing class are - * changed. - * - * @see com.itmill.toolkit.terminal.VariableOwner#changeVariables(java.lang.Object, - * java.util.Map) - */ - public void changeVariables(Object source, Map variables) { - } - - /* Dependency -framework is deprecated */ - public void dependsOn(VariableOwner depended) { - } - - public void removeDirectDependency(VariableOwner depended) { - } - - public Set getDirectDependencies() { - return null; - } - - /* Event functions are not implemented by default -------------------- */ - - /** - * Custom component does not implement any component events by default. - * - * @param listener - * the listener to add. - */ - public void addListener(Component.Listener listener) { - } - - /** - * Custom component does not implement any component events by default. - * - * @param listener - * the listener to remove. - */ - public void removeListener(Component.Listener listener) { - } - - /** - * Gets the component type. - * - * The component type is textual type of the component. This is included in - * the UIDL as component tag attribute. If the component type is null - * (default), the component tag is not included in the UIDL at all. - * - * @return the component type. - */ - public String getComponentType() { - return componentType; - } - - /** - * Sets the component type. - * - * The component type is textual type of the component. This is included in - * the UIDL as component tag attribute. If the component type is null - * (default), the component tag is not included in the UIDL at all. - * - * @param componentType - * the componentType to set. - */ - public void setComponentType(String componentType) { - this.componentType = componentType; - } - - /** - * Custom component does not implement custom styles by default. - * - * @see com.itmill.toolkit.ui.Component#getStyle() - */ - public void addStyleName(String style) { - } - - /** - * Custom component does not implement custom styles by default. - * - * @see com.itmill.toolkit.ui.Component#getStyle() - */ - public void removeStyleName(String style) { - - } + /** + * The root component implementing the custom component. + */ + private Component root = null; + + /** + * The visibility of the component. + */ + private boolean visible = true; + + /** + * The parent of the component. + */ + private Component parent = null; + + /** + * Type of the component. + */ + private String componentType = null; + + /** + * List of repaint request listeners or null if not listened at all. + */ + private LinkedList repaintRequestListeners = null; + + /** + * Are all the repaint listeners notified about recent changes ? + */ + private boolean repaintRequestListenersNotified = false; + + /** + * Constructs a new custom component. + * + *

+ * The component is implemented by wrapping the methods of the composition + * root component given as parameter. The composition root must be set + * before the component can be used. + *

+ */ + public CustomComponent() { + } + + /** + * Constructs a new custom component. + * + *

+ * The component is implemented by wrapping the methods of the composition + * root component given as parameter. The composition root must not be null + * and can not be changed after the composition. + *

+ * + * @param compositionRoot + * the root of the composition component tree. + */ + public CustomComponent(Component compositionRoot) { + setCompositionRoot(compositionRoot); + } + + /** + * Returns the composition root. + * + * @return the Component Composition root. + */ + protected final Component getCompositionRoot() { + return root; + } + + /** + * Sets the compositions root. + *

+ * The composition root must be set to non-null value before the component + * can be used. The composition root can only be set once. + *

+ * + * @param compositionRoot + * the root of the composition component tree. + */ + protected final void setCompositionRoot(Component compositionRoot) { + if (compositionRoot != root && root != null) { + root.setParent(null); + } + root = compositionRoot; + if (root != null) { + root.setParent(this); + } + } + + /* Basic component features ------------------------------------------ */ + + /** + * Notifies the component that it is connected to an application. + * + * @see com.itmill.toolkit.ui.Component#attach() + */ + public void attach() { + if (root != null) { + root.attach(); + requestRepaint(); + } + } + + /** + * Notifies the component that it is detached from the application. + * + * @see com.itmill.toolkit.ui.Component#detach() + */ + public void detach() { + if (root != null) { + root.detach(); + } + } + + /** + * Gets the component's parent application + * + * @see com.itmill.toolkit.ui.Component#getApplication() + */ + public Application getApplication() { + if (parent == null) { + return null; + } + return parent.getApplication(); + } + + /** + * The caption of the custom component is by default the caption of the root + * component, or null if the root is not set. + * + * @see com.itmill.toolkit.ui.Component#getCaption() + */ + public String getCaption() { + if (root == null) { + return null; + } + return root.getCaption(); + } + + /** + * The icon of the custom component is by default the icon of the root + * component, or null if the root is not set. + * + * @see com.itmill.toolkit.ui.Component#getIcon() + */ + public Resource getIcon() { + if (root == null) { + return null; + } + return root.getIcon(); + } + + /** + * The icon of the custom component is by default the locale of the parent + * or null if the parent is not set. + * + * @see com.itmill.toolkit.ui.Component#getLocale() + */ + public Locale getLocale() { + if (parent == null) { + return null; + } + return parent.getLocale(); + } + + /** + * Gets the visual parent of the component. + * + * @see com.itmill.toolkit.ui.Component#getParent() + */ + public Component getParent() { + return parent; + } + + /** + * Custom component does not implement custom styles by default and this + * function returns null. + * + * @see com.itmill.toolkit.ui.Component#getStyle() + */ + public String getStyleName() { + return null; + } + + /** + * Gets the component's parent window. + * + * @see com.itmill.toolkit.ui.Component#getWindow() + */ + public Window getWindow() { + if (parent == null) { + return null; + } + return parent.getWindow(); + } + + /** + * Custom component is always enabled by default. + * + * @see com.itmill.toolkit.ui.Component#isEnabled() + */ + public boolean isEnabled() { + return true; + } + + /** + * Custom component is by default in the non-immediate mode. The + * immediateness of the custom component is defined by the components it is + * composed of. + * + * @see com.itmill.toolkit.terminal.VariableOwner#isImmediate() + */ + public boolean isImmediate() { + return false; + } + + /** + * The custom components are not readonly by default. + * + * @see com.itmill.toolkit.ui.Component#isReadOnly() + */ + public boolean isReadOnly() { + return false; + } + + /** + * Tests if the component is visible or not. + * + * @see com.itmill.toolkit.ui.Component#isVisible() + */ + public boolean isVisible() { + return visible; + } + + /* Documentation copied from interface */ + public void requestRepaint() { + + // The effect of the repaint request is identical to case where a + // child requests repaint + childRequestedRepaint(null); + } + + /* Documentation copied from interface */ + public void childRequestedRepaint(Collection alreadyNotified) { + + // Notify listeners only once + if (!repaintRequestListenersNotified) { + + // Notify the listeners + if (repaintRequestListeners != null + && !repaintRequestListeners.isEmpty()) { + Object[] listeners = repaintRequestListeners.toArray(); + RepaintRequestEvent event = new RepaintRequestEvent(this); + for (int i = 0; i < listeners.length; i++) { + if (alreadyNotified == null) { + alreadyNotified = new LinkedList(); + } + if (!alreadyNotified.contains(listeners[i])) { + ((RepaintRequestListener) listeners[i]) + .repaintRequested(event); + alreadyNotified.add(listeners[i]); + } + } + } + + repaintRequestListenersNotified = true; + + // Notify the parent + Component parent = getParent(); + if (parent != null) { + parent.childRequestedRepaint(alreadyNotified); + } + + } + } + + /* Documentation copied from interface */ + public void addListener(RepaintRequestListener listener) { + if (repaintRequestListeners == null) { + repaintRequestListeners = new LinkedList(); + } + if (!repaintRequestListeners.contains(listener)) { + repaintRequestListeners.add(listener); + } + } + + /* Documentation copied from interface */ + public void removeListener(RepaintRequestListener listener) { + if (repaintRequestListeners != null) { + repaintRequestListeners.remove(listener); + if (repaintRequestListeners.isEmpty()) { + repaintRequestListeners = null; + } + } + } + + /** + * The custom component is allways enabled by default. + */ + public void setEnabled(boolean enabled) { + } + + /** + * Sets the component's parent component. + * + * @see com.itmill.toolkit.ui.Component#setParent(com.itmill.toolkit.ui.Component) + */ + public void setParent(Component parent) { + + // If the parent is not changed, dont do nothing + if (parent == this.parent) { + return; + } + + // Sends the detach event if the component have been connected to a + // window + if (getApplication() != null) { + detach(); + this.parent = null; + } + + // Connects to new parent + this.parent = parent; + + // Sends the attach event if connected to a window + if (getApplication() != null) { + attach(); + } + } + + /** + * Sets the component's to read-only mode to the specified state. + * + * @see com.itmill.toolkit.ui.Component#setReadOnly(boolean) + */ + public void setReadOnly(boolean readOnly) { + } + + /** + * Custom component does not implement custom styles by default. + * + * @see com.itmill.toolkit.ui.Component#setStyle(java.lang.String) + */ + public void setStyleName(String style) { + } + + /** + * Sets the components visibility status. + * + * @see com.itmill.toolkit.ui.Component#setVisible(boolean) + */ + public void setVisible(boolean visible) { + this.visible = visible; + } + + /* Documented in super interface */ + public void requestRepaintRequests() { + repaintRequestListenersNotified = false; + } + + /* Documented in super interface */ + public void paint(PaintTarget target) throws PaintException { + if (root == null) { + throw new IllegalStateException("Composition root must be set to" + + " non-null value before the " + getClass().getName() + + " can be painted"); + } + + if (isVisible()) { + String type = getComponentType(); + if (type != null) { + if (!target.startTag(this, "component")) { + target.addAttribute("type", type); + root.paint(target); + } + target.endTag("component"); + } else { + root.paint(target); + } + } + repaintRequestListenersNotified = false; + } + + /** + * Called when one or more variables handled by the implementing class are + * changed. + * + * @see com.itmill.toolkit.terminal.VariableOwner#changeVariables(java.lang.Object, + * java.util.Map) + */ + public void changeVariables(Object source, Map variables) { + } + + /* Dependency -framework is deprecated */ + public void dependsOn(VariableOwner depended) { + } + + public void removeDirectDependency(VariableOwner depended) { + } + + public Set getDirectDependencies() { + return null; + } + + /* Event functions are not implemented by default -------------------- */ + + /** + * Custom component does not implement any component events by default. + * + * @param listener + * the listener to add. + */ + public void addListener(Component.Listener listener) { + } + + /** + * Custom component does not implement any component events by default. + * + * @param listener + * the listener to remove. + */ + public void removeListener(Component.Listener listener) { + } + + /** + * Gets the component type. + * + * The component type is textual type of the component. This is included in + * the UIDL as component tag attribute. If the component type is null + * (default), the component tag is not included in the UIDL at all. + * + * @return the component type. + */ + public String getComponentType() { + return componentType; + } + + /** + * Sets the component type. + * + * The component type is textual type of the component. This is included in + * the UIDL as component tag attribute. If the component type is null + * (default), the component tag is not included in the UIDL at all. + * + * @param componentType + * the componentType to set. + */ + public void setComponentType(String componentType) { + this.componentType = componentType; + } + + /** + * Custom component does not implement custom styles by default. + * + * @see com.itmill.toolkit.ui.Component#getStyle() + */ + public void addStyleName(String style) { + } + + /** + * Custom component does not implement custom styles by default. + * + * @see com.itmill.toolkit.ui.Component#getStyle() + */ + public void removeStyleName(String style) { + + } } diff --git a/src/com/itmill/toolkit/ui/CustomLayout.java b/src/com/itmill/toolkit/ui/CustomLayout.java index 6eb165cb4c..283c1edf19 100644 --- a/src/com/itmill/toolkit/ui/CustomLayout.java +++ b/src/com/itmill/toolkit/ui/CustomLayout.java @@ -63,214 +63,217 @@ import com.itmill.toolkit.terminal.PaintTarget; */ public class CustomLayout extends AbstractLayout { - /** - * Custom layout slots containing the components. - */ - private HashMap slots = new HashMap(); + /** + * Custom layout slots containing the components. + */ + private HashMap slots = new HashMap(); - private String templateName; + private String templateName; - /** - * Constructor for custom layout with given template name. - */ - public CustomLayout(String template) { - templateName = template; - } + /** + * Constructor for custom layout with given template name. + */ + public CustomLayout(String template) { + templateName = template; + } - /** - * Gets the component UIDL tag. - * - * @return the Component UIDL tag as string. - */ - public String getTag() { - return "customlayout"; - } + /** + * Gets the component UIDL tag. + * + * @return the Component UIDL tag as string. + */ + public String getTag() { + return "customlayout"; + } - /** - * Adds the component into this container to given location. - * - * @param c - * the component to be added. - * @param location - * the location of the component. - */ - public void addComponent(Component c, String location) { - Component old = (Component) slots.get(location); - if (old != null) { - removeComponent(old); - } - slots.put(location, c); - c.setParent(this); - fireComponentAttachEvent(c); - requestRepaint(); - } + /** + * Adds the component into this container to given location. + * + * @param c + * the component to be added. + * @param location + * the location of the component. + */ + public void addComponent(Component c, String location) { + Component old = (Component) slots.get(location); + if (old != null) { + removeComponent(old); + } + slots.put(location, c); + c.setParent(this); + fireComponentAttachEvent(c); + requestRepaint(); + } - /** - * Adds the component into this container. The component is added without - * specifying the location (empty string is then used as location). Only one - * component can be added to the default "" location and adding more - * components into that location overwrites the old components. - * - * @param c - * the component to be added. - */ - public void addComponent(Component c) { - this.addComponent(c, ""); - } + /** + * Adds the component into this container. The component is added without + * specifying the location (empty string is then used as location). Only one + * component can be added to the default "" location and adding more + * components into that location overwrites the old components. + * + * @param c + * the component to be added. + */ + public void addComponent(Component c) { + this.addComponent(c, ""); + } - /** - * Removes the component from this container. - * - * @param c - * the component to be removed. - */ - public void removeComponent(Component c) { - if (c == null) - return; - slots.values().remove(c); - c.setParent(null); - fireComponentDetachEvent(c); - requestRepaint(); - } + /** + * Removes the component from this container. + * + * @param c + * the component to be removed. + */ + public void removeComponent(Component c) { + if (c == null) { + return; + } + slots.values().remove(c); + c.setParent(null); + fireComponentDetachEvent(c); + requestRepaint(); + } - /** - * Removes the component from this container from given location. - * - * @param location - * the Location identifier of the component. - */ - public void removeComponent(String location) { - this.removeComponent((Component) slots.get(location)); - } + /** + * Removes the component from this container from given location. + * + * @param location + * the Location identifier of the component. + */ + public void removeComponent(String location) { + this.removeComponent((Component) slots.get(location)); + } - /** - * Gets the component container iterator for going trough all the components - * in the container. - * - * @return the Iterator of the components inside the container. - */ - public Iterator getComponentIterator() { - return slots.values().iterator(); - } + /** + * Gets the component container iterator for going trough all the components + * in the container. + * + * @return the Iterator of the components inside the container. + */ + public Iterator getComponentIterator() { + return slots.values().iterator(); + } - /** - * Gets the child-component by its location. - * - * @param location - * the name of the location where the requested component - * resides. - * @return the Component in the given location or null if not found. - */ - public Component getComponent(String location) { - return (Component) slots.get(location); - } + /** + * Gets the child-component by its location. + * + * @param location + * the name of the location where the requested component + * resides. + * @return the Component in the given location or null if not found. + */ + public Component getComponent(String location) { + return (Component) slots.get(location); + } - /** - * Paints the content of this component. - * - * @param target - * @throws PaintException - * if the paint operation failed. - */ - public void paintContent(PaintTarget target) throws PaintException { - super.paintContent(target); + /** + * Paints the content of this component. + * + * @param target + * @throws PaintException + * if the paint operation failed. + */ + public void paintContent(PaintTarget target) throws PaintException { + super.paintContent(target); - target.addAttribute("template", templateName); - // Adds all items in all the locations - for (Iterator i = slots.keySet().iterator(); i.hasNext();) { - // Gets the (location,component) - String location = (String) i.next(); - Component c = (Component) slots.get(location); - if (c != null) { - // Writes the item - target.startTag("location"); - target.addAttribute("name", location); - c.paint(target); - target.endTag("location"); - } - } - } + target.addAttribute("template", templateName); + // Adds all items in all the locations + for (Iterator i = slots.keySet().iterator(); i.hasNext();) { + // Gets the (location,component) + String location = (String) i.next(); + Component c = (Component) slots.get(location); + if (c != null) { + // Writes the item + target.startTag("location"); + target.addAttribute("name", location); + c.paint(target); + target.endTag("location"); + } + } + } - /* Documented in superclass */ - public void replaceComponent(Component oldComponent, Component newComponent) { + /* Documented in superclass */ + public void replaceComponent(Component oldComponent, Component newComponent) { - // Gets the locations - String oldLocation = null; - String newLocation = null; - for (Iterator i = slots.keySet().iterator(); i.hasNext();) { - String location = (String) i.next(); - Component component = (Component) slots.get(location); - if (component == oldComponent) - oldLocation = location; - if (component == newComponent) - newLocation = location; - } + // Gets the locations + String oldLocation = null; + String newLocation = null; + for (Iterator i = slots.keySet().iterator(); i.hasNext();) { + String location = (String) i.next(); + Component component = (Component) slots.get(location); + if (component == oldComponent) { + oldLocation = location; + } + if (component == newComponent) { + newLocation = location; + } + } - if (oldLocation == null) - addComponent(newComponent); - else if (newLocation == null) { - removeComponent(oldLocation); - addComponent(newComponent, oldLocation); - } else { - slots.put(newLocation, oldComponent); - slots.put(oldLocation, newComponent); - requestRepaint(); - } - } + if (oldLocation == null) { + addComponent(newComponent); + } else if (newLocation == null) { + removeComponent(oldLocation); + addComponent(newComponent, oldLocation); + } else { + slots.put(newLocation, oldComponent); + slots.put(oldLocation, newComponent); + requestRepaint(); + } + } - /** - * CustomLayout's template selecting was previously implemented with - * setStyle. Overriding to improve backwards compatibility. - * - * @param name - * template name - */ - public void setStyle(String name) { - setTemplateName(name); - } + /** + * CustomLayout's template selecting was previously implemented with + * setStyle. Overriding to improve backwards compatibility. + * + * @param name + * template name + */ + public void setStyle(String name) { + setTemplateName(name); + } - /** Get the name of the template */ - public String getTemplateName() { - return templateName; - } + /** Get the name of the template */ + public String getTemplateName() { + return templateName; + } - /** - * Set the name of the template used to draw custom layout. - * - * With GWT-adapter, the template with name 'templatename' is loaded from - * ITMILL/themes/themename/layouts/templatename.html. If the theme has not - * been set (with Application.setTheme()), themename is 'default'. - * - * @param templateName - */ - public void setTemplateName(String templateName) { - this.templateName = templateName; - requestRepaint(); - } + /** + * Set the name of the template used to draw custom layout. + * + * With GWT-adapter, the template with name 'templatename' is loaded from + * ITMILL/themes/themename/layouts/templatename.html. If the theme has not + * been set (with Application.setTheme()), themename is 'default'. + * + * @param templateName + */ + public void setTemplateName(String templateName) { + this.templateName = templateName; + requestRepaint(); + } - /** - * Although most layouts support margins, CustomLayout does not. The - * behaviour of this layout is determined almost completely by the actual - * template. - * - * @throws UnsupportedOperationException - */ - public void setMargin(boolean enabled) { - throw new UnsupportedOperationException( - "CustomLayout does not support margins."); - } + /** + * Although most layouts support margins, CustomLayout does not. The + * behaviour of this layout is determined almost completely by the actual + * template. + * + * @throws UnsupportedOperationException + */ + public void setMargin(boolean enabled) { + throw new UnsupportedOperationException( + "CustomLayout does not support margins."); + } - /** - * Although most layouts support margins, CustomLayout does not. The - * behaviour of this layout is determined almost completely by the actual - * template. - * - * @throws UnsupportedOperationException - */ - public void setMargin(boolean topEnabled, boolean rightEnabled, - boolean bottomEnabled, boolean leftEnabled) { - throw new UnsupportedOperationException( - "CustomLayout does not support margins."); - } + /** + * Although most layouts support margins, CustomLayout does not. The + * behaviour of this layout is determined almost completely by the actual + * template. + * + * @throws UnsupportedOperationException + */ + public void setMargin(boolean topEnabled, boolean rightEnabled, + boolean bottomEnabled, boolean leftEnabled) { + throw new UnsupportedOperationException( + "CustomLayout does not support margins."); + } } diff --git a/src/com/itmill/toolkit/ui/Embedded.java b/src/com/itmill/toolkit/ui/Embedded.java index 6a2a93cd26..6f00c7855e 100644 --- a/src/com/itmill/toolkit/ui/Embedded.java +++ b/src/com/itmill/toolkit/ui/Embedded.java @@ -46,532 +46,532 @@ import com.itmill.toolkit.terminal.Sizeable; */ public class Embedded extends AbstractComponent implements Sizeable { - /** - * General object type. - */ - public static final int TYPE_OBJECT = 0; - - /** - * Image types. - */ - public static final int TYPE_IMAGE = 1; - - /** - * Browser ("iframe") type. - */ - public static final int TYPE_BROWSER = 2; - - /** - * Type of the object. - */ - private int type = TYPE_OBJECT; - - /** - * Source of the embedded object. - */ - private Resource source = null; - - /** - * Dimensions of the object. - */ - private int width = -1; - - private int height = -1; - - private int widthUnits = Sizeable.UNITS_PIXELS; - - private int heightUnits = Sizeable.UNITS_PIXELS; - - /** - * Generic object attributes. - */ - private String mimeType = null; - - private String standby = null; - - /** - * Hash of object parameteres. - */ - private final Hashtable parameters = new Hashtable(); - - /** - * Applet or other client side runnable properties. - */ - private String codebase = null; - - private String codetype = null; - - private String classId = null; - - private String archive = null; - - /** - * Creates a new empty Embedded object. - */ - public Embedded() { - } - - /** - * Creates a new empty Embedded object with caption. - * - * @param caption - */ - public Embedded(String caption) { - setCaption(caption); - } - - /** - * Creates a new Embedded object whose contents is loaded from given - * resource. The dimensions are assumed if possible. The type is guessed - * from resource. - * - * @param caption - * @param source - * the Source of the embedded object. - */ - public Embedded(String caption, Resource source) { - setCaption(caption); - setSource(source); - } - - /** - * Gets the component UIDL tag. - * - * @return the Component UIDL tag as string. - */ - public String getTag() { - return "embedded"; - } - - /** - * Invoked when the component state should be painted. - */ - public void paintContent(PaintTarget target) throws PaintException { - - switch (type) { - case TYPE_IMAGE: - target.addAttribute("type", "image"); - break; - case TYPE_BROWSER: - target.addAttribute("type", "browser"); - break; - default: - break; - } - - if (source != null) { - target.addAttribute("src", source); - } - - // Dimensions - if (width > 0) { - target.addAttribute("width", "" + width - + Sizeable.UNIT_SYMBOLS[this.widthUnits]); - } - if (height > 0) { - target.addAttribute("height", "" + height - + Sizeable.UNIT_SYMBOLS[this.heightUnits]); - } - if (mimeType != null && !"".equals(mimeType)) { - target.addAttribute("mimetype", mimeType); - } - if (classId != null && !"".equals(classId)) { - target.addAttribute("classid", classId); - } - if (codebase != null && !"".equals(codebase)) { - target.addAttribute("codebase", codebase); - } - if (codetype != null && !"".equals(codetype)) { - target.addAttribute("codetype", codetype); - } - if (standby != null && !"".equals(standby)) { - target.addAttribute("standby", standby); - } - if (archive != null && !"".equals(archive)) { - target.addAttribute("archive", archive); - } - - // Params - for (Iterator i = this.getParameterNames(); i.hasNext();) { - target.startTag("embeddedparam"); - String key = (String) i.next(); - target.addAttribute("name", key); - target.addAttribute("value", getParameter(key)); - target.endTag("embeddedparam"); - } - } - - /** - * Sets an object parameter. Parameters are optional information, and they - * are passed to the instantiated object. Parameters are are stored as name - * value pairs. This overrides the previous value assigned to this - * parameter. - * - * @param name - * the name of the parameter. - * @param value - * the value of the parameter. - */ - public void setParameter(String name, String value) { - parameters.put(name, value); - requestRepaint(); - } - - /** - * Gets the value of an object parameter. Parameters are optional - * information, and they are passed to the instantiated object. Parameters - * are are stored as name value pairs. - * - * @return the Value of parameter or null if not found. - */ - public String getParameter(String name) { - return (String) parameters.get(name); - } - - /** - * Removes an object parameter from the list. - * - * @param name - * the name of the parameter to remove. - */ - public void removeParameter(String name) { - parameters.remove(name); - requestRepaint(); - } - - /** - * Gets the embedded object parameter names. - * - * @return the Iterator of parameters names. - */ - public Iterator getParameterNames() { - return parameters.keySet().iterator(); - } - - /** - * Gets the codebase, the root-path used to access resources with relative - * paths. - * - * @return the code base. - */ - public String getCodebase() { - return codebase; - } - - /** - * Gets the MIME-Type of the code. - * - * @return the MIME-Type of the code. - */ - public String getCodetype() { - return codetype; - } - - /** - * Gets the MIME-Type of the object. - * - * @return the MIME-Type of the object. - */ - public String getMimeType() { - return mimeType; - } - - /** - * Gets the standby text displayed when the object is loading. - * - * @return the standby text. - */ - public String getStandby() { - return standby; - } - - /** - * Sets the codebase, the root-path used to access resources with relative - * paths. - * - * @param codebase - * the codebase to set. - */ - public void setCodebase(String codebase) { - if (codebase != this.codebase - || (codebase != null && !codebase.equals(this.codebase))) { - this.codebase = codebase; - requestRepaint(); - } - } - - /** - * Sets the codetype, the MIME-Type of the code. - * - * @param codetype - * the codetype to set. - */ - public void setCodetype(String codetype) { - if (codetype != this.codetype - || (codetype != null && !codetype.equals(this.codetype))) { - this.codetype = codetype; - requestRepaint(); - } - } - - /** - * Sets the mimeType, the MIME-Type of the object. - * - * @param mimeType - * the mimeType to set. - */ - public void setMimeType(String mimeType) { - if (mimeType != this.mimeType - || (mimeType != null && !mimeType.equals(this.mimeType))) { - this.mimeType = mimeType; - requestRepaint(); - } - } - - /** - * Sets the standby, the text to display while loading the object. - * - * @param standby - * the standby to set. - */ - public void setStandby(String standby) { - if (standby != this.standby - || (standby != null && !standby.equals(this.standby))) { - this.standby = standby; - requestRepaint(); - } - } - - /** - * Returns the visual height of the object. Default height is -1, which is - * interpreted as "unspecified". - * - * @return the height in units specified by heightUnits property. - */ - public int getHeight() { - return height; - } - - /** - * Returns the visual width of the object. Default width is -1, which is - * interpreted as "unspecified". - * - * @return the width in units specified by widthUnits property. - */ - public int getWidth() { - return width; - } - - /** - * Sets the visual height of the object. Default height is -1, which is - * interpreted as "unspecified". - * - * @param height - * the height in units specified by heightUnits property. - */ - public void setHeight(int height) { - if (this.height != height) { - this.height = height; - requestRepaint(); - } - } - - /** - * Sets the visual width of the object. Default width is -1, which is - * interpreted as "unspecified". - * - * @param width - * the width in units specified by widthUnits property. - */ - public void setWidth(int width) { - if (this.width != width) { - this.width = width; - requestRepaint(); - } - } - - /** - * Gets the classId attribute. - * - * @return the class id. - */ - public String getClassId() { - return classId; - } - - /** - * Sets the classId attribute. - * - * @param classId - * the classId to set. - */ - public void setClassId(String classId) { - if (classId != this.classId - || (classId != null && !classId.equals(classId))) { - this.classId = classId; - requestRepaint(); - } - } - - /** - * Gets the resource contained in the embedded object. - * - * @return the Resource - */ - public Resource getSource() { - return source; - } - - /** - * Gets the type of the embedded object. - *

- * This can be one of the following: - *

    - *
  • TYPE_OBJECT (This is the default) - *
  • TYPE_IMAGE - *
- *

- * - * @return the type. - */ - public int getType() { - return type; - } - - /** - * Sets the object source resource. The dimensions are assumed if possible. - * The type is guessed from resource. - * - * @param source - * the source to set. - */ - public void setSource(Resource source) { - if (source != null && !source.equals(this.source)) { - this.source = source; - String mt = source.getMIMEType(); - if ((mt.substring(0, mt.indexOf("/")).equalsIgnoreCase("image"))) { - type = TYPE_IMAGE; - } else { - // Keep previous type - } - requestRepaint(); - } - } - - /** - * Sets the object type. - *

- * This can be one of the following: - *

    - *
  • TYPE_OBJECT (This is the default) - *
  • TYPE_IMAGE - *
- *

- * - * @param type - * the type to set. - */ - public void setType(int type) { - if (type != TYPE_OBJECT && type != TYPE_IMAGE && type != TYPE_BROWSER) { - throw new IllegalArgumentException("Unsupported type"); - } - if (type != this.type) { - this.type = type; - requestRepaint(); - } - } - - /** - * Gets the archive attribute. - * - * @return the archive attribute. - */ - public String getArchive() { - return archive; - } - - /** - * Sets the archive attribute. - * - * @param archive - * the archive string to set. - */ - public void setArchive(String archive) { - if (archive != this.archive - || (archive != null && !archive.equals(this.archive))) { - this.archive = archive; - requestRepaint(); - } - } - - /** - * Gets the height property units. Default units are - * Sizeable.UNITS_PIXELS. - * - * @see com.itmill.toolkit.terminal.Sizeable#getHeightUnits() - */ - public int getHeightUnits() { - return this.heightUnits; - } - - /** - * Gets the width property units. Default units are - * Sizeable.UNITS_PIXELS. - * - * @see com.itmill.toolkit.terminal.Sizeable#getWidthUnits() - */ - public int getWidthUnits() { - return this.widthUnits; - } - - /** - * Sets the height property units. - * - * @see com.itmill.toolkit.terminal.Sizeable#setHeightUnits(int) - */ - public void setHeightUnits(int units) { - if (units >= 0 && units <= Sizeable.UNITS_PERCENTAGE - && this.heightUnits != units) { - this.heightUnits = units; - requestRepaint(); - } - } - - /** - * Sets the width property units. - * - * @see com.itmill.toolkit.terminal.Sizeable#setWidthUnits(int) - */ - public void setWidthUnits(int units) { - if (units >= 0 && units <= Sizeable.UNITS_PERCENTAGE - && this.widthUnits != units) { - this.widthUnits = units; - requestRepaint(); - } - } - - /* - * (non-Javadoc) - * - * @see com.itmill.toolkit.terminal.Sizeable#setSizeFull() - */ - public void setSizeFull() { - setWidth(100); - setHeight(100); - setWidthUnits(UNITS_PERCENTAGE); - setHeightUnits(UNITS_PERCENTAGE); - } - - /* - * (non-Javadoc) - * - * @see com.itmill.toolkit.terminal.Sizeable#setSizeUndefined() - */ - public void setSizeUndefined() { - setWidth(-1); - setHeight(-1); - setWidthUnits(UNITS_PIXELS); - setHeightUnits(UNITS_PIXELS); - } + /** + * General object type. + */ + public static final int TYPE_OBJECT = 0; + + /** + * Image types. + */ + public static final int TYPE_IMAGE = 1; + + /** + * Browser ("iframe") type. + */ + public static final int TYPE_BROWSER = 2; + + /** + * Type of the object. + */ + private int type = TYPE_OBJECT; + + /** + * Source of the embedded object. + */ + private Resource source = null; + + /** + * Dimensions of the object. + */ + private int width = -1; + + private int height = -1; + + private int widthUnits = Sizeable.UNITS_PIXELS; + + private int heightUnits = Sizeable.UNITS_PIXELS; + + /** + * Generic object attributes. + */ + private String mimeType = null; + + private String standby = null; + + /** + * Hash of object parameteres. + */ + private final Hashtable parameters = new Hashtable(); + + /** + * Applet or other client side runnable properties. + */ + private String codebase = null; + + private String codetype = null; + + private String classId = null; + + private String archive = null; + + /** + * Creates a new empty Embedded object. + */ + public Embedded() { + } + + /** + * Creates a new empty Embedded object with caption. + * + * @param caption + */ + public Embedded(String caption) { + setCaption(caption); + } + + /** + * Creates a new Embedded object whose contents is loaded from given + * resource. The dimensions are assumed if possible. The type is guessed + * from resource. + * + * @param caption + * @param source + * the Source of the embedded object. + */ + public Embedded(String caption, Resource source) { + setCaption(caption); + setSource(source); + } + + /** + * Gets the component UIDL tag. + * + * @return the Component UIDL tag as string. + */ + public String getTag() { + return "embedded"; + } + + /** + * Invoked when the component state should be painted. + */ + public void paintContent(PaintTarget target) throws PaintException { + + switch (type) { + case TYPE_IMAGE: + target.addAttribute("type", "image"); + break; + case TYPE_BROWSER: + target.addAttribute("type", "browser"); + break; + default: + break; + } + + if (source != null) { + target.addAttribute("src", source); + } + + // Dimensions + if (width > 0) { + target.addAttribute("width", "" + width + + Sizeable.UNIT_SYMBOLS[widthUnits]); + } + if (height > 0) { + target.addAttribute("height", "" + height + + Sizeable.UNIT_SYMBOLS[heightUnits]); + } + if (mimeType != null && !"".equals(mimeType)) { + target.addAttribute("mimetype", mimeType); + } + if (classId != null && !"".equals(classId)) { + target.addAttribute("classid", classId); + } + if (codebase != null && !"".equals(codebase)) { + target.addAttribute("codebase", codebase); + } + if (codetype != null && !"".equals(codetype)) { + target.addAttribute("codetype", codetype); + } + if (standby != null && !"".equals(standby)) { + target.addAttribute("standby", standby); + } + if (archive != null && !"".equals(archive)) { + target.addAttribute("archive", archive); + } + + // Params + for (Iterator i = getParameterNames(); i.hasNext();) { + target.startTag("embeddedparam"); + String key = (String) i.next(); + target.addAttribute("name", key); + target.addAttribute("value", getParameter(key)); + target.endTag("embeddedparam"); + } + } + + /** + * Sets an object parameter. Parameters are optional information, and they + * are passed to the instantiated object. Parameters are are stored as name + * value pairs. This overrides the previous value assigned to this + * parameter. + * + * @param name + * the name of the parameter. + * @param value + * the value of the parameter. + */ + public void setParameter(String name, String value) { + parameters.put(name, value); + requestRepaint(); + } + + /** + * Gets the value of an object parameter. Parameters are optional + * information, and they are passed to the instantiated object. Parameters + * are are stored as name value pairs. + * + * @return the Value of parameter or null if not found. + */ + public String getParameter(String name) { + return (String) parameters.get(name); + } + + /** + * Removes an object parameter from the list. + * + * @param name + * the name of the parameter to remove. + */ + public void removeParameter(String name) { + parameters.remove(name); + requestRepaint(); + } + + /** + * Gets the embedded object parameter names. + * + * @return the Iterator of parameters names. + */ + public Iterator getParameterNames() { + return parameters.keySet().iterator(); + } + + /** + * Gets the codebase, the root-path used to access resources with relative + * paths. + * + * @return the code base. + */ + public String getCodebase() { + return codebase; + } + + /** + * Gets the MIME-Type of the code. + * + * @return the MIME-Type of the code. + */ + public String getCodetype() { + return codetype; + } + + /** + * Gets the MIME-Type of the object. + * + * @return the MIME-Type of the object. + */ + public String getMimeType() { + return mimeType; + } + + /** + * Gets the standby text displayed when the object is loading. + * + * @return the standby text. + */ + public String getStandby() { + return standby; + } + + /** + * Sets the codebase, the root-path used to access resources with relative + * paths. + * + * @param codebase + * the codebase to set. + */ + public void setCodebase(String codebase) { + if (codebase != this.codebase + || (codebase != null && !codebase.equals(this.codebase))) { + this.codebase = codebase; + requestRepaint(); + } + } + + /** + * Sets the codetype, the MIME-Type of the code. + * + * @param codetype + * the codetype to set. + */ + public void setCodetype(String codetype) { + if (codetype != this.codetype + || (codetype != null && !codetype.equals(this.codetype))) { + this.codetype = codetype; + requestRepaint(); + } + } + + /** + * Sets the mimeType, the MIME-Type of the object. + * + * @param mimeType + * the mimeType to set. + */ + public void setMimeType(String mimeType) { + if (mimeType != this.mimeType + || (mimeType != null && !mimeType.equals(this.mimeType))) { + this.mimeType = mimeType; + requestRepaint(); + } + } + + /** + * Sets the standby, the text to display while loading the object. + * + * @param standby + * the standby to set. + */ + public void setStandby(String standby) { + if (standby != this.standby + || (standby != null && !standby.equals(this.standby))) { + this.standby = standby; + requestRepaint(); + } + } + + /** + * Returns the visual height of the object. Default height is -1, which is + * interpreted as "unspecified". + * + * @return the height in units specified by heightUnits property. + */ + public int getHeight() { + return height; + } + + /** + * Returns the visual width of the object. Default width is -1, which is + * interpreted as "unspecified". + * + * @return the width in units specified by widthUnits property. + */ + public int getWidth() { + return width; + } + + /** + * Sets the visual height of the object. Default height is -1, which is + * interpreted as "unspecified". + * + * @param height + * the height in units specified by heightUnits property. + */ + public void setHeight(int height) { + if (this.height != height) { + this.height = height; + requestRepaint(); + } + } + + /** + * Sets the visual width of the object. Default width is -1, which is + * interpreted as "unspecified". + * + * @param width + * the width in units specified by widthUnits property. + */ + public void setWidth(int width) { + if (this.width != width) { + this.width = width; + requestRepaint(); + } + } + + /** + * Gets the classId attribute. + * + * @return the class id. + */ + public String getClassId() { + return classId; + } + + /** + * Sets the classId attribute. + * + * @param classId + * the classId to set. + */ + public void setClassId(String classId) { + if (classId != this.classId + || (classId != null && !classId.equals(classId))) { + this.classId = classId; + requestRepaint(); + } + } + + /** + * Gets the resource contained in the embedded object. + * + * @return the Resource + */ + public Resource getSource() { + return source; + } + + /** + * Gets the type of the embedded object. + *

+ * This can be one of the following: + *

    + *
  • TYPE_OBJECT (This is the default) + *
  • TYPE_IMAGE + *
+ *

+ * + * @return the type. + */ + public int getType() { + return type; + } + + /** + * Sets the object source resource. The dimensions are assumed if possible. + * The type is guessed from resource. + * + * @param source + * the source to set. + */ + public void setSource(Resource source) { + if (source != null && !source.equals(this.source)) { + this.source = source; + String mt = source.getMIMEType(); + if ((mt.substring(0, mt.indexOf("/")).equalsIgnoreCase("image"))) { + type = TYPE_IMAGE; + } else { + // Keep previous type + } + requestRepaint(); + } + } + + /** + * Sets the object type. + *

+ * This can be one of the following: + *

    + *
  • TYPE_OBJECT (This is the default) + *
  • TYPE_IMAGE + *
+ *

+ * + * @param type + * the type to set. + */ + public void setType(int type) { + if (type != TYPE_OBJECT && type != TYPE_IMAGE && type != TYPE_BROWSER) { + throw new IllegalArgumentException("Unsupported type"); + } + if (type != this.type) { + this.type = type; + requestRepaint(); + } + } + + /** + * Gets the archive attribute. + * + * @return the archive attribute. + */ + public String getArchive() { + return archive; + } + + /** + * Sets the archive attribute. + * + * @param archive + * the archive string to set. + */ + public void setArchive(String archive) { + if (archive != this.archive + || (archive != null && !archive.equals(this.archive))) { + this.archive = archive; + requestRepaint(); + } + } + + /** + * Gets the height property units. Default units are + * Sizeable.UNITS_PIXELS. + * + * @see com.itmill.toolkit.terminal.Sizeable#getHeightUnits() + */ + public int getHeightUnits() { + return heightUnits; + } + + /** + * Gets the width property units. Default units are + * Sizeable.UNITS_PIXELS. + * + * @see com.itmill.toolkit.terminal.Sizeable#getWidthUnits() + */ + public int getWidthUnits() { + return widthUnits; + } + + /** + * Sets the height property units. + * + * @see com.itmill.toolkit.terminal.Sizeable#setHeightUnits(int) + */ + public void setHeightUnits(int units) { + if (units >= 0 && units <= Sizeable.UNITS_PERCENTAGE + && heightUnits != units) { + heightUnits = units; + requestRepaint(); + } + } + + /** + * Sets the width property units. + * + * @see com.itmill.toolkit.terminal.Sizeable#setWidthUnits(int) + */ + public void setWidthUnits(int units) { + if (units >= 0 && units <= Sizeable.UNITS_PERCENTAGE + && widthUnits != units) { + widthUnits = units; + requestRepaint(); + } + } + + /* + * (non-Javadoc) + * + * @see com.itmill.toolkit.terminal.Sizeable#setSizeFull() + */ + public void setSizeFull() { + setWidth(100); + setHeight(100); + setWidthUnits(UNITS_PERCENTAGE); + setHeightUnits(UNITS_PERCENTAGE); + } + + /* + * (non-Javadoc) + * + * @see com.itmill.toolkit.terminal.Sizeable#setSizeUndefined() + */ + public void setSizeUndefined() { + setWidth(-1); + setHeight(-1); + setWidthUnits(UNITS_PIXELS); + setHeightUnits(UNITS_PIXELS); + } } diff --git a/src/com/itmill/toolkit/ui/ExpandLayout.java b/src/com/itmill/toolkit/ui/ExpandLayout.java index 47b75e5b74..54fc05be19 100644 --- a/src/com/itmill/toolkit/ui/ExpandLayout.java +++ b/src/com/itmill/toolkit/ui/ExpandLayout.java @@ -23,103 +23,109 @@ import com.itmill.toolkit.terminal.Sizeable; */ public class ExpandLayout extends OrderedLayout { - private Component expanded; - - public ExpandLayout() { - setSizeFull(); - } - - public ExpandLayout(int orientation) { - this(); - setOrientation(orientation); - } - - /** - * @param c - * Component which container will be maximized - */ - public void expand(Component c) { - this.expanded = c; - requestRepaint(); - } - - public String getTag() { - return "expandlayout"; - } - - public void paintContent(PaintTarget target) throws PaintException { - - // Add margin info. Defaults to false. - target.addAttribute("margins", margins.getBitMask()); - - // Size - if (getHeight() >= 0) - target.addAttribute("height", "" + getHeight() - + Sizeable.UNIT_SYMBOLS[getHeightUnits()]); - if (getWidth() >= 0) - target.addAttribute("width", "" + getWidth() - + Sizeable.UNIT_SYMBOLS[getWidthUnits()]); - - // Adds the attributes: orientation - // note that the default values (b/vertival) are omitted - if (getOrientation() == ORIENTATION_HORIZONTAL) - target.addAttribute("orientation", "horizontal"); - - String[] alignmentsArray = new String[components.size()]; - - // Adds all items in all the locations - int index = 0; - for (Iterator i = getComponentIterator(); i.hasNext();) { - Component c = (Component) i.next(); - if (c != null) { - target.startTag("cc"); - if (c == expanded) - target.addAttribute("expanded", true); - c.paint(target); - target.endTag("cc"); - } - alignmentsArray[index++] = String.valueOf(getComponentAlignment(c)); - - } - - // Add child component alignment info to layout tag - target.addAttribute("alignments", alignmentsArray); - - } - - public void addComponent(Component c, int index) { - if (expanded == null) { - expanded = c; - } - super.addComponent(c, index); - } - - public void addComponent(Component c) { - if (expanded == null) { - expanded = c; - } - super.addComponent(c); - } - - public void addComponentAsFirst(Component c) { - if (expanded == null) { - expanded = c; - } - super.addComponentAsFirst(c); - } - - public void removeComponent(Component c) { - super.removeComponent(c); - if (c == expanded && this.getComponentIterator().hasNext()) - expanded = (Component) this.getComponentIterator().next(); - else - expanded = null; - } - - public void replaceComponent(Component oldComponent, Component newComponent) { - super.replaceComponent(oldComponent, newComponent); - if (oldComponent == expanded) - expanded = newComponent; - } + private Component expanded; + + public ExpandLayout() { + setSizeFull(); + } + + public ExpandLayout(int orientation) { + this(); + setOrientation(orientation); + } + + /** + * @param c + * Component which container will be maximized + */ + public void expand(Component c) { + expanded = c; + requestRepaint(); + } + + public String getTag() { + return "expandlayout"; + } + + public void paintContent(PaintTarget target) throws PaintException { + + // Add margin info. Defaults to false. + target.addAttribute("margins", margins.getBitMask()); + + // Size + if (getHeight() >= 0) { + target.addAttribute("height", "" + getHeight() + + Sizeable.UNIT_SYMBOLS[getHeightUnits()]); + } + if (getWidth() >= 0) { + target.addAttribute("width", "" + getWidth() + + Sizeable.UNIT_SYMBOLS[getWidthUnits()]); + } + + // Adds the attributes: orientation + // note that the default values (b/vertival) are omitted + if (getOrientation() == ORIENTATION_HORIZONTAL) { + target.addAttribute("orientation", "horizontal"); + } + + String[] alignmentsArray = new String[components.size()]; + + // Adds all items in all the locations + int index = 0; + for (Iterator i = getComponentIterator(); i.hasNext();) { + Component c = (Component) i.next(); + if (c != null) { + target.startTag("cc"); + if (c == expanded) { + target.addAttribute("expanded", true); + } + c.paint(target); + target.endTag("cc"); + } + alignmentsArray[index++] = String.valueOf(getComponentAlignment(c)); + + } + + // Add child component alignment info to layout tag + target.addAttribute("alignments", alignmentsArray); + + } + + public void addComponent(Component c, int index) { + if (expanded == null) { + expanded = c; + } + super.addComponent(c, index); + } + + public void addComponent(Component c) { + if (expanded == null) { + expanded = c; + } + super.addComponent(c); + } + + public void addComponentAsFirst(Component c) { + if (expanded == null) { + expanded = c; + } + super.addComponentAsFirst(c); + } + + public void removeComponent(Component c) { + super.removeComponent(c); + if (c == expanded && getComponentIterator().hasNext()) { + expanded = (Component) getComponentIterator().next(); + } else { + expanded = null; + } + } + + public void replaceComponent(Component oldComponent, Component newComponent) { + super.replaceComponent(oldComponent, newComponent); + if (oldComponent == expanded) { + expanded = newComponent; + } + } } diff --git a/src/com/itmill/toolkit/ui/Field.java b/src/com/itmill/toolkit/ui/Field.java index 8b11f93b26..e4248f8e9b 100644 --- a/src/com/itmill/toolkit/ui/Field.java +++ b/src/com/itmill/toolkit/ui/Field.java @@ -37,79 +37,79 @@ import com.itmill.toolkit.ui.Component.Focusable; * */ public interface Field extends Component, BufferedValidatable, Property, - Property.ValueChangeNotifier, Property.ValueChangeListener, - Property.Editor, Focusable { - - /** - * Sets the Caption. - * - * @param caption - */ - void setCaption(String caption); - - String getDescription(); - - /** - * Sets the Description. - * - * @param caption - */ - void setDescription(String caption); - - /** - * Is this field required. - * - * Required fields must filled by the user. - * - * @return true if the field is required,otherwise - * false. - * @since 3.1 - */ - public boolean isRequired(); - - /** - * Sets the field required. Required fields must filled by the user. - * - * @param required - * Is the field required. - * @since 3.1 - */ - public void setRequired(boolean required); - - /** - * An Event object specifying the Field whose value has been - * changed. - * - * @author IT Mill Ltd. - * @version - * @VERSION@ - * @since 3.0 - */ - public class ValueChangeEvent extends Component.Event implements - Property.ValueChangeEvent { - - /** - * Serial generated by eclipse. - */ - private static final long serialVersionUID = 3545803169444672816L; - - /** - * Constructs a new event object with the specified source field object. - * - * @param source - * the field that caused the event. - */ - public ValueChangeEvent(Field source) { - super(source); - } - - /** - * Gets the Property which triggered the event. - * - * @return the Source Property of the event. - */ - public Property getProperty() { - return (Property) getSource(); - } - } + Property.ValueChangeNotifier, Property.ValueChangeListener, + Property.Editor, Focusable { + + /** + * Sets the Caption. + * + * @param caption + */ + void setCaption(String caption); + + String getDescription(); + + /** + * Sets the Description. + * + * @param caption + */ + void setDescription(String caption); + + /** + * Is this field required. + * + * Required fields must filled by the user. + * + * @return true if the field is required,otherwise + * false. + * @since 3.1 + */ + public boolean isRequired(); + + /** + * Sets the field required. Required fields must filled by the user. + * + * @param required + * Is the field required. + * @since 3.1 + */ + public void setRequired(boolean required); + + /** + * An Event object specifying the Field whose value has been + * changed. + * + * @author IT Mill Ltd. + * @version + * @VERSION@ + * @since 3.0 + */ + public class ValueChangeEvent extends Component.Event implements + Property.ValueChangeEvent { + + /** + * Serial generated by eclipse. + */ + private static final long serialVersionUID = 3545803169444672816L; + + /** + * Constructs a new event object with the specified source field object. + * + * @param source + * the field that caused the event. + */ + public ValueChangeEvent(Field source) { + super(source); + } + + /** + * Gets the Property which triggered the event. + * + * @return the Source Property of the event. + */ + public Property getProperty() { + return (Property) getSource(); + } + } } diff --git a/src/com/itmill/toolkit/ui/FieldFactory.java b/src/com/itmill/toolkit/ui/FieldFactory.java index fb71c4c38e..7abbe29909 100644 --- a/src/com/itmill/toolkit/ui/FieldFactory.java +++ b/src/com/itmill/toolkit/ui/FieldFactory.java @@ -43,56 +43,56 @@ import com.itmill.toolkit.data.Property; */ public interface FieldFactory { - /** - * Creates a field based on type of data. - * - * @param type - * the type of data presented in field. - * @param uiContext - * the component where the field is presented. - * @return Field the field suitable for editing the specified data. - * - */ - Field createField(Class type, Component uiContext); + /** + * Creates a field based on type of data. + * + * @param type + * the type of data presented in field. + * @param uiContext + * the component where the field is presented. + * @return Field the field suitable for editing the specified data. + * + */ + Field createField(Class type, Component uiContext); - /** - * Creates a field based on the property datasource. - * - * @param property - * the property datasource. - * @param uiContext - * the component where the field is presented. - * @return Field the field suitable for editing the specified data. - */ - Field createField(Property property, Component uiContext); + /** + * Creates a field based on the property datasource. + * + * @param property + * the property datasource. + * @param uiContext + * the component where the field is presented. + * @return Field the field suitable for editing the specified data. + */ + Field createField(Property property, Component uiContext); - /** - * Creates a field based on the item and property id. - * - * @param item - * the item where the property belongs to. - * @param propertyId - * the Id of the property. - * @param uiContext - * the component where the field is presented. - * @return Field the field suitable for editing the specified data. - */ - Field createField(Item item, Object propertyId, Component uiContext); + /** + * Creates a field based on the item and property id. + * + * @param item + * the item where the property belongs to. + * @param propertyId + * the Id of the property. + * @param uiContext + * the component where the field is presented. + * @return Field the field suitable for editing the specified data. + */ + Field createField(Item item, Object propertyId, Component uiContext); - /** - * Creates a field based on the container item id and property id. - * - * @param container - * the Container where the property belongs to. - * @param itemId - * the item Id. - * @param propertyId - * the Id of the property. - * @param uiContext - * the component where the field is presented. - * @return Field the field suitable for editing the specified data. - */ - Field createField(Container container, Object itemId, Object propertyId, - Component uiContext); + /** + * Creates a field based on the container item id and property id. + * + * @param container + * the Container where the property belongs to. + * @param itemId + * the item Id. + * @param propertyId + * the Id of the property. + * @param uiContext + * the component where the field is presented. + * @return Field the field suitable for editing the specified data. + */ + Field createField(Container container, Object itemId, Object propertyId, + Component uiContext); } \ No newline at end of file diff --git a/src/com/itmill/toolkit/ui/Form.java b/src/com/itmill/toolkit/ui/Form.java index 784b97e040..765fcc15b0 100644 --- a/src/com/itmill/toolkit/ui/Form.java +++ b/src/com/itmill/toolkit/ui/Form.java @@ -34,7 +34,11 @@ import java.util.HashMap; import java.util.Iterator; import java.util.LinkedList; -import com.itmill.toolkit.data.*; +import com.itmill.toolkit.data.Buffered; +import com.itmill.toolkit.data.Item; +import com.itmill.toolkit.data.Property; +import com.itmill.toolkit.data.Validatable; +import com.itmill.toolkit.data.Validator; import com.itmill.toolkit.data.Validator.InvalidValueException; import com.itmill.toolkit.data.util.BeanItem; import com.itmill.toolkit.terminal.PaintException; @@ -72,851 +76,887 @@ import com.itmill.toolkit.terminal.PaintTarget; * @since 3.0 */ public class Form extends AbstractField implements Item.Editor, Buffered, Item, - Validatable { - - private Object propertyValue; - - /** - * Layout of the form. - */ - private Layout layout; - - /** - * Item connected to this form as datasource. - */ - private Item itemDatasource; - - /** - * Ordered list of property ids in this editor. - */ - private LinkedList propertyIds = new LinkedList(); - - /** - * Current buffered source exception. - */ - private Buffered.SourceException currentBufferedSourceException = null; - - /** - * Is the form in write trough mode. - */ - private boolean writeThrough = true; - - /** - * Is the form in read trough mode. - */ - private boolean readThrough = true; - - /** - * Mapping from propertyName to corresponding field. - */ - private HashMap fields = new HashMap(); - - /** - * Field factory for this form. - */ - private FieldFactory fieldFactory; - - /** - * Registered Validators. - */ - private LinkedList validators; - - /** - * Visible item properties. - */ - private Collection visibleItemProperties; - - /** - * Contructs a new form with default layout. - * - *

- * By default the form uses OrderedLayout with - * form-style. - *

- * - * @param formLayout - * the layout of the form. - */ - public Form() { - this(null); - } - - /** - * Contructs a new form with given layout. - * - * @param formLayout - * the layout of the form. - */ - public Form(Layout formLayout) { - this(formLayout, new BaseFieldFactory()); - } - - /** - * Contructs a new form with given layout and FieldFactory. - * - * @param formLayout - * the layout of the form. - * @param fieldFactory - * the FieldFactory of the form. - */ - public Form(Layout formLayout, FieldFactory fieldFactory) { - super(); - setLayout(formLayout); - setFieldFactory(fieldFactory); - } - - /* Documented in interface */ - public String getTag() { - return "form"; - } - - /* Documented in interface */ - public void paintContent(PaintTarget target) throws PaintException { - super.paintContent(target); - layout.paint(target); - } - - /* - * Commit changes to the data source Don't add a JavaDoc comment here, we - * use the default one from the interface. - */ - public void commit() throws Buffered.SourceException { - - LinkedList problems = null; - - // Try to commit all - for (Iterator i = propertyIds.iterator(); i.hasNext();) - try { - Field f = ((Field) fields.get(i.next())); - // Commit only non-readonly fields. - if (!f.isReadOnly()) { - f.commit(); - } - } catch (Buffered.SourceException e) { - if (problems == null) - problems = new LinkedList(); - problems.add(e); - } - - // No problems occurred - if (problems == null) { - if (currentBufferedSourceException != null) { - currentBufferedSourceException = null; - requestRepaint(); - } - return; - } - - // Commit problems - Throwable[] causes = new Throwable[problems.size()]; - int index = 0; - for (Iterator i = problems.iterator(); i.hasNext();) - causes[index++] = (Throwable) i.next(); - Buffered.SourceException e = new Buffered.SourceException(this, causes); - currentBufferedSourceException = e; - requestRepaint(); - throw e; - } - - /* - * Discards local changes and refresh values from the data source Don't add - * a JavaDoc comment here, we use the default one from the interface. - */ - public void discard() throws Buffered.SourceException { - - LinkedList problems = null; - - // Try to discard all changes - for (Iterator i = propertyIds.iterator(); i.hasNext();) - try { - ((Field) fields.get(i.next())).discard(); - } catch (Buffered.SourceException e) { - if (problems == null) - problems = new LinkedList(); - problems.add(e); - } - - // No problems occurred - if (problems == null) { - if (currentBufferedSourceException != null) { - currentBufferedSourceException = null; - requestRepaint(); - } - return; - } - - // Discards problems occurred - Throwable[] causes = new Throwable[problems.size()]; - int index = 0; - for (Iterator i = problems.iterator(); i.hasNext();) - causes[index++] = (Throwable) i.next(); - Buffered.SourceException e = new Buffered.SourceException(this, causes); - currentBufferedSourceException = e; - requestRepaint(); - throw e; - } - - /* - * Is the object modified but not committed? Don't add a JavaDoc comment - * here, we use the default one from the interface. - */ - public boolean isModified() { - for (Iterator i = propertyIds.iterator(); i.hasNext();) { - Field f = (Field) fields.get(i.next()); - if (f != null && f.isModified()) - return true; - - } - return false; - } - - /* - * Is the editor in a read-through mode? Don't add a JavaDoc comment here, - * we use the default one from the interface. - */ - public boolean isReadThrough() { - return readThrough; - } - - /* - * Is the editor in a write-through mode? Don't add a JavaDoc comment here, - * we use the default one from the interface. - */ - public boolean isWriteThrough() { - return writeThrough; - } - - /* - * Sets the editor's read-through mode to the specified status. Don't add a - * JavaDoc comment here, we use the default one from the interface. - */ - public void setReadThrough(boolean readThrough) { - if (readThrough != this.readThrough) { - this.readThrough = readThrough; - for (Iterator i = propertyIds.iterator(); i.hasNext();) - ((Field) fields.get(i.next())).setReadThrough(readThrough); - } - } - - /* - * Sets the editor's read-through mode to the specified status. Don't add a - * JavaDoc comment here, we use the default one from the interface. - */ - public void setWriteThrough(boolean writeThrough) { - if (writeThrough != this.writeThrough) { - this.writeThrough = writeThrough; - for (Iterator i = propertyIds.iterator(); i.hasNext();) - ((Field) fields.get(i.next())).setWriteThrough(writeThrough); - } - } - - /** - * Adds a new property to form and create corresponding field. - * - * @see com.itmill.toolkit.data.Item#addItemProperty(Object, Property) - */ - public boolean addItemProperty(Object id, Property property) { - - // Checks inputs - if (id == null || property == null) - throw new NullPointerException("Id and property must be non-null"); - - // Checks that the property id is not reserved - if (propertyIds.contains(id)) - return false; - - // Gets suitable field - Field field = this.fieldFactory.createField(property, this); - if (field == null) - return false; - - // Configures the field - try { - field.setPropertyDataSource(property); - String caption = id.toString(); - if (caption.length() > 50) - caption = caption.substring(0, 47) + "..."; - if (caption.length() > 0) - caption = "" + Character.toUpperCase(caption.charAt(0)) - + caption.substring(1, caption.length()); - field.setCaption(caption); - } catch (Throwable ignored) { - return false; - } - - addField(id, field); - - return true; - } - - /** - * Adds the field to form. - * - *

- * The property id must not be already used in the form. - *

- * - *

- * This field is added to the form layout in the default position (the - * position used by {@link Layout#addComponent(Component)} method. In the - * special case that the underlying layout is a custom layout, string - * representation of the property id is used instead of the default - * location. - *

- * - * @param propertyId - * the Property id the the field. - * @param field - * the New field added to the form. - */ - public void addField(Object propertyId, Field field) { - - if (propertyId != null && field != null) { - this.dependsOn(field); - field.dependsOn(this); - fields.put(propertyId, field); - propertyIds.addLast(propertyId); - field.setReadThrough(readThrough); - field.setWriteThrough(writeThrough); - - if (layout instanceof CustomLayout) - ((CustomLayout) layout).addComponent(field, propertyId - .toString()); - else - layout.addComponent(field); - - requestRepaint(); - } - } - - /** - * The property identified by the property id. - * - *

- * The property data source of the field specified with property id is - * returned. If there is a (with specified property id) having no data - * source, the field is returned instead of the data source. - *

- * - * @see com.itmill.toolkit.data.Item#getItemProperty(Object) - */ - public Property getItemProperty(Object id) { - Field field = (Field) fields.get(id); - if (field == null) - return null; - Property property = field.getPropertyDataSource(); - - if (property != null) - return property; - else - return field; - } - - /** - * Gets the field identified by the propertyid. - * - * @param propertyId - * the id of the property. - */ - public Field getField(Object propertyId) { - return (Field) fields.get(propertyId); - } - - /* Documented in interface */ - public Collection getItemPropertyIds() { - return Collections.unmodifiableCollection(propertyIds); - } - - /** - * Removes the property and corresponding field from the form. - * - * @see com.itmill.toolkit.data.Item#removeItemProperty(Object) - */ - public boolean removeItemProperty(Object id) { - - Field field = (Field) fields.get(id); - - if (field != null) { - propertyIds.remove(id); - fields.remove(id); - this.removeDirectDependency(field); - field.removeDirectDependency(this); - layout.removeComponent(field); - return true; - } - - return false; - } - - /** - * Removes all properties and fields from the form. - * - * @return the Success of the operation. Removal of all fields succeeded if - * (and only if) the return value is true. - */ - public boolean removeAllProperties() { - Object[] properties = propertyIds.toArray(); - boolean success = true; - - for (int i = 0; i < properties.length; i++) - if (!removeItemProperty(properties[i])) - success = false; - - return success; - } - - /* Documented in the interface */ - public Item getItemDataSource() { - return itemDatasource; - } - - /** - * Sets the item datasource for the form. - * - *

- * Setting item datasource clears any fields, the form might contain and - * adds all the properties as fields to the form. - *

- * - * @see com.itmill.toolkit.data.Item.Viewer#setItemDataSource(Item) - */ - public void setItemDataSource(Item newDataSource) { - setItemDataSource(newDataSource, newDataSource != null ? newDataSource - .getItemPropertyIds() : null); - } - - /** - * Set the item datasource for the form, but limit the form contents to - * specified properties of the item. - * - *

- * Setting item datasource clears any fields, the form might contain and - * adds the specified the properties as fields to the form, in the specified - * order. - *

- * - * @see com.itmill.toolkit.data.Item.Viewer#setItemDataSource(Item) - */ - public void setItemDataSource(Item newDataSource, Collection propertyIds) { - - // Removes all fields first from the form - removeAllProperties(); - - // Sets the datasource - itemDatasource = newDataSource; - - // If the new datasource is null, just set null datasource - if (itemDatasource == null) - return; - - // Adds all the properties to this form - for (Iterator i = propertyIds.iterator(); i.hasNext();) { - Object id = i.next(); - Property property = itemDatasource.getItemProperty(id); - if (id != null && property != null) { - Field f = this.fieldFactory.createField(itemDatasource, id, - this); - if (f != null) { - f.setPropertyDataSource(property); - addField(id, f); - } - } - } - } - - /** - * Gets the layout of the form. - * - *

- * By default form uses OrderedLayout with form-style. - *

- * - * @return the Layout of the form. - */ - public Layout getLayout() { - return layout; - } - - /** - * Sets the layout of the form. - * - *

- * By default form uses OrderedLayout with form-style. - *

- * - * @param newLayout - * the Layout of the form. - */ - public void setLayout(Layout newLayout) { - - // Use orderedlayout by default - if (newLayout == null) { - newLayout = new FormLayout(); - } - - // Move components from previous layout - if (this.layout != null) { - newLayout.moveComponentsFrom(this.layout); - this.layout.setParent(null); - } - - // Replace the previous layout - newLayout.setParent(this); - this.layout = newLayout; - } - - /** - * Sets the form field to be selectable from static list of changes. - * - *

- * The list values and descriptions are given as array. The value-array must - * contain the current value of the field and the lengths of the arrays must - * match. Null values are not supported. - *

- * - * @param propertyId - * the id of the property. - * @param values - * @param descriptions - * @return the select property generated - */ - public Select replaceWithSelect(Object propertyId, Object[] values, - Object[] descriptions) { - - // Checks the parameters - if (propertyId == null || values == null || descriptions == null) - throw new NullPointerException("All parameters must be non-null"); - if (values.length != descriptions.length) - throw new IllegalArgumentException( - "Value and description list are of different size"); - - // Gets the old field - Field oldField = (Field) fields.get(propertyId); - if (oldField == null) - throw new IllegalArgumentException("Field with given propertyid '" - + propertyId.toString() + "' can not be found."); - Object value = oldField.getValue(); - - // Checks that the value exists and check if the select should - // be forced in multiselect mode - boolean found = false; - boolean isMultiselect = false; - for (int i = 0; i < values.length && !found; i++) - if (values[i] == value - || (value != null && value.equals(values[i]))) - found = true; - if (value != null && !found) { - if (value instanceof Collection) { - for (Iterator it = ((Collection) value).iterator(); it - .hasNext();) { - Object val = it.next(); - found = false; - for (int i = 0; i < values.length && !found; i++) - if (values[i] == val - || (val != null && val.equals(values[i]))) - found = true; - if (!found) - throw new IllegalArgumentException( - "Currently selected value '" + val - + "' of property '" - + propertyId.toString() - + "' was not found"); - } - isMultiselect = true; - } else - throw new IllegalArgumentException("Current value '" + value - + "' of property '" + propertyId.toString() - + "' was not found"); - } - - // Creates the new field matching to old field parameters - Select newField = new Select(); - if (isMultiselect) - newField.setMultiSelect(true); - newField.setCaption(oldField.getCaption()); - newField.setReadOnly(oldField.isReadOnly()); - newField.setReadThrough(oldField.isReadThrough()); - newField.setWriteThrough(oldField.isWriteThrough()); - - // Creates the options list - newField.addContainerProperty("desc", String.class, ""); - newField.setItemCaptionPropertyId("desc"); - for (int i = 0; i < values.length; i++) { - Object id = values[i]; - if (id == null) { - id = new Object(); - newField.setNullSelectionItemId(id); - } - Item item = newField.addItem(id); - if (item != null) - item.getItemProperty("desc").setValue( - descriptions[i].toString()); - } - - // Sets the property data source - Property property = oldField.getPropertyDataSource(); - oldField.setPropertyDataSource(null); - newField.setPropertyDataSource(property); - - // Replaces the old field with new one - layout.replaceComponent(oldField, newField); - fields.put(propertyId, newField); - this.removeDirectDependency(oldField); - oldField.removeDirectDependency(this); - this.dependsOn(newField); - newField.dependsOn(this); - - return newField; - } - - /** - * Notifies the component that it is connected to an application - * - * @see com.itmill.toolkit.ui.Component#attach() - */ - public void attach() { - super.attach(); - layout.attach(); - } - - /** - * Notifies the component that it is detached from the application. - * - * @see com.itmill.toolkit.ui.Component#detach() - */ - public void detach() { - super.detach(); - layout.detach(); - } - - /** - * Adds a new validator for this object. - * - * @see com.itmill.toolkit.data.Validatable#addValidator(com.itmill.toolkit.data.Validator) - */ - public void addValidator(Validator validator) { - - if (this.validators == null) { - this.validators = new LinkedList(); - } - this.validators.add(validator); - } - - /** - * Removes a previously registered validator from the object. - * - * @see com.itmill.toolkit.data.Validatable#removeValidator(com.itmill.toolkit.data.Validator) - */ - public void removeValidator(Validator validator) { - if (this.validators != null) { - this.validators.remove(validator); - } - } - - /** - * Gets the Lists all validators currently registered for the object. - * - * @see com.itmill.toolkit.data.Validatable#getValidators() - */ - public Collection getValidators() { - if (this.validators == null) { - this.validators = new LinkedList(); - } - return this.validators; - } - - /** - * Tests the current value of the object against all registered validators - * - * @see com.itmill.toolkit.data.Validatable#isValid() - */ - public boolean isValid() { - boolean valid = true; - for (Iterator i = propertyIds.iterator(); i.hasNext();) - valid &= ((Field) fields.get(i.next())).isValid(); - return valid; - } - - /** - * Checks the validity of the validatable. - * - * @see com.itmill.toolkit.data.Validatable#validate() - */ - public void validate() throws InvalidValueException { - for (Iterator i = propertyIds.iterator(); i.hasNext();) - ((Field) fields.get(i.next())).validate(); - } - - /** - * Checks the validabtable object accept invalid values. - * - * @see com.itmill.toolkit.data.Validatable#isInvalidAllowed() - */ - public boolean isInvalidAllowed() { - return true; - } - - /** - * Should the validabtable object accept invalid values. - * - * @see com.itmill.toolkit.data.Validatable#setInvalidAllowed(boolean) - */ - public void setInvalidAllowed(boolean invalidValueAllowed) - throws UnsupportedOperationException { - throw new UnsupportedOperationException(); - } - - /** - * Sets the component's to read-only mode to the specified state. - * - * @see com.itmill.toolkit.ui.Component#setReadOnly(boolean) - */ - public void setReadOnly(boolean readOnly) { - super.setReadOnly(readOnly); - for (Iterator i = propertyIds.iterator(); i.hasNext();) - ((Field) fields.get(i.next())).setReadOnly(readOnly); - } - - /** - * Sets the field factory of Form. - * - * FieldFactory is used to create fields for form properties. - * By default the form uses BaseFieldFactory to create Field instances. - * - * @param fieldFactory - * the New factory used to create the fields. - * @see Field - * @see FieldFactory - */ - public void setFieldFactory(FieldFactory fieldFactory) { - this.fieldFactory = fieldFactory; - } - - /** - * Get the field factory of the form. - * - * @return the FieldFactory Factory used to create the fields. - */ - public FieldFactory getFieldFactory() { - return this.fieldFactory; - } - - /** - * Gets the field type. - * - * @see com.itmill.toolkit.ui.AbstractField#getType() - */ - public Class getType() { - if (getPropertyDataSource() != null) - return getPropertyDataSource().getType(); - return Object.class; - } - - /** - * Sets the internal value. - * - * This is relevant when the Form is used as Field. - * - * @see com.itmill.toolkit.ui.AbstractField#setInternalValue(java.lang.Object) - */ - protected void setInternalValue(Object newValue) { - // Stores the old value - Object oldValue = this.propertyValue; - - // Sets the current Value - super.setInternalValue(newValue); - this.propertyValue = newValue; - - // Ignores form updating if data object has not changed. - if (oldValue != newValue) { - setFormDataSource(newValue, getVisibleItemProperties()); - } - } - - /** - * Gets the first field in form. - * - * @return the Field. - */ - private Field getFirstField() { - Object id = null; - if (this.getItemPropertyIds() != null) { - id = this.getItemPropertyIds().iterator().next(); - } - if (id != null) - return this.getField(id); - return null; - } - - /** - * Updates the internal form datasource. - * - * Method setFormDataSource. - * - * @param data - * @param properties - */ - protected void setFormDataSource(Object data, Collection properties) { - - // If data is an item use it. - Item item = null; - if (data instanceof Item) { - item = (Item) data; - } else if (data != null) { - item = new BeanItem(data); - } - - // Sets the datasource to form - if (item != null && properties != null) { - // Shows only given properties - this.setItemDataSource(item, properties); - } else { - // Shows all properties - this.setItemDataSource(item); - } - } - - /** - * Returns the visibleProperties. - * - * @return the Collection of visible Item properites. - */ - public Collection getVisibleItemProperties() { - return visibleItemProperties; - } - - /** - * Sets the visibleProperties. - * - * @param visibleProperties - * the visibleProperties to set. - */ - public void setVisibleItemProperties(Collection visibleProperties) { - this.visibleItemProperties = visibleProperties; - Object value = getValue(); - setFormDataSource(value, getVisibleItemProperties()); - } - - /** - * Focuses the first field in the form. - * - * @see com.itmill.toolkit.ui.Component.Focusable#focus() - */ - public void focus() { - Field f = getFirstField(); - if (f != null) { - f.focus(); - } - } - - /** - * Sets the Tabulator index of this Focusable component. - * - * @see com.itmill.toolkit.ui.Component.Focusable#setTabIndex(int) - */ - public void setTabIndex(int tabIndex) { - super.setTabIndex(tabIndex); - for (Iterator i = this.getItemPropertyIds().iterator(); i.hasNext();) - (this.getField(i.next())).setTabIndex(tabIndex); - } + Validatable { + + private Object propertyValue; + + /** + * Layout of the form. + */ + private Layout layout; + + /** + * Item connected to this form as datasource. + */ + private Item itemDatasource; + + /** + * Ordered list of property ids in this editor. + */ + private LinkedList propertyIds = new LinkedList(); + + /** + * Current buffered source exception. + */ + private Buffered.SourceException currentBufferedSourceException = null; + + /** + * Is the form in write trough mode. + */ + private boolean writeThrough = true; + + /** + * Is the form in read trough mode. + */ + private boolean readThrough = true; + + /** + * Mapping from propertyName to corresponding field. + */ + private HashMap fields = new HashMap(); + + /** + * Field factory for this form. + */ + private FieldFactory fieldFactory; + + /** + * Registered Validators. + */ + private LinkedList validators; + + /** + * Visible item properties. + */ + private Collection visibleItemProperties; + + /** + * Contructs a new form with default layout. + * + *

+ * By default the form uses OrderedLayout with + * form-style. + *

+ * + * @param formLayout + * the layout of the form. + */ + public Form() { + this(null); + } + + /** + * Contructs a new form with given layout. + * + * @param formLayout + * the layout of the form. + */ + public Form(Layout formLayout) { + this(formLayout, new BaseFieldFactory()); + } + + /** + * Contructs a new form with given layout and FieldFactory. + * + * @param formLayout + * the layout of the form. + * @param fieldFactory + * the FieldFactory of the form. + */ + public Form(Layout formLayout, FieldFactory fieldFactory) { + super(); + setLayout(formLayout); + setFieldFactory(fieldFactory); + } + + /* Documented in interface */ + public String getTag() { + return "form"; + } + + /* Documented in interface */ + public void paintContent(PaintTarget target) throws PaintException { + super.paintContent(target); + layout.paint(target); + } + + /* + * Commit changes to the data source Don't add a JavaDoc comment here, we + * use the default one from the interface. + */ + public void commit() throws Buffered.SourceException { + + LinkedList problems = null; + + // Try to commit all + for (Iterator i = propertyIds.iterator(); i.hasNext();) { + try { + Field f = ((Field) fields.get(i.next())); + // Commit only non-readonly fields. + if (!f.isReadOnly()) { + f.commit(); + } + } catch (Buffered.SourceException e) { + if (problems == null) { + problems = new LinkedList(); + } + problems.add(e); + } + } + + // No problems occurred + if (problems == null) { + if (currentBufferedSourceException != null) { + currentBufferedSourceException = null; + requestRepaint(); + } + return; + } + + // Commit problems + Throwable[] causes = new Throwable[problems.size()]; + int index = 0; + for (Iterator i = problems.iterator(); i.hasNext();) { + causes[index++] = (Throwable) i.next(); + } + Buffered.SourceException e = new Buffered.SourceException(this, causes); + currentBufferedSourceException = e; + requestRepaint(); + throw e; + } + + /* + * Discards local changes and refresh values from the data source Don't add + * a JavaDoc comment here, we use the default one from the interface. + */ + public void discard() throws Buffered.SourceException { + + LinkedList problems = null; + + // Try to discard all changes + for (Iterator i = propertyIds.iterator(); i.hasNext();) { + try { + ((Field) fields.get(i.next())).discard(); + } catch (Buffered.SourceException e) { + if (problems == null) { + problems = new LinkedList(); + } + problems.add(e); + } + } + + // No problems occurred + if (problems == null) { + if (currentBufferedSourceException != null) { + currentBufferedSourceException = null; + requestRepaint(); + } + return; + } + + // Discards problems occurred + Throwable[] causes = new Throwable[problems.size()]; + int index = 0; + for (Iterator i = problems.iterator(); i.hasNext();) { + causes[index++] = (Throwable) i.next(); + } + Buffered.SourceException e = new Buffered.SourceException(this, causes); + currentBufferedSourceException = e; + requestRepaint(); + throw e; + } + + /* + * Is the object modified but not committed? Don't add a JavaDoc comment + * here, we use the default one from the interface. + */ + public boolean isModified() { + for (Iterator i = propertyIds.iterator(); i.hasNext();) { + Field f = (Field) fields.get(i.next()); + if (f != null && f.isModified()) { + return true; + } + + } + return false; + } + + /* + * Is the editor in a read-through mode? Don't add a JavaDoc comment here, + * we use the default one from the interface. + */ + public boolean isReadThrough() { + return readThrough; + } + + /* + * Is the editor in a write-through mode? Don't add a JavaDoc comment here, + * we use the default one from the interface. + */ + public boolean isWriteThrough() { + return writeThrough; + } + + /* + * Sets the editor's read-through mode to the specified status. Don't add a + * JavaDoc comment here, we use the default one from the interface. + */ + public void setReadThrough(boolean readThrough) { + if (readThrough != this.readThrough) { + this.readThrough = readThrough; + for (Iterator i = propertyIds.iterator(); i.hasNext();) { + ((Field) fields.get(i.next())).setReadThrough(readThrough); + } + } + } + + /* + * Sets the editor's read-through mode to the specified status. Don't add a + * JavaDoc comment here, we use the default one from the interface. + */ + public void setWriteThrough(boolean writeThrough) { + if (writeThrough != this.writeThrough) { + this.writeThrough = writeThrough; + for (Iterator i = propertyIds.iterator(); i.hasNext();) { + ((Field) fields.get(i.next())).setWriteThrough(writeThrough); + } + } + } + + /** + * Adds a new property to form and create corresponding field. + * + * @see com.itmill.toolkit.data.Item#addItemProperty(Object, Property) + */ + public boolean addItemProperty(Object id, Property property) { + + // Checks inputs + if (id == null || property == null) { + throw new NullPointerException("Id and property must be non-null"); + } + + // Checks that the property id is not reserved + if (propertyIds.contains(id)) { + return false; + } + + // Gets suitable field + Field field = fieldFactory.createField(property, this); + if (field == null) { + return false; + } + + // Configures the field + try { + field.setPropertyDataSource(property); + String caption = id.toString(); + if (caption.length() > 50) { + caption = caption.substring(0, 47) + "..."; + } + if (caption.length() > 0) { + caption = "" + Character.toUpperCase(caption.charAt(0)) + + caption.substring(1, caption.length()); + } + field.setCaption(caption); + } catch (Throwable ignored) { + return false; + } + + addField(id, field); + + return true; + } + + /** + * Adds the field to form. + * + *

+ * The property id must not be already used in the form. + *

+ * + *

+ * This field is added to the form layout in the default position (the + * position used by {@link Layout#addComponent(Component)} method. In the + * special case that the underlying layout is a custom layout, string + * representation of the property id is used instead of the default + * location. + *

+ * + * @param propertyId + * the Property id the the field. + * @param field + * the New field added to the form. + */ + public void addField(Object propertyId, Field field) { + + if (propertyId != null && field != null) { + dependsOn(field); + field.dependsOn(this); + fields.put(propertyId, field); + propertyIds.addLast(propertyId); + field.setReadThrough(readThrough); + field.setWriteThrough(writeThrough); + + if (layout instanceof CustomLayout) { + ((CustomLayout) layout).addComponent(field, propertyId + .toString()); + } else { + layout.addComponent(field); + } + + requestRepaint(); + } + } + + /** + * The property identified by the property id. + * + *

+ * The property data source of the field specified with property id is + * returned. If there is a (with specified property id) having no data + * source, the field is returned instead of the data source. + *

+ * + * @see com.itmill.toolkit.data.Item#getItemProperty(Object) + */ + public Property getItemProperty(Object id) { + Field field = (Field) fields.get(id); + if (field == null) { + return null; + } + Property property = field.getPropertyDataSource(); + + if (property != null) { + return property; + } else { + return field; + } + } + + /** + * Gets the field identified by the propertyid. + * + * @param propertyId + * the id of the property. + */ + public Field getField(Object propertyId) { + return (Field) fields.get(propertyId); + } + + /* Documented in interface */ + public Collection getItemPropertyIds() { + return Collections.unmodifiableCollection(propertyIds); + } + + /** + * Removes the property and corresponding field from the form. + * + * @see com.itmill.toolkit.data.Item#removeItemProperty(Object) + */ + public boolean removeItemProperty(Object id) { + + Field field = (Field) fields.get(id); + + if (field != null) { + propertyIds.remove(id); + fields.remove(id); + removeDirectDependency(field); + field.removeDirectDependency(this); + layout.removeComponent(field); + return true; + } + + return false; + } + + /** + * Removes all properties and fields from the form. + * + * @return the Success of the operation. Removal of all fields succeeded if + * (and only if) the return value is true. + */ + public boolean removeAllProperties() { + Object[] properties = propertyIds.toArray(); + boolean success = true; + + for (int i = 0; i < properties.length; i++) { + if (!removeItemProperty(properties[i])) { + success = false; + } + } + + return success; + } + + /* Documented in the interface */ + public Item getItemDataSource() { + return itemDatasource; + } + + /** + * Sets the item datasource for the form. + * + *

+ * Setting item datasource clears any fields, the form might contain and + * adds all the properties as fields to the form. + *

+ * + * @see com.itmill.toolkit.data.Item.Viewer#setItemDataSource(Item) + */ + public void setItemDataSource(Item newDataSource) { + setItemDataSource(newDataSource, newDataSource != null ? newDataSource + .getItemPropertyIds() : null); + } + + /** + * Set the item datasource for the form, but limit the form contents to + * specified properties of the item. + * + *

+ * Setting item datasource clears any fields, the form might contain and + * adds the specified the properties as fields to the form, in the specified + * order. + *

+ * + * @see com.itmill.toolkit.data.Item.Viewer#setItemDataSource(Item) + */ + public void setItemDataSource(Item newDataSource, Collection propertyIds) { + + // Removes all fields first from the form + removeAllProperties(); + + // Sets the datasource + itemDatasource = newDataSource; + + // If the new datasource is null, just set null datasource + if (itemDatasource == null) { + return; + } + + // Adds all the properties to this form + for (Iterator i = propertyIds.iterator(); i.hasNext();) { + Object id = i.next(); + Property property = itemDatasource.getItemProperty(id); + if (id != null && property != null) { + Field f = fieldFactory.createField(itemDatasource, id, this); + if (f != null) { + f.setPropertyDataSource(property); + addField(id, f); + } + } + } + } + + /** + * Gets the layout of the form. + * + *

+ * By default form uses OrderedLayout with form-style. + *

+ * + * @return the Layout of the form. + */ + public Layout getLayout() { + return layout; + } + + /** + * Sets the layout of the form. + * + *

+ * By default form uses OrderedLayout with form-style. + *

+ * + * @param newLayout + * the Layout of the form. + */ + public void setLayout(Layout newLayout) { + + // Use orderedlayout by default + if (newLayout == null) { + newLayout = new FormLayout(); + } + + // Move components from previous layout + if (layout != null) { + newLayout.moveComponentsFrom(layout); + layout.setParent(null); + } + + // Replace the previous layout + newLayout.setParent(this); + layout = newLayout; + } + + /** + * Sets the form field to be selectable from static list of changes. + * + *

+ * The list values and descriptions are given as array. The value-array must + * contain the current value of the field and the lengths of the arrays must + * match. Null values are not supported. + *

+ * + * @param propertyId + * the id of the property. + * @param values + * @param descriptions + * @return the select property generated + */ + public Select replaceWithSelect(Object propertyId, Object[] values, + Object[] descriptions) { + + // Checks the parameters + if (propertyId == null || values == null || descriptions == null) { + throw new NullPointerException("All parameters must be non-null"); + } + if (values.length != descriptions.length) { + throw new IllegalArgumentException( + "Value and description list are of different size"); + } + + // Gets the old field + Field oldField = (Field) fields.get(propertyId); + if (oldField == null) { + throw new IllegalArgumentException("Field with given propertyid '" + + propertyId.toString() + "' can not be found."); + } + Object value = oldField.getValue(); + + // Checks that the value exists and check if the select should + // be forced in multiselect mode + boolean found = false; + boolean isMultiselect = false; + for (int i = 0; i < values.length && !found; i++) { + if (values[i] == value + || (value != null && value.equals(values[i]))) { + found = true; + } + } + if (value != null && !found) { + if (value instanceof Collection) { + for (Iterator it = ((Collection) value).iterator(); it + .hasNext();) { + Object val = it.next(); + found = false; + for (int i = 0; i < values.length && !found; i++) { + if (values[i] == val + || (val != null && val.equals(values[i]))) { + found = true; + } + } + if (!found) { + throw new IllegalArgumentException( + "Currently selected value '" + val + + "' of property '" + + propertyId.toString() + + "' was not found"); + } + } + isMultiselect = true; + } else { + throw new IllegalArgumentException("Current value '" + value + + "' of property '" + propertyId.toString() + + "' was not found"); + } + } + + // Creates the new field matching to old field parameters + Select newField = new Select(); + if (isMultiselect) { + newField.setMultiSelect(true); + } + newField.setCaption(oldField.getCaption()); + newField.setReadOnly(oldField.isReadOnly()); + newField.setReadThrough(oldField.isReadThrough()); + newField.setWriteThrough(oldField.isWriteThrough()); + + // Creates the options list + newField.addContainerProperty("desc", String.class, ""); + newField.setItemCaptionPropertyId("desc"); + for (int i = 0; i < values.length; i++) { + Object id = values[i]; + if (id == null) { + id = new Object(); + newField.setNullSelectionItemId(id); + } + Item item = newField.addItem(id); + if (item != null) { + item.getItemProperty("desc").setValue( + descriptions[i].toString()); + } + } + + // Sets the property data source + Property property = oldField.getPropertyDataSource(); + oldField.setPropertyDataSource(null); + newField.setPropertyDataSource(property); + + // Replaces the old field with new one + layout.replaceComponent(oldField, newField); + fields.put(propertyId, newField); + removeDirectDependency(oldField); + oldField.removeDirectDependency(this); + dependsOn(newField); + newField.dependsOn(this); + + return newField; + } + + /** + * Notifies the component that it is connected to an application + * + * @see com.itmill.toolkit.ui.Component#attach() + */ + public void attach() { + super.attach(); + layout.attach(); + } + + /** + * Notifies the component that it is detached from the application. + * + * @see com.itmill.toolkit.ui.Component#detach() + */ + public void detach() { + super.detach(); + layout.detach(); + } + + /** + * Adds a new validator for this object. + * + * @see com.itmill.toolkit.data.Validatable#addValidator(com.itmill.toolkit.data.Validator) + */ + public void addValidator(Validator validator) { + + if (validators == null) { + validators = new LinkedList(); + } + validators.add(validator); + } + + /** + * Removes a previously registered validator from the object. + * + * @see com.itmill.toolkit.data.Validatable#removeValidator(com.itmill.toolkit.data.Validator) + */ + public void removeValidator(Validator validator) { + if (validators != null) { + validators.remove(validator); + } + } + + /** + * Gets the Lists all validators currently registered for the object. + * + * @see com.itmill.toolkit.data.Validatable#getValidators() + */ + public Collection getValidators() { + if (validators == null) { + validators = new LinkedList(); + } + return validators; + } + + /** + * Tests the current value of the object against all registered validators + * + * @see com.itmill.toolkit.data.Validatable#isValid() + */ + public boolean isValid() { + boolean valid = true; + for (Iterator i = propertyIds.iterator(); i.hasNext();) { + valid &= ((Field) fields.get(i.next())).isValid(); + } + return valid; + } + + /** + * Checks the validity of the validatable. + * + * @see com.itmill.toolkit.data.Validatable#validate() + */ + public void validate() throws InvalidValueException { + for (Iterator i = propertyIds.iterator(); i.hasNext();) { + ((Field) fields.get(i.next())).validate(); + } + } + + /** + * Checks the validabtable object accept invalid values. + * + * @see com.itmill.toolkit.data.Validatable#isInvalidAllowed() + */ + public boolean isInvalidAllowed() { + return true; + } + + /** + * Should the validabtable object accept invalid values. + * + * @see com.itmill.toolkit.data.Validatable#setInvalidAllowed(boolean) + */ + public void setInvalidAllowed(boolean invalidValueAllowed) + throws UnsupportedOperationException { + throw new UnsupportedOperationException(); + } + + /** + * Sets the component's to read-only mode to the specified state. + * + * @see com.itmill.toolkit.ui.Component#setReadOnly(boolean) + */ + public void setReadOnly(boolean readOnly) { + super.setReadOnly(readOnly); + for (Iterator i = propertyIds.iterator(); i.hasNext();) { + ((Field) fields.get(i.next())).setReadOnly(readOnly); + } + } + + /** + * Sets the field factory of Form. + * + * FieldFactory is used to create fields for form properties. + * By default the form uses BaseFieldFactory to create Field instances. + * + * @param fieldFactory + * the New factory used to create the fields. + * @see Field + * @see FieldFactory + */ + public void setFieldFactory(FieldFactory fieldFactory) { + this.fieldFactory = fieldFactory; + } + + /** + * Get the field factory of the form. + * + * @return the FieldFactory Factory used to create the fields. + */ + public FieldFactory getFieldFactory() { + return fieldFactory; + } + + /** + * Gets the field type. + * + * @see com.itmill.toolkit.ui.AbstractField#getType() + */ + public Class getType() { + if (getPropertyDataSource() != null) { + return getPropertyDataSource().getType(); + } + return Object.class; + } + + /** + * Sets the internal value. + * + * This is relevant when the Form is used as Field. + * + * @see com.itmill.toolkit.ui.AbstractField#setInternalValue(java.lang.Object) + */ + protected void setInternalValue(Object newValue) { + // Stores the old value + Object oldValue = propertyValue; + + // Sets the current Value + super.setInternalValue(newValue); + propertyValue = newValue; + + // Ignores form updating if data object has not changed. + if (oldValue != newValue) { + setFormDataSource(newValue, getVisibleItemProperties()); + } + } + + /** + * Gets the first field in form. + * + * @return the Field. + */ + private Field getFirstField() { + Object id = null; + if (getItemPropertyIds() != null) { + id = getItemPropertyIds().iterator().next(); + } + if (id != null) { + return getField(id); + } + return null; + } + + /** + * Updates the internal form datasource. + * + * Method setFormDataSource. + * + * @param data + * @param properties + */ + protected void setFormDataSource(Object data, Collection properties) { + + // If data is an item use it. + Item item = null; + if (data instanceof Item) { + item = (Item) data; + } else if (data != null) { + item = new BeanItem(data); + } + + // Sets the datasource to form + if (item != null && properties != null) { + // Shows only given properties + this.setItemDataSource(item, properties); + } else { + // Shows all properties + this.setItemDataSource(item); + } + } + + /** + * Returns the visibleProperties. + * + * @return the Collection of visible Item properites. + */ + public Collection getVisibleItemProperties() { + return visibleItemProperties; + } + + /** + * Sets the visibleProperties. + * + * @param visibleProperties + * the visibleProperties to set. + */ + public void setVisibleItemProperties(Collection visibleProperties) { + visibleItemProperties = visibleProperties; + Object value = getValue(); + setFormDataSource(value, getVisibleItemProperties()); + } + + /** + * Focuses the first field in the form. + * + * @see com.itmill.toolkit.ui.Component.Focusable#focus() + */ + public void focus() { + Field f = getFirstField(); + if (f != null) { + f.focus(); + } + } + + /** + * Sets the Tabulator index of this Focusable component. + * + * @see com.itmill.toolkit.ui.Component.Focusable#setTabIndex(int) + */ + public void setTabIndex(int tabIndex) { + super.setTabIndex(tabIndex); + for (Iterator i = getItemPropertyIds().iterator(); i.hasNext();) { + (getField(i.next())).setTabIndex(tabIndex); + } + } } diff --git a/src/com/itmill/toolkit/ui/FormLayout.java b/src/com/itmill/toolkit/ui/FormLayout.java index f7ec090977..c81ba29ab0 100644 --- a/src/com/itmill/toolkit/ui/FormLayout.java +++ b/src/com/itmill/toolkit/ui/FormLayout.java @@ -2,8 +2,8 @@ package com.itmill.toolkit.ui; public class FormLayout extends OrderedLayout { - public String getTag() { - return "formlayout"; - } + public String getTag() { + return "formlayout"; + } } diff --git a/src/com/itmill/toolkit/ui/GridLayout.java b/src/com/itmill/toolkit/ui/GridLayout.java index 901842bed7..0e0d80172e 100644 --- a/src/com/itmill/toolkit/ui/GridLayout.java +++ b/src/com/itmill/toolkit/ui/GridLayout.java @@ -61,992 +61,1011 @@ import com.itmill.toolkit.terminal.gwt.client.ui.AlignmentInfo; */ public class GridLayout extends AbstractLayout { - /** - * Initial grid columns. - */ - private int cols = 0; - - /** - * Initial grid rows. - */ - private int rows = 0; - - /** - * Cursor X position: this is where the next component with unspecified x,y - * is inserted - */ - private int cursorX = 0; - - /** - * Cursor Y position: this is where the next component with unspecified x,y - * is inserted - */ - private int cursorY = 0; - - /** - * Contains all items that are placed on the grid. These are components with - * grid area definition. - */ - private LinkedList areas = new LinkedList(); - - /** - * Mapping from components to their respective areas. - */ - private LinkedList components = new LinkedList(); - - /** - * Mapping from components to alignments (horizontal + vertical). - */ - private Map componentToAlignment = new HashMap(); - - /** - * Contained component should be aligned horizontally to the left. - */ - public static final int ALIGNMENT_LEFT = AlignmentInfo.ALIGNMENT_LEFT; - - /** - * Contained component should be aligned horizontally to the right. - */ - public static final int ALIGNMENT_RIGHT = AlignmentInfo.ALIGNMENT_RIGHT; - - /** - * Contained component should be aligned vertically to the top. - */ - public static final int ALIGNMENT_TOP = AlignmentInfo.ALIGNMENT_TOP; - - /** - * Contained component should be aligned vertically to the bottom. - */ - public static final int ALIGNMENT_BOTTOM = AlignmentInfo.ALIGNMENT_BOTTOM; - - /** - * Contained component should be horizontally aligned to center. - */ - public static final int ALIGNMENT_HORIZONTAL_CENTER = AlignmentInfo.ALIGNMENT_HORIZONTAL_CENTER; - - /** - * Contained component should be vertically aligned to center. - */ - public static final int ALIGNMENT_VERTICAL_CENTER = AlignmentInfo.ALIGNMENT_VERTICAL_CENTER; - - /** - * Is spacing between contained components enabled. Defaults to false. - */ - private boolean spacing = false; - - /** - * Constructor for grid of given size (number of cells). Note that grid's - * final size depends on the items that are added into the grid. Grid grows - * if you add components outside the grid's area. - * - * @param columns - * Number of columns in the grid. - * @param rows - * Number of rows in the grid. - */ - public GridLayout(int columns, int rows) { - setColumns(columns); - setRows(rows); - } - - /** - * Constructs an empty grid layout that is extended as needed. - */ - public GridLayout() { - this(1, 1); - } - - /** - *

- * Adds a component with a specified area to the grid. The area the new - * component should take is defined by specifying the upper left corner - * (column1, row1) and the lower right corner (column2, row2) of the area. - *

- * - *

- * If the new component overlaps with any of the existing components already - * present in the grid the operation will fail and an - * {@link OverlapsException} is thrown. - *

- * - * @param c - * the component to be added. - * @param column1 - * the column of the upper left corner of the area c - * is supposed to occupy. - * @param row1 - * the row of the upper left corner of the area c - * is supposed to occupy. - * @param column2 - * the column of the lower right corner of the area - * c is supposed to occupy. - * @param row2 - * the row of the lower right corner of the area c - * is supposed to occupy. - * @throws OverlapsException - * if the new component overlaps with any of the components - * already in the grid. - * @throws OutOfBoundsException - * if the cells are outside of the grid area. - */ - public void addComponent(Component component, int column1, int row1, - int column2, int row2) throws OverlapsException, - OutOfBoundsException { - - if (component == null) - throw new NullPointerException("Component must not be null"); - - // Checks that the component does not already exist in the container - if (components.contains(component)) - throw new IllegalArgumentException( - "Component is already in the container"); - - // Creates the area - Area area = new Area(component, column1, row1, column2, row2); - - // Checks the validity of the coordinates - if (column2 < column1 || row2 < row1) - throw new IllegalArgumentException( - "Illegal coordinates for the component"); - if (column1 < 0 || row1 < 0 || column2 >= cols || row2 >= rows) - throw new OutOfBoundsException(area); - - // Checks that newItem does not overlap with existing items - checkExistingOverlaps(area); - - // Inserts the component to right place at the list - // Respect top-down, left-right ordering - component.setParent(this); - Iterator i = areas.iterator(); - int index = 0; - boolean done = false; - while (!done && i.hasNext()) { - Area existingArea = (Area) i.next(); - if ((existingArea.row1 >= row1 && existingArea.column1 > column1) - || existingArea.row1 > row1) { - areas.add(index, area); - components.add(index, component); - done = true; - } - index++; - } - if (!done) { - areas.addLast(area); - components.addLast(component); - } - - super.addComponent(component); - requestRepaint(); - } - - /** - * Tests if the given area overlaps with any of the items already on the - * grid. - * - * @param area - * the Area to be checked for overlapping. - * @throws OverlapsException - * if area overlaps with any existing area. - */ - private void checkExistingOverlaps(Area area) throws OverlapsException { - for (Iterator i = areas.iterator(); i.hasNext();) { - Area existingArea = (Area) i.next(); - if (existingArea.overlaps(area)) - - // Component not added, overlaps with existing component - throw new OverlapsException(existingArea); - } - } - - /** - * Adds the component into this container to cells column1,row1 (NortWest - * corner of the area.) End coordinates (SouthEast corner of the area) are - * the same as column1,row1. Component width and height is 1. - * - * @param c - * the component to be added. - * @param column - * the column index. - * @param row - * the row index. - */ - public void addComponent(Component c, int column, int row) { - this.addComponent(c, column, row, column, row); - } - - /** - * Force the next component to be added to the beginning of the next line. - * By calling this function user can ensure that no more components are - * added to the right of the previous component. - * - * @see #space() - */ - public void newLine() { - cursorX = 0; - cursorY++; - } - - /** - * Moves the cursor forwards by one. If the cursor goes out of the right - * grid border, move it to next line. - * - * @see #newLine() - */ - public void space() { - cursorX++; - if (cursorX >= cols) { - cursorX = 0; - cursorY++; - } - } - - /** - * Adds the component into this container to the cursor position. If the - * cursor position is already occupied, the cursor is moved forwards to find - * free position. If the cursor goes out from the bottom of the grid, the - * grid is automatically extended. - * - * @param c - * the component to be added. - */ - public void addComponent(Component component) { - - // Finds first available place from the grid - Area area; - boolean done = false; - while (!done) - try { - area = new Area(component, cursorX, cursorY, cursorX, cursorY); - checkExistingOverlaps(area); - done = true; - } catch (OverlapsException ignored) { - space(); - } - - // Extends the grid if needed - cols = cursorX >= cols ? cursorX + 1 : cols; - rows = cursorY >= rows ? cursorY + 1 : rows; - - addComponent(component, cursorX, cursorY); - } - - /** - * Removes the given component from this container. - * - * @param c - * the component to be removed. - */ - public void removeComponent(Component component) { - - // Check that the component is contained in the container - if (component == null || !components.contains(component)) - return; - - super.removeComponent(component); - - Area area = null; - for (Iterator i = areas.iterator(); area == null && i.hasNext();) { - Area a = (Area) i.next(); - if (a.getComponent() == component) - area = a; - } - - components.remove(component); - if (area != null) - areas.remove(area); - - componentToAlignment.remove(component); - - requestRepaint(); - } - - /** - * Removes the component specified with it's cell index. - * - * @param column - * the Component's column. - * @param row - * the Component's row. - */ - public void removeComponent(int column, int row) { - - // Finds the area - for (Iterator i = areas.iterator(); i.hasNext();) { - Area area = (Area) i.next(); - if (area.getColumn1() == column && area.getRow1() == row) { - removeComponent(area.getComponent()); - return; - } - } - } - - /** - * Gets an Iterator to the component container contents. Using the Iterator - * it's possible to step through the contents of the container. - * - * @return the Iterator of the components inside the container. - */ - public Iterator getComponentIterator() { - return Collections.unmodifiableCollection(components).iterator(); - } - - /** - * Paints the contents of this component. - * - * @param target - * the Paint Event. - * @throws PaintException - * if the paint operation failed. - */ - public void paintContent(PaintTarget target) throws PaintException { - - super.paintContent(target); - - // TODO refactor attribute names in future release. - target.addAttribute("h", rows); - target.addAttribute("w", cols); - - if (this.spacing) - target.addAttribute("spacing", this.spacing); - - // Area iterator - Iterator areaiterator = areas.iterator(); - - // Current item to be processed (fetch first item) - Area area = areaiterator.hasNext() ? (Area) areaiterator.next() : null; - - // Collects rowspan related information here - HashMap cellUsed = new HashMap(); - - // Empty cell collector - int emptyCells = 0; - - // Iterates every applicable row - for (int cury = 0; cury < rows; cury++) { - target.startTag("gr"); - - // Iterates every applicable column - for (int curx = 0; curx < cols; curx++) { - - // Checks if current item is located at curx,cury - if (area != null && (area.row1 == cury) - && (area.column1 == curx)) { - - // First check if empty cell needs to be rendered - if (emptyCells > 0) { - target.startTag("gc"); - target.addAttribute("x", curx - emptyCells); - target.addAttribute("y", cury); - if (emptyCells > 1) { - target.addAttribute("w", emptyCells); - } - target.endTag("gc"); - emptyCells = 0; - } - - // Now proceed rendering current item - int cols = (area.column2 - area.column1) + 1; - int rows = (area.row2 - area.row1) + 1; - target.startTag("gc"); - - target.addAttribute("x", curx); - target.addAttribute("y", cury); - - if (cols > 1) { - target.addAttribute("w", cols); - } - if (rows > 1) { - target.addAttribute("h", rows); - } - area.getComponent().paint(target); - - target.endTag("gc"); - - // Fetch next item - if (areaiterator.hasNext()) { - area = (Area) areaiterator.next(); - } else { - area = null; - } - - // Updates the cellUsed if rowspan needed - if (rows > 1) { - int spannedx = curx; - for (int j = 1; j <= cols; j++) { - cellUsed.put(new Integer(spannedx), new Integer( - cury + rows - 1)); - spannedx++; - } - } - - // Skips the current item's spanned columns - if (cols > 1) { - curx += cols - 1; - } - - } else { - - // Checks against cellUsed, render space or ignore cell - if (cellUsed.containsKey(new Integer(curx))) { - - // Current column contains already an item, - // check if rowspan affects at current x,y position - int rowspanDepth = ((Integer) cellUsed.get(new Integer( - curx))).intValue(); - - if (rowspanDepth >= cury) { - - // ignore cell - // Check if empty cell needs to be rendered - if (emptyCells > 0) { - target.startTag("gc"); - target.addAttribute("x", curx - emptyCells); - target.addAttribute("y", cury); - if (emptyCells > 1) { - target.addAttribute("w", emptyCells); - } - target.endTag("gc"); - - emptyCells = 0; - } - } else { - - // empty cell is needed - emptyCells++; - - // Removes the cellUsed key as it has become - // obsolete - cellUsed.remove(new Integer(curx)); - } - } else { - - // empty cell is needed - emptyCells++; - } - } - - } // iterates every column - - // Last column handled of current row - - // Checks if empty cell needs to be rendered - if (emptyCells > 0) { - target.startTag("gc"); - target.addAttribute("x", cols - emptyCells); - target.addAttribute("y", cury); - if (emptyCells > 1) { - target.addAttribute("w", emptyCells); - } - target.endTag("gc"); - - emptyCells = 0; - } - - target.endTag("gr"); - } // iterates every row - - // Last row handled - } - - /** - * Gets the components UIDL tag. - * - * @return the Component UIDL tag as string. - * @see com.itmill.toolkit.ui.AbstractComponent#getTag() - */ - public String getTag() { - return "gridlayout"; - } - - /** - * This class defines an area on a grid. An Area is defined by the cells of - * its upper left corner (column1,row1) and lower right corner - * (column2,row2). - * - * @author IT Mill Ltd. - * @version - * @VERSION@ - * @since 3.0 - */ - public class Area { - - /** - * The column of the upper left corner cell of the area. - */ - private int column1; - - /** - * The row of the upper left corner cell of the area. - */ - private int row1; - - /** - * The column of the lower right corner cell of the area. - */ - private int column2; - - /** - * The row of the lower right corner cell of the area. - */ - private int row2; - - /** - * Component painted on the area. - */ - private Component component; - - /** - *

- * Construct a new area on a grid. - *

- * - * @param component - * the component connected to the area. - * @param column1 - * The column of the upper left corner cell of the area - * c is supposed to occupy. - * @param row1 - * The row of the upper left corner cell of the area - * c is supposed to occupy. - * @param column2 - * The column of the lower right corner cell of the area - * c is supposed to occupy. - * @param row2 - * The row of the lower right corner cell of the area - * c is supposed to occupy. - * @throws OverlapsException - * if the new component overlaps with any of the components - * already in the grid - */ - public Area(Component component, int column1, int row1, int column2, - int row2) { - this.column1 = column1; - this.row1 = row1; - this.column2 = column2; - this.row2 = row2; - this.component = component; - } - - /** - * Tests if the given Area overlaps with an another Area. - * - * @param other - * the Another Area that's to be tested for overlap with this - * area. - * @return true if other overlaps with - * this area, false if it doesn't. - */ - public boolean overlaps(Area other) { - return column1 <= other.getColumn2() && row1 <= other.getRow2() - && column2 >= other.getColumn1() && row2 >= other.getRow1(); - - } - - /** - * Gets the component connected to the area. - * - * @return the Component. - */ - public Component getComponent() { - return component; - } - - /** - * Sets the component connected to the area. - * - *

- * This function only sets the value in the datastructure and does not - * send any events or set parents. - *

- * - * @param newComponent - * the new connected overriding the existing one. - */ - protected void setComponent(Component newComponent) { - component = newComponent; - } - - /** - * @deprecated Use getColumn1() instead. - * - * @see com.itmill.toolkit.ui.GridLayout#getColumn1() - */ - public int getX1() { - return getColumn1(); - } - - /** - * Gets the column of the top-left corner cell. - * - * @return the column of the top-left corner cell. - */ - public int getColumn1() { - return column1; - } - - /** - * @deprecated Use getColumn2() instead. - * - * @see com.itmill.toolkit.ui.GridLayout#getColumn2() - */ - public int getX2() { - return getColumn2(); - } - - /** - * Gets the column of the bottom-right corner cell. - * - * @return the column of the bottom-right corner cell. - */ - public int getColumn2() { - return column2; - } - - /** - * @deprecated Use getRow1() instead. - * - * @see com.itmill.toolkit.ui.GridLayout#getRow1() - */ - public int getY1() { - return getRow1(); - } - - /** - * Gets the row of the top-left corner cell. - * - * @return the row of the top-left corner cell. - */ - public int getRow1() { - return row1; - } - - /** - * @deprecated Use getRow2() instead. - * - * @see com.itmill.toolkit.ui.GridLayout#getRow2() - */ - public int getY2() { - return getRow2(); - } - - /** - * Gets the row of the bottom-right corner cell. - * - * @return the row of the bottom-right corner cell. - */ - public int getRow2() { - return row2; - } - - } - - /** - * An Exception object which is thrown when two Items occupy - * the same space on a grid. - * - * @author IT Mill Ltd. - * @version - * @VERSION@ - * @since 3.0 - */ - public class OverlapsException extends java.lang.RuntimeException { - - /** - * Serial generated by eclipse. - */ - private static final long serialVersionUID = 3978144339870101561L; - - private Area existingArea; - - /** - * Constructs an OverlapsException. - * - * @param existingArea - */ - public OverlapsException(Area existingArea) { - this.existingArea = existingArea; - } - - /** - * Gets the area . - * - * @return the existing area. - */ - public Area getArea() { - return existingArea; - } - } - - /** - * An Exception object which is thrown when an area exceeds - * the bounds of the grid. - * - * @author IT Mill Ltd. - * @version - * @VERSION@ - * @since 3.0 - */ - public class OutOfBoundsException extends java.lang.RuntimeException { - - /** - * Serial generated by eclipse. - */ - private static final long serialVersionUID = 3618985589664592694L; - - private Area areaOutOfBounds; - - /** - * Constructs an OoutOfBoundsException with the specified - * detail message. - * - * @param areaOutOfBounds - */ - public OutOfBoundsException(Area areaOutOfBounds) { - this.areaOutOfBounds = areaOutOfBounds; - } - - /** - * Gets the area that is out of bounds. - * - * @return the area out of Bound. - */ - public Area getArea() { - return areaOutOfBounds; - } - } - - /** - * Sets the width of the layout. - *

- * NOTE: The behaviour of this methdod has changed in - * version 5.0. Now this method won't set the number of columns in the grid - * like it used to (use {@link #setColumns()} for that). Instead, it sets - * the actual visual width of the layout in pixels or in another unit - * specified in {@link Sizeable}.UNIT_SYMBOLS. - *

- */ - public void setWidth(int width) { - super.setWidth(width); - } - - /** - * Gets the width of the layout. - *

- * NOTE: The behaviour of this methdod has changed in - * version 5.0. Now this method won't return the number of columns in the - * grid like it used to (use {@link #getColumns()} for that). Instead, it - * returns the actual visual width of the layout in pixels or in another - * unit specified in {@link Sizeable}.UNIT_SYMBOLS. - *

- */ - public int getWidth() { - return super.getWidth(); - } - - /** - * Sets the number of columns in the grid. The column count can not be - * reduced if there are any areas that would be outside of the shrunk grid. - * - * @param columns - * the new number of columns in the grid. - */ - public void setColumns(int columns) { - - // The the param - if (columns < 1) - throw new IllegalArgumentException( - "The number of columns and rows in the grid must be at least 1"); - - // In case of no change - if (this.cols == columns) - return; - - // Checks for overlaps - if (this.cols > columns) - for (Iterator i = areas.iterator(); i.hasNext();) { - Area area = (Area) i.next(); - if (area.column2 >= columns) - throw new OutOfBoundsException(area); - } - - this.cols = columns; - - requestRepaint(); - } - - /** - * Get the number of columns in the grid. - * - * @return the number of columns in the grid. - */ - public final int getColumns() { - return this.cols; - } - - /** - * Set the height of the layout. - *

- * NOTE: The behaviour of this methdod has changed in - * version 5.0. Now this method won't set the number of rows in the grid - * like it used to (use {@link #setRows()} for that). Instead, it sets the - * actual visual height of the layout in pixels or in another unit specified - * in {@link Sizeable}.UNIT_SYMBOLS. - *

- */ - public void setHeight(int height) { - super.setHeight(height); - } - - /** - * Gets the height of the layout. - *

- * NOTE: The behaviour of this methdod has changed in - * version 5.0. Now this method won't return the number of rows in the grid - * like it used to (use {@link #getRows()} for that). Instead, it returns - * the actual visual height of the layout in pixels or in another unit - * specified in {@link Sizeable}.UNIT_SYMBOLS. - *

- */ - public int getHeight() { - return super.getHeight(); - } - - /** - * Sets the number of rows in the grid. The number of rows can not be - * reduced if there are any areas that would be outside of the shrunk grid. - * - * @param rows - * the new number of rows in the grid. - */ - public void setRows(int rows) { - - // The the param - if (rows < 1) - throw new IllegalArgumentException( - "The number of columns and rows in the grid must be at least 1"); - - // In case of no change - if (this.rows == rows) - return; - - // Checks for overlaps - if (this.rows > rows) - for (Iterator i = areas.iterator(); i.hasNext();) { - Area area = (Area) i.next(); - if (area.row2 >= rows) - throw new OutOfBoundsException(area); - } - - this.rows = rows; - - requestRepaint(); - } - - /** - * Get the number of rows in the grid. - * - * @return the number of rows in the grid. - */ - public final int getRows() { - return this.rows; - } - - /** - * Gets the current cursor x-position. The cursor position points the - * position for the next component that is added without specifying its - * coordinates (grid cell). When the cursor position is occupied, the next - * component will be added to first free position after the cursor. - * - * @return the grid column the Cursor is on. - */ - public int getCursorX() { - return cursorX; - } - - /** - * Gets the current cursor y-position. The cursor position points the - * position for the next component that is added without specifying its - * coordinates (grid cell). When the cursor position is occupied, the next - * component will be added to first free position after the cursor. - * - * @return the grid row the Cursor is on. - */ - public int getCursorY() { - return cursorY; - } - - /* Documented in superclass */ - public void replaceComponent(Component oldComponent, Component newComponent) { - - // Gets the locations - Area oldLocation = null; - Area newLocation = null; - for (Iterator i = areas.iterator(); i.hasNext();) { - Area location = (Area) i.next(); - Component component = (Component) location.getComponent(); - if (component == oldComponent) - oldLocation = location; - if (component == newComponent) - newLocation = location; - } - - if (oldLocation == null) - addComponent(newComponent); - else if (newLocation == null) { - removeComponent(oldComponent); - addComponent(newComponent, oldLocation.getColumn1(), oldLocation - .getRow1(), oldLocation.getColumn2(), oldLocation.getRow2()); - } else { - oldLocation.setComponent(newComponent); - newLocation.setComponent(oldComponent); - requestRepaint(); - } - } - - /* - * Removes all components from this container. - * - * @see com.itmill.toolkit.ui.ComponentContainer#removeAllComponents() - */ - public void removeAllComponents() { - super.removeAllComponents(); - this.componentToAlignment = new HashMap(); - this.cursorX = 0; - this.cursorY = 0; - } - - /** - * Set alignment for one contained component in this layout. - * - * @param childComponent - * the component to align within it's layout cell. - * @param horizontalAlignment - * the horizontal alignment for the child component (left, - * center, right). - * @param verticalAlignment - * the vertical alignment for the child component (top, center, - * bottom). - */ - public void setComponentAlignment(Component childComponent, - int horizontalAlignment, int verticalAlignment) { - componentToAlignment.put(childComponent, new Integer( - horizontalAlignment + verticalAlignment)); - } - - /** - * Enable spacing between child components within this layout. - * - *

- * NOTE: This will only affect spaces between components, - * not also all around spacing of the layout (i.e. do not mix this with HTML - * Table elements cellspacing-attribute). Use {@link #setMargin(boolean)} to - * add extra space around the layout. - *

- * - * @param enabled - */ - public void setSpacing(boolean enabled) { - this.spacing = enabled; - } + /** + * Initial grid columns. + */ + private int cols = 0; + + /** + * Initial grid rows. + */ + private int rows = 0; + + /** + * Cursor X position: this is where the next component with unspecified x,y + * is inserted + */ + private int cursorX = 0; + + /** + * Cursor Y position: this is where the next component with unspecified x,y + * is inserted + */ + private int cursorY = 0; + + /** + * Contains all items that are placed on the grid. These are components with + * grid area definition. + */ + private LinkedList areas = new LinkedList(); + + /** + * Mapping from components to their respective areas. + */ + private LinkedList components = new LinkedList(); + + /** + * Mapping from components to alignments (horizontal + vertical). + */ + private Map componentToAlignment = new HashMap(); + + /** + * Contained component should be aligned horizontally to the left. + */ + public static final int ALIGNMENT_LEFT = AlignmentInfo.ALIGNMENT_LEFT; + + /** + * Contained component should be aligned horizontally to the right. + */ + public static final int ALIGNMENT_RIGHT = AlignmentInfo.ALIGNMENT_RIGHT; + + /** + * Contained component should be aligned vertically to the top. + */ + public static final int ALIGNMENT_TOP = AlignmentInfo.ALIGNMENT_TOP; + + /** + * Contained component should be aligned vertically to the bottom. + */ + public static final int ALIGNMENT_BOTTOM = AlignmentInfo.ALIGNMENT_BOTTOM; + + /** + * Contained component should be horizontally aligned to center. + */ + public static final int ALIGNMENT_HORIZONTAL_CENTER = AlignmentInfo.ALIGNMENT_HORIZONTAL_CENTER; + + /** + * Contained component should be vertically aligned to center. + */ + public static final int ALIGNMENT_VERTICAL_CENTER = AlignmentInfo.ALIGNMENT_VERTICAL_CENTER; + + /** + * Is spacing between contained components enabled. Defaults to false. + */ + private boolean spacing = false; + + /** + * Constructor for grid of given size (number of cells). Note that grid's + * final size depends on the items that are added into the grid. Grid grows + * if you add components outside the grid's area. + * + * @param columns + * Number of columns in the grid. + * @param rows + * Number of rows in the grid. + */ + public GridLayout(int columns, int rows) { + setColumns(columns); + setRows(rows); + } + + /** + * Constructs an empty grid layout that is extended as needed. + */ + public GridLayout() { + this(1, 1); + } + + /** + *

+ * Adds a component with a specified area to the grid. The area the new + * component should take is defined by specifying the upper left corner + * (column1, row1) and the lower right corner (column2, row2) of the area. + *

+ * + *

+ * If the new component overlaps with any of the existing components already + * present in the grid the operation will fail and an + * {@link OverlapsException} is thrown. + *

+ * + * @param c + * the component to be added. + * @param column1 + * the column of the upper left corner of the area + * c is supposed to occupy. + * @param row1 + * the row of the upper left corner of the area + * c is supposed to occupy. + * @param column2 + * the column of the lower right corner of the area + * c is supposed to occupy. + * @param row2 + * the row of the lower right corner of the area + * c is supposed to occupy. + * @throws OverlapsException + * if the new component overlaps with any of the components + * already in the grid. + * @throws OutOfBoundsException + * if the cells are outside of the grid area. + */ + public void addComponent(Component component, int column1, int row1, + int column2, int row2) throws OverlapsException, + OutOfBoundsException { + + if (component == null) { + throw new NullPointerException("Component must not be null"); + } + + // Checks that the component does not already exist in the container + if (components.contains(component)) { + throw new IllegalArgumentException( + "Component is already in the container"); + } + + // Creates the area + Area area = new Area(component, column1, row1, column2, row2); + + // Checks the validity of the coordinates + if (column2 < column1 || row2 < row1) { + throw new IllegalArgumentException( + "Illegal coordinates for the component"); + } + if (column1 < 0 || row1 < 0 || column2 >= cols || row2 >= rows) { + throw new OutOfBoundsException(area); + } + + // Checks that newItem does not overlap with existing items + checkExistingOverlaps(area); + + // Inserts the component to right place at the list + // Respect top-down, left-right ordering + component.setParent(this); + Iterator i = areas.iterator(); + int index = 0; + boolean done = false; + while (!done && i.hasNext()) { + Area existingArea = (Area) i.next(); + if ((existingArea.row1 >= row1 && existingArea.column1 > column1) + || existingArea.row1 > row1) { + areas.add(index, area); + components.add(index, component); + done = true; + } + index++; + } + if (!done) { + areas.addLast(area); + components.addLast(component); + } + + super.addComponent(component); + requestRepaint(); + } + + /** + * Tests if the given area overlaps with any of the items already on the + * grid. + * + * @param area + * the Area to be checked for overlapping. + * @throws OverlapsException + * if area overlaps with any existing area. + */ + private void checkExistingOverlaps(Area area) throws OverlapsException { + for (Iterator i = areas.iterator(); i.hasNext();) { + Area existingArea = (Area) i.next(); + if (existingArea.overlaps(area)) { + // Component not added, overlaps with existing component + throw new OverlapsException(existingArea); + } + } + } + + /** + * Adds the component into this container to cells column1,row1 (NortWest + * corner of the area.) End coordinates (SouthEast corner of the area) are + * the same as column1,row1. Component width and height is 1. + * + * @param c + * the component to be added. + * @param column + * the column index. + * @param row + * the row index. + */ + public void addComponent(Component c, int column, int row) { + this.addComponent(c, column, row, column, row); + } + + /** + * Force the next component to be added to the beginning of the next line. + * By calling this function user can ensure that no more components are + * added to the right of the previous component. + * + * @see #space() + */ + public void newLine() { + cursorX = 0; + cursorY++; + } + + /** + * Moves the cursor forwards by one. If the cursor goes out of the right + * grid border, move it to next line. + * + * @see #newLine() + */ + public void space() { + cursorX++; + if (cursorX >= cols) { + cursorX = 0; + cursorY++; + } + } + + /** + * Adds the component into this container to the cursor position. If the + * cursor position is already occupied, the cursor is moved forwards to find + * free position. If the cursor goes out from the bottom of the grid, the + * grid is automatically extended. + * + * @param c + * the component to be added. + */ + public void addComponent(Component component) { + + // Finds first available place from the grid + Area area; + boolean done = false; + while (!done) { + try { + area = new Area(component, cursorX, cursorY, cursorX, cursorY); + checkExistingOverlaps(area); + done = true; + } catch (OverlapsException ignored) { + space(); + } + } + + // Extends the grid if needed + cols = cursorX >= cols ? cursorX + 1 : cols; + rows = cursorY >= rows ? cursorY + 1 : rows; + + addComponent(component, cursorX, cursorY); + } + + /** + * Removes the given component from this container. + * + * @param c + * the component to be removed. + */ + public void removeComponent(Component component) { + + // Check that the component is contained in the container + if (component == null || !components.contains(component)) { + return; + } + + super.removeComponent(component); + + Area area = null; + for (Iterator i = areas.iterator(); area == null && i.hasNext();) { + Area a = (Area) i.next(); + if (a.getComponent() == component) { + area = a; + } + } + + components.remove(component); + if (area != null) { + areas.remove(area); + } + + componentToAlignment.remove(component); + + requestRepaint(); + } + + /** + * Removes the component specified with it's cell index. + * + * @param column + * the Component's column. + * @param row + * the Component's row. + */ + public void removeComponent(int column, int row) { + + // Finds the area + for (Iterator i = areas.iterator(); i.hasNext();) { + Area area = (Area) i.next(); + if (area.getColumn1() == column && area.getRow1() == row) { + removeComponent(area.getComponent()); + return; + } + } + } + + /** + * Gets an Iterator to the component container contents. Using the Iterator + * it's possible to step through the contents of the container. + * + * @return the Iterator of the components inside the container. + */ + public Iterator getComponentIterator() { + return Collections.unmodifiableCollection(components).iterator(); + } + + /** + * Paints the contents of this component. + * + * @param target + * the Paint Event. + * @throws PaintException + * if the paint operation failed. + */ + public void paintContent(PaintTarget target) throws PaintException { + + super.paintContent(target); + + // TODO refactor attribute names in future release. + target.addAttribute("h", rows); + target.addAttribute("w", cols); + + if (spacing) { + target.addAttribute("spacing", spacing); + } + + // Area iterator + Iterator areaiterator = areas.iterator(); + + // Current item to be processed (fetch first item) + Area area = areaiterator.hasNext() ? (Area) areaiterator.next() : null; + + // Collects rowspan related information here + HashMap cellUsed = new HashMap(); + + // Empty cell collector + int emptyCells = 0; + + // Iterates every applicable row + for (int cury = 0; cury < rows; cury++) { + target.startTag("gr"); + + // Iterates every applicable column + for (int curx = 0; curx < cols; curx++) { + + // Checks if current item is located at curx,cury + if (area != null && (area.row1 == cury) + && (area.column1 == curx)) { + + // First check if empty cell needs to be rendered + if (emptyCells > 0) { + target.startTag("gc"); + target.addAttribute("x", curx - emptyCells); + target.addAttribute("y", cury); + if (emptyCells > 1) { + target.addAttribute("w", emptyCells); + } + target.endTag("gc"); + emptyCells = 0; + } + + // Now proceed rendering current item + int cols = (area.column2 - area.column1) + 1; + int rows = (area.row2 - area.row1) + 1; + target.startTag("gc"); + + target.addAttribute("x", curx); + target.addAttribute("y", cury); + + if (cols > 1) { + target.addAttribute("w", cols); + } + if (rows > 1) { + target.addAttribute("h", rows); + } + area.getComponent().paint(target); + + target.endTag("gc"); + + // Fetch next item + if (areaiterator.hasNext()) { + area = (Area) areaiterator.next(); + } else { + area = null; + } + + // Updates the cellUsed if rowspan needed + if (rows > 1) { + int spannedx = curx; + for (int j = 1; j <= cols; j++) { + cellUsed.put(new Integer(spannedx), new Integer( + cury + rows - 1)); + spannedx++; + } + } + + // Skips the current item's spanned columns + if (cols > 1) { + curx += cols - 1; + } + + } else { + + // Checks against cellUsed, render space or ignore cell + if (cellUsed.containsKey(new Integer(curx))) { + + // Current column contains already an item, + // check if rowspan affects at current x,y position + int rowspanDepth = ((Integer) cellUsed.get(new Integer( + curx))).intValue(); + + if (rowspanDepth >= cury) { + + // ignore cell + // Check if empty cell needs to be rendered + if (emptyCells > 0) { + target.startTag("gc"); + target.addAttribute("x", curx - emptyCells); + target.addAttribute("y", cury); + if (emptyCells > 1) { + target.addAttribute("w", emptyCells); + } + target.endTag("gc"); + + emptyCells = 0; + } + } else { + + // empty cell is needed + emptyCells++; + + // Removes the cellUsed key as it has become + // obsolete + cellUsed.remove(new Integer(curx)); + } + } else { + + // empty cell is needed + emptyCells++; + } + } + + } // iterates every column + + // Last column handled of current row + + // Checks if empty cell needs to be rendered + if (emptyCells > 0) { + target.startTag("gc"); + target.addAttribute("x", cols - emptyCells); + target.addAttribute("y", cury); + if (emptyCells > 1) { + target.addAttribute("w", emptyCells); + } + target.endTag("gc"); + + emptyCells = 0; + } + + target.endTag("gr"); + } // iterates every row + + // Last row handled + } + + /** + * Gets the components UIDL tag. + * + * @return the Component UIDL tag as string. + * @see com.itmill.toolkit.ui.AbstractComponent#getTag() + */ + public String getTag() { + return "gridlayout"; + } + + /** + * This class defines an area on a grid. An Area is defined by the cells of + * its upper left corner (column1,row1) and lower right corner + * (column2,row2). + * + * @author IT Mill Ltd. + * @version + * @VERSION@ + * @since 3.0 + */ + public class Area { + + /** + * The column of the upper left corner cell of the area. + */ + private int column1; + + /** + * The row of the upper left corner cell of the area. + */ + private int row1; + + /** + * The column of the lower right corner cell of the area. + */ + private int column2; + + /** + * The row of the lower right corner cell of the area. + */ + private int row2; + + /** + * Component painted on the area. + */ + private Component component; + + /** + *

+ * Construct a new area on a grid. + *

+ * + * @param component + * the component connected to the area. + * @param column1 + * The column of the upper left corner cell of the area + * c is supposed to occupy. + * @param row1 + * The row of the upper left corner cell of the area + * c is supposed to occupy. + * @param column2 + * The column of the lower right corner cell of the area + * c is supposed to occupy. + * @param row2 + * The row of the lower right corner cell of the area + * c is supposed to occupy. + * @throws OverlapsException + * if the new component overlaps with any of the + * components already in the grid + */ + public Area(Component component, int column1, int row1, int column2, + int row2) { + this.column1 = column1; + this.row1 = row1; + this.column2 = column2; + this.row2 = row2; + this.component = component; + } + + /** + * Tests if the given Area overlaps with an another Area. + * + * @param other + * the Another Area that's to be tested for overlap with + * this area. + * @return true if other overlaps with + * this area, false if it doesn't. + */ + public boolean overlaps(Area other) { + return column1 <= other.getColumn2() && row1 <= other.getRow2() + && column2 >= other.getColumn1() && row2 >= other.getRow1(); + + } + + /** + * Gets the component connected to the area. + * + * @return the Component. + */ + public Component getComponent() { + return component; + } + + /** + * Sets the component connected to the area. + * + *

+ * This function only sets the value in the datastructure and does not + * send any events or set parents. + *

+ * + * @param newComponent + * the new connected overriding the existing one. + */ + protected void setComponent(Component newComponent) { + component = newComponent; + } + + /** + * @deprecated Use getColumn1() instead. + * + * @see com.itmill.toolkit.ui.GridLayout#getColumn1() + */ + public int getX1() { + return getColumn1(); + } + + /** + * Gets the column of the top-left corner cell. + * + * @return the column of the top-left corner cell. + */ + public int getColumn1() { + return column1; + } + + /** + * @deprecated Use getColumn2() instead. + * + * @see com.itmill.toolkit.ui.GridLayout#getColumn2() + */ + public int getX2() { + return getColumn2(); + } + + /** + * Gets the column of the bottom-right corner cell. + * + * @return the column of the bottom-right corner cell. + */ + public int getColumn2() { + return column2; + } + + /** + * @deprecated Use getRow1() instead. + * + * @see com.itmill.toolkit.ui.GridLayout#getRow1() + */ + public int getY1() { + return getRow1(); + } + + /** + * Gets the row of the top-left corner cell. + * + * @return the row of the top-left corner cell. + */ + public int getRow1() { + return row1; + } + + /** + * @deprecated Use getRow2() instead. + * + * @see com.itmill.toolkit.ui.GridLayout#getRow2() + */ + public int getY2() { + return getRow2(); + } + + /** + * Gets the row of the bottom-right corner cell. + * + * @return the row of the bottom-right corner cell. + */ + public int getRow2() { + return row2; + } + + } + + /** + * An Exception object which is thrown when two Items occupy + * the same space on a grid. + * + * @author IT Mill Ltd. + * @version + * @VERSION@ + * @since 3.0 + */ + public class OverlapsException extends java.lang.RuntimeException { + + /** + * Serial generated by eclipse. + */ + private static final long serialVersionUID = 3978144339870101561L; + + private Area existingArea; + + /** + * Constructs an OverlapsException. + * + * @param existingArea + */ + public OverlapsException(Area existingArea) { + this.existingArea = existingArea; + } + + /** + * Gets the area . + * + * @return the existing area. + */ + public Area getArea() { + return existingArea; + } + } + + /** + * An Exception object which is thrown when an area exceeds + * the bounds of the grid. + * + * @author IT Mill Ltd. + * @version + * @VERSION@ + * @since 3.0 + */ + public class OutOfBoundsException extends java.lang.RuntimeException { + + /** + * Serial generated by eclipse. + */ + private static final long serialVersionUID = 3618985589664592694L; + + private Area areaOutOfBounds; + + /** + * Constructs an OoutOfBoundsException with the specified + * detail message. + * + * @param areaOutOfBounds + */ + public OutOfBoundsException(Area areaOutOfBounds) { + this.areaOutOfBounds = areaOutOfBounds; + } + + /** + * Gets the area that is out of bounds. + * + * @return the area out of Bound. + */ + public Area getArea() { + return areaOutOfBounds; + } + } + + /** + * Sets the width of the layout. + *

+ * NOTE: The behaviour of this methdod has changed in + * version 5.0. Now this method won't set the number of columns in the grid + * like it used to (use {@link #setColumns()} for that). Instead, it sets + * the actual visual width of the layout in pixels or in another unit + * specified in {@link Sizeable}.UNIT_SYMBOLS. + *

+ */ + public void setWidth(int width) { + super.setWidth(width); + } + + /** + * Gets the width of the layout. + *

+ * NOTE: The behaviour of this methdod has changed in + * version 5.0. Now this method won't return the number of columns in the + * grid like it used to (use {@link #getColumns()} for that). Instead, it + * returns the actual visual width of the layout in pixels or in another + * unit specified in {@link Sizeable}.UNIT_SYMBOLS. + *

+ */ + public int getWidth() { + return super.getWidth(); + } + + /** + * Sets the number of columns in the grid. The column count can not be + * reduced if there are any areas that would be outside of the shrunk grid. + * + * @param columns + * the new number of columns in the grid. + */ + public void setColumns(int columns) { + + // The the param + if (columns < 1) { + throw new IllegalArgumentException( + "The number of columns and rows in the grid must be at least 1"); + } + + // In case of no change + if (cols == columns) { + return; + } + + // Checks for overlaps + if (cols > columns) { + for (Iterator i = areas.iterator(); i.hasNext();) { + Area area = (Area) i.next(); + if (area.column2 >= columns) { + throw new OutOfBoundsException(area); + } + } + } + + cols = columns; + + requestRepaint(); + } + + /** + * Get the number of columns in the grid. + * + * @return the number of columns in the grid. + */ + public final int getColumns() { + return cols; + } + + /** + * Set the height of the layout. + *

+ * NOTE: The behaviour of this methdod has changed in + * version 5.0. Now this method won't set the number of rows in the grid + * like it used to (use {@link #setRows()} for that). Instead, it sets the + * actual visual height of the layout in pixels or in another unit specified + * in {@link Sizeable}.UNIT_SYMBOLS. + *

+ */ + public void setHeight(int height) { + super.setHeight(height); + } + + /** + * Gets the height of the layout. + *

+ * NOTE: The behaviour of this methdod has changed in + * version 5.0. Now this method won't return the number of rows in the grid + * like it used to (use {@link #getRows()} for that). Instead, it returns + * the actual visual height of the layout in pixels or in another unit + * specified in {@link Sizeable}.UNIT_SYMBOLS. + *

+ */ + public int getHeight() { + return super.getHeight(); + } + + /** + * Sets the number of rows in the grid. The number of rows can not be + * reduced if there are any areas that would be outside of the shrunk grid. + * + * @param rows + * the new number of rows in the grid. + */ + public void setRows(int rows) { + + // The the param + if (rows < 1) { + throw new IllegalArgumentException( + "The number of columns and rows in the grid must be at least 1"); + } + + // In case of no change + if (this.rows == rows) { + return; + } + + // Checks for overlaps + if (this.rows > rows) { + for (Iterator i = areas.iterator(); i.hasNext();) { + Area area = (Area) i.next(); + if (area.row2 >= rows) { + throw new OutOfBoundsException(area); + } + } + } + + this.rows = rows; + + requestRepaint(); + } + + /** + * Get the number of rows in the grid. + * + * @return the number of rows in the grid. + */ + public final int getRows() { + return rows; + } + + /** + * Gets the current cursor x-position. The cursor position points the + * position for the next component that is added without specifying its + * coordinates (grid cell). When the cursor position is occupied, the next + * component will be added to first free position after the cursor. + * + * @return the grid column the Cursor is on. + */ + public int getCursorX() { + return cursorX; + } + + /** + * Gets the current cursor y-position. The cursor position points the + * position for the next component that is added without specifying its + * coordinates (grid cell). When the cursor position is occupied, the next + * component will be added to first free position after the cursor. + * + * @return the grid row the Cursor is on. + */ + public int getCursorY() { + return cursorY; + } + + /* Documented in superclass */ + public void replaceComponent(Component oldComponent, Component newComponent) { + + // Gets the locations + Area oldLocation = null; + Area newLocation = null; + for (Iterator i = areas.iterator(); i.hasNext();) { + Area location = (Area) i.next(); + Component component = location.getComponent(); + if (component == oldComponent) { + oldLocation = location; + } + if (component == newComponent) { + newLocation = location; + } + } + + if (oldLocation == null) { + addComponent(newComponent); + } else if (newLocation == null) { + removeComponent(oldComponent); + addComponent(newComponent, oldLocation.getColumn1(), oldLocation + .getRow1(), oldLocation.getColumn2(), oldLocation.getRow2()); + } else { + oldLocation.setComponent(newComponent); + newLocation.setComponent(oldComponent); + requestRepaint(); + } + } + + /* + * Removes all components from this container. + * + * @see com.itmill.toolkit.ui.ComponentContainer#removeAllComponents() + */ + public void removeAllComponents() { + super.removeAllComponents(); + componentToAlignment = new HashMap(); + cursorX = 0; + cursorY = 0; + } + + /** + * Set alignment for one contained component in this layout. + * + * @param childComponent + * the component to align within it's layout cell. + * @param horizontalAlignment + * the horizontal alignment for the child component (left, + * center, right). + * @param verticalAlignment + * the vertical alignment for the child component (top, + * center, bottom). + */ + public void setComponentAlignment(Component childComponent, + int horizontalAlignment, int verticalAlignment) { + componentToAlignment.put(childComponent, new Integer( + horizontalAlignment + verticalAlignment)); + } + + /** + * Enable spacing between child components within this layout. + * + *

+ * NOTE: This will only affect spaces between components, + * not also all around spacing of the layout (i.e. do not mix this with HTML + * Table elements cellspacing-attribute). Use {@link #setMargin(boolean)} to + * add extra space around the layout. + *

+ * + * @param enabled + */ + public void setSpacing(boolean enabled) { + spacing = enabled; + } } diff --git a/src/com/itmill/toolkit/ui/Label.java b/src/com/itmill/toolkit/ui/Label.java index 1a3684fbe7..30a8ceaebc 100644 --- a/src/com/itmill/toolkit/ui/Label.java +++ b/src/com/itmill/toolkit/ui/Label.java @@ -61,485 +61,499 @@ import com.itmill.toolkit.terminal.PaintTarget; * @since 3.0 */ public class Label extends AbstractComponent implements Property, - Property.Viewer, Property.ValueChangeListener, - Property.ValueChangeNotifier, Comparable { - - /** - * Content mode, where the label contains only plain text. The getValue() - * result is coded to XML when painting. - */ - public static final int CONTENT_TEXT = 0; - - /** - * Content mode, where the label contains preformatted text. - */ - public static final int CONTENT_PREFORMATTED = 1; - - /** - * Formatted content mode, where the contents is XML restricted to the UIDL - * 1.0 formatting markups. - */ - public static final int CONTENT_UIDL = 2; - - /** - * Content mode, where the label contains XHTML. Contents is then enclosed - * in DIV elements having namespace of - * "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd". - */ - public static final int CONTENT_XHTML = 3; - - /** - * Content mode, where the label contains well-formed or well-balanced XML. - * Each of the root elements must have their default namespace specified. - */ - public static final int CONTENT_XML = 4; - - /** - * Content mode, where the label contains RAW output. Output is not required - * to comply to with XML. In Web Adapter output is inserted inside the - * resulting HTML document as-is. This is useful for some specific purposes - * where possibly broken HTML content needs to be shown, but in most cases - * XHTML mode should be preferred. - */ - public static final int CONTENT_RAW = 5; - - /** - * The default content mode is plain text. - */ - public static final int CONTENT_DEFAULT = CONTENT_TEXT; - - /** Array of content mode names that are rendered in UIDL as mode attribute. */ - private static final String[] CONTENT_MODE_NAME = { "text", "pre", "uidl", - "xhtml", "xml", "raw" }; - - private Property dataSource; - - private int contentMode = CONTENT_DEFAULT; - - /** - * Creates an empty Label. - */ - public Label() { - setPropertyDataSource(new ObjectProperty("", String.class)); - } - - /** - * Creates a new instance of Label with text-contents. - * - * @param content - */ - public Label(String content) { - setPropertyDataSource(new ObjectProperty(content, String.class)); - } - - /** - * Creates a new instance of Label with text-contents read from given - * datasource. - * - * @param contentSource - */ - public Label(Property contentSource) { - setPropertyDataSource(contentSource); - } - - /** - * Creates a new instance of Label with text-contents. - * - * @param content - * @param contentMode - */ - public Label(String content, int contentMode) { - setPropertyDataSource(new ObjectProperty(content, String.class)); - setContentMode(contentMode); - } - - /** - * Creates a new instance of Label with text-contents read from given - * datasource. - * - * @param contentSource - * @param contentMode - */ - public Label(Property contentSource, int contentMode) { - setPropertyDataSource(contentSource); - setContentMode(contentMode); - } - - /** - * Get the component UIDL tag. - * - * @return the Component UIDL tag as string. - */ - public String getTag() { - return "label"; - } - - /** - * Set the component to read-only. Readonly is not used in label. - * - * @param readOnly - * True to enable read-only mode, False to disable it. - */ - public void setReadOnly(boolean readOnly) { - if (dataSource == null) - throw new IllegalStateException("Datasource must be se"); - dataSource.setReadOnly(readOnly); - } - - /** - * Is the component read-only ? Readonly is not used in label - this returns - * allways false. - * - * @return true if the component is in read only mode. - */ - public boolean isReadOnly() { - if (dataSource == null) - throw new IllegalStateException("Datasource must be se"); - return dataSource.isReadOnly(); - } - - /** - * Paints the content of this component. - * - * @param target - * the Paint Event. - * @throws PaintException - * if the Paint Operation fails. - */ - public void paintContent(PaintTarget target) throws PaintException { - if (contentMode != CONTENT_TEXT) - target.addAttribute("mode", CONTENT_MODE_NAME[contentMode]); - if (contentMode == CONTENT_TEXT) - target.addText(toString()); - else if (contentMode == CONTENT_UIDL) - target.addUIDL(toString()); - else if (contentMode == CONTENT_XHTML) { - target.startTag("data"); - target.addXMLSection("div", toString(), - "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"); - target.endTag("data"); - } else if (contentMode == CONTENT_PREFORMATTED) { - target.startTag("pre"); - target.addText(toString()); - target.endTag("pre"); - } else if (contentMode == CONTENT_XML) { - target.addXMLSection("data", toString(), null); - } else if (contentMode == CONTENT_RAW) { - target.startTag("data"); - target.addAttribute("escape", false); - target.addCharacterData(toString()); - target.endTag("data"); - } - - } - - /** - * Gets the value of the label. Value of the label is the XML contents of - * the label. - * - * @return the Value of the label. - */ - public Object getValue() { - if (dataSource == null) - throw new IllegalStateException("Datasource must be se"); - return dataSource.getValue(); - } - - /** - * Set the value of the label. Value of the label is the XML contents of the - * label. - * - * @param newValue - * the New value of the label. - */ - public void setValue(Object newValue) { - if (dataSource == null) - throw new IllegalStateException("Datasource must be se"); - this.dataSource.setValue(newValue); - } - - /** - * @see java.lang.Object#toString() - */ - public String toString() { - if (dataSource == null) - throw new IllegalStateException("Datasource must be se"); - return dataSource.toString(); - } - - /** - * Gets the type of the Property. - * - * @see com.itmill.toolkit.data.Property#getType() - */ - public Class getType() { - if (dataSource == null) - throw new IllegalStateException("Datasource must be se"); - return dataSource.getType(); - } - - /** - * Gets the viewing data-source property. - * - * @return the data source property. - * @see com.itmill.toolkit.data.Property.Viewer#getPropertyDataSource() - */ - public Property getPropertyDataSource() { - return dataSource; - } - - /** - * Sets the property as data-source for viewing. - * - * @param newDataSource - * the new data source Property - * @see com.itmill.toolkit.data.Property.Viewer#setPropertyDataSource(com.itmill.toolkit.data.Property) - */ - public void setPropertyDataSource(Property newDataSource) { - // Stops listening the old data source changes - if (dataSource != null - && Property.ValueChangeNotifier.class - .isAssignableFrom(dataSource.getClass())) - ((Property.ValueChangeNotifier) dataSource).removeListener(this); - - // Sets the new data source - dataSource = newDataSource; - - // Listens the new data source if possible - if (dataSource != null - && Property.ValueChangeNotifier.class - .isAssignableFrom(dataSource.getClass())) - ((Property.ValueChangeNotifier) dataSource).addListener(this); - } - - /** - * Gets the content mode of the Label. - * - *

- * Possible content modes include: - *

    - *
  • CONTENT_TEXT Content mode, where the label contains only - * plain text. The getValue() result is coded to XML when painting.
  • - *
  • CONTENT_PREFORMATTED Content mode, where the label contains - * preformatted text.
  • - *
  • CONTENT_UIDL Formatted content mode, where the contents is - * XML restricted to the UIDL 1.0 formatting markups.
  • - *
  • CONTENT_XHTML Content mode, where the label contains XHTML. - * Contents is then enclosed in DIV elements having namespace of - * "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd".
  • - *
  • CONTENT_XML Content mode, where the label contains - * well-formed or well-balanced XML. Each of the root elements must have - * their default namespace specified.
  • - *
  • CONTENT_RAW Content mode, where the label contains RAW - * output. Output is not required to comply to with XML. In Web Adapter - * output is inserted inside the resulting HTML document as-is. This is - * useful for some specific purposes where possibly broken HTML content - * needs to be shown, but in most cases XHTML mode should be preferred.
  • - *
- *

- * - * @return the Content mode of the label. - */ - public int getContentMode() { - return contentMode; - } - - /** - * Sets the content mode of the Label. - * - *

- * Possible content modes include: - *

    - *
  • CONTENT_TEXT Content mode, where the label contains only - * plain text. The getValue() result is coded to XML when painting.
  • - *
  • CONTENT_PREFORMATTED Content mode, where the label contains - * preformatted text.
  • - *
  • CONTENT_UIDL Formatted content mode, where the contents is - * XML restricted to the UIDL 1.0 formatting markups.
  • - *
  • CONTENT_XHTML Content mode, where the label contains XHTML. - * Contents is then enclosed in DIV elements having namespace of - * "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd".
  • - *
  • CONTENT_XML Content mode, where the label contains - * well-formed or well-balanced XML. Each of the root elements must have - * their default namespace specified.
  • - *
  • CONTENT_RAW Content mode, where the label contains RAW - * output. Output is not required to comply to with XML. In Web Adapter - * output is inserted inside the resulting HTML document as-is. This is - * useful for some specific purposes where possibly broken HTML content - * needs to be shown, but in most cases XHTML mode should be preferred.
  • - *
- *

- * - * @param contentMode - * the New content mode of the label. - */ - public void setContentMode(int contentMode) { - if (contentMode >= CONTENT_TEXT && contentMode <= CONTENT_RAW) - this.contentMode = contentMode; - } - - /* Value change events ****************************************** */ - - private static final Method VALUE_CHANGE_METHOD; - - static { - try { - VALUE_CHANGE_METHOD = Property.ValueChangeListener.class - .getDeclaredMethod("valueChange", - new Class[] { Property.ValueChangeEvent.class }); - } catch (java.lang.NoSuchMethodException e) { - // This should never happen - throw new java.lang.RuntimeException(); - } - } - - /** - * Value change event - * - * @author IT Mill Ltd. - * @version - * @VERSION@ - * @since 3.0 - */ - public class ValueChangeEvent extends Component.Event implements - Property.ValueChangeEvent { - - /** - * Serial generated by eclipse. - */ - private static final long serialVersionUID = 3906084563938586935L; - - /** - * New instance of text change event - * - * @param source - * the Source of the event. - */ - public ValueChangeEvent(Label source) { - super(source); - } - - /** - * Gets the Property that has been modified. - * - * @see com.itmill.toolkit.data.Property.ValueChangeEvent#getProperty() - */ - public Property getProperty() { - return (Property) getSource(); - } - } - - /** - * Adds the value change listener. - * - * @param listener - * the Listener to be added. - * @see com.itmill.toolkit.data.Property.ValueChangeNotifier#addListener(com.itmill.toolkit.data.Property.ValueChangeListener) - */ - public void addListener(Property.ValueChangeListener listener) { - addListener(Label.ValueChangeEvent.class, listener, VALUE_CHANGE_METHOD); - } - - /** - * Removes the value change listener. - * - * @param listener - * the Listener to be removed. - * @see com.itmill.toolkit.data.Property.ValueChangeNotifier#removeListener(com.itmill.toolkit.data.Property.ValueChangeListener) - */ - public void removeListener(Property.ValueChangeListener listener) { - removeListener(Label.ValueChangeEvent.class, listener, - VALUE_CHANGE_METHOD); - } - - /** - * Emits the options change event. - */ - protected void fireValueChange() { - // Set the error message - fireEvent(new Label.ValueChangeEvent(this)); - requestRepaint(); - } - - /** - * Listens the value change events from data source. - * - * @see com.itmill.toolkit.data.Property.ValueChangeListener#valueChange(Property.ValueChangeEvent) - */ - public void valueChange(Property.ValueChangeEvent event) { - fireValueChange(); - } - - /** - * Compares the Label to other objects. - * - *

- * Labels can be compared to other labels for sorting label contents. This - * is especially handy for sorting table columns. - *

- * - *

- * In RAW, PREFORMATTED and TEXT modes, the label contents are compared as - * is. In XML, UIDL and XHTML modes, only CDATA is compared and tags - * ignored. If the other object is not a Label, its toString() return value - * is used in comparison. - *

- * - * @param other - * the Other object to compare to. - * @return a negative integer, zero, or a positive integer as this object is - * less than, equal to, or greater than the specified object. - * @see java.lang.Comparable#compareTo(java.lang.Object) - */ - public int compareTo(Object other) { - - String thisValue; - String otherValue; - - if (contentMode == CONTENT_XML || contentMode == CONTENT_UIDL - || contentMode == CONTENT_XHTML) - thisValue = stripTags(toString()); - else - thisValue = toString(); - - if (other instanceof Label - && (((Label) other).getContentMode() == CONTENT_XML - || ((Label) other).getContentMode() == CONTENT_UIDL || ((Label) other) - .getContentMode() == CONTENT_XHTML)) - otherValue = stripTags(other.toString()); - else - otherValue = other.toString(); - - return thisValue.compareTo(otherValue); - } - - /** - * Strips the tags from the XML. - * - * @param xml - * the String containing a XML snippet. - * @return the original XML without tags. - */ - private String stripTags(String xml) { - - StringBuffer res = new StringBuffer(); - - int processed = 0; - int xmlLen = xml.length(); - while (processed < xmlLen) { - int next = xml.indexOf('<', processed); - if (next < 0) - next = xmlLen; - res.append(xml.substring(processed, next)); - if (processed < xmlLen) { - next = xml.indexOf('>', processed); - if (next < 0) - next = xmlLen; - processed = next + 1; - } - } - - return res.toString(); - } + Property.Viewer, Property.ValueChangeListener, + Property.ValueChangeNotifier, Comparable { + + /** + * Content mode, where the label contains only plain text. The getValue() + * result is coded to XML when painting. + */ + public static final int CONTENT_TEXT = 0; + + /** + * Content mode, where the label contains preformatted text. + */ + public static final int CONTENT_PREFORMATTED = 1; + + /** + * Formatted content mode, where the contents is XML restricted to the UIDL + * 1.0 formatting markups. + */ + public static final int CONTENT_UIDL = 2; + + /** + * Content mode, where the label contains XHTML. Contents is then enclosed + * in DIV elements having namespace of + * "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd". + */ + public static final int CONTENT_XHTML = 3; + + /** + * Content mode, where the label contains well-formed or well-balanced XML. + * Each of the root elements must have their default namespace specified. + */ + public static final int CONTENT_XML = 4; + + /** + * Content mode, where the label contains RAW output. Output is not required + * to comply to with XML. In Web Adapter output is inserted inside the + * resulting HTML document as-is. This is useful for some specific purposes + * where possibly broken HTML content needs to be shown, but in most cases + * XHTML mode should be preferred. + */ + public static final int CONTENT_RAW = 5; + + /** + * The default content mode is plain text. + */ + public static final int CONTENT_DEFAULT = CONTENT_TEXT; + + /** Array of content mode names that are rendered in UIDL as mode attribute. */ + private static final String[] CONTENT_MODE_NAME = { "text", "pre", "uidl", + "xhtml", "xml", "raw" }; + + private Property dataSource; + + private int contentMode = CONTENT_DEFAULT; + + /** + * Creates an empty Label. + */ + public Label() { + setPropertyDataSource(new ObjectProperty("", String.class)); + } + + /** + * Creates a new instance of Label with text-contents. + * + * @param content + */ + public Label(String content) { + setPropertyDataSource(new ObjectProperty(content, String.class)); + } + + /** + * Creates a new instance of Label with text-contents read from given + * datasource. + * + * @param contentSource + */ + public Label(Property contentSource) { + setPropertyDataSource(contentSource); + } + + /** + * Creates a new instance of Label with text-contents. + * + * @param content + * @param contentMode + */ + public Label(String content, int contentMode) { + setPropertyDataSource(new ObjectProperty(content, String.class)); + setContentMode(contentMode); + } + + /** + * Creates a new instance of Label with text-contents read from given + * datasource. + * + * @param contentSource + * @param contentMode + */ + public Label(Property contentSource, int contentMode) { + setPropertyDataSource(contentSource); + setContentMode(contentMode); + } + + /** + * Get the component UIDL tag. + * + * @return the Component UIDL tag as string. + */ + public String getTag() { + return "label"; + } + + /** + * Set the component to read-only. Readonly is not used in label. + * + * @param readOnly + * True to enable read-only mode, False to disable it. + */ + public void setReadOnly(boolean readOnly) { + if (dataSource == null) { + throw new IllegalStateException("Datasource must be se"); + } + dataSource.setReadOnly(readOnly); + } + + /** + * Is the component read-only ? Readonly is not used in label - this returns + * allways false. + * + * @return true if the component is in read only mode. + */ + public boolean isReadOnly() { + if (dataSource == null) { + throw new IllegalStateException("Datasource must be se"); + } + return dataSource.isReadOnly(); + } + + /** + * Paints the content of this component. + * + * @param target + * the Paint Event. + * @throws PaintException + * if the Paint Operation fails. + */ + public void paintContent(PaintTarget target) throws PaintException { + if (contentMode != CONTENT_TEXT) { + target.addAttribute("mode", CONTENT_MODE_NAME[contentMode]); + } + if (contentMode == CONTENT_TEXT) { + target.addText(toString()); + } else if (contentMode == CONTENT_UIDL) { + target.addUIDL(toString()); + } else if (contentMode == CONTENT_XHTML) { + target.startTag("data"); + target.addXMLSection("div", toString(), + "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"); + target.endTag("data"); + } else if (contentMode == CONTENT_PREFORMATTED) { + target.startTag("pre"); + target.addText(toString()); + target.endTag("pre"); + } else if (contentMode == CONTENT_XML) { + target.addXMLSection("data", toString(), null); + } else if (contentMode == CONTENT_RAW) { + target.startTag("data"); + target.addAttribute("escape", false); + target.addCharacterData(toString()); + target.endTag("data"); + } + + } + + /** + * Gets the value of the label. Value of the label is the XML contents of + * the label. + * + * @return the Value of the label. + */ + public Object getValue() { + if (dataSource == null) { + throw new IllegalStateException("Datasource must be se"); + } + return dataSource.getValue(); + } + + /** + * Set the value of the label. Value of the label is the XML contents of the + * label. + * + * @param newValue + * the New value of the label. + */ + public void setValue(Object newValue) { + if (dataSource == null) { + throw new IllegalStateException("Datasource must be se"); + } + dataSource.setValue(newValue); + } + + /** + * @see java.lang.Object#toString() + */ + public String toString() { + if (dataSource == null) { + throw new IllegalStateException("Datasource must be se"); + } + return dataSource.toString(); + } + + /** + * Gets the type of the Property. + * + * @see com.itmill.toolkit.data.Property#getType() + */ + public Class getType() { + if (dataSource == null) { + throw new IllegalStateException("Datasource must be se"); + } + return dataSource.getType(); + } + + /** + * Gets the viewing data-source property. + * + * @return the data source property. + * @see com.itmill.toolkit.data.Property.Viewer#getPropertyDataSource() + */ + public Property getPropertyDataSource() { + return dataSource; + } + + /** + * Sets the property as data-source for viewing. + * + * @param newDataSource + * the new data source Property + * @see com.itmill.toolkit.data.Property.Viewer#setPropertyDataSource(com.itmill.toolkit.data.Property) + */ + public void setPropertyDataSource(Property newDataSource) { + // Stops listening the old data source changes + if (dataSource != null + && Property.ValueChangeNotifier.class + .isAssignableFrom(dataSource.getClass())) { + ((Property.ValueChangeNotifier) dataSource).removeListener(this); + } + + // Sets the new data source + dataSource = newDataSource; + + // Listens the new data source if possible + if (dataSource != null + && Property.ValueChangeNotifier.class + .isAssignableFrom(dataSource.getClass())) { + ((Property.ValueChangeNotifier) dataSource).addListener(this); + } + } + + /** + * Gets the content mode of the Label. + * + *

+ * Possible content modes include: + *

    + *
  • CONTENT_TEXT Content mode, where the label contains only + * plain text. The getValue() result is coded to XML when painting.
  • + *
  • CONTENT_PREFORMATTED Content mode, where the label contains + * preformatted text.
  • + *
  • CONTENT_UIDL Formatted content mode, where the contents is + * XML restricted to the UIDL 1.0 formatting markups.
  • + *
  • CONTENT_XHTML Content mode, where the label contains XHTML. + * Contents is then enclosed in DIV elements having namespace of + * "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd".
  • + *
  • CONTENT_XML Content mode, where the label contains + * well-formed or well-balanced XML. Each of the root elements must have + * their default namespace specified.
  • + *
  • CONTENT_RAW Content mode, where the label contains RAW + * output. Output is not required to comply to with XML. In Web Adapter + * output is inserted inside the resulting HTML document as-is. This is + * useful for some specific purposes where possibly broken HTML content + * needs to be shown, but in most cases XHTML mode should be preferred.
  • + *
+ *

+ * + * @return the Content mode of the label. + */ + public int getContentMode() { + return contentMode; + } + + /** + * Sets the content mode of the Label. + * + *

+ * Possible content modes include: + *

    + *
  • CONTENT_TEXT Content mode, where the label contains only + * plain text. The getValue() result is coded to XML when painting.
  • + *
  • CONTENT_PREFORMATTED Content mode, where the label contains + * preformatted text.
  • + *
  • CONTENT_UIDL Formatted content mode, where the contents is + * XML restricted to the UIDL 1.0 formatting markups.
  • + *
  • CONTENT_XHTML Content mode, where the label contains XHTML. + * Contents is then enclosed in DIV elements having namespace of + * "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd".
  • + *
  • CONTENT_XML Content mode, where the label contains + * well-formed or well-balanced XML. Each of the root elements must have + * their default namespace specified.
  • + *
  • CONTENT_RAW Content mode, where the label contains RAW + * output. Output is not required to comply to with XML. In Web Adapter + * output is inserted inside the resulting HTML document as-is. This is + * useful for some specific purposes where possibly broken HTML content + * needs to be shown, but in most cases XHTML mode should be preferred.
  • + *
+ *

+ * + * @param contentMode + * the New content mode of the label. + */ + public void setContentMode(int contentMode) { + if (contentMode >= CONTENT_TEXT && contentMode <= CONTENT_RAW) { + this.contentMode = contentMode; + } + } + + /* Value change events ****************************************** */ + + private static final Method VALUE_CHANGE_METHOD; + + static { + try { + VALUE_CHANGE_METHOD = Property.ValueChangeListener.class + .getDeclaredMethod("valueChange", + new Class[] { Property.ValueChangeEvent.class }); + } catch (java.lang.NoSuchMethodException e) { + // This should never happen + throw new java.lang.RuntimeException(); + } + } + + /** + * Value change event + * + * @author IT Mill Ltd. + * @version + * @VERSION@ + * @since 3.0 + */ + public class ValueChangeEvent extends Component.Event implements + Property.ValueChangeEvent { + + /** + * Serial generated by eclipse. + */ + private static final long serialVersionUID = 3906084563938586935L; + + /** + * New instance of text change event + * + * @param source + * the Source of the event. + */ + public ValueChangeEvent(Label source) { + super(source); + } + + /** + * Gets the Property that has been modified. + * + * @see com.itmill.toolkit.data.Property.ValueChangeEvent#getProperty() + */ + public Property getProperty() { + return (Property) getSource(); + } + } + + /** + * Adds the value change listener. + * + * @param listener + * the Listener to be added. + * @see com.itmill.toolkit.data.Property.ValueChangeNotifier#addListener(com.itmill.toolkit.data.Property.ValueChangeListener) + */ + public void addListener(Property.ValueChangeListener listener) { + addListener(Label.ValueChangeEvent.class, listener, VALUE_CHANGE_METHOD); + } + + /** + * Removes the value change listener. + * + * @param listener + * the Listener to be removed. + * @see com.itmill.toolkit.data.Property.ValueChangeNotifier#removeListener(com.itmill.toolkit.data.Property.ValueChangeListener) + */ + public void removeListener(Property.ValueChangeListener listener) { + removeListener(Label.ValueChangeEvent.class, listener, + VALUE_CHANGE_METHOD); + } + + /** + * Emits the options change event. + */ + protected void fireValueChange() { + // Set the error message + fireEvent(new Label.ValueChangeEvent(this)); + requestRepaint(); + } + + /** + * Listens the value change events from data source. + * + * @see com.itmill.toolkit.data.Property.ValueChangeListener#valueChange(Property.ValueChangeEvent) + */ + public void valueChange(Property.ValueChangeEvent event) { + fireValueChange(); + } + + /** + * Compares the Label to other objects. + * + *

+ * Labels can be compared to other labels for sorting label contents. This + * is especially handy for sorting table columns. + *

+ * + *

+ * In RAW, PREFORMATTED and TEXT modes, the label contents are compared as + * is. In XML, UIDL and XHTML modes, only CDATA is compared and tags + * ignored. If the other object is not a Label, its toString() return value + * is used in comparison. + *

+ * + * @param other + * the Other object to compare to. + * @return a negative integer, zero, or a positive integer as this object is + * less than, equal to, or greater than the specified object. + * @see java.lang.Comparable#compareTo(java.lang.Object) + */ + public int compareTo(Object other) { + + String thisValue; + String otherValue; + + if (contentMode == CONTENT_XML || contentMode == CONTENT_UIDL + || contentMode == CONTENT_XHTML) { + thisValue = stripTags(toString()); + } else { + thisValue = toString(); + } + + if (other instanceof Label + && (((Label) other).getContentMode() == CONTENT_XML + || ((Label) other).getContentMode() == CONTENT_UIDL || ((Label) other) + .getContentMode() == CONTENT_XHTML)) { + otherValue = stripTags(other.toString()); + } else { + otherValue = other.toString(); + } + + return thisValue.compareTo(otherValue); + } + + /** + * Strips the tags from the XML. + * + * @param xml + * the String containing a XML snippet. + * @return the original XML without tags. + */ + private String stripTags(String xml) { + + StringBuffer res = new StringBuffer(); + + int processed = 0; + int xmlLen = xml.length(); + while (processed < xmlLen) { + int next = xml.indexOf('<', processed); + if (next < 0) { + next = xmlLen; + } + res.append(xml.substring(processed, next)); + if (processed < xmlLen) { + next = xml.indexOf('>', processed); + if (next < 0) { + next = xmlLen; + } + processed = next + 1; + } + } + + return res.toString(); + } } diff --git a/src/com/itmill/toolkit/ui/Layout.java b/src/com/itmill/toolkit/ui/Layout.java index 53c4ed791d..8e6062db81 100644 --- a/src/com/itmill/toolkit/ui/Layout.java +++ b/src/com/itmill/toolkit/ui/Layout.java @@ -30,7 +30,6 @@ package com.itmill.toolkit.ui; import com.itmill.toolkit.terminal.Sizeable; - /** * Extension to the {@link ComponentContainer} interface which adds the * layouting control to the elements in the container. This is required by the @@ -44,28 +43,28 @@ import com.itmill.toolkit.terminal.Sizeable; */ public interface Layout extends ComponentContainer, Sizeable { - /** - * Enable layout margins. Affects all four sides of the layout. This will - * tell the client-side implementation to leave extra space around the - * layout. The client-side implementation decides the actual amount, and it - * can vary between themes. - * - * @param enabled - */ - public void setMargin(boolean enabled); + /** + * Enable layout margins. Affects all four sides of the layout. This will + * tell the client-side implementation to leave extra space around the + * layout. The client-side implementation decides the actual amount, and it + * can vary between themes. + * + * @param enabled + */ + public void setMargin(boolean enabled); - /** - * Enable specific layout margins. This will tell the client-side - * implementation to leave extra space around the layout in specified edges, - * clockwise from top (top, right, bottom, left). The client-side - * implementation decides the actual amount, and it can vary between themes. - * - * @param top - * @param right - * @param bottom - * @param left - */ - public void setMargin(boolean top, boolean right, boolean bottom, - boolean left); + /** + * Enable specific layout margins. This will tell the client-side + * implementation to leave extra space around the layout in specified edges, + * clockwise from top (top, right, bottom, left). The client-side + * implementation decides the actual amount, and it can vary between themes. + * + * @param top + * @param right + * @param bottom + * @param left + */ + public void setMargin(boolean top, boolean right, boolean bottom, + boolean left); } diff --git a/src/com/itmill/toolkit/ui/Link.java b/src/com/itmill/toolkit/ui/Link.java index 8945931f00..db9d6a7239 100644 --- a/src/com/itmill/toolkit/ui/Link.java +++ b/src/com/itmill/toolkit/ui/Link.java @@ -42,250 +42,254 @@ import com.itmill.toolkit.terminal.Resource; */ public class Link extends AbstractComponent { - /* Target window border type constant: No window border */ - public static final int TARGET_BORDER_NONE = Window.BORDER_NONE; - - /* Target window border type constant: Minimal window border */ - public static final int TARGET_BORDER_MINIMAL = Window.BORDER_MINIMAL; - - /* Target window border type constant: Default window border */ - public static final int TARGET_BORDER_DEFAULT = Window.BORDER_DEFAULT; - - private Resource resource = null; - - private Window window = null; - - private String targetName; - - private int targetBorder = TARGET_BORDER_DEFAULT; - - private int targetWidth = -1; - - private int targetHeight = -1; - - /** - * Creates a new link. - */ - public Link() { - - } - - /** - * Creates a new link to a window. - */ - public Link(Window window) { - - // Sets the link caption to match window caption - setCaption(window.getCaption()); - - // Sets the target - setTargetName(window.getName()); - - setTargetName(window.getName()); - setTargetWidth(window.getWidth()); - setTargetHeight(window.getHeight()); - setTargetBorder(window.getBorder()); - } - - /** - * Creates a new instance of Link. - * - * @param caption - * @param resource - */ - public Link(String caption, Resource resource) { - setCaption(caption); - this.resource = resource; - } - - /** - * Creates a new instance of Link that opens a new window. - * - * - * @param caption - * the Link text. - * @param targetName - * the name of the target window where the link opens to. Empty - * name of null implies that the target is opened to the window - * containing the link. - * @param width - * the Width of the target window. - * @param height - * the Height of the target window. - * @param border - * the Border style of the target window. - * - */ - public Link(String caption, Resource resource, String targetName, - int width, int height, int border) { - setCaption(caption); - this.resource = resource; - setTargetName(targetName); - setTargetWidth(width); - setTargetHeight(height); - setTargetBorder(border); - } - - /** - * Gets the component UIDL tag. - * - * @return the Component UIDL tag as string. - */ - public String getTag() { - return "link"; - } - - /** - * Paints the content of this component. - * - * @param target - * the Paint Event. - * @throws PaintException - * if the paint operation failed. - */ - public void paintContent(PaintTarget target) throws PaintException { - - if (resource != null) - target.addAttribute("src", resource); - else - return; - - // Target window name - String name = getTargetName(); - if (name != null && name.length() > 0) - target.addAttribute("name", name); - - // Target window size - if (getTargetWidth() >= 0) - target.addAttribute("width", getTargetWidth()); - if (getTargetHeight() >= 0) - target.addAttribute("height", getTargetHeight()); - - // Target window border - switch (getTargetBorder()) { - case TARGET_BORDER_MINIMAL: - target.addAttribute("border", "minimal"); - break; - case TARGET_BORDER_NONE: - target.addAttribute("border", "none"); - break; - } - } - - /** - * Returns the target window border. - * - * @return the target window border. - */ - public int getTargetBorder() { - return targetBorder; - } - - /** - * Returns the target window height or -1 if not set. - * - * @return the target window height. - */ - public int getTargetHeight() { - return targetHeight < 0 ? -1 : targetHeight; - } - - /** - * Returns the target window name. Empty name of null implies that the - * target is opened to the window containing the link. - * - * @return the target window name. - */ - public String getTargetName() { - return targetName; - } - - /** - * Returns the target window width or -1 if not set. - * - * @return the target window width. - */ - public int getTargetWidth() { - return targetWidth < 0 ? -1 : targetWidth; - } - - /** - * Sets the border of the target window. - * - * @param targetBorder - * the targetBorder to set. - */ - public void setTargetBorder(int targetBorder) { - if (targetBorder == TARGET_BORDER_DEFAULT - || targetBorder == TARGET_BORDER_MINIMAL - || targetBorder == TARGET_BORDER_NONE) { - this.targetBorder = targetBorder; - requestRepaint(); - } - } - - /** - * Sets the target window height. - * - * @param targetHeight - * the targetHeight to set. - */ - public void setTargetHeight(int targetHeight) { - this.targetHeight = targetHeight; - requestRepaint(); - } - - /** - * Sets the target window name. - * - * @param targetName - * the targetName to set. - */ - public void setTargetName(String targetName) { - this.targetName = targetName; - requestRepaint(); - } - - /** - * Sets the target window width. - * - * @param targetWidth - * the targetWidth to set. - */ - public void setTargetWidth(int targetWidth) { - this.targetWidth = targetWidth; - requestRepaint(); - } - - /** - * Returns the resource this link opens. - * - * @return the Resource. - */ - public Resource getResource() { - return resource; - } - - /** - * Returns the window this link opens. - * - * @return the Window. - */ - public Window getWindow() { - return window; - } - - /** - * Sets the resource this link opens. - * - * @param resource - * the resource to set. - */ - public void setResource(Resource resource) { - this.resource = resource; - if (resource != null) { - window = null; - } - requestRepaint(); - } + /* Target window border type constant: No window border */ + public static final int TARGET_BORDER_NONE = Window.BORDER_NONE; + + /* Target window border type constant: Minimal window border */ + public static final int TARGET_BORDER_MINIMAL = Window.BORDER_MINIMAL; + + /* Target window border type constant: Default window border */ + public static final int TARGET_BORDER_DEFAULT = Window.BORDER_DEFAULT; + + private Resource resource = null; + + private Window window = null; + + private String targetName; + + private int targetBorder = TARGET_BORDER_DEFAULT; + + private int targetWidth = -1; + + private int targetHeight = -1; + + /** + * Creates a new link. + */ + public Link() { + + } + + /** + * Creates a new link to a window. + */ + public Link(Window window) { + + // Sets the link caption to match window caption + setCaption(window.getCaption()); + + // Sets the target + setTargetName(window.getName()); + + setTargetName(window.getName()); + setTargetWidth(window.getWidth()); + setTargetHeight(window.getHeight()); + setTargetBorder(window.getBorder()); + } + + /** + * Creates a new instance of Link. + * + * @param caption + * @param resource + */ + public Link(String caption, Resource resource) { + setCaption(caption); + this.resource = resource; + } + + /** + * Creates a new instance of Link that opens a new window. + * + * + * @param caption + * the Link text. + * @param targetName + * the name of the target window where the link opens to. + * Empty name of null implies that the target is opened to + * the window containing the link. + * @param width + * the Width of the target window. + * @param height + * the Height of the target window. + * @param border + * the Border style of the target window. + * + */ + public Link(String caption, Resource resource, String targetName, + int width, int height, int border) { + setCaption(caption); + this.resource = resource; + setTargetName(targetName); + setTargetWidth(width); + setTargetHeight(height); + setTargetBorder(border); + } + + /** + * Gets the component UIDL tag. + * + * @return the Component UIDL tag as string. + */ + public String getTag() { + return "link"; + } + + /** + * Paints the content of this component. + * + * @param target + * the Paint Event. + * @throws PaintException + * if the paint operation failed. + */ + public void paintContent(PaintTarget target) throws PaintException { + + if (resource != null) { + target.addAttribute("src", resource); + } else { + return; + } + + // Target window name + String name = getTargetName(); + if (name != null && name.length() > 0) { + target.addAttribute("name", name); + } + + // Target window size + if (getTargetWidth() >= 0) { + target.addAttribute("width", getTargetWidth()); + } + if (getTargetHeight() >= 0) { + target.addAttribute("height", getTargetHeight()); + } + + // Target window border + switch (getTargetBorder()) { + case TARGET_BORDER_MINIMAL: + target.addAttribute("border", "minimal"); + break; + case TARGET_BORDER_NONE: + target.addAttribute("border", "none"); + break; + } + } + + /** + * Returns the target window border. + * + * @return the target window border. + */ + public int getTargetBorder() { + return targetBorder; + } + + /** + * Returns the target window height or -1 if not set. + * + * @return the target window height. + */ + public int getTargetHeight() { + return targetHeight < 0 ? -1 : targetHeight; + } + + /** + * Returns the target window name. Empty name of null implies that the + * target is opened to the window containing the link. + * + * @return the target window name. + */ + public String getTargetName() { + return targetName; + } + + /** + * Returns the target window width or -1 if not set. + * + * @return the target window width. + */ + public int getTargetWidth() { + return targetWidth < 0 ? -1 : targetWidth; + } + + /** + * Sets the border of the target window. + * + * @param targetBorder + * the targetBorder to set. + */ + public void setTargetBorder(int targetBorder) { + if (targetBorder == TARGET_BORDER_DEFAULT + || targetBorder == TARGET_BORDER_MINIMAL + || targetBorder == TARGET_BORDER_NONE) { + this.targetBorder = targetBorder; + requestRepaint(); + } + } + + /** + * Sets the target window height. + * + * @param targetHeight + * the targetHeight to set. + */ + public void setTargetHeight(int targetHeight) { + this.targetHeight = targetHeight; + requestRepaint(); + } + + /** + * Sets the target window name. + * + * @param targetName + * the targetName to set. + */ + public void setTargetName(String targetName) { + this.targetName = targetName; + requestRepaint(); + } + + /** + * Sets the target window width. + * + * @param targetWidth + * the targetWidth to set. + */ + public void setTargetWidth(int targetWidth) { + this.targetWidth = targetWidth; + requestRepaint(); + } + + /** + * Returns the resource this link opens. + * + * @return the Resource. + */ + public Resource getResource() { + return resource; + } + + /** + * Returns the window this link opens. + * + * @return the Window. + */ + public Window getWindow() { + return window; + } + + /** + * Sets the resource this link opens. + * + * @param resource + * the resource to set. + */ + public void setResource(Resource resource) { + this.resource = resource; + if (resource != null) { + window = null; + } + requestRepaint(); + } } diff --git a/src/com/itmill/toolkit/ui/OptionGroup.java b/src/com/itmill/toolkit/ui/OptionGroup.java index f58667c43e..0d7ff51245 100644 --- a/src/com/itmill/toolkit/ui/OptionGroup.java +++ b/src/com/itmill/toolkit/ui/OptionGroup.java @@ -14,25 +14,25 @@ import com.itmill.toolkit.terminal.PaintTarget; */ public class OptionGroup extends AbstractSelect { - public OptionGroup() { - super(); - } - - public OptionGroup(String caption, Collection options) { - super(caption, options); - } - - public OptionGroup(String caption, Container dataSource) { - super(caption, dataSource); - } - - public OptionGroup(String caption) { - super(caption); - } - - public void paintContent(PaintTarget target) throws PaintException { - target.addAttribute("type", "optiongroup"); - super.paintContent(target); - } + public OptionGroup() { + super(); + } + + public OptionGroup(String caption, Collection options) { + super(caption, options); + } + + public OptionGroup(String caption, Container dataSource) { + super(caption, dataSource); + } + + public OptionGroup(String caption) { + super(caption); + } + + public void paintContent(PaintTarget target) throws PaintException { + target.addAttribute("type", "optiongroup"); + super.paintContent(target); + } } diff --git a/src/com/itmill/toolkit/ui/OrderedLayout.java b/src/com/itmill/toolkit/ui/OrderedLayout.java index 72e98a7c2d..30eed5c2d3 100644 --- a/src/com/itmill/toolkit/ui/OrderedLayout.java +++ b/src/com/itmill/toolkit/ui/OrderedLayout.java @@ -50,317 +50,324 @@ import com.itmill.toolkit.terminal.gwt.client.ui.AlignmentInfo; */ public class OrderedLayout extends AbstractLayout { - /* Predefined orientations ***************************************** */ - - /** - * Components are to be laid out vertically. - */ - public static int ORIENTATION_VERTICAL = 0; - - /** - * Components are to be laid out horizontally. - */ - public static int ORIENTATION_HORIZONTAL = 1; - - /** - * Custom layout slots containing the components. - */ - protected LinkedList components = new LinkedList(); - - /* Child component alignments ************************************** */ - - /** - * Mapping from components to alignments (horizontal + vertical). - */ - private Map componentToAlignment = new HashMap(); - - /** - * Contained component should be aligned horizontally to the left. - */ - public static final int ALIGNMENT_LEFT = AlignmentInfo.ALIGNMENT_LEFT; - - /** - * Contained component should be aligned horizontally to the right. - */ - public static final int ALIGNMENT_RIGHT = AlignmentInfo.ALIGNMENT_RIGHT; - - /** - * Contained component should be aligned vertically to the top. - */ - public static final int ALIGNMENT_TOP = AlignmentInfo.ALIGNMENT_TOP; - - /** - * Contained component should be aligned vertically to the bottom. - */ - public static final int ALIGNMENT_BOTTOM = AlignmentInfo.ALIGNMENT_BOTTOM; - - /** - * Contained component should be horizontally aligned to center. - */ - public static final int ALIGNMENT_HORIZONTAL_CENTER = AlignmentInfo.ALIGNMENT_HORIZONTAL_CENTER; - - /** - * Contained component should be vertically aligned to center. - */ - public static final int ALIGNMENT_VERTICAL_CENTER = AlignmentInfo.ALIGNMENT_VERTICAL_CENTER; - - private static final int ALIGNMENT_DEFAULT = ALIGNMENT_TOP + ALIGNMENT_LEFT; - - /** - * Orientation of the layout. - */ - private int orientation; - - /** - * Is spacing between contained components enabled. Defaults to false. - */ - private boolean spacing = false; - - /** - * Creates a new ordered layout. The order of the layout is - * ORIENTATION_VERTICAL. - */ - public OrderedLayout() { - orientation = ORIENTATION_VERTICAL; - } - - /** - * Create a new ordered layout. The orientation of the layout is given as - * parameters. - * - * @param orientation - * the Orientation of the layout. - */ - public OrderedLayout(int orientation) { - this.orientation = orientation; - } - - /** - * Gets the component UIDL tag. - * - * @return the Component UIDL tag as string. - */ - public String getTag() { - return "orderedlayout"; - } - - /** - * Add a component into this container. The component is added to the right - * or under the previous component. - * - * @param c - * the component to be added. - */ - public void addComponent(Component c) { - components.add(c); - super.addComponent(c); - requestRepaint(); - } - - /** - * Adds a component into this container. The component is added to the left - * or on top of the other components. - * - * @param c - * the component to be added. - */ - public void addComponentAsFirst(Component c) { - components.addFirst(c); - super.addComponent(c); - requestRepaint(); - } - - /** - * Adds a component into indexed position in this container. - * - * @param c - * the component to be added. - * @param index - * the Index of the component position. The components currently - * in and after the position are shifted forwards. - */ - public void addComponent(Component c, int index) { - components.add(index, c); - super.addComponent(c); - requestRepaint(); - } - - /** - * Removes the component from this container. - * - * @param c - * the component to be removed. - */ - public void removeComponent(Component c) { - super.removeComponent(c); - components.remove(c); - componentToAlignment.remove(c); - requestRepaint(); - } - - /** - * Gets the component container iterator for going trough all the components - * in the container. - * - * @return the Iterator of the components inside the container. - */ - public Iterator getComponentIterator() { - return components.iterator(); - } - - /** - * Paints the content of this component. - * - * @param target - * the Paint Event. - * @throws PaintException - * if the paint operation failed. - */ - public void paintContent(PaintTarget target) throws PaintException { - super.paintContent(target); - - // Adds the attributes: orientation - // note that the default values (b/vertical) are omitted - if (orientation == ORIENTATION_HORIZONTAL) - target.addAttribute("orientation", "horizontal"); - - // Add spacing attribute (omitted if false) - if (this.spacing) - target.addAttribute("spacing", this.spacing); - - String[] alignmentsArray = new String[components.size()]; - // Adds all items in all the locations - int index = 0; - for (Iterator i = components.iterator(); i.hasNext();) { - Component c = (Component) i.next(); - if (c != null) { - // Paint child component UIDL - c.paint(target); - alignmentsArray[index++] = String.valueOf(getComponentAlignment(c)); - } - } - - // Add child component alignment info to layout tag - target.addAttribute("alignments", alignmentsArray); - } - - /** - * Gets the orientation of the container. - * - * @return the Value of property orientation. - */ - public int getOrientation() { - return this.orientation; - } - - /** - * Set the orientation of the container. - * - * @param orientation - * the New value of property orientation. - */ - public void setOrientation(int orientation) { - - // Checks the validity of the argument - if (orientation < ORIENTATION_VERTICAL - || orientation > ORIENTATION_HORIZONTAL) - throw new IllegalArgumentException(); - - this.orientation = orientation; - - // requestRepaint() - // FIXME remove lines below and uncomment above - // Workaround to bypass IOrderedLayouts limitations (separate classes - // for different orientation + subtreecacing) - Iterator it = getComponentIterator(); - while (it.hasNext()) { - Component c = (Component) it.next(); - c.requestRepaint(); - } - } - - /* Documented in superclass */ - public void replaceComponent(Component oldComponent, Component newComponent) { - - // Gets the locations - int oldLocation = -1; - int newLocation = -1; - int location = 0; - for (Iterator i = components.iterator(); i.hasNext();) { - Component component = (Component) i.next(); - - if (component == oldComponent) - oldLocation = location; - if (component == newComponent) - newLocation = location; - - location++; - } - - if (oldLocation == -1) - addComponent(newComponent); - else if (newLocation == -1) { - removeComponent(oldComponent); - addComponent(newComponent, oldLocation); - } else { - if (oldLocation > newLocation) { - components.remove(oldComponent); - components.add(newLocation, oldComponent); - components.remove(newComponent); - componentToAlignment.remove(newComponent); - components.add(oldLocation, newComponent); - } else { - components.remove(newComponent); - components.add(oldLocation, newComponent); - components.remove(oldComponent); - componentToAlignment.remove(oldComponent); - components.add(newLocation, oldComponent); - } - - requestRepaint(); - } - } - - /** - * Set alignment for one contained component in this layout. Alignment is - * calculated as a bit mask of the two passed values. - * - * @param childComponent - * the component to align within it's layout cell. - * @param horizontalAlignment - * the horizontal alignment for the child component (left, - * center, right). - * @param verticalAlignment - * the vertical alignment for the child component (top, center, - * bottom). - */ - public void setComponentAlignment(Component childComponent, - int horizontalAlignment, int verticalAlignment) { - componentToAlignment.put(childComponent, new Integer( - horizontalAlignment + verticalAlignment)); - } - - public int getComponentAlignment(Component childComponent) { - Integer bitMask = (Integer) componentToAlignment.get(childComponent); - if(bitMask != null) - return bitMask.intValue(); - else - return ALIGNMENT_DEFAULT; - } - - /** - * Enable spacing between child components within this layout. - * - *

- * NOTE: This will only affect spaces between components, - * not also all around spacing of the layout (i.e. do not mix this with HTML - * Table elements cellspacing-attribute). Use {@link #setMargin(boolean)} to - * add extra space around the layout. - *

- * - * @param enabled - */ - public void setSpacing(boolean enabled) { - this.spacing = enabled; - } + /* Predefined orientations ***************************************** */ + + /** + * Components are to be laid out vertically. + */ + public static int ORIENTATION_VERTICAL = 0; + + /** + * Components are to be laid out horizontally. + */ + public static int ORIENTATION_HORIZONTAL = 1; + + /** + * Custom layout slots containing the components. + */ + protected LinkedList components = new LinkedList(); + + /* Child component alignments ************************************** */ + + /** + * Mapping from components to alignments (horizontal + vertical). + */ + private Map componentToAlignment = new HashMap(); + + /** + * Contained component should be aligned horizontally to the left. + */ + public static final int ALIGNMENT_LEFT = AlignmentInfo.ALIGNMENT_LEFT; + + /** + * Contained component should be aligned horizontally to the right. + */ + public static final int ALIGNMENT_RIGHT = AlignmentInfo.ALIGNMENT_RIGHT; + + /** + * Contained component should be aligned vertically to the top. + */ + public static final int ALIGNMENT_TOP = AlignmentInfo.ALIGNMENT_TOP; + + /** + * Contained component should be aligned vertically to the bottom. + */ + public static final int ALIGNMENT_BOTTOM = AlignmentInfo.ALIGNMENT_BOTTOM; + + /** + * Contained component should be horizontally aligned to center. + */ + public static final int ALIGNMENT_HORIZONTAL_CENTER = AlignmentInfo.ALIGNMENT_HORIZONTAL_CENTER; + + /** + * Contained component should be vertically aligned to center. + */ + public static final int ALIGNMENT_VERTICAL_CENTER = AlignmentInfo.ALIGNMENT_VERTICAL_CENTER; + + private static final int ALIGNMENT_DEFAULT = ALIGNMENT_TOP + ALIGNMENT_LEFT; + + /** + * Orientation of the layout. + */ + private int orientation; + + /** + * Is spacing between contained components enabled. Defaults to false. + */ + private boolean spacing = false; + + /** + * Creates a new ordered layout. The order of the layout is + * ORIENTATION_VERTICAL. + */ + public OrderedLayout() { + orientation = ORIENTATION_VERTICAL; + } + + /** + * Create a new ordered layout. The orientation of the layout is given as + * parameters. + * + * @param orientation + * the Orientation of the layout. + */ + public OrderedLayout(int orientation) { + this.orientation = orientation; + } + + /** + * Gets the component UIDL tag. + * + * @return the Component UIDL tag as string. + */ + public String getTag() { + return "orderedlayout"; + } + + /** + * Add a component into this container. The component is added to the right + * or under the previous component. + * + * @param c + * the component to be added. + */ + public void addComponent(Component c) { + components.add(c); + super.addComponent(c); + requestRepaint(); + } + + /** + * Adds a component into this container. The component is added to the left + * or on top of the other components. + * + * @param c + * the component to be added. + */ + public void addComponentAsFirst(Component c) { + components.addFirst(c); + super.addComponent(c); + requestRepaint(); + } + + /** + * Adds a component into indexed position in this container. + * + * @param c + * the component to be added. + * @param index + * the Index of the component position. The components + * currently in and after the position are shifted forwards. + */ + public void addComponent(Component c, int index) { + components.add(index, c); + super.addComponent(c); + requestRepaint(); + } + + /** + * Removes the component from this container. + * + * @param c + * the component to be removed. + */ + public void removeComponent(Component c) { + super.removeComponent(c); + components.remove(c); + componentToAlignment.remove(c); + requestRepaint(); + } + + /** + * Gets the component container iterator for going trough all the components + * in the container. + * + * @return the Iterator of the components inside the container. + */ + public Iterator getComponentIterator() { + return components.iterator(); + } + + /** + * Paints the content of this component. + * + * @param target + * the Paint Event. + * @throws PaintException + * if the paint operation failed. + */ + public void paintContent(PaintTarget target) throws PaintException { + super.paintContent(target); + + // Adds the attributes: orientation + // note that the default values (b/vertical) are omitted + if (orientation == ORIENTATION_HORIZONTAL) { + target.addAttribute("orientation", "horizontal"); + } + + // Add spacing attribute (omitted if false) + if (spacing) { + target.addAttribute("spacing", spacing); + } + + String[] alignmentsArray = new String[components.size()]; + // Adds all items in all the locations + int index = 0; + for (Iterator i = components.iterator(); i.hasNext();) { + Component c = (Component) i.next(); + if (c != null) { + // Paint child component UIDL + c.paint(target); + alignmentsArray[index++] = String + .valueOf(getComponentAlignment(c)); + } + } + + // Add child component alignment info to layout tag + target.addAttribute("alignments", alignmentsArray); + } + + /** + * Gets the orientation of the container. + * + * @return the Value of property orientation. + */ + public int getOrientation() { + return orientation; + } + + /** + * Set the orientation of the container. + * + * @param orientation + * the New value of property orientation. + */ + public void setOrientation(int orientation) { + + // Checks the validity of the argument + if (orientation < ORIENTATION_VERTICAL + || orientation > ORIENTATION_HORIZONTAL) { + throw new IllegalArgumentException(); + } + + this.orientation = orientation; + + // requestRepaint() + // FIXME remove lines below and uncomment above + // Workaround to bypass IOrderedLayouts limitations (separate classes + // for different orientation + subtreecacing) + Iterator it = getComponentIterator(); + while (it.hasNext()) { + Component c = (Component) it.next(); + c.requestRepaint(); + } + } + + /* Documented in superclass */ + public void replaceComponent(Component oldComponent, Component newComponent) { + + // Gets the locations + int oldLocation = -1; + int newLocation = -1; + int location = 0; + for (Iterator i = components.iterator(); i.hasNext();) { + Component component = (Component) i.next(); + + if (component == oldComponent) { + oldLocation = location; + } + if (component == newComponent) { + newLocation = location; + } + + location++; + } + + if (oldLocation == -1) { + addComponent(newComponent); + } else if (newLocation == -1) { + removeComponent(oldComponent); + addComponent(newComponent, oldLocation); + } else { + if (oldLocation > newLocation) { + components.remove(oldComponent); + components.add(newLocation, oldComponent); + components.remove(newComponent); + componentToAlignment.remove(newComponent); + components.add(oldLocation, newComponent); + } else { + components.remove(newComponent); + components.add(oldLocation, newComponent); + components.remove(oldComponent); + componentToAlignment.remove(oldComponent); + components.add(newLocation, oldComponent); + } + + requestRepaint(); + } + } + + /** + * Set alignment for one contained component in this layout. Alignment is + * calculated as a bit mask of the two passed values. + * + * @param childComponent + * the component to align within it's layout cell. + * @param horizontalAlignment + * the horizontal alignment for the child component (left, + * center, right). + * @param verticalAlignment + * the vertical alignment for the child component (top, + * center, bottom). + */ + public void setComponentAlignment(Component childComponent, + int horizontalAlignment, int verticalAlignment) { + componentToAlignment.put(childComponent, new Integer( + horizontalAlignment + verticalAlignment)); + } + + public int getComponentAlignment(Component childComponent) { + Integer bitMask = (Integer) componentToAlignment.get(childComponent); + if (bitMask != null) { + return bitMask.intValue(); + } else { + return ALIGNMENT_DEFAULT; + } + } + + /** + * Enable spacing between child components within this layout. + * + *

+ * NOTE: This will only affect spaces between components, + * not also all around spacing of the layout (i.e. do not mix this with HTML + * Table elements cellspacing-attribute). Use {@link #setMargin(boolean)} to + * add extra space around the layout. + *

+ * + * @param enabled + */ + public void setSpacing(boolean enabled) { + spacing = enabled; + } } diff --git a/src/com/itmill/toolkit/ui/Panel.java b/src/com/itmill/toolkit/ui/Panel.java index 69cc3fe2d9..541effb479 100644 --- a/src/com/itmill/toolkit/ui/Panel.java +++ b/src/com/itmill/toolkit/ui/Panel.java @@ -50,546 +50,561 @@ import com.itmill.toolkit.terminal.Sizeable; * @since 3.0 */ public class Panel extends AbstractComponentContainer implements Sizeable, - Scrollable, ComponentContainer.ComponentAttachListener, - ComponentContainer.ComponentDetachListener, Action.Container { - - public static final String STYLE_LIGHT = "light"; - - public static final String STYLE_EMPHASIZE = "emphasize"; - - /** - * Height of the layout. Set to -1 for undefined height. - */ - private int height = -1; - - /** - * Height unit. - * - * @see com.itmill.toolkit.terminal.Sizeable.UNIT_SYMBOLS; - */ - private int heightUnit = UNITS_PIXELS; - - /** - * Width of the layout. Set to -1 for undefined width. - */ - private int width = -1; - - /** - * Width unit. - * - * @see com.itmill.toolkit.terminal.Sizeable.UNIT_SYMBOLS; - */ - private int widthUnit = UNITS_PIXELS; - - /** - * Layout of the panel. - */ - private Layout layout; - - /** - * Scroll X position. - */ - private int scrollOffsetX = 0; - - /** - * Scroll Y position. - */ - private int scrollOffsetY = 0; - - /** - * Scrolling mode. - */ - private boolean scrollable = false; - - /** List of action handlers */ - private LinkedList actionHandlers = null; - - /** Action mapper */ - private KeyMapper actionMapper = null; - - /** - * Creates a new empty panel. Ordered layout is used. - */ - public Panel() { - setLayout(null); - } - - /** - * Creates a new empty panel with given layout. Layout must be non-null. - * - * @param layout - * the layout used in the panel. - */ - public Panel(Layout layout) { - setLayout(layout); - } - - /** - * Creates a new empty panel with caption. Default layout is used. - * - * @param caption - * the caption used in the panel. - */ - public Panel(String caption) { - this(caption, null); - } - - /** - * Creates a new empty panel with caption. - * - * @param caption - * the caption of the panel. - * @param layout - * the layout used in the panel. - */ - public Panel(String caption, Layout layout) { - this(layout); - setCaption(caption); - } - - /** - * Gets the current layout of the panel. - * - * @return the Current layout of the panel. - */ - public Layout getLayout() { - return this.layout; - } - - /** - * Sets the layout of the panel. All the components are moved to new layout. - * - * @param layout - * the New layout of the panel. - */ - public void setLayout(Layout layout) { - - // Only allow non-null layouts - if (layout == null) { - layout = new OrderedLayout(); - // Force margins by default - layout.setMargin(true); - } - - // Sets the panel to be parent for the layout - layout.setParent(this); - dependsOn(layout); - - // If panel already contains a layout, move the contents to new one - // and detach old layout from the panel - if (this.layout != null) { - layout.moveComponentsFrom(this.layout); - removeDirectDependency(this.layout); - this.layout.setParent(null); - } - - // Removes the event listeners from the old layout - if (this.layout != null) { - this.layout - .removeListener((ComponentContainer.ComponentAttachListener) this); - this.layout - .removeListener((ComponentContainer.ComponentDetachListener) this); - } - - // Sets the new layout - this.layout = layout; - - // Adds the event listeners for new layout - layout.addListener((ComponentContainer.ComponentAttachListener) this); - layout.addListener((ComponentContainer.ComponentDetachListener) this); - } - - /** - * Paints the content of this component. - * - * @param target - * the Paint Event. - * @throws PaintException - * if the paint operation failed. - */ - public void paintContent(PaintTarget target) throws PaintException { - layout.paint(target); - - // Add size info as variables - if (getHeight() > -1) - target.addVariable(this, "height", getHeight() - + UNIT_SYMBOLS[getHeightUnits()]); - if (getWidth() > -1) - target.addVariable(this, "width", getWidth() - + UNIT_SYMBOLS[getWidthUnits()]); - - if (isScrollable()) { - target.addVariable(this, "scrollleft", getScrollOffsetX()); - target.addVariable(this, "scrolldown", getScrollOffsetY()); - } - - if (actionHandlers != null && !actionHandlers.isEmpty()) { - target.addVariable(this, "action", ""); - target.startTag("actions"); - - for (Iterator ahi = actionHandlers.iterator(); ahi.hasNext();) { - Action[] aa = ((Action.Handler) ahi.next()).getActions(null, - this); - if (aa != null) { - for (int ai = 0; ai < aa.length; ai++) { - Action a = aa[ai]; - target.startTag("action"); - String akey = actionMapper.key(aa[ai]); - target.addAttribute("key", akey); - if (a.getCaption() != null) - target.addAttribute("caption", a.getCaption()); - if (a.getIcon() != null) - target.addAttribute("icon", a.getIcon()); - if (a instanceof ShortcutAction) { - ShortcutAction sa = (ShortcutAction) a; - target.addAttribute("kc", sa.getKeyCode()); - int[] modifiers = sa.getModifiers(); - if (modifiers != null) { - String[] smodifiers = new String[modifiers.length]; - for (int i = 0; i < modifiers.length; i++) - smodifiers[i] = String - .valueOf(modifiers[i]); - target.addAttribute("mk", smodifiers); - } - } - target.endTag("action"); - } - } - } - target.endTag("actions"); - } - } - - /** - * Gets the component UIDL tag. - * - * @return the Component UIDL tag as string. - */ - public String getTag() { - return "panel"; - } - - /** - * Adds the component into this container. - * - * @param c - * the component to be added. - * @see com.itmill.toolkit.ui.AbstractComponentContainer#addComponent(com.itmill.toolkit.ui.Component) - */ - public void addComponent(Component c) { - layout.addComponent(c); - // No repaint request is made as we except the underlying container to - // request repaints - } - - /** - * Removes the component from this container. - * - * @param c - * The component to be added. - * @see com.itmill.toolkit.ui.AbstractComponentContainer#removeComponent(com.itmill.toolkit.ui.Component) - */ - public void removeComponent(Component c) { - layout.removeComponent(c); - // No repaint request is made as we except the underlying container to - // request repaints - } - - /** - * Gets the component container iterator for going trough all the components - * in the container. - * - * @return the Iterator of the components inside the container. - * @see com.itmill.toolkit.ui.ComponentContainer#getComponentIterator() - */ - public Iterator getComponentIterator() { - return layout.getComponentIterator(); - } - - /** - * Called when one or more variables handled by the implementing class are - * changed. - * - * @see com.itmill.toolkit.terminal.VariableOwner#changeVariables(Object, - * Map) - */ - public void changeVariables(Object source, Map variables) { - super.changeVariables(source, variables); - - // Get new size - Integer newWidth = (Integer) variables.get("width"); - Integer newHeight = (Integer) variables.get("height"); - if (newWidth != null && newWidth.intValue() != getWidth()) { - setWidth(newWidth.intValue()); - // ensure units as we are reading pixels - setWidthUnits(UNITS_PIXELS); - - } - if (newHeight != null && newHeight.intValue() != getHeight()) { - setHeight(newHeight.intValue()); - // ensure units as we are reading pixels - setHeightUnits(UNITS_PIXELS); - } - - // Scrolling - Integer newScrollX = (Integer) variables.get("scrollleft"); - Integer newScrollY = (Integer) variables.get("scrolldown"); - if (newScrollX != null && newScrollX.intValue() != getScrollOffsetX()) - setScrollOffsetX(newScrollX.intValue()); - if (newScrollY != null && newScrollY.intValue() != getScrollOffsetY()) - setScrollOffsetY(newScrollY.intValue()); - - // Actions - if (variables.containsKey("action")) { - String key = (String) variables.get("action"); - Action action = (Action) actionMapper.get(key); - if (action != null && actionHandlers != null) - for (Iterator i = actionHandlers.iterator(); i.hasNext();) - ((Action.Handler) i.next()) - .handleAction(action, this, this); - } - - } - - /* Scrolling functionality */ - - /* Documented in interface */ - public int getScrollOffsetX() { - return scrollOffsetX; - } - - /* Documented in interface */ - public int getScrollOffsetY() { - return scrollOffsetY; - } - - /* Documented in interface */ - public boolean isScrollable() { - return scrollable; - } - - /* Documented in interface */ - public void setScrollable(boolean isScrollingEnabled) { - if (scrollable != isScrollingEnabled) { - scrollable = isScrollingEnabled; - requestRepaint(); - } - } - - /* Documented in interface */ - public void setScrollOffsetX(int pixelsScrolledLeft) { - if (pixelsScrolledLeft < 0) - throw new IllegalArgumentException( - "Scroll offset must be at least 0"); - if (this.scrollOffsetX != pixelsScrolledLeft) { - scrollOffsetX = pixelsScrolledLeft; - requestRepaint(); - } - } - - /* Documented in interface */ - public void setScrollOffsetY(int pixelsScrolledDown) { - if (pixelsScrolledDown < 0) - throw new IllegalArgumentException( - "Scroll offset must be at least 0"); - if (this.scrollOffsetY != pixelsScrolledDown) { - scrollOffsetY = pixelsScrolledDown; - requestRepaint(); - } - } - - /* Documented in superclass */ - public void replaceComponent(Component oldComponent, Component newComponent) { - - layout.replaceComponent(oldComponent, newComponent); - } - - /** - * A new component is attached to container. - * - * @see com.itmill.toolkit.ui.ComponentContainer.ComponentAttachListener#componentAttachedToContainer(com.itmill.toolkit.ui.ComponentContainer.ComponentAttachEvent) - */ - public void componentAttachedToContainer(ComponentAttachEvent event) { - if (event.getContainer() == layout) - fireComponentAttachEvent(event.getAttachedComponent()); - } - - /** - * A component has been detached from container. - * - * @see com.itmill.toolkit.ui.ComponentContainer.ComponentDetachListener#componentDetachedFromContainer(com.itmill.toolkit.ui.ComponentContainer.ComponentDetachEvent) - */ - public void componentDetachedFromContainer(ComponentDetachEvent event) { - if (event.getContainer() == layout) - fireComponentDetachEvent(event.getDetachedComponent()); - } - - /** - * Notifies the component that it is connected to an application. - * - * @see com.itmill.toolkit.ui.Component#attach() - */ - public void attach() { - super.attach(); - if (layout != null) - layout.attach(); - } - - /** - * Notifies the component that it is detached from the application. - * - * @see com.itmill.toolkit.ui.Component#detach() - */ - public void detach() { - if (layout != null) - layout.detach(); - } - - /** - * Removes all components from this container. - * - * @see com.itmill.toolkit.ui.ComponentContainer#removeAllComponents() - */ - public void removeAllComponents() { - layout.removeAllComponents(); - } - - public void addActionHandler(Handler actionHandler) { - if (actionHandler != null) { - - if (actionHandlers == null) { - actionHandlers = new LinkedList(); - actionMapper = new KeyMapper(); - } - - if (!actionHandlers.contains(actionHandler)) { - actionHandlers.add(actionHandler); - requestRepaint(); - } - } - - } - - /** - * Removes an action handler. - * - * @see com.itmill.toolkit.event.Action.Container#removeActionHandler(Action.Handler) - */ - public void removeActionHandler(Action.Handler actionHandler) { - - if (actionHandlers != null && actionHandlers.contains(actionHandler)) { - - actionHandlers.remove(actionHandler); - - if (actionHandlers.isEmpty()) { - actionHandlers = null; - actionMapper = null; - } - - requestRepaint(); - } - } - - /* - * (non-Javadoc) - * - * @see com.itmill.toolkit.terminal.Sizeable#getHeight() - */ - public int getHeight() { - return height; - } - - /* - * (non-Javadoc) - * - * @see com.itmill.toolkit.terminal.Sizeable#getHeightUnits() - */ - public int getHeightUnits() { - return heightUnit; - } - - /* - * (non-Javadoc) - * - * @see com.itmill.toolkit.terminal.Sizeable#getWidth() - */ - public int getWidth() { - return width; - } - - /* - * (non-Javadoc) - * - * @see com.itmill.toolkit.terminal.Sizeable#getWidthUnits() - */ - public int getWidthUnits() { - return widthUnit; - } - - /* - * (non-Javadoc) - * - * @see com.itmill.toolkit.terminal.Sizeable#setHeight(int) - */ - public void setHeight(int height) { - this.height = height; - requestRepaint(); - } - - /* - * (non-Javadoc) - * - * @see com.itmill.toolkit.terminal.Sizeable#setHeightUnits(int) - */ - public void setHeightUnits(int units) { - this.heightUnit = units; - requestRepaint(); - } - - /* - * (non-Javadoc) - * - * @see com.itmill.toolkit.terminal.Sizeable#setSizeFull() - */ - public void setSizeFull() { - height = 100; - width = 100; - heightUnit = UNITS_PERCENTAGE; - widthUnit = UNITS_PERCENTAGE; - requestRepaint(); - } - - /* - * (non-Javadoc) - * - * @see com.itmill.toolkit.terminal.Sizeable#setSizeUndefined() - */ - public void setSizeUndefined() { - height = -1; - width = -1; - heightUnit = UNITS_PIXELS; - widthUnit = UNITS_PIXELS; - requestRepaint(); - } - - /* - * (non-Javadoc) - * - * @see com.itmill.toolkit.terminal.Sizeable#setWidth(int) - */ - public void setWidth(int width) { - this.width = width; - requestRepaint(); - } - - /* - * (non-Javadoc) - * - * @see com.itmill.toolkit.terminal.Sizeable#setWidthUnits(int) - */ - public void setWidthUnits(int units) { - this.widthUnit = units; - requestRepaint(); - } + Scrollable, ComponentContainer.ComponentAttachListener, + ComponentContainer.ComponentDetachListener, Action.Container { + + public static final String STYLE_LIGHT = "light"; + + public static final String STYLE_EMPHASIZE = "emphasize"; + + /** + * Height of the layout. Set to -1 for undefined height. + */ + private int height = -1; + + /** + * Height unit. + * + * @see com.itmill.toolkit.terminal.Sizeable.UNIT_SYMBOLS; + */ + private int heightUnit = UNITS_PIXELS; + + /** + * Width of the layout. Set to -1 for undefined width. + */ + private int width = -1; + + /** + * Width unit. + * + * @see com.itmill.toolkit.terminal.Sizeable.UNIT_SYMBOLS; + */ + private int widthUnit = UNITS_PIXELS; + + /** + * Layout of the panel. + */ + private Layout layout; + + /** + * Scroll X position. + */ + private int scrollOffsetX = 0; + + /** + * Scroll Y position. + */ + private int scrollOffsetY = 0; + + /** + * Scrolling mode. + */ + private boolean scrollable = false; + + /** List of action handlers */ + private LinkedList actionHandlers = null; + + /** Action mapper */ + private KeyMapper actionMapper = null; + + /** + * Creates a new empty panel. Ordered layout is used. + */ + public Panel() { + setLayout(null); + } + + /** + * Creates a new empty panel with given layout. Layout must be non-null. + * + * @param layout + * the layout used in the panel. + */ + public Panel(Layout layout) { + setLayout(layout); + } + + /** + * Creates a new empty panel with caption. Default layout is used. + * + * @param caption + * the caption used in the panel. + */ + public Panel(String caption) { + this(caption, null); + } + + /** + * Creates a new empty panel with caption. + * + * @param caption + * the caption of the panel. + * @param layout + * the layout used in the panel. + */ + public Panel(String caption, Layout layout) { + this(layout); + setCaption(caption); + } + + /** + * Gets the current layout of the panel. + * + * @return the Current layout of the panel. + */ + public Layout getLayout() { + return layout; + } + + /** + * Sets the layout of the panel. All the components are moved to new layout. + * + * @param layout + * the New layout of the panel. + */ + public void setLayout(Layout layout) { + + // Only allow non-null layouts + if (layout == null) { + layout = new OrderedLayout(); + // Force margins by default + layout.setMargin(true); + } + + // Sets the panel to be parent for the layout + layout.setParent(this); + dependsOn(layout); + + // If panel already contains a layout, move the contents to new one + // and detach old layout from the panel + if (this.layout != null) { + layout.moveComponentsFrom(this.layout); + removeDirectDependency(this.layout); + this.layout.setParent(null); + } + + // Removes the event listeners from the old layout + if (this.layout != null) { + this.layout + .removeListener((ComponentContainer.ComponentAttachListener) this); + this.layout + .removeListener((ComponentContainer.ComponentDetachListener) this); + } + + // Sets the new layout + this.layout = layout; + + // Adds the event listeners for new layout + layout.addListener((ComponentContainer.ComponentAttachListener) this); + layout.addListener((ComponentContainer.ComponentDetachListener) this); + } + + /** + * Paints the content of this component. + * + * @param target + * the Paint Event. + * @throws PaintException + * if the paint operation failed. + */ + public void paintContent(PaintTarget target) throws PaintException { + layout.paint(target); + + // Add size info as variables + if (getHeight() > -1) { + target.addVariable(this, "height", getHeight() + + UNIT_SYMBOLS[getHeightUnits()]); + } + if (getWidth() > -1) { + target.addVariable(this, "width", getWidth() + + UNIT_SYMBOLS[getWidthUnits()]); + } + + if (isScrollable()) { + target.addVariable(this, "scrollleft", getScrollOffsetX()); + target.addVariable(this, "scrolldown", getScrollOffsetY()); + } + + if (actionHandlers != null && !actionHandlers.isEmpty()) { + target.addVariable(this, "action", ""); + target.startTag("actions"); + + for (Iterator ahi = actionHandlers.iterator(); ahi.hasNext();) { + Action[] aa = ((Action.Handler) ahi.next()).getActions(null, + this); + if (aa != null) { + for (int ai = 0; ai < aa.length; ai++) { + Action a = aa[ai]; + target.startTag("action"); + String akey = actionMapper.key(aa[ai]); + target.addAttribute("key", akey); + if (a.getCaption() != null) { + target.addAttribute("caption", a.getCaption()); + } + if (a.getIcon() != null) { + target.addAttribute("icon", a.getIcon()); + } + if (a instanceof ShortcutAction) { + ShortcutAction sa = (ShortcutAction) a; + target.addAttribute("kc", sa.getKeyCode()); + int[] modifiers = sa.getModifiers(); + if (modifiers != null) { + String[] smodifiers = new String[modifiers.length]; + for (int i = 0; i < modifiers.length; i++) { + smodifiers[i] = String + .valueOf(modifiers[i]); + } + target.addAttribute("mk", smodifiers); + } + } + target.endTag("action"); + } + } + } + target.endTag("actions"); + } + } + + /** + * Gets the component UIDL tag. + * + * @return the Component UIDL tag as string. + */ + public String getTag() { + return "panel"; + } + + /** + * Adds the component into this container. + * + * @param c + * the component to be added. + * @see com.itmill.toolkit.ui.AbstractComponentContainer#addComponent(com.itmill.toolkit.ui.Component) + */ + public void addComponent(Component c) { + layout.addComponent(c); + // No repaint request is made as we except the underlying container to + // request repaints + } + + /** + * Removes the component from this container. + * + * @param c + * The component to be added. + * @see com.itmill.toolkit.ui.AbstractComponentContainer#removeComponent(com.itmill.toolkit.ui.Component) + */ + public void removeComponent(Component c) { + layout.removeComponent(c); + // No repaint request is made as we except the underlying container to + // request repaints + } + + /** + * Gets the component container iterator for going trough all the components + * in the container. + * + * @return the Iterator of the components inside the container. + * @see com.itmill.toolkit.ui.ComponentContainer#getComponentIterator() + */ + public Iterator getComponentIterator() { + return layout.getComponentIterator(); + } + + /** + * Called when one or more variables handled by the implementing class are + * changed. + * + * @see com.itmill.toolkit.terminal.VariableOwner#changeVariables(Object, + * Map) + */ + public void changeVariables(Object source, Map variables) { + super.changeVariables(source, variables); + + // Get new size + Integer newWidth = (Integer) variables.get("width"); + Integer newHeight = (Integer) variables.get("height"); + if (newWidth != null && newWidth.intValue() != getWidth()) { + setWidth(newWidth.intValue()); + // ensure units as we are reading pixels + setWidthUnits(UNITS_PIXELS); + + } + if (newHeight != null && newHeight.intValue() != getHeight()) { + setHeight(newHeight.intValue()); + // ensure units as we are reading pixels + setHeightUnits(UNITS_PIXELS); + } + + // Scrolling + Integer newScrollX = (Integer) variables.get("scrollleft"); + Integer newScrollY = (Integer) variables.get("scrolldown"); + if (newScrollX != null && newScrollX.intValue() != getScrollOffsetX()) { + setScrollOffsetX(newScrollX.intValue()); + } + if (newScrollY != null && newScrollY.intValue() != getScrollOffsetY()) { + setScrollOffsetY(newScrollY.intValue()); + } + + // Actions + if (variables.containsKey("action")) { + String key = (String) variables.get("action"); + Action action = (Action) actionMapper.get(key); + if (action != null && actionHandlers != null) { + for (Iterator i = actionHandlers.iterator(); i.hasNext();) { + ((Action.Handler) i.next()) + .handleAction(action, this, this); + } + } + } + + } + + /* Scrolling functionality */ + + /* Documented in interface */ + public int getScrollOffsetX() { + return scrollOffsetX; + } + + /* Documented in interface */ + public int getScrollOffsetY() { + return scrollOffsetY; + } + + /* Documented in interface */ + public boolean isScrollable() { + return scrollable; + } + + /* Documented in interface */ + public void setScrollable(boolean isScrollingEnabled) { + if (scrollable != isScrollingEnabled) { + scrollable = isScrollingEnabled; + requestRepaint(); + } + } + + /* Documented in interface */ + public void setScrollOffsetX(int pixelsScrolledLeft) { + if (pixelsScrolledLeft < 0) { + throw new IllegalArgumentException( + "Scroll offset must be at least 0"); + } + if (scrollOffsetX != pixelsScrolledLeft) { + scrollOffsetX = pixelsScrolledLeft; + requestRepaint(); + } + } + + /* Documented in interface */ + public void setScrollOffsetY(int pixelsScrolledDown) { + if (pixelsScrolledDown < 0) { + throw new IllegalArgumentException( + "Scroll offset must be at least 0"); + } + if (scrollOffsetY != pixelsScrolledDown) { + scrollOffsetY = pixelsScrolledDown; + requestRepaint(); + } + } + + /* Documented in superclass */ + public void replaceComponent(Component oldComponent, Component newComponent) { + + layout.replaceComponent(oldComponent, newComponent); + } + + /** + * A new component is attached to container. + * + * @see com.itmill.toolkit.ui.ComponentContainer.ComponentAttachListener#componentAttachedToContainer(com.itmill.toolkit.ui.ComponentContainer.ComponentAttachEvent) + */ + public void componentAttachedToContainer(ComponentAttachEvent event) { + if (event.getContainer() == layout) { + fireComponentAttachEvent(event.getAttachedComponent()); + } + } + + /** + * A component has been detached from container. + * + * @see com.itmill.toolkit.ui.ComponentContainer.ComponentDetachListener#componentDetachedFromContainer(com.itmill.toolkit.ui.ComponentContainer.ComponentDetachEvent) + */ + public void componentDetachedFromContainer(ComponentDetachEvent event) { + if (event.getContainer() == layout) { + fireComponentDetachEvent(event.getDetachedComponent()); + } + } + + /** + * Notifies the component that it is connected to an application. + * + * @see com.itmill.toolkit.ui.Component#attach() + */ + public void attach() { + super.attach(); + if (layout != null) { + layout.attach(); + } + } + + /** + * Notifies the component that it is detached from the application. + * + * @see com.itmill.toolkit.ui.Component#detach() + */ + public void detach() { + if (layout != null) { + layout.detach(); + } + } + + /** + * Removes all components from this container. + * + * @see com.itmill.toolkit.ui.ComponentContainer#removeAllComponents() + */ + public void removeAllComponents() { + layout.removeAllComponents(); + } + + public void addActionHandler(Handler actionHandler) { + if (actionHandler != null) { + + if (actionHandlers == null) { + actionHandlers = new LinkedList(); + actionMapper = new KeyMapper(); + } + + if (!actionHandlers.contains(actionHandler)) { + actionHandlers.add(actionHandler); + requestRepaint(); + } + } + + } + + /** + * Removes an action handler. + * + * @see com.itmill.toolkit.event.Action.Container#removeActionHandler(Action.Handler) + */ + public void removeActionHandler(Action.Handler actionHandler) { + + if (actionHandlers != null && actionHandlers.contains(actionHandler)) { + + actionHandlers.remove(actionHandler); + + if (actionHandlers.isEmpty()) { + actionHandlers = null; + actionMapper = null; + } + + requestRepaint(); + } + } + + /* + * (non-Javadoc) + * + * @see com.itmill.toolkit.terminal.Sizeable#getHeight() + */ + public int getHeight() { + return height; + } + + /* + * (non-Javadoc) + * + * @see com.itmill.toolkit.terminal.Sizeable#getHeightUnits() + */ + public int getHeightUnits() { + return heightUnit; + } + + /* + * (non-Javadoc) + * + * @see com.itmill.toolkit.terminal.Sizeable#getWidth() + */ + public int getWidth() { + return width; + } + + /* + * (non-Javadoc) + * + * @see com.itmill.toolkit.terminal.Sizeable#getWidthUnits() + */ + public int getWidthUnits() { + return widthUnit; + } + + /* + * (non-Javadoc) + * + * @see com.itmill.toolkit.terminal.Sizeable#setHeight(int) + */ + public void setHeight(int height) { + this.height = height; + requestRepaint(); + } + + /* + * (non-Javadoc) + * + * @see com.itmill.toolkit.terminal.Sizeable#setHeightUnits(int) + */ + public void setHeightUnits(int units) { + heightUnit = units; + requestRepaint(); + } + + /* + * (non-Javadoc) + * + * @see com.itmill.toolkit.terminal.Sizeable#setSizeFull() + */ + public void setSizeFull() { + height = 100; + width = 100; + heightUnit = UNITS_PERCENTAGE; + widthUnit = UNITS_PERCENTAGE; + requestRepaint(); + } + + /* + * (non-Javadoc) + * + * @see com.itmill.toolkit.terminal.Sizeable#setSizeUndefined() + */ + public void setSizeUndefined() { + height = -1; + width = -1; + heightUnit = UNITS_PIXELS; + widthUnit = UNITS_PIXELS; + requestRepaint(); + } + + /* + * (non-Javadoc) + * + * @see com.itmill.toolkit.terminal.Sizeable#setWidth(int) + */ + public void setWidth(int width) { + this.width = width; + requestRepaint(); + } + + /* + * (non-Javadoc) + * + * @see com.itmill.toolkit.terminal.Sizeable#setWidthUnits(int) + */ + public void setWidthUnits(int units) { + widthUnit = units; + requestRepaint(); + } } diff --git a/src/com/itmill/toolkit/ui/ProgressIndicator.java b/src/com/itmill/toolkit/ui/ProgressIndicator.java index 5a82fe441c..2314e833e1 100644 --- a/src/com/itmill/toolkit/ui/ProgressIndicator.java +++ b/src/com/itmill/toolkit/ui/ProgressIndicator.java @@ -48,214 +48,222 @@ import com.itmill.toolkit.terminal.PaintTarget; * @since 4 */ public class ProgressIndicator extends AbstractField implements Property, - Property.Viewer, Property.ValueChangeListener { - - /** - * Content mode, where the label contains only plain text. The getValue() - * result is coded to XML when painting. - */ - public static final int CONTENT_TEXT = 0; - - /** - * Content mode, where the label contains preformatted text. - */ - public static final int CONTENT_PREFORMATTED = 1; - - private boolean indeterminate = false; - - private Property dataSource; - - private int pollingInterval = 1000; - - /** - * Creates an a new ProgressIndicator. - */ - public ProgressIndicator() { - setPropertyDataSource(new ObjectProperty(new Float(0), Float.class)); - } - - /** - * Creates a new instance of ProgressIndicator with given state. - * - * @param value - */ - public ProgressIndicator(Float value) { - setPropertyDataSource(new ObjectProperty(value, Float.class)); - } - - /** - * Creates a new instance of ProgressIndicator with stae read from given - * datasource. - * - * @param contentSource - */ - public ProgressIndicator(Property contentSource) { - setPropertyDataSource(contentSource); - } - - /** - * Gets the component UIDL tag. - * - * @return the Component UIDL tag as string. - */ - public String getTag() { - return "progressindicator"; - } - - /** - * Sets the component to read-only. Readonly is not used in - * ProgressIndicator. - * - * @param readOnly - * True to enable read-only mode, False to disable it. - */ - public void setReadOnly(boolean readOnly) { - if (dataSource == null) - throw new IllegalStateException("Datasource must be se"); - dataSource.setReadOnly(readOnly); - } - - /** - * Is the component read-only ? Readonly is not used in ProgressIndicator - - * this returns allways false. - * - * @return True if the component is in read only mode. - */ - public boolean isReadOnly() { - if (dataSource == null) - throw new IllegalStateException("Datasource must be se"); - return dataSource.isReadOnly(); - } - - /** - * Paints the content of this component. - * - * @param target - * the Paint Event. - * @throws PaintException - * if the Paint Operation fails. - */ - public void paintContent(PaintTarget target) throws PaintException { - target.addAttribute("indeterminate", indeterminate); - target.addAttribute("pollinginterval", pollingInterval); - target.addAttribute("state", this.getValue().toString()); - } - - /** - * Gets the value of the ProgressIndicator. Value of the ProgressIndicator - * is Float between 0 and 1. - * - * @return the Value of the ProgressIndicator. - * @see com.itmill.toolkit.ui.AbstractField#getValue() - */ - public Object getValue() { - if (dataSource == null) - throw new IllegalStateException("Datasource must be se"); - return dataSource.getValue(); - } - - /** - * Sets the value of the ProgressIndicator. Value of the ProgressIndicator - * is the Float between 0 and 1. - * - * @param newValue - * the New value of the ProgressIndicator. - * @see com.itmill.toolkit.ui.AbstractField#setValue(java.lang.Object) - */ - public void setValue(Object newValue) { - if (dataSource == null) - throw new IllegalStateException("Datasource must be se"); - this.dataSource.setValue(newValue); - } - - /** - * @see com.itmill.toolkit.ui.AbstractField#toString() - */ - public String toString() { - if (dataSource == null) - throw new IllegalStateException("Datasource must be se"); - return dataSource.toString(); - } - - /** - * @see com.itmill.toolkit.ui.AbstractField#getType() - */ - public Class getType() { - if (dataSource == null) - throw new IllegalStateException("Datasource must be se"); - return dataSource.getType(); - } - - /** - * Gets the viewing data-source property. - * - * @return the datasource. - * @see com.itmill.toolkit.ui.AbstractField#getPropertyDataSource() - */ - public Property getPropertyDataSource() { - return dataSource; - } - - /** - * Sets the property as data-source for viewing. - * - * @param newDataSource - * the new data source. - * @see com.itmill.toolkit.ui.AbstractField#setPropertyDataSource(com.itmill.toolkit.data.Property) - */ - public void setPropertyDataSource(Property newDataSource) { - // Stops listening the old data source changes - if (dataSource != null - && Property.ValueChangeNotifier.class - .isAssignableFrom(dataSource.getClass())) - ((Property.ValueChangeNotifier) dataSource).removeListener(this); - - // Sets the new data source - dataSource = newDataSource; - - // Listens the new data source if possible - if (dataSource != null - && Property.ValueChangeNotifier.class - .isAssignableFrom(dataSource.getClass())) - ((Property.ValueChangeNotifier) dataSource).addListener(this); - } - - /** - * Gets the mode of ProgressIndicator. - * - * @return true if in indeterminate mode. - */ - public boolean getContentMode() { - return indeterminate; - } - - /** - * Sets the ProgressIndicator to indeterminate mode. - * - * @param newValue - * true to set to indeterminate mode. - */ - public void setIndeterminate(boolean newValue) { - indeterminate = newValue; - } - - /** - * Sets the interval that component checks for progress. - * - * @param newValue - * the interval in milliseconds. - */ - public void setPollingInterval(int newValue) { - pollingInterval = newValue; - } - - /** - * Gets the interval that component checks for progress. - * - * @return the interval in milliseconds. - */ - public int getPollingInterval() { - return pollingInterval; - } + Property.Viewer, Property.ValueChangeListener { + + /** + * Content mode, where the label contains only plain text. The getValue() + * result is coded to XML when painting. + */ + public static final int CONTENT_TEXT = 0; + + /** + * Content mode, where the label contains preformatted text. + */ + public static final int CONTENT_PREFORMATTED = 1; + + private boolean indeterminate = false; + + private Property dataSource; + + private int pollingInterval = 1000; + + /** + * Creates an a new ProgressIndicator. + */ + public ProgressIndicator() { + setPropertyDataSource(new ObjectProperty(new Float(0), Float.class)); + } + + /** + * Creates a new instance of ProgressIndicator with given state. + * + * @param value + */ + public ProgressIndicator(Float value) { + setPropertyDataSource(new ObjectProperty(value, Float.class)); + } + + /** + * Creates a new instance of ProgressIndicator with stae read from given + * datasource. + * + * @param contentSource + */ + public ProgressIndicator(Property contentSource) { + setPropertyDataSource(contentSource); + } + + /** + * Gets the component UIDL tag. + * + * @return the Component UIDL tag as string. + */ + public String getTag() { + return "progressindicator"; + } + + /** + * Sets the component to read-only. Readonly is not used in + * ProgressIndicator. + * + * @param readOnly + * True to enable read-only mode, False to disable it. + */ + public void setReadOnly(boolean readOnly) { + if (dataSource == null) { + throw new IllegalStateException("Datasource must be se"); + } + dataSource.setReadOnly(readOnly); + } + + /** + * Is the component read-only ? Readonly is not used in ProgressIndicator - + * this returns allways false. + * + * @return True if the component is in read only mode. + */ + public boolean isReadOnly() { + if (dataSource == null) { + throw new IllegalStateException("Datasource must be se"); + } + return dataSource.isReadOnly(); + } + + /** + * Paints the content of this component. + * + * @param target + * the Paint Event. + * @throws PaintException + * if the Paint Operation fails. + */ + public void paintContent(PaintTarget target) throws PaintException { + target.addAttribute("indeterminate", indeterminate); + target.addAttribute("pollinginterval", pollingInterval); + target.addAttribute("state", getValue().toString()); + } + + /** + * Gets the value of the ProgressIndicator. Value of the ProgressIndicator + * is Float between 0 and 1. + * + * @return the Value of the ProgressIndicator. + * @see com.itmill.toolkit.ui.AbstractField#getValue() + */ + public Object getValue() { + if (dataSource == null) { + throw new IllegalStateException("Datasource must be se"); + } + return dataSource.getValue(); + } + + /** + * Sets the value of the ProgressIndicator. Value of the ProgressIndicator + * is the Float between 0 and 1. + * + * @param newValue + * the New value of the ProgressIndicator. + * @see com.itmill.toolkit.ui.AbstractField#setValue(java.lang.Object) + */ + public void setValue(Object newValue) { + if (dataSource == null) { + throw new IllegalStateException("Datasource must be se"); + } + dataSource.setValue(newValue); + } + + /** + * @see com.itmill.toolkit.ui.AbstractField#toString() + */ + public String toString() { + if (dataSource == null) { + throw new IllegalStateException("Datasource must be se"); + } + return dataSource.toString(); + } + + /** + * @see com.itmill.toolkit.ui.AbstractField#getType() + */ + public Class getType() { + if (dataSource == null) { + throw new IllegalStateException("Datasource must be se"); + } + return dataSource.getType(); + } + + /** + * Gets the viewing data-source property. + * + * @return the datasource. + * @see com.itmill.toolkit.ui.AbstractField#getPropertyDataSource() + */ + public Property getPropertyDataSource() { + return dataSource; + } + + /** + * Sets the property as data-source for viewing. + * + * @param newDataSource + * the new data source. + * @see com.itmill.toolkit.ui.AbstractField#setPropertyDataSource(com.itmill.toolkit.data.Property) + */ + public void setPropertyDataSource(Property newDataSource) { + // Stops listening the old data source changes + if (dataSource != null + && Property.ValueChangeNotifier.class + .isAssignableFrom(dataSource.getClass())) { + ((Property.ValueChangeNotifier) dataSource).removeListener(this); + } + + // Sets the new data source + dataSource = newDataSource; + + // Listens the new data source if possible + if (dataSource != null + && Property.ValueChangeNotifier.class + .isAssignableFrom(dataSource.getClass())) { + ((Property.ValueChangeNotifier) dataSource).addListener(this); + } + } + + /** + * Gets the mode of ProgressIndicator. + * + * @return true if in indeterminate mode. + */ + public boolean getContentMode() { + return indeterminate; + } + + /** + * Sets the ProgressIndicator to indeterminate mode. + * + * @param newValue + * true to set to indeterminate mode. + */ + public void setIndeterminate(boolean newValue) { + indeterminate = newValue; + } + + /** + * Sets the interval that component checks for progress. + * + * @param newValue + * the interval in milliseconds. + */ + public void setPollingInterval(int newValue) { + pollingInterval = newValue; + } + + /** + * Gets the interval that component checks for progress. + * + * @return the interval in milliseconds. + */ + public int getPollingInterval() { + return pollingInterval; + } } diff --git a/src/com/itmill/toolkit/ui/RichTextArea.java b/src/com/itmill/toolkit/ui/RichTextArea.java index 27817611c0..96043b5751 100644 --- a/src/com/itmill/toolkit/ui/RichTextArea.java +++ b/src/com/itmill/toolkit/ui/RichTextArea.java @@ -4,16 +4,13 @@ import com.itmill.toolkit.terminal.PaintException; import com.itmill.toolkit.terminal.PaintTarget; /** - * TODO dont' allow getting into bad state - * TODO implement Sizeable interface + * TODO dont' allow getting into bad state TODO implement Sizeable interface */ public class RichTextArea extends TextField { - public void paintContent(PaintTarget target) throws PaintException { - target.addAttribute("richtext", true); - super.paintContent(target); - } - - + public void paintContent(PaintTarget target) throws PaintException { + target.addAttribute("richtext", true); + super.paintContent(target); + } } diff --git a/src/com/itmill/toolkit/ui/Slider.java b/src/com/itmill/toolkit/ui/Slider.java index 76047097ad..02191f8cfd 100644 --- a/src/com/itmill/toolkit/ui/Slider.java +++ b/src/com/itmill/toolkit/ui/Slider.java @@ -41,428 +41,440 @@ import com.itmill.toolkit.terminal.PaintTarget; */ public class Slider extends AbstractField { - public static final int ORIENTATION_HORIZONTAL = 0; - - public static final int ORIENTATION_VERTICAL = 1; - - /** - * Style constant representing a scrollbar styled slider. Use this with - * {@link #addStyleName(String)}. Default styling usually represents a - * common slider found e.g. in Adobe Photoshop. The client side - * implementation dictates how different styles will look. - */ - public static final String STYLE_SCROLLBAR = "scrollbar"; - - /** Minimum value of slider */ - private double min = 0; - - /** Maximum value of slider */ - private double max = 100; - - /** - * Resolution, how many digits are considered relevant after desimal point. - * Must be a non-negative value - */ - private int resolution = 0; - - /** - * Slider orientation (horizontal/vertical), defaults . - */ - private int orientation = ORIENTATION_HORIZONTAL; - - /** - * Slider size in pixels. In horizontal mode, if set to -1, allow 100% width - * of container. In vertical mode, if set to -1, default height is - * determined by the client-side implementation. - */ - private int size = -1; - - /** - * Handle (draggable control element) size in percents relative to base - * size. Must be a value between 1-99. Other values are converted to nearest - * bound. A negative value sets the width to auto (client-side - * implementation calculates). - */ - private int handleSize = -1; - - /** - * Show arrows that can be pressed to slide the handle in some increments - * (client-side implementation decides the increment, usually somewhere - * between 5-10% of slide range). - */ - private boolean arrows = false; - - /** - * Default Slider constructor. Sets all values to defaults and the slide - * handle at minimum value. - * - */ - public Slider() { - super(); - super.setValue(new Double(min)); - } - - /** - * Create a new slider with the caption given as parameter. All slider - * values set to defaults. - * - * @param caption - * The caption for this Slider (e.g. "Volume"). - */ - public Slider(String caption) { - this(); - setCaption(caption); - } - - /** - * Create a new slider with given range and resolution - * - * @param min - * @param max - * @param resolution - */ - public Slider(double min, double max, int resolution) { - this(); - setMin(min); - setMax(max); - setResolution(resolution); - } - - /** - * Create a new slider with given range - * - * @param min - * @param max - */ - public Slider(int min, int max) { - this(); - setMin(min); - setMax(max); - setResolution(0); - } - - /** - * Create a new slider with given caption and range - * - * @param caption - * @param min - * @param max - */ - public Slider(String caption, int min, int max) { - this(min, max); - setCaption(caption); - } - - /** - * Gets the biggest possible value in Sliders range. - * - * @return the biggest value slider can have - */ - public double getMax() { - return max; - } - - /** - * Set the maximum value of the Slider. If the current value of the Slider - * is out of new bounds, the value is set to new minimum. - * - * @param max - * New maximum value of the Slider. - */ - public void setMax(double max) { - this.max = max; - try { - if ((new Double(getValue().toString())).doubleValue() > max) - super.setValue(new Double(max)); - } catch (ClassCastException e) { - super.setValue(new Double(max)); - } - requestRepaint(); - } - - /** - * Gets the minimum value in Sliders range. - * - * @return the smalles value slider can have - */ - public double getMin() { - return min; - } - - /** - * Set the minimum value of the Slider. If the current value of the Slider - * is out of new bounds, the value is set to new minimum. - * - * @param min - * New minimum value of the Slider. - */ - public void setMin(double min) { - this.min = min; - try { - if ((new Double(getValue().toString())).doubleValue() < min) - super.setValue(new Double(min)); - } catch (ClassCastException e) { - super.setValue(new Double(min)); - } - requestRepaint(); - } - - /** - * Get the current orientation of the Slider (horizontal or vertical). - * - * @return orientation - */ - public int getOrientation() { - return orientation; - } - - /** - * Set the orientation of the Slider. - * - * @param int - * new orientation - */ - public void setOrientation(int orientation) { - this.orientation = orientation; - requestRepaint(); - } - - /** - * Get the current resolution of the Slider. - * - * @return resolution - */ - public int getResolution() { - return resolution; - } - - /** - * Set a new resolution for the Slider. - * - * @param resolution - */ - public void setResolution(int resolution) { - if (resolution < 0) - return; - this.resolution = resolution; - requestRepaint(); - } - - /** - * Set the value of this Slider. - * - * @param value - * New value of Slider. Must be within Sliders range (min - max), - * otherwise throws an exception. - * @param repaintIsNotNeeded - * If true, client-side is not requested to repaint itself. - * @throws ValueOutOfBoundsException - */ - public void setValue(Double value, boolean repaintIsNotNeeded) - throws ValueOutOfBoundsException { - double v = value.doubleValue(); - double newValue; - if (resolution > 0) { - // Round up to resolution - newValue = (int) (v * (double) Math.pow(10, resolution)); - newValue = newValue / (double) Math.pow(10, resolution); - if (min > newValue || max < newValue) - throw new ValueOutOfBoundsException(value); - } else { - newValue = (int) v; - if (min > newValue || max < newValue) - throw new ValueOutOfBoundsException(value); - } - super.setValue(new Double(newValue), repaintIsNotNeeded); - } - - /** - * Set the value of this Slider. - * - * @param value - * New value of Slider. Must be within Sliders range (min - max), - * otherwise throws an exception. - * @throws ValueOutOfBoundsException - */ - public void setValue(Double value) throws ValueOutOfBoundsException { - setValue(value, false); - } - - /** - * Set the value of this Slider. - * - * @param value - * New value of Slider. Must be within Sliders range (min - max), - * otherwise throws an exception. - * @throws ValueOutOfBoundsException - */ - public void setValue(double value) throws ValueOutOfBoundsException { - setValue(new Double(value), false); - } - - /** - * Get the current Slider size. - * - * @return size in pixels or -1 for auto sizing. - */ - public int getSize() { - return size; - } - - /** - * Set the size for this Slider. - * - * @param size - * in pixels, or -1 auto sizing. - */ - public void setSize(int size) { - this.size = size; - requestRepaint(); - } - - /** - * Get the handle size of this Slider. - * - * @return handle size in percentages. - */ - public int getHandleSize() { - return handleSize; - } - - /** - * Set the handle size of this Slider. - * - * @param handleSize - * in percentages relative to slider base size. - */ - public void setHandleSize(int handleSize) { - if (handleSize < 0) - this.handleSize = -1; - else if (handleSize > 99) - this.handleSize = 99; - else if (handleSize < 1) - this.handleSize = 1; - else - this.handleSize = handleSize; - requestRepaint(); - } - - /* - * Show or hide slider arrows. - * - * @param visible - *//* - public void setArrows(boolean visible) { - arrows = visible; - requestRepaint(); - }*/ - - /* - * Does the slider have arrows? - * - * @return arrows visible - *//* - public boolean isArrowsVisible() { - return arrows; - }*/ - - public String getTag() { - return "slider"; - } - - public void paintContent(PaintTarget target) throws PaintException { - super.paintContent(target); - - target.addAttribute("min", min); - if (max > min) - target.addAttribute("max", max); - else - target.addAttribute("max", min); - target.addAttribute("resolution", resolution); - - if (resolution > 0) - target.addVariable(this, "value", ((Double) getValue()) - .doubleValue()); - else - target.addVariable(this, "value", ((Double) getValue()).intValue()); - - if (orientation == ORIENTATION_VERTICAL) - target.addAttribute("vertical", true); - - if (arrows) - target.addAttribute("arrows", true); - - if (size > -1) - target.addAttribute("size", size); - - if (min != max && min < max) - target.addAttribute("hsize", handleSize); - else - target.addAttribute("hsize", 100); - - } - - /** - * Invoked when the value of a variable has changed. Slider listeners are - * notified if the slider value has changed. - * - * @param source - * @param variables - */ - public void changeVariables(Object source, Map variables) { - if (variables.containsKey("value")) { - Object value = variables.get("value"); - Double newValue = new Double(value.toString()); - if (newValue != null && newValue != getValue() - && !newValue.equals(getValue())) { - try { - setValue(newValue, true); - } catch (ValueOutOfBoundsException e) { - // Convert to nearest bound - double out = e.getValue().doubleValue(); - if (out < min) - out = min; - if (out > max) - out = max; - super.setValue(new Double(out), false); - } - } - } - } - - /** - * ValueOutOfBoundsException - * - * @author IT Mill Ltd. - * - */ - public class ValueOutOfBoundsException extends Exception { - - /** - * Serial generated by Eclipse. - */ - private static final long serialVersionUID = -6451298598644446340L; - - private Double value; - - /** - * Constructs an ValueOutOfBoundsException with the - * specified detail message. - * - * @param valueOutOfBounds - */ - public ValueOutOfBoundsException(Double valueOutOfBounds) { - this.value = valueOutOfBounds; - } - - public Double getValue() { - return this.value; - } - - } - - public Class getType() { - return Double.class; - } + public static final int ORIENTATION_HORIZONTAL = 0; + + public static final int ORIENTATION_VERTICAL = 1; + + /** + * Style constant representing a scrollbar styled slider. Use this with + * {@link #addStyleName(String)}. Default styling usually represents a + * common slider found e.g. in Adobe Photoshop. The client side + * implementation dictates how different styles will look. + */ + public static final String STYLE_SCROLLBAR = "scrollbar"; + + /** Minimum value of slider */ + private double min = 0; + + /** Maximum value of slider */ + private double max = 100; + + /** + * Resolution, how many digits are considered relevant after desimal point. + * Must be a non-negative value + */ + private int resolution = 0; + + /** + * Slider orientation (horizontal/vertical), defaults . + */ + private int orientation = ORIENTATION_HORIZONTAL; + + /** + * Slider size in pixels. In horizontal mode, if set to -1, allow 100% width + * of container. In vertical mode, if set to -1, default height is + * determined by the client-side implementation. + */ + private int size = -1; + + /** + * Handle (draggable control element) size in percents relative to base + * size. Must be a value between 1-99. Other values are converted to nearest + * bound. A negative value sets the width to auto (client-side + * implementation calculates). + */ + private int handleSize = -1; + + /** + * Show arrows that can be pressed to slide the handle in some increments + * (client-side implementation decides the increment, usually somewhere + * between 5-10% of slide range). + */ + private boolean arrows = false; + + /** + * Default Slider constructor. Sets all values to defaults and the slide + * handle at minimum value. + * + */ + public Slider() { + super(); + super.setValue(new Double(min)); + } + + /** + * Create a new slider with the caption given as parameter. All slider + * values set to defaults. + * + * @param caption + * The caption for this Slider (e.g. "Volume"). + */ + public Slider(String caption) { + this(); + setCaption(caption); + } + + /** + * Create a new slider with given range and resolution + * + * @param min + * @param max + * @param resolution + */ + public Slider(double min, double max, int resolution) { + this(); + setMin(min); + setMax(max); + setResolution(resolution); + } + + /** + * Create a new slider with given range + * + * @param min + * @param max + */ + public Slider(int min, int max) { + this(); + setMin(min); + setMax(max); + setResolution(0); + } + + /** + * Create a new slider with given caption and range + * + * @param caption + * @param min + * @param max + */ + public Slider(String caption, int min, int max) { + this(min, max); + setCaption(caption); + } + + /** + * Gets the biggest possible value in Sliders range. + * + * @return the biggest value slider can have + */ + public double getMax() { + return max; + } + + /** + * Set the maximum value of the Slider. If the current value of the Slider + * is out of new bounds, the value is set to new minimum. + * + * @param max + * New maximum value of the Slider. + */ + public void setMax(double max) { + this.max = max; + try { + if ((new Double(getValue().toString())).doubleValue() > max) { + super.setValue(new Double(max)); + } + } catch (ClassCastException e) { + super.setValue(new Double(max)); + } + requestRepaint(); + } + + /** + * Gets the minimum value in Sliders range. + * + * @return the smalles value slider can have + */ + public double getMin() { + return min; + } + + /** + * Set the minimum value of the Slider. If the current value of the Slider + * is out of new bounds, the value is set to new minimum. + * + * @param min + * New minimum value of the Slider. + */ + public void setMin(double min) { + this.min = min; + try { + if ((new Double(getValue().toString())).doubleValue() < min) { + super.setValue(new Double(min)); + } + } catch (ClassCastException e) { + super.setValue(new Double(min)); + } + requestRepaint(); + } + + /** + * Get the current orientation of the Slider (horizontal or vertical). + * + * @return orientation + */ + public int getOrientation() { + return orientation; + } + + /** + * Set the orientation of the Slider. + * + * @param int + * new orientation + */ + public void setOrientation(int orientation) { + this.orientation = orientation; + requestRepaint(); + } + + /** + * Get the current resolution of the Slider. + * + * @return resolution + */ + public int getResolution() { + return resolution; + } + + /** + * Set a new resolution for the Slider. + * + * @param resolution + */ + public void setResolution(int resolution) { + if (resolution < 0) { + return; + } + this.resolution = resolution; + requestRepaint(); + } + + /** + * Set the value of this Slider. + * + * @param value + * New value of Slider. Must be within Sliders range (min - + * max), otherwise throws an exception. + * @param repaintIsNotNeeded + * If true, client-side is not requested to repaint itself. + * @throws ValueOutOfBoundsException + */ + public void setValue(Double value, boolean repaintIsNotNeeded) + throws ValueOutOfBoundsException { + double v = value.doubleValue(); + double newValue; + if (resolution > 0) { + // Round up to resolution + newValue = (int) (v * Math.pow(10, resolution)); + newValue = newValue / Math.pow(10, resolution); + if (min > newValue || max < newValue) { + throw new ValueOutOfBoundsException(value); + } + } else { + newValue = (int) v; + if (min > newValue || max < newValue) { + throw new ValueOutOfBoundsException(value); + } + } + super.setValue(new Double(newValue), repaintIsNotNeeded); + } + + /** + * Set the value of this Slider. + * + * @param value + * New value of Slider. Must be within Sliders range (min - + * max), otherwise throws an exception. + * @throws ValueOutOfBoundsException + */ + public void setValue(Double value) throws ValueOutOfBoundsException { + setValue(value, false); + } + + /** + * Set the value of this Slider. + * + * @param value + * New value of Slider. Must be within Sliders range (min - + * max), otherwise throws an exception. + * @throws ValueOutOfBoundsException + */ + public void setValue(double value) throws ValueOutOfBoundsException { + setValue(new Double(value), false); + } + + /** + * Get the current Slider size. + * + * @return size in pixels or -1 for auto sizing. + */ + public int getSize() { + return size; + } + + /** + * Set the size for this Slider. + * + * @param size + * in pixels, or -1 auto sizing. + */ + public void setSize(int size) { + this.size = size; + requestRepaint(); + } + + /** + * Get the handle size of this Slider. + * + * @return handle size in percentages. + */ + public int getHandleSize() { + return handleSize; + } + + /** + * Set the handle size of this Slider. + * + * @param handleSize + * in percentages relative to slider base size. + */ + public void setHandleSize(int handleSize) { + if (handleSize < 0) { + this.handleSize = -1; + } else if (handleSize > 99) { + this.handleSize = 99; + } else if (handleSize < 1) { + this.handleSize = 1; + } else { + this.handleSize = handleSize; + } + requestRepaint(); + } + + /* + * Show or hide slider arrows. + * + * @param visible + *//* + * public void setArrows(boolean visible) { arrows = visible; + * requestRepaint(); } + */ + + /* + * Does the slider have arrows? + * + * @return arrows visible + *//* + * public boolean isArrowsVisible() { return arrows; } + */ + + public String getTag() { + return "slider"; + } + + public void paintContent(PaintTarget target) throws PaintException { + super.paintContent(target); + + target.addAttribute("min", min); + if (max > min) { + target.addAttribute("max", max); + } else { + target.addAttribute("max", min); + } + target.addAttribute("resolution", resolution); + + if (resolution > 0) { + target.addVariable(this, "value", ((Double) getValue()) + .doubleValue()); + } else { + target.addVariable(this, "value", ((Double) getValue()).intValue()); + } + + if (orientation == ORIENTATION_VERTICAL) { + target.addAttribute("vertical", true); + } + + if (arrows) { + target.addAttribute("arrows", true); + } + + if (size > -1) { + target.addAttribute("size", size); + } + + if (min != max && min < max) { + target.addAttribute("hsize", handleSize); + } else { + target.addAttribute("hsize", 100); + } + + } + + /** + * Invoked when the value of a variable has changed. Slider listeners are + * notified if the slider value has changed. + * + * @param source + * @param variables + */ + public void changeVariables(Object source, Map variables) { + if (variables.containsKey("value")) { + Object value = variables.get("value"); + Double newValue = new Double(value.toString()); + if (newValue != null && newValue != getValue() + && !newValue.equals(getValue())) { + try { + setValue(newValue, true); + } catch (ValueOutOfBoundsException e) { + // Convert to nearest bound + double out = e.getValue().doubleValue(); + if (out < min) { + out = min; + } + if (out > max) { + out = max; + } + super.setValue(new Double(out), false); + } + } + } + } + + /** + * ValueOutOfBoundsException + * + * @author IT Mill Ltd. + * + */ + public class ValueOutOfBoundsException extends Exception { + + /** + * Serial generated by Eclipse. + */ + private static final long serialVersionUID = -6451298598644446340L; + + private Double value; + + /** + * Constructs an ValueOutOfBoundsException with the + * specified detail message. + * + * @param valueOutOfBounds + */ + public ValueOutOfBoundsException(Double valueOutOfBounds) { + value = valueOutOfBounds; + } + + public Double getValue() { + return value; + } + + } + + public Class getType() { + return Double.class; + } } diff --git a/src/com/itmill/toolkit/ui/SplitPanel.java b/src/com/itmill/toolkit/ui/SplitPanel.java index be17d4ef72..f26d39deda 100644 --- a/src/com/itmill/toolkit/ui/SplitPanel.java +++ b/src/com/itmill/toolkit/ui/SplitPanel.java @@ -47,242 +47,252 @@ import com.itmill.toolkit.terminal.Sizeable; */ public class SplitPanel extends AbstractLayout { - /* Predefined orientations ***************************************** */ - - /** - * Components are to be layed out vertically. - */ - public static int ORIENTATION_VERTICAL = 0; - - /** - * Components are to be layed out horizontally. - */ - public static int ORIENTATION_HORIZONTAL = 1; - - private Component firstComponent; - - private Component secondComponent; - - /** - * Orientation of the layout. - */ - private int orientation; - - private int pos = 50; - - private int posUnit = UNITS_PERCENTAGE; - - /** - * Creates a new split panel. The orientation of the panels is - * ORIENTATION_VERTICAL. - */ - public SplitPanel() { - orientation = ORIENTATION_VERTICAL; - setSizeFull(); - } - - /** - * Create a new split panels. The orientation of the panel is given as - * parameters. - * - * @param orientation - * the Orientation of the layout. - */ - public SplitPanel(int orientation) { - this.orientation = orientation; - setSizeFull(); - } - - /** - * Gets the component UIDL tag. - * - * @return the Component UIDL tag as string. - */ - public String getTag() { - if (orientation == ORIENTATION_HORIZONTAL) { - return "hsplitpanel"; - } else { - return "vsplitpanel"; - } - } - - /** - * Add a component into this container. The component is added to the right - * or under the previous component. - * - * @param c - * the component to be added. - */ - public void addComponent(Component c) { - if (firstComponent == null) { - firstComponent = c; - } else if (secondComponent == null) { - secondComponent = c; - } else { - throw new UnsupportedOperationException( - "Split panel can contain only two components"); - } - super.addComponent(c); - requestRepaint(); - } - - public void setFirstComponent(Component c) { - if (firstComponent != null) { - // detach old - removeComponent(firstComponent); - } - firstComponent = c; - super.addComponent(c); - } - - public void setSecondComponent(Component c) { - if (secondComponent != null) { - // detach old - removeComponent(c); - } - secondComponent = c; - super.addComponent(c); - } - - /** - * Removes the component from this container. - * - * @param c - * the component to be removed. - */ - public void removeComponent(Component c) { - super.removeComponent(c); - if (c == firstComponent) - firstComponent = null; - else - secondComponent = null; - requestRepaint(); - } - - /** - * Gets the component container iterator for going trough all the components - * in the container. - * - * @return the Iterator of the components inside the container. - */ - public Iterator getComponentIterator() { - return new Iterator() { - int i = 0; - - public boolean hasNext() { - if (i < (firstComponent == null ? 0 : 1) - + (secondComponent == null ? 0 : 1)) - return true; - return false; - } - - public Object next() { - if (!hasNext()) - return null; - i++; - if (i == 1) - return firstComponent == null ? secondComponent - : firstComponent; - else if (i == 2) - return secondComponent; - return null; - } - - public void remove() { - if (i == 1) { - if (firstComponent != null) { - setFirstComponent(null); - i = 0; - } else - setSecondComponent(null); - } else if (i == 2) - setSecondComponent(null); - } - }; - } - - /** - * Paints the content of this component. - * - * @param target - * the Paint Event. - * @throws PaintException - * if the paint operation failed. - */ - public void paintContent(PaintTarget target) throws PaintException { - super.paintContent(target); - - String position = pos + UNIT_SYMBOLS[posUnit]; - - target.addAttribute("position", position); - - if (firstComponent != null) - firstComponent.paint(target); - else - (new OrderedLayout()).paint(target); - if (secondComponent != null) - secondComponent.paint(target); - else - (new OrderedLayout()).paint(target); - } - - /** - * Gets the orientation of the container. - * - * @return the Value of property orientation. - */ - public int getOrientation() { - return this.orientation; - } - - /** - * Set the orientation of the container. - * - * @param orientation - * the New value of property orientation. - */ - public void setOrientation(int orientation) { - - // Checks the validity of the argument - if (orientation < ORIENTATION_VERTICAL - || orientation > ORIENTATION_HORIZONTAL) - throw new IllegalArgumentException(); - - this.orientation = orientation; - requestRepaint(); - } - - /* Documented in superclass */ - public void replaceComponent(Component oldComponent, Component newComponent) { - if (oldComponent == firstComponent) { - setFirstComponent(newComponent); - } else if (oldComponent == secondComponent) { - setSecondComponent(secondComponent); - } - requestRepaint(); - } - - /** - * Moves the position of the splitter. - * - * @param pos - * the new size of the first region in persentage - */ - public void setSplitPosition(int pos) { - setSplitPosition(pos, UNITS_PERCENTAGE); - } - - /** - * Moves the position of the splitter with given position and unit. - * - * @param pos - * size of the first region - * @param unit - * the unit (from {@link Sizeable}) in which the size is given. - */ - public void setSplitPosition(int pos, int unit) { - this.pos = pos; - this.posUnit = unit; - } + /* Predefined orientations ***************************************** */ + + /** + * Components are to be layed out vertically. + */ + public static int ORIENTATION_VERTICAL = 0; + + /** + * Components are to be layed out horizontally. + */ + public static int ORIENTATION_HORIZONTAL = 1; + + private Component firstComponent; + + private Component secondComponent; + + /** + * Orientation of the layout. + */ + private int orientation; + + private int pos = 50; + + private int posUnit = UNITS_PERCENTAGE; + + /** + * Creates a new split panel. The orientation of the panels is + * ORIENTATION_VERTICAL. + */ + public SplitPanel() { + orientation = ORIENTATION_VERTICAL; + setSizeFull(); + } + + /** + * Create a new split panels. The orientation of the panel is given as + * parameters. + * + * @param orientation + * the Orientation of the layout. + */ + public SplitPanel(int orientation) { + this.orientation = orientation; + setSizeFull(); + } + + /** + * Gets the component UIDL tag. + * + * @return the Component UIDL tag as string. + */ + public String getTag() { + if (orientation == ORIENTATION_HORIZONTAL) { + return "hsplitpanel"; + } else { + return "vsplitpanel"; + } + } + + /** + * Add a component into this container. The component is added to the right + * or under the previous component. + * + * @param c + * the component to be added. + */ + public void addComponent(Component c) { + if (firstComponent == null) { + firstComponent = c; + } else if (secondComponent == null) { + secondComponent = c; + } else { + throw new UnsupportedOperationException( + "Split panel can contain only two components"); + } + super.addComponent(c); + requestRepaint(); + } + + public void setFirstComponent(Component c) { + if (firstComponent != null) { + // detach old + removeComponent(firstComponent); + } + firstComponent = c; + super.addComponent(c); + } + + public void setSecondComponent(Component c) { + if (secondComponent != null) { + // detach old + removeComponent(c); + } + secondComponent = c; + super.addComponent(c); + } + + /** + * Removes the component from this container. + * + * @param c + * the component to be removed. + */ + public void removeComponent(Component c) { + super.removeComponent(c); + if (c == firstComponent) { + firstComponent = null; + } else { + secondComponent = null; + } + requestRepaint(); + } + + /** + * Gets the component container iterator for going trough all the components + * in the container. + * + * @return the Iterator of the components inside the container. + */ + public Iterator getComponentIterator() { + return new Iterator() { + int i = 0; + + public boolean hasNext() { + if (i < (firstComponent == null ? 0 : 1) + + (secondComponent == null ? 0 : 1)) { + return true; + } + return false; + } + + public Object next() { + if (!hasNext()) { + return null; + } + i++; + if (i == 1) { + return firstComponent == null ? secondComponent + : firstComponent; + } else if (i == 2) { + return secondComponent; + } + return null; + } + + public void remove() { + if (i == 1) { + if (firstComponent != null) { + setFirstComponent(null); + i = 0; + } else { + setSecondComponent(null); + } + } else if (i == 2) { + setSecondComponent(null); + } + } + }; + } + + /** + * Paints the content of this component. + * + * @param target + * the Paint Event. + * @throws PaintException + * if the paint operation failed. + */ + public void paintContent(PaintTarget target) throws PaintException { + super.paintContent(target); + + String position = pos + UNIT_SYMBOLS[posUnit]; + + target.addAttribute("position", position); + + if (firstComponent != null) { + firstComponent.paint(target); + } else { + (new OrderedLayout()).paint(target); + } + if (secondComponent != null) { + secondComponent.paint(target); + } else { + (new OrderedLayout()).paint(target); + } + } + + /** + * Gets the orientation of the container. + * + * @return the Value of property orientation. + */ + public int getOrientation() { + return orientation; + } + + /** + * Set the orientation of the container. + * + * @param orientation + * the New value of property orientation. + */ + public void setOrientation(int orientation) { + + // Checks the validity of the argument + if (orientation < ORIENTATION_VERTICAL + || orientation > ORIENTATION_HORIZONTAL) { + throw new IllegalArgumentException(); + } + + this.orientation = orientation; + requestRepaint(); + } + + /* Documented in superclass */ + public void replaceComponent(Component oldComponent, Component newComponent) { + if (oldComponent == firstComponent) { + setFirstComponent(newComponent); + } else if (oldComponent == secondComponent) { + setSecondComponent(secondComponent); + } + requestRepaint(); + } + + /** + * Moves the position of the splitter. + * + * @param pos + * the new size of the first region in persentage + */ + public void setSplitPosition(int pos) { + setSplitPosition(pos, UNITS_PERCENTAGE); + } + + /** + * Moves the position of the splitter with given position and unit. + * + * @param pos + * size of the first region + * @param unit + * the unit (from {@link Sizeable}) in which the size is + * given. + */ + public void setSplitPosition(int pos, int unit) { + this.pos = pos; + posUnit = unit; + } } diff --git a/src/com/itmill/toolkit/ui/TabSheet.java b/src/com/itmill/toolkit/ui/TabSheet.java index 48df4dc09e..833732224d 100644 --- a/src/com/itmill/toolkit/ui/TabSheet.java +++ b/src/com/itmill/toolkit/ui/TabSheet.java @@ -50,576 +50,589 @@ import com.itmill.toolkit.terminal.Sizeable; */ public class TabSheet extends AbstractComponentContainer implements Sizeable { - /** - * Linked list of component tabs. - */ - private LinkedList tabs = new LinkedList(); - - /** - * Tab -> caption mapping. - */ - private Hashtable tabCaptions = new Hashtable(); - - /** - * Tab -> icon mapping . - */ - private Hashtable tabIcons = new Hashtable(); - - /** - * Selected tab. - */ - private Component selected = null; - - private KeyMapper keyMapper = new KeyMapper(); - - /** - * Holds the value of property tabsHIdden. - */ - private boolean tabsHidden; - - /** - * Height of the layout. Set to -1 for undefined height. - */ - private int height = -1; - - /** - * Height unit. - * - * @see com.itmill.toolkit.terminal.Sizeable.UNIT_SYMBOLS; - */ - private int heightUnit = UNITS_PIXELS; - - /** - * Width of the layout. Set to -1 for undefined width. - */ - private int width = -1; - - /** - * Width unit. - * - * @see com.itmill.toolkit.terminal.Sizeable.UNIT_SYMBOLS; - */ - private int widthUnit = UNITS_PIXELS; - - /** - * Constructs a new Tabsheet. Tabsheet is immediate by default. - */ - public TabSheet() { - super(); - setImmediate(true); - } - - /** - * Gets the component container iterator for going trough all the components - * in the container. - * - * @return the Iterator of the components inside the container. - */ - public Iterator getComponentIterator() { - return java.util.Collections.unmodifiableList(tabs).iterator(); - } - - /** - * Removes the component from this container. - * - * @param c - * the component to be removed. - */ - public void removeComponent(Component c) { - if (c != null && tabs.contains(c)) { - super.removeComponent(c); - keyMapper.remove(c); - tabs.remove(c); - tabCaptions.remove(c); - if (c.equals(selected)) { - if (tabs.isEmpty()) - selected = null; - else { - selected = (Component) tabs.getFirst(); - fireSelectedTabChange(); - } - } - requestRepaint(); - } - } - - /** - * Adds the component into this container. The component is added as a tab - * where its default tab-caption is the caption of the component. - * - * @param c - * the component to be added. - */ - public void addComponent(Component c) { - addTab(c, c.getCaption(), getIcon()); - } - - /** - * Adds the new tab into TabSheet. - * - * @param c - * the component to be added onto tab. - * @param caption - * the caption of the tab. - * @param icon - * the Set the icon of the tab. - */ - public void addTab(Component c, String caption, Resource icon) { - if (c != null) { - tabs.addLast(c); - tabCaptions.put(c, caption != null ? caption : ""); - if (icon != null) - tabIcons.put(c, icon); - if (selected == null) { - selected = c; - fireSelectedTabChange(); - } - super.addComponent(c); - requestRepaint(); - } - } - - /** - * Gets the component UIDL tag. - * - * @return the Component UIDL tag as string. - */ - public String getTag() { - return "tabsheet"; - } - - /** - * Moves all components from another container to this container. The - * components are removed from the other container. - * - * @param source - * the container components are removed from. - */ - public void moveComponentsFrom(ComponentContainer source) { - for (Iterator i = source.getComponentIterator(); i.hasNext();) { - Component c = (Component) i.next(); - String caption = null; - Resource icon = null; - if (TabSheet.class.isAssignableFrom(source.getClass())) { - caption = ((TabSheet) source).getTabCaption(c); - icon = ((TabSheet) source).getTabIcon(c); - } - source.removeComponent(c); - addTab(c, caption, icon); - - } - } - - /** - * Paints the content of this component. - * - * @param event - * the Paint Event. - * @throws PaintException - * if the paint operation failed. - */ - public void paintContent(PaintTarget target) throws PaintException { - - // Add size info - if (getHeight() > -1) - target.addAttribute("height", getHeight() - + UNIT_SYMBOLS[getHeightUnits()]); - if (getWidth() > -1) - target.addAttribute("width", getWidth() - + UNIT_SYMBOLS[getWidthUnits()]); - - if (areTabsHidden()) - target.addAttribute("hidetabs", true); - - target.startTag("tabs"); - - for (Iterator i = getComponentIterator(); i.hasNext();) { - Component c = (Component) i.next(); - if (!c.isVisible()) - continue; - target.startTag("tab"); - Resource icon = getTabIcon(c); - if (icon != null) - target.addAttribute("icon", icon); - String caption = getTabCaption(c); - if (!c.isEnabled()) { - target.addAttribute("disabled", true); - } - - if (caption != null && caption.length() > 0) - target.addAttribute("caption", caption); - target.addAttribute("key", keyMapper.key(c)); - if (c.equals(selected)) { - target.addAttribute("selected", true); - c.paint(target); - } - target.endTag("tab"); - } - - target.endTag("tabs"); - - if (selected != null) - target.addVariable(this, "selected", keyMapper.key(selected)); - } - - /** - * Are tabs hidden. - * - * @return the Property visibility. - */ - public boolean areTabsHidden() { - return this.tabsHidden; - } - - /** - * Setter for property tabsHidden. - * - * @param tabsHidden - * True if the tabs should be hidden. - */ - public void hideTabs(boolean tabsHidden) { - this.tabsHidden = tabsHidden; - requestRepaint(); - } - - /** - * Gets the caption for a component. - * - * @param c - * the component. - */ - public String getTabCaption(Component c) { - String caption = (String) tabCaptions.get(c); - if (caption == null) - caption = ""; - return caption; - } - - /** - * Sets the caption for a component. - * - * @param c - * the component. - * @param caption - * the caption to set. - */ - public void setTabCaption(Component c, String caption) { - tabCaptions.put(c, caption); - requestRepaint(); - } - - /** - * Gets the icon for a component. - * - * @param c - * the component. - */ - public Resource getTabIcon(Component c) { - return (Resource) tabIcons.get(c); - } - - /** - * ] Sets the icon for a component. - * - * @param c - * @param icon - */ - public void setTabIcon(Component c, Resource icon) { - if (icon == null) - tabIcons.remove(c); - else - tabIcons.put(c, icon); - requestRepaint(); - } - - /** - * Sets the selected tab. - * - * @param c - */ - public void setSelectedTab(Component c) { - if (c != null && tabs.contains(c) && !selected.equals(c)) { - selected = c; - fireSelectedTabChange(); - requestRepaint(); - } - } - - /** - * Gets the selected tab. - * - * @return the selected tab. - */ - public Component getSelectedTab() { - return selected; - } - - /** - * Invoked when the value of a variable has changed. - * - * @see com.itmill.toolkit.ui.AbstractComponent#changeVariables(java.lang.Object, - * java.util.Map) - */ - public void changeVariables(Object source, Map variables) { - if (variables.containsKey("selected")) - setSelectedTab((Component) keyMapper.get((String) variables - .get("selected"))); - } - - /* Documented in superclass */ - public void replaceComponent(Component oldComponent, Component newComponent) { - - // Gets the captions - String oldCaption = getTabCaption(oldComponent); - Resource oldIcon = getTabIcon(oldComponent); - String newCaption = getTabCaption(newComponent); - Resource newIcon = getTabIcon(newComponent); - - // Gets the locations - int oldLocation = -1; - int newLocation = -1; - int location = 0; - for (Iterator i = tabs.iterator(); i.hasNext();) { - Component component = (Component) i.next(); - - if (component == oldComponent) - oldLocation = location; - if (component == newComponent) - newLocation = location; - - location++; - } - - if (oldLocation == -1) - addComponent(newComponent); - else if (newLocation == -1) { - removeComponent(oldComponent); - keyMapper.remove(oldComponent); - addComponent(newComponent); - tabs.remove(newComponent); - tabs.add(oldLocation, newComponent); - setTabCaption(newComponent, oldCaption); - setTabIcon(newComponent, oldIcon); - } else { - if (oldLocation > newLocation) { - tabs.remove(oldComponent); - tabs.add(newLocation, oldComponent); - tabs.remove(newComponent); - tabs.add(oldLocation, newComponent); - } else { - tabs.remove(newComponent); - tabs.add(oldLocation, newComponent); - tabs.remove(oldComponent); - tabs.add(newLocation, oldComponent); - } - setTabCaption(newComponent, oldCaption); - setTabIcon(newComponent, oldIcon); - setTabCaption(oldComponent, newCaption); - setTabIcon(oldComponent, newIcon); - - requestRepaint(); - } - } - - /* Click event ************************************************ */ - - private static final Method SELECTED_TAB_CHANGE_METHOD; - static { - try { - SELECTED_TAB_CHANGE_METHOD = SelectedTabChangeListener.class - .getDeclaredMethod("selectedTabChange", - new Class[] { SelectedTabChangeEvent.class }); - } catch (java.lang.NoSuchMethodException e) { - // This should never happen - throw new java.lang.RuntimeException(); - } - } - - /** - * Selected Tab Change event. This event is thrown, when the selected tab in - * the tab sheet is changed. - * - * @author IT Mill Ltd. - * @version - * @VERSION@ - * @since 3.0 - */ - public class SelectedTabChangeEvent extends Component.Event { - - /** - * Serial generated by eclipse. - */ - private static final long serialVersionUID = 3258129141914940469L; - - /** - * New instance of selected tab change event - * - * @param source - * the Source of the event. - */ - public SelectedTabChangeEvent(Component source) { - super(source); - } - - /** - * Select where the event occurred - * - * @return the Source of the event. - */ - public Select getSelect() { - return (Select) getSource(); - } - } - - /** - * Selected Tab Change Event listener - * - * @author IT Mill Ltd. - * - * @version - * @VERSION@ - * @since 3.0 - */ - public interface SelectedTabChangeListener { - - /** - * Visible tab in tab sheet has has been changed. - * - * @param event - * the Selected tab change event. - */ - public void selectedTabChange(SelectedTabChangeEvent event); - } - - /** - * Adds the selected tab change listener - * - * @param listener - * the Listener to be added. - */ - public void addListener(SelectedTabChangeListener listener) { - addListener(SelectedTabChangeEvent.class, listener, - SELECTED_TAB_CHANGE_METHOD); - } - - /** - * Removes the selected tab change listener - * - * @param listener - * the Listener to be removed. - */ - public void removeListener(SelectedTabChangeListener listener) { - removeListener(SelectedTabChangeEvent.class, listener, - SELECTED_TAB_CHANGE_METHOD); - } - - /** - * Emits the options change event. - */ - protected void fireSelectedTabChange() { - fireEvent(new SelectedTabChangeEvent(this)); - } - - /* - * (non-Javadoc) - * - * @see com.itmill.toolkit.terminal.Sizeable#getHeight() - */ - public int getHeight() { - return height; - } - - /* - * (non-Javadoc) - * - * @see com.itmill.toolkit.terminal.Sizeable#getHeightUnits() - */ - public int getHeightUnits() { - return heightUnit; - } - - /* - * (non-Javadoc) - * - * @see com.itmill.toolkit.terminal.Sizeable#getWidth() - */ - public int getWidth() { - return width; - } - - /* - * (non-Javadoc) - * - * @see com.itmill.toolkit.terminal.Sizeable#getWidthUnits() - */ - public int getWidthUnits() { - return widthUnit; - } - - /* - * (non-Javadoc) - * - * @see com.itmill.toolkit.terminal.Sizeable#setHeight(int) - */ - public void setHeight(int height) { - this.height = height; - requestRepaint(); - } - - /* - * (non-Javadoc) - * - * @see com.itmill.toolkit.terminal.Sizeable#setHeightUnits(int) - */ - public void setHeightUnits(int units) { - this.heightUnit = units; - requestRepaint(); - } - - /* - * (non-Javadoc) - * - * @see com.itmill.toolkit.terminal.Sizeable#setSizeFull() - */ - public void setSizeFull() { - height = 100; - width = 100; - heightUnit = UNITS_PERCENTAGE; - widthUnit = UNITS_PERCENTAGE; - requestRepaint(); - } - - /* - * (non-Javadoc) - * - * @see com.itmill.toolkit.terminal.Sizeable#setSizeUndefined() - */ - public void setSizeUndefined() { - height = -1; - width = -1; - heightUnit = UNITS_PIXELS; - widthUnit = UNITS_PIXELS; - requestRepaint(); - } - - /* - * (non-Javadoc) - * - * @see com.itmill.toolkit.terminal.Sizeable#setWidth(int) - */ - public void setWidth(int width) { - this.width = width; - requestRepaint(); - } - - /* - * (non-Javadoc) - * - * @see com.itmill.toolkit.terminal.Sizeable#setWidthUnits(int) - */ - public void setWidthUnits(int units) { - this.widthUnit = units; - requestRepaint(); - } + /** + * Linked list of component tabs. + */ + private LinkedList tabs = new LinkedList(); + + /** + * Tab -> caption mapping. + */ + private Hashtable tabCaptions = new Hashtable(); + + /** + * Tab -> icon mapping . + */ + private Hashtable tabIcons = new Hashtable(); + + /** + * Selected tab. + */ + private Component selected = null; + + private KeyMapper keyMapper = new KeyMapper(); + + /** + * Holds the value of property tabsHIdden. + */ + private boolean tabsHidden; + + /** + * Height of the layout. Set to -1 for undefined height. + */ + private int height = -1; + + /** + * Height unit. + * + * @see com.itmill.toolkit.terminal.Sizeable.UNIT_SYMBOLS; + */ + private int heightUnit = UNITS_PIXELS; + + /** + * Width of the layout. Set to -1 for undefined width. + */ + private int width = -1; + + /** + * Width unit. + * + * @see com.itmill.toolkit.terminal.Sizeable.UNIT_SYMBOLS; + */ + private int widthUnit = UNITS_PIXELS; + + /** + * Constructs a new Tabsheet. Tabsheet is immediate by default. + */ + public TabSheet() { + super(); + setImmediate(true); + } + + /** + * Gets the component container iterator for going trough all the components + * in the container. + * + * @return the Iterator of the components inside the container. + */ + public Iterator getComponentIterator() { + return java.util.Collections.unmodifiableList(tabs).iterator(); + } + + /** + * Removes the component from this container. + * + * @param c + * the component to be removed. + */ + public void removeComponent(Component c) { + if (c != null && tabs.contains(c)) { + super.removeComponent(c); + keyMapper.remove(c); + tabs.remove(c); + tabCaptions.remove(c); + if (c.equals(selected)) { + if (tabs.isEmpty()) { + selected = null; + } else { + selected = (Component) tabs.getFirst(); + fireSelectedTabChange(); + } + } + requestRepaint(); + } + } + + /** + * Adds the component into this container. The component is added as a tab + * where its default tab-caption is the caption of the component. + * + * @param c + * the component to be added. + */ + public void addComponent(Component c) { + addTab(c, c.getCaption(), getIcon()); + } + + /** + * Adds the new tab into TabSheet. + * + * @param c + * the component to be added onto tab. + * @param caption + * the caption of the tab. + * @param icon + * the Set the icon of the tab. + */ + public void addTab(Component c, String caption, Resource icon) { + if (c != null) { + tabs.addLast(c); + tabCaptions.put(c, caption != null ? caption : ""); + if (icon != null) { + tabIcons.put(c, icon); + } + if (selected == null) { + selected = c; + fireSelectedTabChange(); + } + super.addComponent(c); + requestRepaint(); + } + } + + /** + * Gets the component UIDL tag. + * + * @return the Component UIDL tag as string. + */ + public String getTag() { + return "tabsheet"; + } + + /** + * Moves all components from another container to this container. The + * components are removed from the other container. + * + * @param source + * the container components are removed from. + */ + public void moveComponentsFrom(ComponentContainer source) { + for (Iterator i = source.getComponentIterator(); i.hasNext();) { + Component c = (Component) i.next(); + String caption = null; + Resource icon = null; + if (TabSheet.class.isAssignableFrom(source.getClass())) { + caption = ((TabSheet) source).getTabCaption(c); + icon = ((TabSheet) source).getTabIcon(c); + } + source.removeComponent(c); + addTab(c, caption, icon); + + } + } + + /** + * Paints the content of this component. + * + * @param event + * the Paint Event. + * @throws PaintException + * if the paint operation failed. + */ + public void paintContent(PaintTarget target) throws PaintException { + + // Add size info + if (getHeight() > -1) { + target.addAttribute("height", getHeight() + + UNIT_SYMBOLS[getHeightUnits()]); + } + if (getWidth() > -1) { + target.addAttribute("width", getWidth() + + UNIT_SYMBOLS[getWidthUnits()]); + } + + if (areTabsHidden()) { + target.addAttribute("hidetabs", true); + } + + target.startTag("tabs"); + + for (Iterator i = getComponentIterator(); i.hasNext();) { + Component c = (Component) i.next(); + if (!c.isVisible()) { + continue; + } + target.startTag("tab"); + Resource icon = getTabIcon(c); + if (icon != null) { + target.addAttribute("icon", icon); + } + String caption = getTabCaption(c); + if (!c.isEnabled()) { + target.addAttribute("disabled", true); + } + + if (caption != null && caption.length() > 0) { + target.addAttribute("caption", caption); + } + target.addAttribute("key", keyMapper.key(c)); + if (c.equals(selected)) { + target.addAttribute("selected", true); + c.paint(target); + } + target.endTag("tab"); + } + + target.endTag("tabs"); + + if (selected != null) { + target.addVariable(this, "selected", keyMapper.key(selected)); + } + } + + /** + * Are tabs hidden. + * + * @return the Property visibility. + */ + public boolean areTabsHidden() { + return tabsHidden; + } + + /** + * Setter for property tabsHidden. + * + * @param tabsHidden + * True if the tabs should be hidden. + */ + public void hideTabs(boolean tabsHidden) { + this.tabsHidden = tabsHidden; + requestRepaint(); + } + + /** + * Gets the caption for a component. + * + * @param c + * the component. + */ + public String getTabCaption(Component c) { + String caption = (String) tabCaptions.get(c); + if (caption == null) { + caption = ""; + } + return caption; + } + + /** + * Sets the caption for a component. + * + * @param c + * the component. + * @param caption + * the caption to set. + */ + public void setTabCaption(Component c, String caption) { + tabCaptions.put(c, caption); + requestRepaint(); + } + + /** + * Gets the icon for a component. + * + * @param c + * the component. + */ + public Resource getTabIcon(Component c) { + return (Resource) tabIcons.get(c); + } + + /** + * ] Sets the icon for a component. + * + * @param c + * @param icon + */ + public void setTabIcon(Component c, Resource icon) { + if (icon == null) { + tabIcons.remove(c); + } else { + tabIcons.put(c, icon); + } + requestRepaint(); + } + + /** + * Sets the selected tab. + * + * @param c + */ + public void setSelectedTab(Component c) { + if (c != null && tabs.contains(c) && !selected.equals(c)) { + selected = c; + fireSelectedTabChange(); + requestRepaint(); + } + } + + /** + * Gets the selected tab. + * + * @return the selected tab. + */ + public Component getSelectedTab() { + return selected; + } + + /** + * Invoked when the value of a variable has changed. + * + * @see com.itmill.toolkit.ui.AbstractComponent#changeVariables(java.lang.Object, + * java.util.Map) + */ + public void changeVariables(Object source, Map variables) { + if (variables.containsKey("selected")) { + setSelectedTab((Component) keyMapper.get((String) variables + .get("selected"))); + } + } + + /* Documented in superclass */ + public void replaceComponent(Component oldComponent, Component newComponent) { + + // Gets the captions + String oldCaption = getTabCaption(oldComponent); + Resource oldIcon = getTabIcon(oldComponent); + String newCaption = getTabCaption(newComponent); + Resource newIcon = getTabIcon(newComponent); + + // Gets the locations + int oldLocation = -1; + int newLocation = -1; + int location = 0; + for (Iterator i = tabs.iterator(); i.hasNext();) { + Component component = (Component) i.next(); + + if (component == oldComponent) { + oldLocation = location; + } + if (component == newComponent) { + newLocation = location; + } + + location++; + } + + if (oldLocation == -1) { + addComponent(newComponent); + } else if (newLocation == -1) { + removeComponent(oldComponent); + keyMapper.remove(oldComponent); + addComponent(newComponent); + tabs.remove(newComponent); + tabs.add(oldLocation, newComponent); + setTabCaption(newComponent, oldCaption); + setTabIcon(newComponent, oldIcon); + } else { + if (oldLocation > newLocation) { + tabs.remove(oldComponent); + tabs.add(newLocation, oldComponent); + tabs.remove(newComponent); + tabs.add(oldLocation, newComponent); + } else { + tabs.remove(newComponent); + tabs.add(oldLocation, newComponent); + tabs.remove(oldComponent); + tabs.add(newLocation, oldComponent); + } + setTabCaption(newComponent, oldCaption); + setTabIcon(newComponent, oldIcon); + setTabCaption(oldComponent, newCaption); + setTabIcon(oldComponent, newIcon); + + requestRepaint(); + } + } + + /* Click event ************************************************ */ + + private static final Method SELECTED_TAB_CHANGE_METHOD; + static { + try { + SELECTED_TAB_CHANGE_METHOD = SelectedTabChangeListener.class + .getDeclaredMethod("selectedTabChange", + new Class[] { SelectedTabChangeEvent.class }); + } catch (java.lang.NoSuchMethodException e) { + // This should never happen + throw new java.lang.RuntimeException(); + } + } + + /** + * Selected Tab Change event. This event is thrown, when the selected tab in + * the tab sheet is changed. + * + * @author IT Mill Ltd. + * @version + * @VERSION@ + * @since 3.0 + */ + public class SelectedTabChangeEvent extends Component.Event { + + /** + * Serial generated by eclipse. + */ + private static final long serialVersionUID = 3258129141914940469L; + + /** + * New instance of selected tab change event + * + * @param source + * the Source of the event. + */ + public SelectedTabChangeEvent(Component source) { + super(source); + } + + /** + * Select where the event occurred + * + * @return the Source of the event. + */ + public Select getSelect() { + return (Select) getSource(); + } + } + + /** + * Selected Tab Change Event listener + * + * @author IT Mill Ltd. + * + * @version + * @VERSION@ + * @since 3.0 + */ + public interface SelectedTabChangeListener { + + /** + * Visible tab in tab sheet has has been changed. + * + * @param event + * the Selected tab change event. + */ + public void selectedTabChange(SelectedTabChangeEvent event); + } + + /** + * Adds the selected tab change listener + * + * @param listener + * the Listener to be added. + */ + public void addListener(SelectedTabChangeListener listener) { + addListener(SelectedTabChangeEvent.class, listener, + SELECTED_TAB_CHANGE_METHOD); + } + + /** + * Removes the selected tab change listener + * + * @param listener + * the Listener to be removed. + */ + public void removeListener(SelectedTabChangeListener listener) { + removeListener(SelectedTabChangeEvent.class, listener, + SELECTED_TAB_CHANGE_METHOD); + } + + /** + * Emits the options change event. + */ + protected void fireSelectedTabChange() { + fireEvent(new SelectedTabChangeEvent(this)); + } + + /* + * (non-Javadoc) + * + * @see com.itmill.toolkit.terminal.Sizeable#getHeight() + */ + public int getHeight() { + return height; + } + + /* + * (non-Javadoc) + * + * @see com.itmill.toolkit.terminal.Sizeable#getHeightUnits() + */ + public int getHeightUnits() { + return heightUnit; + } + + /* + * (non-Javadoc) + * + * @see com.itmill.toolkit.terminal.Sizeable#getWidth() + */ + public int getWidth() { + return width; + } + + /* + * (non-Javadoc) + * + * @see com.itmill.toolkit.terminal.Sizeable#getWidthUnits() + */ + public int getWidthUnits() { + return widthUnit; + } + + /* + * (non-Javadoc) + * + * @see com.itmill.toolkit.terminal.Sizeable#setHeight(int) + */ + public void setHeight(int height) { + this.height = height; + requestRepaint(); + } + + /* + * (non-Javadoc) + * + * @see com.itmill.toolkit.terminal.Sizeable#setHeightUnits(int) + */ + public void setHeightUnits(int units) { + heightUnit = units; + requestRepaint(); + } + + /* + * (non-Javadoc) + * + * @see com.itmill.toolkit.terminal.Sizeable#setSizeFull() + */ + public void setSizeFull() { + height = 100; + width = 100; + heightUnit = UNITS_PERCENTAGE; + widthUnit = UNITS_PERCENTAGE; + requestRepaint(); + } + + /* + * (non-Javadoc) + * + * @see com.itmill.toolkit.terminal.Sizeable#setSizeUndefined() + */ + public void setSizeUndefined() { + height = -1; + width = -1; + heightUnit = UNITS_PIXELS; + widthUnit = UNITS_PIXELS; + requestRepaint(); + } + + /* + * (non-Javadoc) + * + * @see com.itmill.toolkit.terminal.Sizeable#setWidth(int) + */ + public void setWidth(int width) { + this.width = width; + requestRepaint(); + } + + /* + * (non-Javadoc) + * + * @see com.itmill.toolkit.terminal.Sizeable#setWidthUnits(int) + */ + public void setWidthUnits(int units) { + widthUnit = units; + requestRepaint(); + } } diff --git a/src/com/itmill/toolkit/ui/Table.java b/src/com/itmill/toolkit/ui/Table.java index 13f5deb456..15ca1e4455 100644 --- a/src/com/itmill/toolkit/ui/Table.java +++ b/src/com/itmill/toolkit/ui/Table.java @@ -61,2535 +61,2522 @@ import com.itmill.toolkit.terminal.Sizeable; * @since 3.0 */ public class Table extends AbstractSelect implements Action.Container, - Container.Ordered, Container.Sortable, Sizeable { - - private static final int CELL_KEY = 0; - - private static final int CELL_HEADER = 1; - - private static final int CELL_ICON = 2; - - private static final int CELL_ITEMID = 3; - - private static final int CELL_FIRSTCOL = 4; - - /** - * Width of the table or -1 if unspecified. - */ - private int width = -1; - - /** - * Height of the table or -1 if unspecified. - */ - private int height = -1; - - /** - * Width unit. - */ - private int widthUnit = Sizeable.UNITS_PIXELS; - - /** - * Height unit. - */ - private int heightUnit = Sizeable.UNITS_PIXELS; - - /** - * Left column alignment. This is the default behaviour. - */ - public static final String ALIGN_LEFT = "b"; - - /** - * Center column alignment. - */ - public static final String ALIGN_CENTER = "c"; - - /** - * Right column alignment. - */ - public static final String ALIGN_RIGHT = "e"; - - /** - * Column header mode: Column headers are hidden. This is the default - * behaviour. - */ - public static final int COLUMN_HEADER_MODE_HIDDEN = -1; - - /** - * Column header mode: Property ID:s are used as column headers. - */ - public static final int COLUMN_HEADER_MODE_ID = 0; - - /** - * Column header mode: Column headers are explicitly specified with - * setColumnHeaders. - */ - public static final int COLUMN_HEADER_MODE_EXPLICIT = 1; - - /** - * Column header mode: Column headers are explicitly specified with - * setColumnHeaders - */ - public static final int COLUMN_HEADER_MODE_EXPLICIT_DEFAULTS_ID = 2; - - /** - * Row caption mode: The row headers are hidden. This is the default - * mode. - */ - public static final int ROW_HEADER_MODE_HIDDEN = -1; - - /** - * Row caption mode: Items Id-objects toString is used as row caption. - */ - public static final int ROW_HEADER_MODE_ID = Select.ITEM_CAPTION_MODE_ID; - - /** - * Row caption mode: Item-objects toString is used as row caption. - */ - public static final int ROW_HEADER_MODE_ITEM = Select.ITEM_CAPTION_MODE_ITEM; - - /** - * Row caption mode: Index of the item is used as item caption. The index - * mode can only be used with the containers implementing Container.Indexed - * interface. - */ - public static final int ROW_HEADER_MODE_INDEX = Select.ITEM_CAPTION_MODE_INDEX; - - /** - * Row caption mode: Item captions are explicitly specified. - */ - public static final int ROW_HEADER_MODE_EXPLICIT = Select.ITEM_CAPTION_MODE_EXPLICIT; - - /** - * Row caption mode: Item captions are read from property specified with - * setItemCaptionPropertyId. - */ - public static final int ROW_HEADER_MODE_PROPERTY = Select.ITEM_CAPTION_MODE_PROPERTY; - - /** - * Row caption mode: Only icons are shown, the captions are hidden. - */ - public static final int ROW_HEADER_MODE_ICON_ONLY = Select.ITEM_CAPTION_MODE_ICON_ONLY; - - /** - * Row caption mode: Item captions are explicitly specified, but if the - * caption is missing, the item id objects toString() is used - * instead. - */ - public static final int ROW_HEADER_MODE_EXPLICIT_DEFAULTS_ID = Select.ITEM_CAPTION_MODE_EXPLICIT_DEFAULTS_ID; - - /* Private table extensions to Select *********************************** */ - - /** - * True if column collapsing is allowed. - */ - private boolean columnCollapsingAllowed = false; - - /** - * True if reordering of columns is allowed on the client side. - */ - private boolean columnReorderingAllowed = false; - - /** - * Keymapper for column ids. - */ - private final KeyMapper columnIdMap = new KeyMapper(); - - /** - * Holds visible column propertyIds - in order. - */ - private LinkedList visibleColumns = new LinkedList(); - - /** - * Holds propertyIds of currently collapsed columns. - */ - private final HashSet collapsedColumns = new HashSet(); - - /** - * Holds headers for visible columns (by propertyId). - */ - private final HashMap columnHeaders = new HashMap(); - - /** - * Holds icons for visible columns (by propertyId). - */ - private final HashMap columnIcons = new HashMap(); - - /** - * Holds alignments for visible columns (by propertyId). - */ - private HashMap columnAlignments = new HashMap(); - - /** - * Holds column widths in pixels for visible columns (by propertyId). - */ - private final HashMap columnWidths = new HashMap(); - - /** - * Holds value of property pageLength. 0 disables paging. - */ - private int pageLength = 15; - - /** - * Id the first item on the current page. - */ - private Object currentPageFirstItemId = null; - - /** - * Index of the first item on the current page. - */ - private int currentPageFirstItemIndex = 0; - - /** - * Holds value of property pageBuffering. - */ - private boolean pageBuffering = false; - - /** - * Holds value of property selectable. - */ - private boolean selectable = false; - - /** - * Holds value of property columnHeaderMode. - */ - private int columnHeaderMode = COLUMN_HEADER_MODE_EXPLICIT_DEFAULTS_ID; - - /** - * True iff the row captions are hidden. - */ - private boolean rowCaptionsAreHidden = true; - - /** - * Page contents buffer used in buffered mode. - */ - private Object[][] pageBuffer = null; - - /** - * List of properties listened - the list is kept to release the listeners - * later. - */ - private LinkedList listenedProperties = null; - - /** - * List of visible components - the is used for needsRepaint calculation. - */ - private LinkedList visibleComponents = null; - - /** - * List of action handlers. - */ - private LinkedList actionHandlers = null; - - /** - * Action mapper. - */ - private KeyMapper actionMapper = null; - - /** - * Table cell editor factory. - */ - private FieldFactory fieldFactory = new BaseFieldFactory(); - - /** - * Is table editable. - */ - private boolean editable = false; - - /** - * Current sorting direction. - */ - private boolean sortAscending = true; - - /** - * Currently table is sorted on this propertyId. - */ - private Object sortContainerPropertyId = null; - - /** - * Is table sorting disabled alltogether; even if some of the properties - * would be sortable. - */ - private boolean sortDisabled = false; - - /** - * Number of rows explicitly requested by the client to be painted on next - * paint. This is -1 if no request by the client is made. Painting the - * component will automatically reset this to -1. - */ - private int reqRowsToPaint = -1; - - /** - * Index of the first rows explicitly requested by the client to be painted. - * This is -1 if no request by the client is made. Painting the component - * will automatically reset this to -1. - */ - private int reqFirstRowToPaint = -1; - - /* Table constructors *************************************************** */ - - /** - * Creates a new empty table. - */ - public Table() { - setRowHeaderMode(ROW_HEADER_MODE_HIDDEN); - } - - /** - * Creates a new empty table with caption. - * - * @param caption - */ - public Table(String caption) { - this(); - setCaption(caption); - } - - /** - * Creates a new table with caption and connect it to a Container. - * - * @param caption - * @param dataSource - */ - public Table(String caption, Container dataSource) { - this(); - setCaption(caption); - setContainerDataSource(dataSource); - } - - /* Table functionality ************************************************** */ - - /** - * Gets the array of visible column property id:s. - * - *

- * The columns are show in the order of their appearance in this array. - *

- * - * @return the Value of property availableColumns. - */ - public Object[] getVisibleColumns() { - if (this.visibleColumns == null) { - return null; - } - return this.visibleColumns.toArray(); - } - - /** - * Sets the array of visible column property id:s. - * - *

- * The columns are show in the order of their appearance in this array. - *

- * - * @param visibleColumns - * the Array of shown property id:s. - */ - public void setVisibleColumns(Object[] visibleColumns) { - - // Visible columns must exist - if (visibleColumns == null) { - throw new NullPointerException( - "Can not set visible columns to null value"); - } - - // Checks that the new visible columns contains no nulls and properties - // exist - Collection properties = getContainerPropertyIds(); - for (int i = 0; i < visibleColumns.length; i++) { - if (visibleColumns[i] == null) { - throw new NullPointerException("Properties must be non-nulls"); - } else if (!properties.contains(visibleColumns[i])) { - throw new IllegalArgumentException( - "Properties must exist in the Container, missing property: " - + visibleColumns[i]); - } - } - - // If this is called befor the constructor is finished, it might be - // uninitialized - LinkedList newVC = new LinkedList(); - for (int i = 0; i < visibleColumns.length; i++) { - newVC.add(visibleColumns[i]); - } - - // Removes alignments, icons and headers from hidden columns - if (this.visibleColumns != null) { - for (Iterator i = this.visibleColumns.iterator(); i.hasNext();) { - Object col = i.next(); - if (!newVC.contains(col)) { - setColumnHeader(col, null); - setColumnAlignment(col, null); - setColumnIcon(col, null); - } - } - } - - this.visibleColumns = newVC; - - // Assures visual refresh - refreshCurrentPage(); - } - - /** - * Gets the headers of the columns. - * - *

- * The headers match the property id:s given my the set visible column - * headers. The table must be set in either - * ROW_HEADER_MODE_EXPLICIT or - * ROW_HEADER_MODE_EXPLICIT_DEFAULTS_ID mode to show the - * headers. In the defaults mode any nulls in the headers array are replaced - * with id.toString() outputs when rendering. - *

- * - * @return the Array of column headers. - */ - public String[] getColumnHeaders() { - if (this.columnHeaders == null) { - return null; - } - String[] headers = new String[this.visibleColumns.size()]; - int i = 0; - for (Iterator it = this.visibleColumns.iterator(); it.hasNext(); i++) { - headers[i] = (String) this.columnHeaders.get(it.next()); - } - return headers; - } - - /** - * Sets the headers of the columns. - * - *

- * The headers match the property id:s given my the set visible column - * headers. The table must be set in either - * ROW_HEADER_MODE_EXPLICIT or - * ROW_HEADER_MODE_EXPLICIT_DEFAULTS_ID mode to show the - * headers. In the defaults mode any nulls in the headers array are replaced - * with id.toString() outputs when rendering. - *

- * - * @param columnHeaders - * the Array of column headers that match the - * getVisibleColumns method. - */ - public void setColumnHeaders(String[] columnHeaders) { - - if (columnHeaders.length != this.visibleColumns.size()) { - throw new IllegalArgumentException( - "The length of the headers array must match the number of visible columns"); - } - - this.columnHeaders.clear(); - int i = 0; - for (Iterator it = this.visibleColumns.iterator(); it.hasNext() - && i < columnHeaders.length; i++) { - this.columnHeaders.put(it.next(), columnHeaders[i]); - } - - // Assures the visual refresh - refreshCurrentPage(); - } - - /** - * Gets the icons of the columns. - * - *

- * The icons in headers match the property id:s given my the set visible - * column headers. The table must be set in either - * ROW_HEADER_MODE_EXPLICIT or - * ROW_HEADER_MODE_EXPLICIT_DEFAULTS_ID mode to show the - * headers with icons. - *

- * - * @return the Array of icons that match the getVisibleColumns. - */ - public Resource[] getColumnIcons() { - if (this.columnIcons == null) { - return null; - } - Resource[] icons = new Resource[this.visibleColumns.size()]; - int i = 0; - for (Iterator it = this.visibleColumns.iterator(); it.hasNext(); i++) { - icons[i] = (Resource) this.columnIcons.get(it.next()); - } - - return icons; - } - - /** - * Sets the icons of the columns. - * - *

- * The icons in headers match the property id:s given my the set visible - * column headers. The table must be set in either - * ROW_HEADER_MODE_EXPLICIT or - * ROW_HEADER_MODE_EXPLICIT_DEFAULTS_ID mode to show the - * headers with icons. - *

- * - * @param columnIcons - * the Array of icons that match the - * getVisibleColumns. - */ - public void setColumnIcons(Resource[] columnIcons) { - - if (columnIcons.length != this.visibleColumns.size()) { - throw new IllegalArgumentException( - "The length of the icons array must match the number of visible columns"); - } - - this.columnIcons.clear(); - int i = 0; - for (Iterator it = this.visibleColumns.iterator(); it.hasNext() - && i < columnIcons.length; i++) { - this.columnIcons.put(it.next(), columnIcons[i]); - } - - // Assure visual refresh - refreshCurrentPage(); - } - - /** - * Gets the array of column alignments. - * - *

- * The items in the array must match the properties identified by - * getVisibleColumns(). The possible values for the - * alignments include: - *

    - *
  • ALIGN_LEFT: Left alignment
  • - *
  • ALIGN_CENTER: Centered
  • - *
  • ALIGN_RIGHT: Right alignment
  • - *
- * The alignments default to ALIGN_LEFT: any null values are - * rendered as align lefts. - *

- * - * @return the Column alignments array. - */ - public String[] getColumnAlignments() { - if (this.columnAlignments == null) { - return null; - } - String[] alignments = new String[this.visibleColumns.size()]; - int i = 0; - for (Iterator it = this.visibleColumns.iterator(); it.hasNext(); i++) { - alignments[i++] = getColumnAlignment(it.next()); - } - - return alignments; - } - - /** - * Sets the column alignments. - * - *

- * The items in the array must match the properties identified by - * getVisibleColumns(). The possible values for the - * alignments include: - *

    - *
  • ALIGN_LEFT: Left alignment
  • - *
  • ALIGN_CENTER: Centered
  • - *
  • ALIGN_RIGHT: Right alignment
  • - *
- * The alignments default to ALIGN_LEFT - *

- * - * @param columnAlignments - * the Column alignments array. - */ - public void setColumnAlignments(String[] columnAlignments) { - - if (columnAlignments.length != this.visibleColumns.size()) { - throw new IllegalArgumentException( - "The length of the alignments array must match the number of visible columns"); - } - - // Checks all alignments - for (int i = 0; i < columnAlignments.length; i++) { - String a = columnAlignments[i]; - if (a != null && !a.equals(ALIGN_LEFT) && !a.equals(ALIGN_CENTER) - && !a.equals(ALIGN_RIGHT)) { - throw new IllegalArgumentException("Column " + i - + " aligment '" + a + "' is invalid"); - } - } - - // Resets the alignments - HashMap newCA = new HashMap(); - int i = 0; - for (Iterator it = this.visibleColumns.iterator(); it.hasNext() - && i < columnAlignments.length; i++) { - newCA.put(it.next(), columnAlignments[i]); - } - this.columnAlignments = newCA; - - // Assures the visual refresh - refreshCurrentPage(); - } - - /** - * Sets columns width (in pixels). Theme may not necessary respect very - * small or very big values. Setting width to -1 (default) means that theme - * will make decision of width. - * - * @param columnId - * colunmns property id - * @param width - * width to be reserved for colunmns content - * @since 4.0.3 - */ - public void setColumnWidth(Object columnId, int width) { - this.columnWidths.put(columnId, new Integer(width)); - } - - /** - * Gets the width of column - * - * @param propertyId - * @return width of colun or -1 when value not set - */ - public int getColumnWidth(Object propertyId) { - Integer value = (Integer) this.columnWidths.get(propertyId); - if (value == null) { - return -1; - } - return value.intValue(); - } - - /** - * Gets the page length. - * - *

- * Setting page length 0 disables paging. - *

- * - * @return the Length of one page. - */ - public int getPageLength() { - return this.pageLength; - } - - /** - * Sets the page length. - * - *

- * Setting page length 0 disables paging. The page length defaults to 15. - *

- * - * @param pageLength - * the Length of one page. - */ - public void setPageLength(int pageLength) { - if (pageLength >= 0 && this.pageLength != pageLength) { - this.pageLength = pageLength; - // "scroll" to first row - setCurrentPageFirstItemIndex(0); - // Assures the visual refresh - refreshCurrentPage(); - } - } - - /** - * Getter for property currentPageFirstItem. - * - * @return the Value of property currentPageFirstItem. - */ - public Object getCurrentPageFirstItemId() { - - // Priorise index over id if indexes are supported - if (this.items instanceof Container.Indexed) { - int index = getCurrentPageFirstItemIndex(); - Object id = null; - if (index >= 0 && index < size()) { - id = ((Container.Indexed) this.items).getIdByIndex(index); - } - if (id != null && !id.equals(this.currentPageFirstItemId)) { - this.currentPageFirstItemId = id; - } - } - - // If there is no item id at all, use the first one - if (this.currentPageFirstItemId == null) { - this.currentPageFirstItemId = ((Container.Ordered) this.items) - .firstItemId(); - } - - return this.currentPageFirstItemId; - } - - /** - * Setter for property currentPageFirstItemId. - * - * @param currentPageFirstItemId - * the New value of property currentPageFirstItemId. - */ - public void setCurrentPageFirstItemId(Object currentPageFirstItemId) { - - // Gets the corresponding index - int index = -1; - try { - index = ((Container.Indexed) this.items) - .indexOfId(currentPageFirstItemId); - } catch (ClassCastException e) { - - // If the table item container does not have index, we have to - // calculates the index by hand - Object id = ((Container.Ordered) this.items).firstItemId(); - while (id != null && !id.equals(currentPageFirstItemId)) { - index++; - id = ((Container.Ordered) this.items).nextItemId(id); - } - if (id == null) { - index = -1; - } - } - - // If the search for item index was successfull - if (index >= 0) { - this.currentPageFirstItemId = currentPageFirstItemId; - this.currentPageFirstItemIndex = index; - } - - // Assures the visual refresh - refreshCurrentPage(); - - } - - /** - * Gets the icon Resource for the specified column. - * - * @param propertyId - * the propertyId indentifying the column. - * @return the icon for the specified column; null if the column has no icon - * set, or if the column is not visible. - */ - public Resource getColumnIcon(Object propertyId) { - return (Resource) this.columnIcons.get(propertyId); - } - - /** - * Sets the icon Resource for the specified column. - *

- * Throws IllegalArgumentException if the specified column is not visible. - *

- * - * @param propertyId - * the propertyId identifying the column. - * @param icon - * the icon Resource to set. - */ - public void setColumnIcon(Object propertyId, Resource icon) { - - if (icon == null) { - this.columnIcons.remove(propertyId); - } else { - this.columnIcons.put(propertyId, icon); - } - - // Assures the visual refresh - refreshCurrentPage(); - } - - /** - * Gets the header for the specified column. - * - * @param propertyId - * the propertyId indentifying the column. - * @return the header for the specifed column if it has one. - */ - public String getColumnHeader(Object propertyId) { - if (getColumnHeaderMode() == COLUMN_HEADER_MODE_HIDDEN) { - return null; - } - - String header = (String) this.columnHeaders.get(propertyId); - if ((header == null && getColumnHeaderMode() == COLUMN_HEADER_MODE_EXPLICIT_DEFAULTS_ID) - || getColumnHeaderMode() == COLUMN_HEADER_MODE_ID) { - header = propertyId.toString(); - } - - return header; - } - - /** - * Sets the column header for the specified column; - * - * @param propertyId - * the propertyId indentifying the column. - * @param header - * the header to set. - */ - public void setColumnHeader(Object propertyId, String header) { - - if (header == null) { - this.columnHeaders.remove(propertyId); - return; - } - this.columnHeaders.put(propertyId, header); - - // Assures the visual refresh - refreshCurrentPage(); - } - - /** - * Gets the specified column's alignment. - * - * @param propertyId - * the propertyID identifying the column. - * @return the specified column's alignment if it as one; null otherwise. - */ - public String getColumnAlignment(Object propertyId) { - String a = (String) this.columnAlignments.get(propertyId); - return a == null ? ALIGN_LEFT : a; - } - - /** - * Sets the specified column's alignment. - * - *

- * Throws IllegalArgumentException if the alignment is not one of the - * following: ALIGN_LEFT, ALIGN_CENTER or ALIGN_RIGHT - *

- * - * @param propertyId - * the propertyID identifying the column. - * @param alignment - * the desired alignment. - */ - public void setColumnAlignment(Object propertyId, String alignment) { - - // Checks for valid alignments - if (alignment != null && !alignment.equals(ALIGN_LEFT) - && !alignment.equals(ALIGN_CENTER) - && !alignment.equals(ALIGN_RIGHT)) { - throw new IllegalArgumentException("Column alignment '" + alignment - + "' is not supported."); - } - - if (alignment == null || alignment.equals(ALIGN_LEFT)) { - this.columnAlignments.remove(propertyId); - return; - } - - this.columnAlignments.put(propertyId, alignment); - - // Assures the visual refresh - refreshCurrentPage(); - } - - /** - * Checks if the specified column is collapsed. - * - * @param propertyId - * the propertyID identifying the column. - * @return true if the column is collapsed; false otherwise; - */ - public boolean isColumnCollapsed(Object propertyId) { - return this.collapsedColumns != null - && this.collapsedColumns.contains(propertyId); - } - - /** - * Sets whether the specified column is collapsed or not. - * - * - * @param propertyId - * the propertyID identifying the column. - * @param collapsed - * the desired collapsedness. - * @throws IllegalAccessException - */ - public void setColumnCollapsed(Object propertyId, boolean collapsed) - throws IllegalAccessException { - if (!isColumnCollapsingAllowed()) { - throw new IllegalAccessException("Column collapsing not allowed!"); - } - - if (collapsed) { - this.collapsedColumns.add(propertyId); - } else { - this.collapsedColumns.remove(propertyId); - } - - // Assures the visual refresh - refreshCurrentPage(); - } - - /** - * Checks if column collapsing is allowed. - * - * @return true if columns can be collapsed; false otherwise. - */ - public boolean isColumnCollapsingAllowed() { - return this.columnCollapsingAllowed; - } - - /** - * Sets whether column collapsing is allowed or not. - * - * @param collapsingAllowed - * specifies whether column collapsing is allowed. - */ - public void setColumnCollapsingAllowed(boolean collapsingAllowed) { - this.columnCollapsingAllowed = collapsingAllowed; - - if (!collapsingAllowed) { - this.collapsedColumns.clear(); - } - - // Assures the visual refresh - refreshCurrentPage(); - } - - /** - * Checks if column reordering is allowed. - * - * @return true if columns can be reordered; false otherwise. - */ - public boolean isColumnReorderingAllowed() { - return this.columnReorderingAllowed; - } - - /** - * Sets whether column reordering is allowed or not. - * - * @param reorderingAllowed - * specifies whether column reordering is allowed. - */ - public void setColumnReorderingAllowed(boolean reorderingAllowed) { - this.columnReorderingAllowed = reorderingAllowed; - - // Assures the visual refresh - refreshCurrentPage(); - } - - /* - * Arranges visible columns according to given columnOrder. Silently ignores - * colimnId:s that are not visible columns, and keeps the internal order of - * visible columns left out of the ordering (trailing). Silently does - * nothing if columnReordering is not allowed. - */ - private void setColumnOrder(Object[] columnOrder) { - if (columnOrder == null || !isColumnReorderingAllowed()) { - return; - } - LinkedList newOrder = new LinkedList(); - for (int i = 0; i < columnOrder.length; i++) { - if (columnOrder[i] != null - && this.visibleColumns.contains(columnOrder[i])) { - this.visibleColumns.remove(columnOrder[i]); - newOrder.add(columnOrder[i]); - } - } - for (Iterator it = this.visibleColumns.iterator(); it.hasNext();) { - Object columnId = it.next(); - if (!newOrder.contains(columnId)) { - newOrder.add(columnId); - } - } - this.visibleColumns = newOrder; - - // Assure visual refresh - refreshCurrentPage(); - } - - /** - * Getter for property currentPageFirstItem. - * - * @return the Value of property currentPageFirstItem. - */ - public int getCurrentPageFirstItemIndex() { - return this.currentPageFirstItemIndex; - } - - /** - * Setter for property currentPageFirstItem. - * - * @param newIndex - * the New value of property currentPageFirstItem. - */ - public void setCurrentPageFirstItemIndex(int newIndex) { - - // Ensures that the new value is valid - if (newIndex < 0) { - newIndex = 0; - } - if (newIndex >= size()) { - newIndex = size() - 1; - } - - // Refresh first item id - if (this.items instanceof Container.Indexed) { - try { - this.currentPageFirstItemId = ((Container.Indexed) this.items) - .getIdByIndex(newIndex); - } catch (IndexOutOfBoundsException e) { - this.currentPageFirstItemId = null; - } - this.currentPageFirstItemIndex = newIndex; - } else { - - // For containers not supporting indexes, we must iterate the - // container forwards / backwards - // next available item forward or backward - - this.currentPageFirstItemId = ((Container.Ordered) this.items) - .firstItemId(); - - // Go forwards in the middle of the list (respect borders) - while (this.currentPageFirstItemIndex < newIndex - && !((Container.Ordered) this.items) - .isLastId(this.currentPageFirstItemId)) { - this.currentPageFirstItemIndex++; - this.currentPageFirstItemId = ((Container.Ordered) this.items) - .nextItemId(this.currentPageFirstItemId); - } - - // If we did hit the border - if (((Container.Ordered) this.items) - .isLastId(this.currentPageFirstItemId)) { - this.currentPageFirstItemIndex = size() - 1; - } - - // Go backwards in the middle of the list (respect borders) - while (this.currentPageFirstItemIndex > newIndex - && !((Container.Ordered) this.items) - .isFirstId(this.currentPageFirstItemId)) { - this.currentPageFirstItemIndex--; - this.currentPageFirstItemId = ((Container.Ordered) this.items) - .prevItemId(this.currentPageFirstItemId); - } - - // If we did hit the border - if (((Container.Ordered) this.items) - .isFirstId(this.currentPageFirstItemId)) { - this.currentPageFirstItemIndex = 0; - } - - // Go forwards once more - while (this.currentPageFirstItemIndex < newIndex - && !((Container.Ordered) this.items) - .isLastId(this.currentPageFirstItemId)) { - this.currentPageFirstItemIndex++; - this.currentPageFirstItemId = ((Container.Ordered) this.items) - .nextItemId(this.currentPageFirstItemId); - } - - // If for some reason we do hit border again, override - // the user index request - if (((Container.Ordered) this.items) - .isLastId(this.currentPageFirstItemId)) { - newIndex = this.currentPageFirstItemIndex = size() - 1; - } - } - - // Assures the visual refresh - refreshCurrentPage(); - } - - /** - * Getter for property pageBuffering. - * - * @return the Value of property pageBuffering. - */ - public boolean isPageBufferingEnabled() { - return this.pageBuffering; - } - - /** - * Setter for property pageBuffering. - * - * @param pageBuffering - * the New value of property pageBuffering. - */ - public void setPageBufferingEnabled(boolean pageBuffering) { - - this.pageBuffering = pageBuffering; - - // If page buffering is disabled, clear the buffer - if (!pageBuffering) { - this.pageBuffer = null; - } - } - - /** - * Getter for property selectable. - * - *

- * The table is not selectable by default. - *

- * - * @return the Value of property selectable. - */ - public boolean isSelectable() { - return this.selectable; - } - - /** - * Setter for property selectable. - * - *

- * The table is not selectable by default. - *

- * - * @param selectable - * the New value of property selectable. - */ - public void setSelectable(boolean selectable) { - if (this.selectable != selectable) { - this.selectable = selectable; - requestRepaint(); - } - } - - /** - * Getter for property columnHeaderMode. - * - * @return the Value of property columnHeaderMode. - */ - public int getColumnHeaderMode() { - return this.columnHeaderMode; - } - - /** - * Setter for property columnHeaderMode. - * - * @param columnHeaderMode - * the New value of property columnHeaderMode. - */ - public void setColumnHeaderMode(int columnHeaderMode) { - if (columnHeaderMode >= COLUMN_HEADER_MODE_HIDDEN - && columnHeaderMode <= COLUMN_HEADER_MODE_EXPLICIT_DEFAULTS_ID) { - this.columnHeaderMode = columnHeaderMode; - } - - // Assures the visual refresh - refreshCurrentPage(); - } - - /** - * Refreshes the current page contents. If the page buffering is turned off, - * it is not necessary to call this explicitely. - */ - public void refreshCurrentPage() { - - // Clear page buffer and notify about the change - this.pageBuffer = null; - requestRepaint(); - } - - /** - * Sets the row header mode. - *

- * The mode can be one of the following ones: - *

    - *
  • ROW_HEADER_MODE_HIDDEN: The row captions are hidden. - *
  • - *
  • ROW_HEADER_MODE_ID: Items Id-objects - * toString() is used as row caption. - *
  • ROW_HEADER_MODE_ITEM: Item-objects - * toString() is used as row caption. - *
  • ROW_HEADER_MODE_PROPERTY: Property set with - * setItemCaptionPropertyId() is used as row header. - *
  • ROW_HEADER_MODE_EXPLICIT_DEFAULTS_ID: Items - * Id-objects toString() is used as row header. If caption is - * explicitly specified, it overrides the id-caption. - *
  • ROW_HEADER_MODE_EXPLICIT: The row headers must be - * explicitly specified.
  • - *
  • ROW_HEADER_MODE_INDEX: The index of the item is used - * as row caption. The index mode can only be used with the containers - * implementing Container.Indexed interface.
  • - *
- * The default value is ROW_HEADER_MODE_HIDDEN - *

- * - * @param mode - * the One of the modes listed above. - */ - public void setRowHeaderMode(int mode) { - if (ROW_HEADER_MODE_HIDDEN == mode) { - this.rowCaptionsAreHidden = true; - } else { - this.rowCaptionsAreHidden = false; - setItemCaptionMode(mode); - } - - // Assure visual refresh - refreshCurrentPage(); - } - - /** - * Gets the row header mode. - * - * @return the Row header mode. - * @see #setRowHeaderMode(int) - */ - public int getRowHeaderMode() { - return this.rowCaptionsAreHidden ? ROW_HEADER_MODE_HIDDEN - : getItemCaptionMode(); - } - - /** - * Adds the new row to table and fill the visible cells with given values. - * - * @param cells - * the Object array that is used for filling the visible cells - * new row. The types must be settable to visible column property - * types. - * @param itemId - * the Id the new row. If null, a new id is automatically - * assigned. If given, the table cant already have a item with - * given id. - * @return Returns item id for the new row. Returns null if operation fails. - */ - public Object addItem(Object[] cells, Object itemId) - throws UnsupportedOperationException { - - Object[] cols = getVisibleColumns(); - - // Checks that a correct number of cells are given - if (cells.length != cols.length) { - return null; - } - - // Creates new item - Item item; - if (itemId == null) { - itemId = this.items.addItem(); - if (itemId == null) { - return null; - } - item = this.items.getItem(itemId); - } else { - item = this.items.addItem(itemId); - } - if (item == null) { - return null; - } - - // Fills the item properties - for (int i = 0; i < cols.length; i++) { - item.getItemProperty(cols[i]).setValue(cells[i]); - } - - return itemId; - } - - /* Overriding select behavior******************************************** */ - - /** - * Sets the Container that serves as the data source of the viewer. - * - * @see com.itmill.toolkit.data.Container.Viewer#setContainerDataSource(Container) - */ - public void setContainerDataSource(Container newDataSource) { - - if (newDataSource == null) { - newDataSource = new IndexedContainer(); - } - - // Assures that the data source is ordered by making unordered - // containers ordered by wrapping them - if (newDataSource instanceof Container.Ordered) { - super.setContainerDataSource(newDataSource); - } else { - super.setContainerDataSource(new ContainerOrderedWrapper( - newDataSource)); - } - - // Resets page position - this.currentPageFirstItemId = null; - this.currentPageFirstItemIndex = 0; - - // Resets column properties - if (this.collapsedColumns != null) { - this.collapsedColumns.clear(); - } - setVisibleColumns(getContainerPropertyIds().toArray()); - - // Assure visual refresh - refreshCurrentPage(); - } - - /* Component basics ***************************************************** */ - - /** - * Invoked when the value of a variable has changed. - * - * @see com.itmill.toolkit.ui.Select#changeVariables(java.lang.Object, - * java.util.Map) - */ - public void changeVariables(Object source, Map variables) { - - if (!isSelectable() && variables.containsKey("selected")) { - // Not-selectable is a special case, AbstractSelect does not support - // TODO could be optimized. - variables = new HashMap(variables); - variables.remove("selected"); - } - - super.changeVariables(source, variables); - - // Page start index - if (variables.containsKey("firstvisible")) { - Integer value = (Integer) variables.get("firstvisible"); - if (value != null) { - setCurrentPageFirstItemIndex(value.intValue()); - } - } - - // Sets requested firstrow and rows for the next paint - if (variables.containsKey("reqfirstrow") - || variables.containsKey("reqrows")) { - Integer value = (Integer) variables.get("reqfirstrow"); - if (value != null) { - this.reqFirstRowToPaint = value.intValue(); - } - value = (Integer) variables.get("reqrows"); - if (value != null) { - this.reqRowsToPaint = value.intValue(); - } - this.pageBuffer = null; - requestRepaint(); - } - - // Actions - if (variables.containsKey("action")) { - StringTokenizer st = new StringTokenizer((String) variables - .get("action"), ","); - if (st.countTokens() == 2) { - Object itemId = this.itemIdMapper.get(st.nextToken()); - Action action = (Action) this.actionMapper.get(st.nextToken()); - if (action != null && containsId(itemId) - && this.actionHandlers != null) { - for (Iterator i = this.actionHandlers.iterator(); i - .hasNext();) { - ((Action.Handler) i.next()).handleAction(action, this, - itemId); - } - } - } - } - - // Sorting - boolean doSort = false; - if (!this.sortDisabled) { - if (variables.containsKey("sortcolumn")) { - String colId = (String) variables.get("sortcolumn"); - if (colId != null && !"".equals(colId) && !"null".equals(colId)) { - Object id = this.columnIdMap.get(colId); - setSortContainerPropertyId(id); - doSort = true; - } - } - if (variables.containsKey("sortascending")) { - boolean state = ((Boolean) variables.get("sortascending")) - .booleanValue(); - if (state != this.sortAscending) { - setSortAscending(state); - doSort = true; - } - } - } - if (doSort) { - this.sort(); - } - - // Dynamic column hide/show and order - // Update visible columns - if (isColumnCollapsingAllowed()) { - if (variables.containsKey("collapsedcolumns")) { - try { - Object[] ids = (Object[]) variables.get("collapsedcolumns"); - for (Iterator it = this.visibleColumns.iterator(); it - .hasNext();) { - setColumnCollapsed(it.next(), false); - } - for (int i = 0; i < ids.length; i++) { - setColumnCollapsed(this.columnIdMap.get(ids[i] - .toString()), true); - } - } catch (Exception ignored) { - } - } - } - if (isColumnReorderingAllowed()) { - if (variables.containsKey("columnorder")) { - try { - Object[] ids = (Object[]) variables.get("columnorder"); - for (int i = 0; i < ids.length; i++) { - ids[i] = this.columnIdMap.get(ids[i].toString()); - } - setColumnOrder(ids); - } catch (Exception ignored) { - } - } - } - } - - /** - * Paints the content of this component. - * - * @param target - * the Paint target. - * @throws PaintException - * if the paint operation failed. - */ - public void paintContent(PaintTarget target) throws PaintException { - - // Focus control id - if (getFocusableId() > 0) { - target.addAttribute("focusid", getFocusableId()); - } - - // The tab ordering number - if (getTabIndex() > 0) { - target.addAttribute("tabindex", getTabIndex()); - } - - // Size - if (getHeight() >= 0) { - target.addAttribute("height", "" + getHeight() - + Sizeable.UNIT_SYMBOLS[getHeightUnits()]); - } - if (getWidth() >= 0) { - target.addAttribute("width", "" + getWidth() - + Sizeable.UNIT_SYMBOLS[getWidthUnits()]); - } - - // Initialize temps - Object[] colids = getVisibleColumns(); - int cols = colids.length; - int first = getCurrentPageFirstItemIndex(); - int total = size(); - int pagelen = getPageLength(); - int colHeadMode = getColumnHeaderMode(); - boolean colheads = colHeadMode != COLUMN_HEADER_MODE_HIDDEN; - boolean rowheads = getRowHeaderMode() != ROW_HEADER_MODE_HIDDEN; - Object[][] cells = getVisibleCells(); - boolean iseditable = isEditable(); - int rows = cells[0].length; - - if (!isNullSelectionAllowed() && getNullSelectionItemId() != null - && containsId(getNullSelectionItemId())) { - total--; - rows--; - } - - // selection support - String[] selectedKeys; - if (isMultiSelect()) { - selectedKeys = new String[((Set) getValue()).size()]; - } else { - selectedKeys = new String[(getValue() == null - && getNullSelectionItemId() == null ? 0 : 1)]; - } - int keyIndex = 0; - - // Table attributes - if (isSelectable()) { - target.addAttribute("selectmode", (isMultiSelect() ? "multi" - : "single")); - } else { - target.addAttribute("selectmode", "none"); - } - target.addAttribute("cols", cols); - target.addAttribute("rows", rows); - target - .addAttribute("firstrow", - (this.reqFirstRowToPaint >= 0 ? this.reqFirstRowToPaint - : first)); - target.addAttribute("totalrows", total); - if (pagelen != 0) { - target.addAttribute("pagelength", pagelen); - } - if (colheads) { - target.addAttribute("colheaders", true); - } - if (rowheads) { - target.addAttribute("rowheaders", true); - } - - // Visible column order - Collection sortables = getSortableContainerPropertyIds(); - ArrayList visibleColOrder = new ArrayList(); - for (Iterator it = this.visibleColumns.iterator(); it.hasNext();) { - Object columnId = it.next(); - if (!isColumnCollapsed(columnId)) { - visibleColOrder.add(this.columnIdMap.key(columnId)); - } - } - target.addAttribute("vcolorder", visibleColOrder.toArray()); - - // Rows - Set actionSet = new LinkedHashSet(); - boolean selectable = isSelectable(); - boolean[] iscomponent = new boolean[this.visibleColumns.size()]; - int iscomponentIndex = 0; - for (Iterator it = this.visibleColumns.iterator(); it.hasNext() - && iscomponentIndex < iscomponent.length;) { - Object columnId = it.next(); - Class colType = getType(columnId); - iscomponent[iscomponentIndex++] = colType != null - && Component.class.isAssignableFrom(colType); - } - target.startTag("rows"); - for (int i = 0; i < cells[0].length; i++) { - Object itemId = cells[CELL_ITEMID][i]; - - if (!isNullSelectionAllowed() && getNullSelectionItemId() != null - && itemId == getNullSelectionItemId()) { - // Remove null selection item if null selection is not allowed - continue; - } - - target.startTag("tr"); - - // tr attributes - if (rowheads) { - if (cells[CELL_ICON][i] != null) { - target.addAttribute("icon", (Resource) cells[CELL_ICON][i]); - } - if (cells[CELL_HEADER][i] != null) { - target.addAttribute("caption", - (String) cells[CELL_HEADER][i]); - } - } - target.addAttribute("key", Integer.parseInt(cells[CELL_KEY][i] - .toString())); - if (this.actionHandlers != null || isSelectable()) { - if (isSelected(itemId) && keyIndex < selectedKeys.length) { - target.addAttribute("selected", true); - selectedKeys[keyIndex++] = (String) cells[CELL_KEY][i]; - } - } - - // Actions - if (this.actionHandlers != null) { - ArrayList keys = new ArrayList(); - for (Iterator ahi = this.actionHandlers.iterator(); ahi - .hasNext();) { - Action[] aa = ((Action.Handler) ahi.next()).getActions( - itemId, this); - if (aa != null) { - for (int ai = 0; ai < aa.length; ai++) { - String key = this.actionMapper.key(aa[ai]); - actionSet.add(aa[ai]); - keys.add(key); - } - } - } - target.addAttribute("al", keys.toArray()); - } - - // cells - int currentColumn = 0; - for (Iterator it = this.visibleColumns.iterator(); it.hasNext(); currentColumn++) { - Object columnId = it.next(); - if (columnId == null || isColumnCollapsed(columnId)) { - continue; - } - if ((iscomponent[currentColumn] || iseditable) - && Component.class.isInstance(cells[CELL_FIRSTCOL - + currentColumn][i])) { - Component c = (Component) cells[CELL_FIRSTCOL - + currentColumn][i]; - if (c == null) { - target.addText(""); - } else { - c.paint(target); - } - } else { - target - .addText((String) cells[CELL_FIRSTCOL - + currentColumn][i]); - } - } - - target.endTag("tr"); - } - target.endTag("rows"); - - // The select variable is only enabled if selectable - if (selectable) { - target.addVariable(this, "selected", selectedKeys); - } - - // The cursors are only shown on pageable table - if (first != 0 || getPageLength() > 0) { - target.addVariable(this, "firstvisible", first); - } - - // Sorting - if (getContainerDataSource() instanceof Container.Sortable) { - target.addVariable(this, "sortcolumn", this.columnIdMap - .key(this.sortContainerPropertyId)); - target.addVariable(this, "sortascending", this.sortAscending); - } - - // Resets and paints "to be painted next" variables. Also reset - // pageBuffer - this.reqFirstRowToPaint = -1; - this.reqRowsToPaint = -1; - this.pageBuffer = null; - target.addVariable(this, "reqrows", this.reqRowsToPaint); - target.addVariable(this, "reqfirstrow", this.reqFirstRowToPaint); - - // Actions - if (!actionSet.isEmpty()) { - target.addVariable(this, "action", ""); - target.startTag("actions"); - for (Iterator it = actionSet.iterator(); it.hasNext();) { - Action a = (Action) it.next(); - target.startTag("action"); - if (a.getCaption() != null) { - target.addAttribute("caption", a.getCaption()); - } - if (a.getIcon() != null) { - target.addAttribute("icon", a.getIcon()); - } - target.addAttribute("key", this.actionMapper.key(a)); - target.endTag("action"); - } - target.endTag("actions"); - } - if (this.columnReorderingAllowed) { - String[] colorder = new String[this.visibleColumns.size()]; - int i = 0; - for (Iterator it = this.visibleColumns.iterator(); it.hasNext() - && i < colorder.length;) { - colorder[i++] = this.columnIdMap.key(it.next()); - } - target.addVariable(this, "columnorder", colorder); - } - // Available columns - if (this.columnCollapsingAllowed) { - HashSet ccs = new HashSet(); - for (Iterator i = this.visibleColumns.iterator(); i.hasNext();) { - Object o = i.next(); - if (isColumnCollapsed(o)) { - ccs.add(o); - } - } - String[] collapsedkeys = new String[ccs.size()]; - int nextColumn = 0; - for (Iterator it = this.visibleColumns.iterator(); it.hasNext() - && nextColumn < collapsedkeys.length;) { - Object columnId = it.next(); - if (isColumnCollapsed(columnId)) { - collapsedkeys[nextColumn++] = this.columnIdMap - .key(columnId); - } - } - target.addVariable(this, "collapsedcolumns", collapsedkeys); - } - target.startTag("visiblecolumns"); - int i = 0; - for (Iterator it = this.visibleColumns.iterator(); it.hasNext(); i++) { - Object columnId = it.next(); - if (columnId != null) { - target.startTag("column"); - target.addAttribute("cid", this.columnIdMap.key(columnId)); - String head = getColumnHeader(columnId); - target.addAttribute("caption", (head != null ? head : "")); - if (isColumnCollapsed(columnId)) { - target.addAttribute("collapsed", true); - } - if (colheads) { - if (getColumnIcon(columnId) != null) { - target.addAttribute("icon", getColumnIcon(columnId)); - } - if (sortables.contains(columnId)) { - target.addAttribute("sortable", true); - } - } - if (!ALIGN_LEFT.equals(getColumnAlignment(columnId))) { - target.addAttribute("align", getColumnAlignment(columnId)); - } - if (getColumnWidth(columnId) > -1) { - target.addAttribute("width", String - .valueOf(getColumnWidth(columnId))); - } - - target.endTag("column"); - } - } - target.endTag("visiblecolumns"); - } - - /** - * Gets the UIDL tag corresponding to component. - * - * @return the UIDL tag as string. - */ - public String getTag() { - return "table"; - } - - /** - * Gets the cached visible table contents. - * - * @return the cahced visible table conetents. - */ - private Object[][] getVisibleCells() { - - // Returns a buffered value if possible - if (this.pageBuffer != null && isPageBufferingEnabled()) { - return this.pageBuffer; - } - - // Stops listening the old properties and initialise the list - if (this.listenedProperties == null) { - this.listenedProperties = new LinkedList(); - } else { - for (Iterator i = this.listenedProperties.iterator(); i.hasNext();) { - ((Property.ValueChangeNotifier) i.next()).removeListener(this); - } - } - - // Detach old visible component from the table - if (this.visibleComponents == null) { - this.visibleComponents = new LinkedList(); - } else { - for (Iterator i = this.visibleComponents.iterator(); i.hasNext();) { - ((Component) i.next()).setParent(null); - } - this.visibleComponents.clear(); - } - - // Collects the basic facts about the table page - Object[] colids = getVisibleColumns(); - int cols = colids.length; - int pagelen = getPageLength(); - int firstIndex = getCurrentPageFirstItemIndex(); - int rows = size(); - if (rows > 0 && firstIndex >= 0) { - rows -= firstIndex; - } - if (pagelen > 0 && pagelen < rows) { - rows = pagelen; - } - - // If "to be painted next" variables are set, use them - if (this.reqRowsToPaint >= 0) { - rows = this.reqRowsToPaint; - } - Object id; - if (this.reqFirstRowToPaint >= 0 && this.reqFirstRowToPaint < size()) { - firstIndex = this.reqFirstRowToPaint; - } - if (size() > 0) { - if (rows + firstIndex > size()) { - rows = size() - firstIndex; - } - } else { - rows = 0; - } - - Object[][] cells = new Object[cols + CELL_FIRSTCOL][rows]; - if (rows == 0) { - return cells; - } - - // Gets the first item id - if (this.items instanceof Container.Indexed) { - id = ((Container.Indexed) this.items).getIdByIndex(firstIndex); - } else { - id = ((Container.Ordered) this.items).firstItemId(); - for (int i = 0; i < firstIndex; i++) { - id = ((Container.Ordered) this.items).nextItemId(id); - } - } - - int headmode = getRowHeaderMode(); - boolean[] iscomponent = new boolean[cols]; - for (int i = 0; i < cols; i++) { - iscomponent[i] = Component.class - .isAssignableFrom(getType(colids[i])); - } - - // Creates the page contents - int filledRows = 0; - for (int i = 0; i < rows && id != null; i++) { - cells[CELL_ITEMID][i] = id; - cells[CELL_KEY][i] = this.itemIdMapper.key(id); - if (headmode != ROW_HEADER_MODE_HIDDEN) { - switch (headmode) { - case ROW_HEADER_MODE_INDEX: - cells[CELL_HEADER][i] = String.valueOf(i + firstIndex + 1); - break; - default: - cells[CELL_HEADER][i] = getItemCaption(id); - } - cells[CELL_ICON][i] = getItemIcon(id); - } - if (cols > 0) { - for (int j = 0; j < cols; j++) { - Object value = null; - Property p = getContainerProperty(id, colids[j]); - if (p != null) { - if (p instanceof Property.ValueChangeNotifier) { - ((Property.ValueChangeNotifier) p) - .addListener(this); - this.listenedProperties.add(p); - } - if (iscomponent[j]) { - value = p.getValue(); - } else if (p != null) { - value = getPropertyValue(id, colids[j], p); - } else { - value = getPropertyValue(id, colids[j], null); - } - } else { - value = ""; - } - - if (value instanceof Component) { - ((Component) value).setParent(this); - this.visibleComponents.add(value); - } - cells[CELL_FIRSTCOL + j][i] = value; - - } - } - id = ((Container.Ordered) this.items).nextItemId(id); - - filledRows++; - } - - // Assures that all the rows of the cell-buffer are valid - if (filledRows != cells[0].length) { - Object[][] temp = new Object[cells.length][filledRows]; - for (int i = 0; i < cells.length; i++) { - for (int j = 0; j < filledRows; j++) { - temp[i][j] = cells[i][j]; - } - } - cells = temp; - } - - // Saves the results to internal buffer iff in buffering mode - // to possible conserve memory from large non-buffered pages - if (isPageBufferingEnabled()) { - this.pageBuffer = cells; - } - - return cells; - } - - /** - * Gets the value of property. - * - * By default if the table is editable the fieldFactory is used to create - * editors for table cells. Otherwise formatPropertyValue is used to format - * the value representation. - * - * @param rowId - * the Id of the row (same as item Id). - * @param colId - * the Id of the column. - * @param property - * the Property to be presented. - * @return Object Either formatted value or Component for field. - * @see #setFieldFactory(FieldFactory) - */ - protected Object getPropertyValue(Object rowId, Object colId, - Property property) { - if (isEditable() && this.fieldFactory != null) { - Field f = this.fieldFactory.createField(getContainerDataSource(), - rowId, colId, this); - if (f != null) { - f.setPropertyDataSource(property); - return f; - } - } - - return formatPropertyValue(rowId, colId, property); - } - - /** - * Formats table cell property values. By default the property.toString() - * and return a empty string for null properties. - * - * @param rowId - * the Id of the row (same as item Id). - * @param colId - * the Id of the column. - * @param property - * the Property to be formatted. - * @return the String representation of property and its value. - * @since 3.1 - */ - protected String formatPropertyValue(Object rowId, Object colId, - Property property) { - if (property == null) { - return ""; - } - return property.toString(); - } - - /* Action container *************************************************** */ - - /** - * Registers a new action handler for this container - * - * @see com.itmill.toolkit.event.Action.Container#addActionHandler(Action.Handler) - */ - public void addActionHandler(Action.Handler actionHandler) { - - if (actionHandler != null) { - - if (this.actionHandlers == null) { - this.actionHandlers = new LinkedList(); - this.actionMapper = new KeyMapper(); - } - - if (!this.actionHandlers.contains(actionHandler)) { - this.actionHandlers.add(actionHandler); - requestRepaint(); - } - - } - } - - /** - * Removes a previously registered action handler for the contents of this - * container. - * - * @see com.itmill.toolkit.event.Action.Container#removeActionHandler(Action.Handler) - */ - public void removeActionHandler(Action.Handler actionHandler) { - - if (this.actionHandlers != null - && this.actionHandlers.contains(actionHandler)) { - - this.actionHandlers.remove(actionHandler); - - if (this.actionHandlers.isEmpty()) { - this.actionHandlers = null; - this.actionMapper = null; - } - - requestRepaint(); - } - } - - /* Property value change listening support **************************** */ - - /** - * Notifies this listener that the Property's value has changed. - * - * @see com.itmill.toolkit.data.Property.ValueChangeListener#valueChange(Property.ValueChangeEvent) - */ - public void valueChange(Property.ValueChangeEvent event) { - super.valueChange(event); - requestRepaint(); - } - - /** - * Notifies the component that it is connected to an application. - * - * @see com.itmill.toolkit.ui.Component#attach() - */ - public void attach() { - super.attach(); - - if (this.visibleComponents != null) { - for (Iterator i = this.visibleComponents.iterator(); i.hasNext();) { - ((Component) i.next()).attach(); - } - } - } - - /** - * Notifies the component that it is detached from the application - * - * @see com.itmill.toolkit.ui.Component#detach() - */ - public void detach() { - super.detach(); - - if (this.visibleComponents != null) { - for (Iterator i = this.visibleComponents.iterator(); i.hasNext();) { - ((Component) i.next()).detach(); - } - } - } - - /** - * Removes all Items from the Container. - * - * @see com.itmill.toolkit.data.Container#removeAllItems() - */ - public boolean removeAllItems() { - this.currentPageFirstItemId = null; - this.currentPageFirstItemIndex = 0; - return super.removeAllItems(); - } - - /** - * Removes the Item identified by ItemId from the Container. - * - * @see com.itmill.toolkit.data.Container#removeItem(Object) - */ - public boolean removeItem(Object itemId) { - Object nextItemId = ((Container.Ordered) this.items).nextItemId(itemId); - boolean ret = super.removeItem(itemId); - if (ret && (itemId != null) - && (itemId.equals(this.currentPageFirstItemId))) { - this.currentPageFirstItemId = nextItemId; - } - return ret; - } - - /** - * Removes a Property specified by the given Property ID from the Container. - * - * @see com.itmill.toolkit.data.Container#removeContainerProperty(Object) - */ - public boolean removeContainerProperty(Object propertyId) - throws UnsupportedOperationException { - - // If a visible property is removed, remove the corresponding column - this.visibleColumns.remove(propertyId); - this.columnAlignments.remove(propertyId); - this.columnIcons.remove(propertyId); - this.columnHeaders.remove(propertyId); - - return super.removeContainerProperty(propertyId); - } - - /** - * Adds a new property to the table and show it as a visible column. - * - * @param propertyId - * the Id of the proprty. - * @param type - * the class of the property. - * @param defaultValue - * the default value given for all existing items. - * @see com.itmill.toolkit.data.Container#addContainerProperty(Object, - * Class, Object) - */ - public boolean addContainerProperty(Object propertyId, Class type, - Object defaultValue) throws UnsupportedOperationException { - if (!super.addContainerProperty(propertyId, type, defaultValue)) { - return false; - } - if (!this.visibleColumns.contains(propertyId)) { - this.visibleColumns.add(propertyId); - } - return true; - } - - /** - * Adds a new property to the table and show it as a visible column. - * - * @param propertyId - * the Id of the proprty - * @param type - * the class of the property - * @param defaultValue - * the default value given for all existing items - * @param columnHeader - * the Explicit header of the column. If explicit header is not - * needed, this should be set null. - * @param columnIcon - * the Icon of the column. If icon is not needed, this should be - * set null. - * @param columnAlignment - * the Alignment of the column. Null implies align left. - * @throws UnsupportedOperationException - * if the operation is not supported. - * @see com.itmill.toolkit.data.Container#addContainerProperty(Object, - * Class, Object) - */ - public boolean addContainerProperty(Object propertyId, Class type, - Object defaultValue, String columnHeader, Resource columnIcon, - String columnAlignment) throws UnsupportedOperationException { - if (!this.addContainerProperty(propertyId, type, defaultValue)) { - return false; - } - setColumnAlignment(propertyId, columnAlignment); - setColumnHeader(propertyId, columnHeader); - setColumnIcon(propertyId, columnIcon); - return true; - } - - /** - * Returns the list of items on the current page - * - * @see com.itmill.toolkit.ui.Select#getVisibleItemIds() - */ - public Collection getVisibleItemIds() { - - LinkedList visible = new LinkedList(); - - Object[][] cells = getVisibleCells(); - for (int i = 0; i < cells[CELL_ITEMID].length; i++) { - visible.add(cells[CELL_ITEMID][i]); - } - - return visible; - } - - /** - * Container datasource item set change. Table must flush its buffers on - * change. - * - * @see com.itmill.toolkit.data.Container.ItemSetChangeListener#containerItemSetChange(com.itmill.toolkit.data.Container.ItemSetChangeEvent) - */ - public void containerItemSetChange(Container.ItemSetChangeEvent event) { - this.pageBuffer = null; - super.containerItemSetChange(event); - setCurrentPageFirstItemIndex(getCurrentPageFirstItemIndex()); - } - - /** - * Container datasource property set change. Table must flush its buffers on - * change. - * - * @see com.itmill.toolkit.data.Container.PropertySetChangeListener#containerPropertySetChange(com.itmill.toolkit.data.Container.PropertySetChangeEvent) - */ - public void containerPropertySetChange( - Container.PropertySetChangeEvent event) { - this.pageBuffer = null; - super.containerPropertySetChange(event); - } - - /** - * Adding new items is not supported. - * - * @throws UnsupportedOperationException - * if set to true. - * @see com.itmill.toolkit.ui.Select#setNewItemsAllowed(boolean) - */ - public void setNewItemsAllowed(boolean allowNewOptions) - throws UnsupportedOperationException { - if (allowNewOptions) { - throw new UnsupportedOperationException(); - } - } - - /** - * Focusing to this component is not supported. - * - * @throws UnsupportedOperationException - * if invoked. - * @see com.itmill.toolkit.ui.AbstractField#focus() - */ - public void focus() throws UnsupportedOperationException { - throw new UnsupportedOperationException(); - } - - /** - * Gets the ID of the Item following the Item that corresponds to itemId. - * - * @see com.itmill.toolkit.data.Container.Ordered#nextItemId(java.lang.Object) - */ - public Object nextItemId(Object itemId) { - return ((Container.Ordered) this.items).nextItemId(itemId); - } - - /** - * Gets the ID of the Item preceding the Item that corresponds to the - * itemId. - * - * @see com.itmill.toolkit.data.Container.Ordered#prevItemId(java.lang.Object) - */ - public Object prevItemId(Object itemId) { - return ((Container.Ordered) this.items).prevItemId(itemId); - } - - /** - * Gets the ID of the first Item in the Container. - * - * @see com.itmill.toolkit.data.Container.Ordered#firstItemId() - */ - public Object firstItemId() { - return ((Container.Ordered) this.items).firstItemId(); - } - - /** - * Gets the ID of the last Item in the Container. - * - * @see com.itmill.toolkit.data.Container.Ordered#lastItemId() - */ - public Object lastItemId() { - return ((Container.Ordered) this.items).lastItemId(); - } - - /** - * Tests if the Item corresponding to the given Item ID is the first Item in - * the Container. - * - * @see com.itmill.toolkit.data.Container.Ordered#isFirstId(java.lang.Object) - */ - public boolean isFirstId(Object itemId) { - return ((Container.Ordered) this.items).isFirstId(itemId); - } - - /** - * Tests if the Item corresponding to the given Item ID is the last Item in - * the Container. - * - * @see com.itmill.toolkit.data.Container.Ordered#isLastId(java.lang.Object) - */ - public boolean isLastId(Object itemId) { - return ((Container.Ordered) this.items).isLastId(itemId); - } - - /** - * Adds new item after the given item. - * - * @see com.itmill.toolkit.data.Container.Ordered#addItemAfter(java.lang.Object) - */ - public Object addItemAfter(Object previousItemId) - throws UnsupportedOperationException { - return ((Container.Ordered) this.items).addItemAfter(previousItemId); - } - - /** - * Adds new item after the given item. - * - * @see com.itmill.toolkit.data.Container.Ordered#addItemAfter(java.lang.Object, - * java.lang.Object) - */ - public Item addItemAfter(Object previousItemId, Object newItemId) - throws UnsupportedOperationException { - return ((Container.Ordered) this.items).addItemAfter(previousItemId, - newItemId); - } - - /** - * Gets the FieldFactory that is used to create editor for table cells. - * - * The FieldFactory is only used if the Table is editable. - * - * @return FieldFactory used to create the Field instances. - * @see #isEditable - */ - public FieldFactory getFieldFactory() { - return this.fieldFactory; - } - - /** - * Sets the FieldFactory that is used to create editor for table cells. - * - * The FieldFactory is only used if the Table is editable. By default the - * BaseFieldFactory is used. - * - * @param fieldFactory - * the field factory to set. - * @see #isEditable - * @see BaseFieldFactory - * - */ - public void setFieldFactory(FieldFactory fieldFactory) { - this.fieldFactory = fieldFactory; - - // Assure visual refresh - refreshCurrentPage(); - } - - /** - * Is table editable. - * - * If table is editable a editor of type Field is created for each table - * cell. The assigned FieldFactory is used to create the instances. - * - * To provide custom editors for table cells create a class implementins the - * FieldFactory interface, and assign it to table, and set the editable - * property to true. - * - * @return true if table is editable, false oterwise. - * @see Field - * @see FieldFactory - * - */ - public boolean isEditable() { - return this.editable; - } - - /** - * Sets the editable property. - * - * If table is editable a editor of type Field is created for each table - * cell. The assigned FieldFactory is used to create the instances. - * - * To provide custom editors for table cells create a class implementins the - * FieldFactory interface, and assign it to table, and set the editable - * property to true. - * - * @param editable - * true if table should be editable by user. - * @see Field - * @see FieldFactory - * - */ - public void setEditable(boolean editable) { - this.editable = editable; - - // Assure visual refresh - refreshCurrentPage(); - } - - /** - * Sorts the table. - * - * @throws UnsupportedOperationException - * if the container data source does not implement - * Container.Sortable - * @see com.itmill.toolkit.data.Container.Sortable#sort(java.lang.Object[], - * boolean[]) - * - */ - public void sort(Object[] propertyId, boolean[] ascending) - throws UnsupportedOperationException { - Container c = getContainerDataSource(); - if (c instanceof Container.Sortable) { - int pageIndex = getCurrentPageFirstItemIndex(); - ((Container.Sortable) c).sort(propertyId, ascending); - setCurrentPageFirstItemIndex(pageIndex); - } else if (c != null) { - throw new UnsupportedOperationException( - "Underlying Data does not allow sorting"); - } - } - - /** - * Sorts the table by currently selected sorting column. - * - * @throws UnsupportedOperationException - * if the container data source does not implement - * Container.Sortable - */ - public void sort() { - if (getSortContainerPropertyId() == null) { - return; - } - sort(new Object[] { this.sortContainerPropertyId }, - new boolean[] { this.sortAscending }); - } - - /** - * Gets the container property IDs, which can be used to sort the item. - * - * @see com.itmill.toolkit.data.Container.Sortable#getSortableContainerPropertyIds() - */ - public Collection getSortableContainerPropertyIds() { - Container c = getContainerDataSource(); - if (c instanceof Container.Sortable && !isSortDisabled()) { - return ((Container.Sortable) c).getSortableContainerPropertyIds(); - } else { - return new LinkedList(); - } - } - - /** - * Gets the currently sorted column property ID. - * - * @return the Container property id of the currently sorted column. - */ - public Object getSortContainerPropertyId() { - return this.sortContainerPropertyId; - } - - /** - * Sets the currently sorted column property id. - * - * @param propertyId - * the Container property id of the currently sorted column. - */ - public void setSortContainerPropertyId(Object propertyId) { - if ((this.sortContainerPropertyId != null && !this.sortContainerPropertyId - .equals(propertyId)) - || (this.sortContainerPropertyId == null && propertyId != null)) { - this.sortContainerPropertyId = propertyId; - sort(); - } - - // Assures the visual refresh - refreshCurrentPage(); - } - - /** - * Is the table currently sorted in ascending order. - * - * @return true if ascending, false if - * descending. - */ - public boolean isSortAscending() { - return this.sortAscending; - } - - /** - * Sets the table in ascending order. - * - * @param ascending - * true if ascending, false if - * descending. - */ - public void setSortAscending(boolean ascending) { - if (this.sortAscending != ascending) { - this.sortAscending = ascending; - sort(); - } - - // Assures the visual refresh - refreshCurrentPage(); - } - - /** - * Is sorting disabled altogether. - * - * True iff no sortable columns are given even in the case where data source - * would support this. - * - * @return True iff sorting is disabled. - */ - public boolean isSortDisabled() { - return this.sortDisabled; - } - - /** - * Disables the sorting altogether. - * - * To disable sorting altogether, set to true. In this case no sortable - * columns are given even in the case where datasource would support this. - * - * @param sortDisabled - * True iff sorting is disabled. - */ - public void setSortDisabled(boolean sortDisabled) { - if (this.sortDisabled != sortDisabled) { - this.sortDisabled = sortDisabled; - refreshCurrentPage(); - } - } - - /** - * Gets height property unit. - * - * @see com.itmill.toolkit.terminal.Sizeable#getHeightUnits() - */ - public int getHeightUnits() { - return this.heightUnit; - } - - /** - * Gets width property unit. - * - * @see com.itmill.toolkit.terminal.Sizeable#getWidthUnits() - */ - public int getWidthUnits() { - return this.widthUnit; - } - - /** - * Sets height units. - * - * @see com.itmill.toolkit.terminal.Sizeable#setHeightUnits(int) - */ - public void setHeightUnits(int units) { - this.heightUnit = units; - } - - /** - * Sets width units. Table supports only Sizeable.UNITS_PIXELS and - * Sizeable.UNITS_PERCENTAGE. Setting to any other throws - * IllegalArgumentException. - * - * @see com.itmill.toolkit.terminal.Sizeable#setWidthUnits(int) - */ - public void setWidthUnits(int units) { - if (units != Sizeable.UNITS_PIXELS - && units != Sizeable.UNITS_PERCENTAGE) { - throw new IllegalArgumentException(); - } - this.widthUnit = units; - } - - /** - * Gets height. - * - * @return height value as a positive integer or negative value if not - * assigned. - * @see com.itmill.toolkit.terminal.Sizeable#getHeight() - */ - public int getHeight() { - return this.height; - } - - /** - * Gets width. - * - * @return width value as positive integer or negative value if not - * assigned. - * @see com.itmill.toolkit.terminal.Sizeable#getWidth() - */ - public int getWidth() { - return this.width; - } - - /** - * Sets height. Use negative value to let the client decide the height. - * - * @param height - * the height to set. - */ - public void setHeight(int height) { - this.height = height; - requestRepaint(); - } - - /** - * Sets width. Use negative value to allow the client decide the width. - * - * @param width - * the width to set. - */ - public void setWidth(int width) { - this.width = width; - requestRepaint(); - } - - /** - * Table does not support lazy options loading mode. Setting this true will - * throw UnsupportedOperationException. - * - * @see com.itmill.toolkit.ui.Select#setLazyLoading(boolean) - */ - public void setLazyLoading(boolean useLazyLoading) { - if (useLazyLoading) { - throw new UnsupportedOperationException( - "Lazy options loading is not supported by Table."); - } - } - - /* - * (non-Javadoc) - * - * @see com.itmill.toolkit.terminal.Sizeable#setSizeFull() - */ - public void setSizeFull() { - setWidth(100); - setHeight(100); - setWidthUnits(UNITS_PERCENTAGE); - setHeightUnits(UNITS_PERCENTAGE); - } - - /* - * (non-Javadoc) - * - * @see com.itmill.toolkit.terminal.Sizeable#setSizeUndefined() - */ - public void setSizeUndefined() { - setWidth(-1); - setHeight(-1); - setWidthUnits(UNITS_PIXELS); - setHeightUnits(UNITS_PIXELS); - } + Container.Ordered, Container.Sortable, Sizeable { + + private static final int CELL_KEY = 0; + + private static final int CELL_HEADER = 1; + + private static final int CELL_ICON = 2; + + private static final int CELL_ITEMID = 3; + + private static final int CELL_FIRSTCOL = 4; + + /** + * Width of the table or -1 if unspecified. + */ + private int width = -1; + + /** + * Height of the table or -1 if unspecified. + */ + private int height = -1; + + /** + * Width unit. + */ + private int widthUnit = Sizeable.UNITS_PIXELS; + + /** + * Height unit. + */ + private int heightUnit = Sizeable.UNITS_PIXELS; + + /** + * Left column alignment. This is the default behaviour. + */ + public static final String ALIGN_LEFT = "b"; + + /** + * Center column alignment. + */ + public static final String ALIGN_CENTER = "c"; + + /** + * Right column alignment. + */ + public static final String ALIGN_RIGHT = "e"; + + /** + * Column header mode: Column headers are hidden. This is the default + * behaviour. + */ + public static final int COLUMN_HEADER_MODE_HIDDEN = -1; + + /** + * Column header mode: Property ID:s are used as column headers. + */ + public static final int COLUMN_HEADER_MODE_ID = 0; + + /** + * Column header mode: Column headers are explicitly specified with + * setColumnHeaders. + */ + public static final int COLUMN_HEADER_MODE_EXPLICIT = 1; + + /** + * Column header mode: Column headers are explicitly specified with + * setColumnHeaders + */ + public static final int COLUMN_HEADER_MODE_EXPLICIT_DEFAULTS_ID = 2; + + /** + * Row caption mode: The row headers are hidden. This is the default + * mode. + */ + public static final int ROW_HEADER_MODE_HIDDEN = -1; + + /** + * Row caption mode: Items Id-objects toString is used as row caption. + */ + public static final int ROW_HEADER_MODE_ID = AbstractSelect.ITEM_CAPTION_MODE_ID; + + /** + * Row caption mode: Item-objects toString is used as row caption. + */ + public static final int ROW_HEADER_MODE_ITEM = AbstractSelect.ITEM_CAPTION_MODE_ITEM; + + /** + * Row caption mode: Index of the item is used as item caption. The index + * mode can only be used with the containers implementing Container.Indexed + * interface. + */ + public static final int ROW_HEADER_MODE_INDEX = AbstractSelect.ITEM_CAPTION_MODE_INDEX; + + /** + * Row caption mode: Item captions are explicitly specified. + */ + public static final int ROW_HEADER_MODE_EXPLICIT = AbstractSelect.ITEM_CAPTION_MODE_EXPLICIT; + + /** + * Row caption mode: Item captions are read from property specified with + * setItemCaptionPropertyId. + */ + public static final int ROW_HEADER_MODE_PROPERTY = AbstractSelect.ITEM_CAPTION_MODE_PROPERTY; + + /** + * Row caption mode: Only icons are shown, the captions are hidden. + */ + public static final int ROW_HEADER_MODE_ICON_ONLY = AbstractSelect.ITEM_CAPTION_MODE_ICON_ONLY; + + /** + * Row caption mode: Item captions are explicitly specified, but if the + * caption is missing, the item id objects toString() is used + * instead. + */ + public static final int ROW_HEADER_MODE_EXPLICIT_DEFAULTS_ID = AbstractSelect.ITEM_CAPTION_MODE_EXPLICIT_DEFAULTS_ID; + + /* Private table extensions to Select *********************************** */ + + /** + * True if column collapsing is allowed. + */ + private boolean columnCollapsingAllowed = false; + + /** + * True if reordering of columns is allowed on the client side. + */ + private boolean columnReorderingAllowed = false; + + /** + * Keymapper for column ids. + */ + private final KeyMapper columnIdMap = new KeyMapper(); + + /** + * Holds visible column propertyIds - in order. + */ + private LinkedList visibleColumns = new LinkedList(); + + /** + * Holds propertyIds of currently collapsed columns. + */ + private final HashSet collapsedColumns = new HashSet(); + + /** + * Holds headers for visible columns (by propertyId). + */ + private final HashMap columnHeaders = new HashMap(); + + /** + * Holds icons for visible columns (by propertyId). + */ + private final HashMap columnIcons = new HashMap(); + + /** + * Holds alignments for visible columns (by propertyId). + */ + private HashMap columnAlignments = new HashMap(); + + /** + * Holds column widths in pixels for visible columns (by propertyId). + */ + private final HashMap columnWidths = new HashMap(); + + /** + * Holds value of property pageLength. 0 disables paging. + */ + private int pageLength = 15; + + /** + * Id the first item on the current page. + */ + private Object currentPageFirstItemId = null; + + /** + * Index of the first item on the current page. + */ + private int currentPageFirstItemIndex = 0; + + /** + * Holds value of property pageBuffering. + */ + private boolean pageBuffering = false; + + /** + * Holds value of property selectable. + */ + private boolean selectable = false; + + /** + * Holds value of property columnHeaderMode. + */ + private int columnHeaderMode = COLUMN_HEADER_MODE_EXPLICIT_DEFAULTS_ID; + + /** + * True iff the row captions are hidden. + */ + private boolean rowCaptionsAreHidden = true; + + /** + * Page contents buffer used in buffered mode. + */ + private Object[][] pageBuffer = null; + + /** + * List of properties listened - the list is kept to release the listeners + * later. + */ + private LinkedList listenedProperties = null; + + /** + * List of visible components - the is used for needsRepaint calculation. + */ + private LinkedList visibleComponents = null; + + /** + * List of action handlers. + */ + private LinkedList actionHandlers = null; + + /** + * Action mapper. + */ + private KeyMapper actionMapper = null; + + /** + * Table cell editor factory. + */ + private FieldFactory fieldFactory = new BaseFieldFactory(); + + /** + * Is table editable. + */ + private boolean editable = false; + + /** + * Current sorting direction. + */ + private boolean sortAscending = true; + + /** + * Currently table is sorted on this propertyId. + */ + private Object sortContainerPropertyId = null; + + /** + * Is table sorting disabled alltogether; even if some of the properties + * would be sortable. + */ + private boolean sortDisabled = false; + + /** + * Number of rows explicitly requested by the client to be painted on next + * paint. This is -1 if no request by the client is made. Painting the + * component will automatically reset this to -1. + */ + private int reqRowsToPaint = -1; + + /** + * Index of the first rows explicitly requested by the client to be painted. + * This is -1 if no request by the client is made. Painting the component + * will automatically reset this to -1. + */ + private int reqFirstRowToPaint = -1; + + /* Table constructors *************************************************** */ + + /** + * Creates a new empty table. + */ + public Table() { + setRowHeaderMode(ROW_HEADER_MODE_HIDDEN); + } + + /** + * Creates a new empty table with caption. + * + * @param caption + */ + public Table(String caption) { + this(); + setCaption(caption); + } + + /** + * Creates a new table with caption and connect it to a Container. + * + * @param caption + * @param dataSource + */ + public Table(String caption, Container dataSource) { + this(); + setCaption(caption); + setContainerDataSource(dataSource); + } + + /* Table functionality ************************************************** */ + + /** + * Gets the array of visible column property id:s. + * + *

+ * The columns are show in the order of their appearance in this array. + *

+ * + * @return the Value of property availableColumns. + */ + public Object[] getVisibleColumns() { + if (visibleColumns == null) { + return null; + } + return visibleColumns.toArray(); + } + + /** + * Sets the array of visible column property id:s. + * + *

+ * The columns are show in the order of their appearance in this array. + *

+ * + * @param visibleColumns + * the Array of shown property id:s. + */ + public void setVisibleColumns(Object[] visibleColumns) { + + // Visible columns must exist + if (visibleColumns == null) { + throw new NullPointerException( + "Can not set visible columns to null value"); + } + + // Checks that the new visible columns contains no nulls and properties + // exist + Collection properties = getContainerPropertyIds(); + for (int i = 0; i < visibleColumns.length; i++) { + if (visibleColumns[i] == null) { + throw new NullPointerException("Properties must be non-nulls"); + } else if (!properties.contains(visibleColumns[i])) { + throw new IllegalArgumentException( + "Properties must exist in the Container, missing property: " + + visibleColumns[i]); + } + } + + // If this is called befor the constructor is finished, it might be + // uninitialized + LinkedList newVC = new LinkedList(); + for (int i = 0; i < visibleColumns.length; i++) { + newVC.add(visibleColumns[i]); + } + + // Removes alignments, icons and headers from hidden columns + if (this.visibleColumns != null) { + for (Iterator i = this.visibleColumns.iterator(); i.hasNext();) { + Object col = i.next(); + if (!newVC.contains(col)) { + setColumnHeader(col, null); + setColumnAlignment(col, null); + setColumnIcon(col, null); + } + } + } + + this.visibleColumns = newVC; + + // Assures visual refresh + refreshCurrentPage(); + } + + /** + * Gets the headers of the columns. + * + *

+ * The headers match the property id:s given my the set visible column + * headers. The table must be set in either + * ROW_HEADER_MODE_EXPLICIT or + * ROW_HEADER_MODE_EXPLICIT_DEFAULTS_ID mode to show the + * headers. In the defaults mode any nulls in the headers array are replaced + * with id.toString() outputs when rendering. + *

+ * + * @return the Array of column headers. + */ + public String[] getColumnHeaders() { + if (columnHeaders == null) { + return null; + } + String[] headers = new String[visibleColumns.size()]; + int i = 0; + for (Iterator it = visibleColumns.iterator(); it.hasNext(); i++) { + headers[i] = (String) columnHeaders.get(it.next()); + } + return headers; + } + + /** + * Sets the headers of the columns. + * + *

+ * The headers match the property id:s given my the set visible column + * headers. The table must be set in either + * ROW_HEADER_MODE_EXPLICIT or + * ROW_HEADER_MODE_EXPLICIT_DEFAULTS_ID mode to show the + * headers. In the defaults mode any nulls in the headers array are replaced + * with id.toString() outputs when rendering. + *

+ * + * @param columnHeaders + * the Array of column headers that match the + * getVisibleColumns method. + */ + public void setColumnHeaders(String[] columnHeaders) { + + if (columnHeaders.length != visibleColumns.size()) { + throw new IllegalArgumentException( + "The length of the headers array must match the number of visible columns"); + } + + this.columnHeaders.clear(); + int i = 0; + for (Iterator it = visibleColumns.iterator(); it.hasNext() + && i < columnHeaders.length; i++) { + this.columnHeaders.put(it.next(), columnHeaders[i]); + } + + // Assures the visual refresh + refreshCurrentPage(); + } + + /** + * Gets the icons of the columns. + * + *

+ * The icons in headers match the property id:s given my the set visible + * column headers. The table must be set in either + * ROW_HEADER_MODE_EXPLICIT or + * ROW_HEADER_MODE_EXPLICIT_DEFAULTS_ID mode to show the + * headers with icons. + *

+ * + * @return the Array of icons that match the getVisibleColumns. + */ + public Resource[] getColumnIcons() { + if (columnIcons == null) { + return null; + } + Resource[] icons = new Resource[visibleColumns.size()]; + int i = 0; + for (Iterator it = visibleColumns.iterator(); it.hasNext(); i++) { + icons[i] = (Resource) columnIcons.get(it.next()); + } + + return icons; + } + + /** + * Sets the icons of the columns. + * + *

+ * The icons in headers match the property id:s given my the set visible + * column headers. The table must be set in either + * ROW_HEADER_MODE_EXPLICIT or + * ROW_HEADER_MODE_EXPLICIT_DEFAULTS_ID mode to show the + * headers with icons. + *

+ * + * @param columnIcons + * the Array of icons that match the + * getVisibleColumns. + */ + public void setColumnIcons(Resource[] columnIcons) { + + if (columnIcons.length != visibleColumns.size()) { + throw new IllegalArgumentException( + "The length of the icons array must match the number of visible columns"); + } + + this.columnIcons.clear(); + int i = 0; + for (Iterator it = visibleColumns.iterator(); it.hasNext() + && i < columnIcons.length; i++) { + this.columnIcons.put(it.next(), columnIcons[i]); + } + + // Assure visual refresh + refreshCurrentPage(); + } + + /** + * Gets the array of column alignments. + * + *

+ * The items in the array must match the properties identified by + * getVisibleColumns(). The possible values for the + * alignments include: + *

    + *
  • ALIGN_LEFT: Left alignment
  • + *
  • ALIGN_CENTER: Centered
  • + *
  • ALIGN_RIGHT: Right alignment
  • + *
+ * The alignments default to ALIGN_LEFT: any null values are + * rendered as align lefts. + *

+ * + * @return the Column alignments array. + */ + public String[] getColumnAlignments() { + if (columnAlignments == null) { + return null; + } + String[] alignments = new String[visibleColumns.size()]; + int i = 0; + for (Iterator it = visibleColumns.iterator(); it.hasNext(); i++) { + alignments[i++] = getColumnAlignment(it.next()); + } + + return alignments; + } + + /** + * Sets the column alignments. + * + *

+ * The items in the array must match the properties identified by + * getVisibleColumns(). The possible values for the + * alignments include: + *

    + *
  • ALIGN_LEFT: Left alignment
  • + *
  • ALIGN_CENTER: Centered
  • + *
  • ALIGN_RIGHT: Right alignment
  • + *
+ * The alignments default to ALIGN_LEFT + *

+ * + * @param columnAlignments + * the Column alignments array. + */ + public void setColumnAlignments(String[] columnAlignments) { + + if (columnAlignments.length != visibleColumns.size()) { + throw new IllegalArgumentException( + "The length of the alignments array must match the number of visible columns"); + } + + // Checks all alignments + for (int i = 0; i < columnAlignments.length; i++) { + String a = columnAlignments[i]; + if (a != null && !a.equals(ALIGN_LEFT) && !a.equals(ALIGN_CENTER) + && !a.equals(ALIGN_RIGHT)) { + throw new IllegalArgumentException("Column " + i + + " aligment '" + a + "' is invalid"); + } + } + + // Resets the alignments + HashMap newCA = new HashMap(); + int i = 0; + for (Iterator it = visibleColumns.iterator(); it.hasNext() + && i < columnAlignments.length; i++) { + newCA.put(it.next(), columnAlignments[i]); + } + this.columnAlignments = newCA; + + // Assures the visual refresh + refreshCurrentPage(); + } + + /** + * Sets columns width (in pixels). Theme may not necessary respect very + * small or very big values. Setting width to -1 (default) means that theme + * will make decision of width. + * + * @param columnId + * colunmns property id + * @param width + * width to be reserved for colunmns content + * @since 4.0.3 + */ + public void setColumnWidth(Object columnId, int width) { + columnWidths.put(columnId, new Integer(width)); + } + + /** + * Gets the width of column + * + * @param propertyId + * @return width of colun or -1 when value not set + */ + public int getColumnWidth(Object propertyId) { + Integer value = (Integer) columnWidths.get(propertyId); + if (value == null) { + return -1; + } + return value.intValue(); + } + + /** + * Gets the page length. + * + *

+ * Setting page length 0 disables paging. + *

+ * + * @return the Length of one page. + */ + public int getPageLength() { + return pageLength; + } + + /** + * Sets the page length. + * + *

+ * Setting page length 0 disables paging. The page length defaults to 15. + *

+ * + * @param pageLength + * the Length of one page. + */ + public void setPageLength(int pageLength) { + if (pageLength >= 0 && this.pageLength != pageLength) { + this.pageLength = pageLength; + // "scroll" to first row + setCurrentPageFirstItemIndex(0); + // Assures the visual refresh + refreshCurrentPage(); + } + } + + /** + * Getter for property currentPageFirstItem. + * + * @return the Value of property currentPageFirstItem. + */ + public Object getCurrentPageFirstItemId() { + + // Priorise index over id if indexes are supported + if (items instanceof Container.Indexed) { + int index = getCurrentPageFirstItemIndex(); + Object id = null; + if (index >= 0 && index < size()) { + id = ((Container.Indexed) items).getIdByIndex(index); + } + if (id != null && !id.equals(currentPageFirstItemId)) { + currentPageFirstItemId = id; + } + } + + // If there is no item id at all, use the first one + if (currentPageFirstItemId == null) { + currentPageFirstItemId = ((Container.Ordered) items).firstItemId(); + } + + return currentPageFirstItemId; + } + + /** + * Setter for property currentPageFirstItemId. + * + * @param currentPageFirstItemId + * the New value of property currentPageFirstItemId. + */ + public void setCurrentPageFirstItemId(Object currentPageFirstItemId) { + + // Gets the corresponding index + int index = -1; + try { + index = ((Container.Indexed) items) + .indexOfId(currentPageFirstItemId); + } catch (ClassCastException e) { + + // If the table item container does not have index, we have to + // calculates the index by hand + Object id = ((Container.Ordered) items).firstItemId(); + while (id != null && !id.equals(currentPageFirstItemId)) { + index++; + id = ((Container.Ordered) items).nextItemId(id); + } + if (id == null) { + index = -1; + } + } + + // If the search for item index was successfull + if (index >= 0) { + this.currentPageFirstItemId = currentPageFirstItemId; + currentPageFirstItemIndex = index; + } + + // Assures the visual refresh + refreshCurrentPage(); + + } + + /** + * Gets the icon Resource for the specified column. + * + * @param propertyId + * the propertyId indentifying the column. + * @return the icon for the specified column; null if the column has no icon + * set, or if the column is not visible. + */ + public Resource getColumnIcon(Object propertyId) { + return (Resource) columnIcons.get(propertyId); + } + + /** + * Sets the icon Resource for the specified column. + *

+ * Throws IllegalArgumentException if the specified column is not visible. + *

+ * + * @param propertyId + * the propertyId identifying the column. + * @param icon + * the icon Resource to set. + */ + public void setColumnIcon(Object propertyId, Resource icon) { + + if (icon == null) { + columnIcons.remove(propertyId); + } else { + columnIcons.put(propertyId, icon); + } + + // Assures the visual refresh + refreshCurrentPage(); + } + + /** + * Gets the header for the specified column. + * + * @param propertyId + * the propertyId indentifying the column. + * @return the header for the specifed column if it has one. + */ + public String getColumnHeader(Object propertyId) { + if (getColumnHeaderMode() == COLUMN_HEADER_MODE_HIDDEN) { + return null; + } + + String header = (String) columnHeaders.get(propertyId); + if ((header == null && getColumnHeaderMode() == COLUMN_HEADER_MODE_EXPLICIT_DEFAULTS_ID) + || getColumnHeaderMode() == COLUMN_HEADER_MODE_ID) { + header = propertyId.toString(); + } + + return header; + } + + /** + * Sets the column header for the specified column; + * + * @param propertyId + * the propertyId indentifying the column. + * @param header + * the header to set. + */ + public void setColumnHeader(Object propertyId, String header) { + + if (header == null) { + columnHeaders.remove(propertyId); + return; + } + columnHeaders.put(propertyId, header); + + // Assures the visual refresh + refreshCurrentPage(); + } + + /** + * Gets the specified column's alignment. + * + * @param propertyId + * the propertyID identifying the column. + * @return the specified column's alignment if it as one; null otherwise. + */ + public String getColumnAlignment(Object propertyId) { + String a = (String) columnAlignments.get(propertyId); + return a == null ? ALIGN_LEFT : a; + } + + /** + * Sets the specified column's alignment. + * + *

+ * Throws IllegalArgumentException if the alignment is not one of the + * following: ALIGN_LEFT, ALIGN_CENTER or ALIGN_RIGHT + *

+ * + * @param propertyId + * the propertyID identifying the column. + * @param alignment + * the desired alignment. + */ + public void setColumnAlignment(Object propertyId, String alignment) { + + // Checks for valid alignments + if (alignment != null && !alignment.equals(ALIGN_LEFT) + && !alignment.equals(ALIGN_CENTER) + && !alignment.equals(ALIGN_RIGHT)) { + throw new IllegalArgumentException("Column alignment '" + alignment + + "' is not supported."); + } + + if (alignment == null || alignment.equals(ALIGN_LEFT)) { + columnAlignments.remove(propertyId); + return; + } + + columnAlignments.put(propertyId, alignment); + + // Assures the visual refresh + refreshCurrentPage(); + } + + /** + * Checks if the specified column is collapsed. + * + * @param propertyId + * the propertyID identifying the column. + * @return true if the column is collapsed; false otherwise; + */ + public boolean isColumnCollapsed(Object propertyId) { + return collapsedColumns != null + && collapsedColumns.contains(propertyId); + } + + /** + * Sets whether the specified column is collapsed or not. + * + * + * @param propertyId + * the propertyID identifying the column. + * @param collapsed + * the desired collapsedness. + * @throws IllegalAccessException + */ + public void setColumnCollapsed(Object propertyId, boolean collapsed) + throws IllegalAccessException { + if (!isColumnCollapsingAllowed()) { + throw new IllegalAccessException("Column collapsing not allowed!"); + } + + if (collapsed) { + collapsedColumns.add(propertyId); + } else { + collapsedColumns.remove(propertyId); + } + + // Assures the visual refresh + refreshCurrentPage(); + } + + /** + * Checks if column collapsing is allowed. + * + * @return true if columns can be collapsed; false otherwise. + */ + public boolean isColumnCollapsingAllowed() { + return columnCollapsingAllowed; + } + + /** + * Sets whether column collapsing is allowed or not. + * + * @param collapsingAllowed + * specifies whether column collapsing is allowed. + */ + public void setColumnCollapsingAllowed(boolean collapsingAllowed) { + columnCollapsingAllowed = collapsingAllowed; + + if (!collapsingAllowed) { + collapsedColumns.clear(); + } + + // Assures the visual refresh + refreshCurrentPage(); + } + + /** + * Checks if column reordering is allowed. + * + * @return true if columns can be reordered; false otherwise. + */ + public boolean isColumnReorderingAllowed() { + return columnReorderingAllowed; + } + + /** + * Sets whether column reordering is allowed or not. + * + * @param reorderingAllowed + * specifies whether column reordering is allowed. + */ + public void setColumnReorderingAllowed(boolean reorderingAllowed) { + columnReorderingAllowed = reorderingAllowed; + + // Assures the visual refresh + refreshCurrentPage(); + } + + /* + * Arranges visible columns according to given columnOrder. Silently ignores + * colimnId:s that are not visible columns, and keeps the internal order of + * visible columns left out of the ordering (trailing). Silently does + * nothing if columnReordering is not allowed. + */ + private void setColumnOrder(Object[] columnOrder) { + if (columnOrder == null || !isColumnReorderingAllowed()) { + return; + } + LinkedList newOrder = new LinkedList(); + for (int i = 0; i < columnOrder.length; i++) { + if (columnOrder[i] != null + && visibleColumns.contains(columnOrder[i])) { + visibleColumns.remove(columnOrder[i]); + newOrder.add(columnOrder[i]); + } + } + for (Iterator it = visibleColumns.iterator(); it.hasNext();) { + Object columnId = it.next(); + if (!newOrder.contains(columnId)) { + newOrder.add(columnId); + } + } + visibleColumns = newOrder; + + // Assure visual refresh + refreshCurrentPage(); + } + + /** + * Getter for property currentPageFirstItem. + * + * @return the Value of property currentPageFirstItem. + */ + public int getCurrentPageFirstItemIndex() { + return currentPageFirstItemIndex; + } + + /** + * Setter for property currentPageFirstItem. + * + * @param newIndex + * the New value of property currentPageFirstItem. + */ + public void setCurrentPageFirstItemIndex(int newIndex) { + + // Ensures that the new value is valid + if (newIndex < 0) { + newIndex = 0; + } + if (newIndex >= size()) { + newIndex = size() - 1; + } + + // Refresh first item id + if (items instanceof Container.Indexed) { + try { + currentPageFirstItemId = ((Container.Indexed) items) + .getIdByIndex(newIndex); + } catch (IndexOutOfBoundsException e) { + currentPageFirstItemId = null; + } + currentPageFirstItemIndex = newIndex; + } else { + + // For containers not supporting indexes, we must iterate the + // container forwards / backwards + // next available item forward or backward + + currentPageFirstItemId = ((Container.Ordered) items).firstItemId(); + + // Go forwards in the middle of the list (respect borders) + while (currentPageFirstItemIndex < newIndex + && !((Container.Ordered) items) + .isLastId(currentPageFirstItemId)) { + currentPageFirstItemIndex++; + currentPageFirstItemId = ((Container.Ordered) items) + .nextItemId(currentPageFirstItemId); + } + + // If we did hit the border + if (((Container.Ordered) items).isLastId(currentPageFirstItemId)) { + currentPageFirstItemIndex = size() - 1; + } + + // Go backwards in the middle of the list (respect borders) + while (currentPageFirstItemIndex > newIndex + && !((Container.Ordered) items) + .isFirstId(currentPageFirstItemId)) { + currentPageFirstItemIndex--; + currentPageFirstItemId = ((Container.Ordered) items) + .prevItemId(currentPageFirstItemId); + } + + // If we did hit the border + if (((Container.Ordered) items).isFirstId(currentPageFirstItemId)) { + currentPageFirstItemIndex = 0; + } + + // Go forwards once more + while (currentPageFirstItemIndex < newIndex + && !((Container.Ordered) items) + .isLastId(currentPageFirstItemId)) { + currentPageFirstItemIndex++; + currentPageFirstItemId = ((Container.Ordered) items) + .nextItemId(currentPageFirstItemId); + } + + // If for some reason we do hit border again, override + // the user index request + if (((Container.Ordered) items).isLastId(currentPageFirstItemId)) { + newIndex = currentPageFirstItemIndex = size() - 1; + } + } + + // Assures the visual refresh + refreshCurrentPage(); + } + + /** + * Getter for property pageBuffering. + * + * @return the Value of property pageBuffering. + */ + public boolean isPageBufferingEnabled() { + return pageBuffering; + } + + /** + * Setter for property pageBuffering. + * + * @param pageBuffering + * the New value of property pageBuffering. + */ + public void setPageBufferingEnabled(boolean pageBuffering) { + + this.pageBuffering = pageBuffering; + + // If page buffering is disabled, clear the buffer + if (!pageBuffering) { + pageBuffer = null; + } + } + + /** + * Getter for property selectable. + * + *

+ * The table is not selectable by default. + *

+ * + * @return the Value of property selectable. + */ + public boolean isSelectable() { + return selectable; + } + + /** + * Setter for property selectable. + * + *

+ * The table is not selectable by default. + *

+ * + * @param selectable + * the New value of property selectable. + */ + public void setSelectable(boolean selectable) { + if (this.selectable != selectable) { + this.selectable = selectable; + requestRepaint(); + } + } + + /** + * Getter for property columnHeaderMode. + * + * @return the Value of property columnHeaderMode. + */ + public int getColumnHeaderMode() { + return columnHeaderMode; + } + + /** + * Setter for property columnHeaderMode. + * + * @param columnHeaderMode + * the New value of property columnHeaderMode. + */ + public void setColumnHeaderMode(int columnHeaderMode) { + if (columnHeaderMode >= COLUMN_HEADER_MODE_HIDDEN + && columnHeaderMode <= COLUMN_HEADER_MODE_EXPLICIT_DEFAULTS_ID) { + this.columnHeaderMode = columnHeaderMode; + } + + // Assures the visual refresh + refreshCurrentPage(); + } + + /** + * Refreshes the current page contents. If the page buffering is turned off, + * it is not necessary to call this explicitely. + */ + public void refreshCurrentPage() { + + // Clear page buffer and notify about the change + pageBuffer = null; + requestRepaint(); + } + + /** + * Sets the row header mode. + *

+ * The mode can be one of the following ones: + *

    + *
  • ROW_HEADER_MODE_HIDDEN: The row captions are hidden. + *
  • + *
  • ROW_HEADER_MODE_ID: Items Id-objects + * toString() is used as row caption. + *
  • ROW_HEADER_MODE_ITEM: Item-objects + * toString() is used as row caption. + *
  • ROW_HEADER_MODE_PROPERTY: Property set with + * setItemCaptionPropertyId() is used as row header. + *
  • ROW_HEADER_MODE_EXPLICIT_DEFAULTS_ID: Items + * Id-objects toString() is used as row header. If caption is + * explicitly specified, it overrides the id-caption. + *
  • ROW_HEADER_MODE_EXPLICIT: The row headers must be + * explicitly specified.
  • + *
  • ROW_HEADER_MODE_INDEX: The index of the item is used + * as row caption. The index mode can only be used with the containers + * implementing Container.Indexed interface.
  • + *
+ * The default value is ROW_HEADER_MODE_HIDDEN + *

+ * + * @param mode + * the One of the modes listed above. + */ + public void setRowHeaderMode(int mode) { + if (ROW_HEADER_MODE_HIDDEN == mode) { + rowCaptionsAreHidden = true; + } else { + rowCaptionsAreHidden = false; + setItemCaptionMode(mode); + } + + // Assure visual refresh + refreshCurrentPage(); + } + + /** + * Gets the row header mode. + * + * @return the Row header mode. + * @see #setRowHeaderMode(int) + */ + public int getRowHeaderMode() { + return rowCaptionsAreHidden ? ROW_HEADER_MODE_HIDDEN + : getItemCaptionMode(); + } + + /** + * Adds the new row to table and fill the visible cells with given values. + * + * @param cells + * the Object array that is used for filling the visible + * cells new row. The types must be settable to visible + * column property types. + * @param itemId + * the Id the new row. If null, a new id is automatically + * assigned. If given, the table cant already have a item + * with given id. + * @return Returns item id for the new row. Returns null if operation fails. + */ + public Object addItem(Object[] cells, Object itemId) + throws UnsupportedOperationException { + + Object[] cols = getVisibleColumns(); + + // Checks that a correct number of cells are given + if (cells.length != cols.length) { + return null; + } + + // Creates new item + Item item; + if (itemId == null) { + itemId = items.addItem(); + if (itemId == null) { + return null; + } + item = items.getItem(itemId); + } else { + item = items.addItem(itemId); + } + if (item == null) { + return null; + } + + // Fills the item properties + for (int i = 0; i < cols.length; i++) { + item.getItemProperty(cols[i]).setValue(cells[i]); + } + + return itemId; + } + + /* Overriding select behavior******************************************** */ + + /** + * Sets the Container that serves as the data source of the viewer. + * + * @see com.itmill.toolkit.data.Container.Viewer#setContainerDataSource(Container) + */ + public void setContainerDataSource(Container newDataSource) { + + if (newDataSource == null) { + newDataSource = new IndexedContainer(); + } + + // Assures that the data source is ordered by making unordered + // containers ordered by wrapping them + if (newDataSource instanceof Container.Ordered) { + super.setContainerDataSource(newDataSource); + } else { + super.setContainerDataSource(new ContainerOrderedWrapper( + newDataSource)); + } + + // Resets page position + currentPageFirstItemId = null; + currentPageFirstItemIndex = 0; + + // Resets column properties + if (collapsedColumns != null) { + collapsedColumns.clear(); + } + setVisibleColumns(getContainerPropertyIds().toArray()); + + // Assure visual refresh + refreshCurrentPage(); + } + + /* Component basics ***************************************************** */ + + /** + * Invoked when the value of a variable has changed. + * + * @see com.itmill.toolkit.ui.Select#changeVariables(java.lang.Object, + * java.util.Map) + */ + public void changeVariables(Object source, Map variables) { + + if (!isSelectable() && variables.containsKey("selected")) { + // Not-selectable is a special case, AbstractSelect does not support + // TODO could be optimized. + variables = new HashMap(variables); + variables.remove("selected"); + } + + super.changeVariables(source, variables); + + // Page start index + if (variables.containsKey("firstvisible")) { + Integer value = (Integer) variables.get("firstvisible"); + if (value != null) { + setCurrentPageFirstItemIndex(value.intValue()); + } + } + + // Sets requested firstrow and rows for the next paint + if (variables.containsKey("reqfirstrow") + || variables.containsKey("reqrows")) { + Integer value = (Integer) variables.get("reqfirstrow"); + if (value != null) { + reqFirstRowToPaint = value.intValue(); + } + value = (Integer) variables.get("reqrows"); + if (value != null) { + reqRowsToPaint = value.intValue(); + } + pageBuffer = null; + requestRepaint(); + } + + // Actions + if (variables.containsKey("action")) { + StringTokenizer st = new StringTokenizer((String) variables + .get("action"), ","); + if (st.countTokens() == 2) { + Object itemId = itemIdMapper.get(st.nextToken()); + Action action = (Action) actionMapper.get(st.nextToken()); + if (action != null && containsId(itemId) + && actionHandlers != null) { + for (Iterator i = actionHandlers.iterator(); i.hasNext();) { + ((Action.Handler) i.next()).handleAction(action, this, + itemId); + } + } + } + } + + // Sorting + boolean doSort = false; + if (!sortDisabled) { + if (variables.containsKey("sortcolumn")) { + String colId = (String) variables.get("sortcolumn"); + if (colId != null && !"".equals(colId) && !"null".equals(colId)) { + Object id = columnIdMap.get(colId); + setSortContainerPropertyId(id); + doSort = true; + } + } + if (variables.containsKey("sortascending")) { + boolean state = ((Boolean) variables.get("sortascending")) + .booleanValue(); + if (state != sortAscending) { + setSortAscending(state); + doSort = true; + } + } + } + if (doSort) { + this.sort(); + } + + // Dynamic column hide/show and order + // Update visible columns + if (isColumnCollapsingAllowed()) { + if (variables.containsKey("collapsedcolumns")) { + try { + Object[] ids = (Object[]) variables.get("collapsedcolumns"); + for (Iterator it = visibleColumns.iterator(); it.hasNext();) { + setColumnCollapsed(it.next(), false); + } + for (int i = 0; i < ids.length; i++) { + setColumnCollapsed(columnIdMap.get(ids[i].toString()), + true); + } + } catch (Exception ignored) { + } + } + } + if (isColumnReorderingAllowed()) { + if (variables.containsKey("columnorder")) { + try { + Object[] ids = (Object[]) variables.get("columnorder"); + for (int i = 0; i < ids.length; i++) { + ids[i] = columnIdMap.get(ids[i].toString()); + } + setColumnOrder(ids); + } catch (Exception ignored) { + } + } + } + } + + /** + * Paints the content of this component. + * + * @param target + * the Paint target. + * @throws PaintException + * if the paint operation failed. + */ + public void paintContent(PaintTarget target) throws PaintException { + + // Focus control id + if (getFocusableId() > 0) { + target.addAttribute("focusid", getFocusableId()); + } + + // The tab ordering number + if (getTabIndex() > 0) { + target.addAttribute("tabindex", getTabIndex()); + } + + // Size + if (getHeight() >= 0) { + target.addAttribute("height", "" + getHeight() + + Sizeable.UNIT_SYMBOLS[getHeightUnits()]); + } + if (getWidth() >= 0) { + target.addAttribute("width", "" + getWidth() + + Sizeable.UNIT_SYMBOLS[getWidthUnits()]); + } + + // Initialize temps + Object[] colids = getVisibleColumns(); + int cols = colids.length; + int first = getCurrentPageFirstItemIndex(); + int total = size(); + int pagelen = getPageLength(); + int colHeadMode = getColumnHeaderMode(); + boolean colheads = colHeadMode != COLUMN_HEADER_MODE_HIDDEN; + boolean rowheads = getRowHeaderMode() != ROW_HEADER_MODE_HIDDEN; + Object[][] cells = getVisibleCells(); + boolean iseditable = isEditable(); + int rows = cells[0].length; + + if (!isNullSelectionAllowed() && getNullSelectionItemId() != null + && containsId(getNullSelectionItemId())) { + total--; + rows--; + } + + // selection support + String[] selectedKeys; + if (isMultiSelect()) { + selectedKeys = new String[((Set) getValue()).size()]; + } else { + selectedKeys = new String[(getValue() == null + && getNullSelectionItemId() == null ? 0 : 1)]; + } + int keyIndex = 0; + + // Table attributes + if (isSelectable()) { + target.addAttribute("selectmode", (isMultiSelect() ? "multi" + : "single")); + } else { + target.addAttribute("selectmode", "none"); + } + target.addAttribute("cols", cols); + target.addAttribute("rows", rows); + target.addAttribute("firstrow", + (reqFirstRowToPaint >= 0 ? reqFirstRowToPaint : first)); + target.addAttribute("totalrows", total); + if (pagelen != 0) { + target.addAttribute("pagelength", pagelen); + } + if (colheads) { + target.addAttribute("colheaders", true); + } + if (rowheads) { + target.addAttribute("rowheaders", true); + } + + // Visible column order + Collection sortables = getSortableContainerPropertyIds(); + ArrayList visibleColOrder = new ArrayList(); + for (Iterator it = visibleColumns.iterator(); it.hasNext();) { + Object columnId = it.next(); + if (!isColumnCollapsed(columnId)) { + visibleColOrder.add(columnIdMap.key(columnId)); + } + } + target.addAttribute("vcolorder", visibleColOrder.toArray()); + + // Rows + Set actionSet = new LinkedHashSet(); + boolean selectable = isSelectable(); + boolean[] iscomponent = new boolean[visibleColumns.size()]; + int iscomponentIndex = 0; + for (Iterator it = visibleColumns.iterator(); it.hasNext() + && iscomponentIndex < iscomponent.length;) { + Object columnId = it.next(); + Class colType = getType(columnId); + iscomponent[iscomponentIndex++] = colType != null + && Component.class.isAssignableFrom(colType); + } + target.startTag("rows"); + for (int i = 0; i < cells[0].length; i++) { + Object itemId = cells[CELL_ITEMID][i]; + + if (!isNullSelectionAllowed() && getNullSelectionItemId() != null + && itemId == getNullSelectionItemId()) { + // Remove null selection item if null selection is not allowed + continue; + } + + target.startTag("tr"); + + // tr attributes + if (rowheads) { + if (cells[CELL_ICON][i] != null) { + target.addAttribute("icon", (Resource) cells[CELL_ICON][i]); + } + if (cells[CELL_HEADER][i] != null) { + target.addAttribute("caption", + (String) cells[CELL_HEADER][i]); + } + } + target.addAttribute("key", Integer.parseInt(cells[CELL_KEY][i] + .toString())); + if (actionHandlers != null || isSelectable()) { + if (isSelected(itemId) && keyIndex < selectedKeys.length) { + target.addAttribute("selected", true); + selectedKeys[keyIndex++] = (String) cells[CELL_KEY][i]; + } + } + + // Actions + if (actionHandlers != null) { + ArrayList keys = new ArrayList(); + for (Iterator ahi = actionHandlers.iterator(); ahi.hasNext();) { + Action[] aa = ((Action.Handler) ahi.next()).getActions( + itemId, this); + if (aa != null) { + for (int ai = 0; ai < aa.length; ai++) { + String key = actionMapper.key(aa[ai]); + actionSet.add(aa[ai]); + keys.add(key); + } + } + } + target.addAttribute("al", keys.toArray()); + } + + // cells + int currentColumn = 0; + for (Iterator it = visibleColumns.iterator(); it.hasNext(); currentColumn++) { + Object columnId = it.next(); + if (columnId == null || isColumnCollapsed(columnId)) { + continue; + } + if ((iscomponent[currentColumn] || iseditable) + && Component.class.isInstance(cells[CELL_FIRSTCOL + + currentColumn][i])) { + Component c = (Component) cells[CELL_FIRSTCOL + + currentColumn][i]; + if (c == null) { + target.addText(""); + } else { + c.paint(target); + } + } else { + target + .addText((String) cells[CELL_FIRSTCOL + + currentColumn][i]); + } + } + + target.endTag("tr"); + } + target.endTag("rows"); + + // The select variable is only enabled if selectable + if (selectable) { + target.addVariable(this, "selected", selectedKeys); + } + + // The cursors are only shown on pageable table + if (first != 0 || getPageLength() > 0) { + target.addVariable(this, "firstvisible", first); + } + + // Sorting + if (getContainerDataSource() instanceof Container.Sortable) { + target.addVariable(this, "sortcolumn", columnIdMap + .key(sortContainerPropertyId)); + target.addVariable(this, "sortascending", sortAscending); + } + + // Resets and paints "to be painted next" variables. Also reset + // pageBuffer + reqFirstRowToPaint = -1; + reqRowsToPaint = -1; + pageBuffer = null; + target.addVariable(this, "reqrows", reqRowsToPaint); + target.addVariable(this, "reqfirstrow", reqFirstRowToPaint); + + // Actions + if (!actionSet.isEmpty()) { + target.addVariable(this, "action", ""); + target.startTag("actions"); + for (Iterator it = actionSet.iterator(); it.hasNext();) { + Action a = (Action) it.next(); + target.startTag("action"); + if (a.getCaption() != null) { + target.addAttribute("caption", a.getCaption()); + } + if (a.getIcon() != null) { + target.addAttribute("icon", a.getIcon()); + } + target.addAttribute("key", actionMapper.key(a)); + target.endTag("action"); + } + target.endTag("actions"); + } + if (columnReorderingAllowed) { + String[] colorder = new String[visibleColumns.size()]; + int i = 0; + for (Iterator it = visibleColumns.iterator(); it.hasNext() + && i < colorder.length;) { + colorder[i++] = columnIdMap.key(it.next()); + } + target.addVariable(this, "columnorder", colorder); + } + // Available columns + if (columnCollapsingAllowed) { + HashSet ccs = new HashSet(); + for (Iterator i = visibleColumns.iterator(); i.hasNext();) { + Object o = i.next(); + if (isColumnCollapsed(o)) { + ccs.add(o); + } + } + String[] collapsedkeys = new String[ccs.size()]; + int nextColumn = 0; + for (Iterator it = visibleColumns.iterator(); it.hasNext() + && nextColumn < collapsedkeys.length;) { + Object columnId = it.next(); + if (isColumnCollapsed(columnId)) { + collapsedkeys[nextColumn++] = columnIdMap.key(columnId); + } + } + target.addVariable(this, "collapsedcolumns", collapsedkeys); + } + target.startTag("visiblecolumns"); + int i = 0; + for (Iterator it = visibleColumns.iterator(); it.hasNext(); i++) { + Object columnId = it.next(); + if (columnId != null) { + target.startTag("column"); + target.addAttribute("cid", columnIdMap.key(columnId)); + String head = getColumnHeader(columnId); + target.addAttribute("caption", (head != null ? head : "")); + if (isColumnCollapsed(columnId)) { + target.addAttribute("collapsed", true); + } + if (colheads) { + if (getColumnIcon(columnId) != null) { + target.addAttribute("icon", getColumnIcon(columnId)); + } + if (sortables.contains(columnId)) { + target.addAttribute("sortable", true); + } + } + if (!ALIGN_LEFT.equals(getColumnAlignment(columnId))) { + target.addAttribute("align", getColumnAlignment(columnId)); + } + if (getColumnWidth(columnId) > -1) { + target.addAttribute("width", String + .valueOf(getColumnWidth(columnId))); + } + + target.endTag("column"); + } + } + target.endTag("visiblecolumns"); + } + + /** + * Gets the UIDL tag corresponding to component. + * + * @return the UIDL tag as string. + */ + public String getTag() { + return "table"; + } + + /** + * Gets the cached visible table contents. + * + * @return the cahced visible table conetents. + */ + private Object[][] getVisibleCells() { + + // Returns a buffered value if possible + if (pageBuffer != null && isPageBufferingEnabled()) { + return pageBuffer; + } + + // Stops listening the old properties and initialise the list + if (listenedProperties == null) { + listenedProperties = new LinkedList(); + } else { + for (Iterator i = listenedProperties.iterator(); i.hasNext();) { + ((Property.ValueChangeNotifier) i.next()).removeListener(this); + } + } + + // Detach old visible component from the table + if (visibleComponents == null) { + visibleComponents = new LinkedList(); + } else { + for (Iterator i = visibleComponents.iterator(); i.hasNext();) { + ((Component) i.next()).setParent(null); + } + visibleComponents.clear(); + } + + // Collects the basic facts about the table page + Object[] colids = getVisibleColumns(); + int cols = colids.length; + int pagelen = getPageLength(); + int firstIndex = getCurrentPageFirstItemIndex(); + int rows = size(); + if (rows > 0 && firstIndex >= 0) { + rows -= firstIndex; + } + if (pagelen > 0 && pagelen < rows) { + rows = pagelen; + } + + // If "to be painted next" variables are set, use them + if (reqRowsToPaint >= 0) { + rows = reqRowsToPaint; + } + Object id; + if (reqFirstRowToPaint >= 0 && reqFirstRowToPaint < size()) { + firstIndex = reqFirstRowToPaint; + } + if (size() > 0) { + if (rows + firstIndex > size()) { + rows = size() - firstIndex; + } + } else { + rows = 0; + } + + Object[][] cells = new Object[cols + CELL_FIRSTCOL][rows]; + if (rows == 0) { + return cells; + } + + // Gets the first item id + if (items instanceof Container.Indexed) { + id = ((Container.Indexed) items).getIdByIndex(firstIndex); + } else { + id = ((Container.Ordered) items).firstItemId(); + for (int i = 0; i < firstIndex; i++) { + id = ((Container.Ordered) items).nextItemId(id); + } + } + + int headmode = getRowHeaderMode(); + boolean[] iscomponent = new boolean[cols]; + for (int i = 0; i < cols; i++) { + iscomponent[i] = Component.class + .isAssignableFrom(getType(colids[i])); + } + + // Creates the page contents + int filledRows = 0; + for (int i = 0; i < rows && id != null; i++) { + cells[CELL_ITEMID][i] = id; + cells[CELL_KEY][i] = itemIdMapper.key(id); + if (headmode != ROW_HEADER_MODE_HIDDEN) { + switch (headmode) { + case ROW_HEADER_MODE_INDEX: + cells[CELL_HEADER][i] = String.valueOf(i + firstIndex + 1); + break; + default: + cells[CELL_HEADER][i] = getItemCaption(id); + } + cells[CELL_ICON][i] = getItemIcon(id); + } + if (cols > 0) { + for (int j = 0; j < cols; j++) { + Object value = null; + Property p = getContainerProperty(id, colids[j]); + if (p != null) { + if (p instanceof Property.ValueChangeNotifier) { + ((Property.ValueChangeNotifier) p) + .addListener(this); + listenedProperties.add(p); + } + if (iscomponent[j]) { + value = p.getValue(); + } else if (p != null) { + value = getPropertyValue(id, colids[j], p); + } else { + value = getPropertyValue(id, colids[j], null); + } + } else { + value = ""; + } + + if (value instanceof Component) { + ((Component) value).setParent(this); + visibleComponents.add(value); + } + cells[CELL_FIRSTCOL + j][i] = value; + + } + } + id = ((Container.Ordered) items).nextItemId(id); + + filledRows++; + } + + // Assures that all the rows of the cell-buffer are valid + if (filledRows != cells[0].length) { + Object[][] temp = new Object[cells.length][filledRows]; + for (int i = 0; i < cells.length; i++) { + for (int j = 0; j < filledRows; j++) { + temp[i][j] = cells[i][j]; + } + } + cells = temp; + } + + // Saves the results to internal buffer iff in buffering mode + // to possible conserve memory from large non-buffered pages + if (isPageBufferingEnabled()) { + pageBuffer = cells; + } + + return cells; + } + + /** + * Gets the value of property. + * + * By default if the table is editable the fieldFactory is used to create + * editors for table cells. Otherwise formatPropertyValue is used to format + * the value representation. + * + * @param rowId + * the Id of the row (same as item Id). + * @param colId + * the Id of the column. + * @param property + * the Property to be presented. + * @return Object Either formatted value or Component for field. + * @see #setFieldFactory(FieldFactory) + */ + protected Object getPropertyValue(Object rowId, Object colId, + Property property) { + if (isEditable() && fieldFactory != null) { + Field f = fieldFactory.createField(getContainerDataSource(), rowId, + colId, this); + if (f != null) { + f.setPropertyDataSource(property); + return f; + } + } + + return formatPropertyValue(rowId, colId, property); + } + + /** + * Formats table cell property values. By default the property.toString() + * and return a empty string for null properties. + * + * @param rowId + * the Id of the row (same as item Id). + * @param colId + * the Id of the column. + * @param property + * the Property to be formatted. + * @return the String representation of property and its value. + * @since 3.1 + */ + protected String formatPropertyValue(Object rowId, Object colId, + Property property) { + if (property == null) { + return ""; + } + return property.toString(); + } + + /* Action container *************************************************** */ + + /** + * Registers a new action handler for this container + * + * @see com.itmill.toolkit.event.Action.Container#addActionHandler(Action.Handler) + */ + public void addActionHandler(Action.Handler actionHandler) { + + if (actionHandler != null) { + + if (actionHandlers == null) { + actionHandlers = new LinkedList(); + actionMapper = new KeyMapper(); + } + + if (!actionHandlers.contains(actionHandler)) { + actionHandlers.add(actionHandler); + requestRepaint(); + } + + } + } + + /** + * Removes a previously registered action handler for the contents of this + * container. + * + * @see com.itmill.toolkit.event.Action.Container#removeActionHandler(Action.Handler) + */ + public void removeActionHandler(Action.Handler actionHandler) { + + if (actionHandlers != null && actionHandlers.contains(actionHandler)) { + + actionHandlers.remove(actionHandler); + + if (actionHandlers.isEmpty()) { + actionHandlers = null; + actionMapper = null; + } + + requestRepaint(); + } + } + + /* Property value change listening support **************************** */ + + /** + * Notifies this listener that the Property's value has changed. + * + * @see com.itmill.toolkit.data.Property.ValueChangeListener#valueChange(Property.ValueChangeEvent) + */ + public void valueChange(Property.ValueChangeEvent event) { + super.valueChange(event); + requestRepaint(); + } + + /** + * Notifies the component that it is connected to an application. + * + * @see com.itmill.toolkit.ui.Component#attach() + */ + public void attach() { + super.attach(); + + if (visibleComponents != null) { + for (Iterator i = visibleComponents.iterator(); i.hasNext();) { + ((Component) i.next()).attach(); + } + } + } + + /** + * Notifies the component that it is detached from the application + * + * @see com.itmill.toolkit.ui.Component#detach() + */ + public void detach() { + super.detach(); + + if (visibleComponents != null) { + for (Iterator i = visibleComponents.iterator(); i.hasNext();) { + ((Component) i.next()).detach(); + } + } + } + + /** + * Removes all Items from the Container. + * + * @see com.itmill.toolkit.data.Container#removeAllItems() + */ + public boolean removeAllItems() { + currentPageFirstItemId = null; + currentPageFirstItemIndex = 0; + return super.removeAllItems(); + } + + /** + * Removes the Item identified by ItemId from the Container. + * + * @see com.itmill.toolkit.data.Container#removeItem(Object) + */ + public boolean removeItem(Object itemId) { + Object nextItemId = ((Container.Ordered) items).nextItemId(itemId); + boolean ret = super.removeItem(itemId); + if (ret && (itemId != null) && (itemId.equals(currentPageFirstItemId))) { + currentPageFirstItemId = nextItemId; + } + return ret; + } + + /** + * Removes a Property specified by the given Property ID from the Container. + * + * @see com.itmill.toolkit.data.Container#removeContainerProperty(Object) + */ + public boolean removeContainerProperty(Object propertyId) + throws UnsupportedOperationException { + + // If a visible property is removed, remove the corresponding column + visibleColumns.remove(propertyId); + columnAlignments.remove(propertyId); + columnIcons.remove(propertyId); + columnHeaders.remove(propertyId); + + return super.removeContainerProperty(propertyId); + } + + /** + * Adds a new property to the table and show it as a visible column. + * + * @param propertyId + * the Id of the proprty. + * @param type + * the class of the property. + * @param defaultValue + * the default value given for all existing items. + * @see com.itmill.toolkit.data.Container#addContainerProperty(Object, + * Class, Object) + */ + public boolean addContainerProperty(Object propertyId, Class type, + Object defaultValue) throws UnsupportedOperationException { + if (!super.addContainerProperty(propertyId, type, defaultValue)) { + return false; + } + if (!visibleColumns.contains(propertyId)) { + visibleColumns.add(propertyId); + } + return true; + } + + /** + * Adds a new property to the table and show it as a visible column. + * + * @param propertyId + * the Id of the proprty + * @param type + * the class of the property + * @param defaultValue + * the default value given for all existing items + * @param columnHeader + * the Explicit header of the column. If explicit header is + * not needed, this should be set null. + * @param columnIcon + * the Icon of the column. If icon is not needed, this should + * be set null. + * @param columnAlignment + * the Alignment of the column. Null implies align left. + * @throws UnsupportedOperationException + * if the operation is not supported. + * @see com.itmill.toolkit.data.Container#addContainerProperty(Object, + * Class, Object) + */ + public boolean addContainerProperty(Object propertyId, Class type, + Object defaultValue, String columnHeader, Resource columnIcon, + String columnAlignment) throws UnsupportedOperationException { + if (!this.addContainerProperty(propertyId, type, defaultValue)) { + return false; + } + setColumnAlignment(propertyId, columnAlignment); + setColumnHeader(propertyId, columnHeader); + setColumnIcon(propertyId, columnIcon); + return true; + } + + /** + * Returns the list of items on the current page + * + * @see com.itmill.toolkit.ui.Select#getVisibleItemIds() + */ + public Collection getVisibleItemIds() { + + LinkedList visible = new LinkedList(); + + Object[][] cells = getVisibleCells(); + for (int i = 0; i < cells[CELL_ITEMID].length; i++) { + visible.add(cells[CELL_ITEMID][i]); + } + + return visible; + } + + /** + * Container datasource item set change. Table must flush its buffers on + * change. + * + * @see com.itmill.toolkit.data.Container.ItemSetChangeListener#containerItemSetChange(com.itmill.toolkit.data.Container.ItemSetChangeEvent) + */ + public void containerItemSetChange(Container.ItemSetChangeEvent event) { + pageBuffer = null; + super.containerItemSetChange(event); + setCurrentPageFirstItemIndex(getCurrentPageFirstItemIndex()); + } + + /** + * Container datasource property set change. Table must flush its buffers on + * change. + * + * @see com.itmill.toolkit.data.Container.PropertySetChangeListener#containerPropertySetChange(com.itmill.toolkit.data.Container.PropertySetChangeEvent) + */ + public void containerPropertySetChange( + Container.PropertySetChangeEvent event) { + pageBuffer = null; + super.containerPropertySetChange(event); + } + + /** + * Adding new items is not supported. + * + * @throws UnsupportedOperationException + * if set to true. + * @see com.itmill.toolkit.ui.Select#setNewItemsAllowed(boolean) + */ + public void setNewItemsAllowed(boolean allowNewOptions) + throws UnsupportedOperationException { + if (allowNewOptions) { + throw new UnsupportedOperationException(); + } + } + + /** + * Focusing to this component is not supported. + * + * @throws UnsupportedOperationException + * if invoked. + * @see com.itmill.toolkit.ui.AbstractField#focus() + */ + public void focus() throws UnsupportedOperationException { + throw new UnsupportedOperationException(); + } + + /** + * Gets the ID of the Item following the Item that corresponds to itemId. + * + * @see com.itmill.toolkit.data.Container.Ordered#nextItemId(java.lang.Object) + */ + public Object nextItemId(Object itemId) { + return ((Container.Ordered) items).nextItemId(itemId); + } + + /** + * Gets the ID of the Item preceding the Item that corresponds to the + * itemId. + * + * @see com.itmill.toolkit.data.Container.Ordered#prevItemId(java.lang.Object) + */ + public Object prevItemId(Object itemId) { + return ((Container.Ordered) items).prevItemId(itemId); + } + + /** + * Gets the ID of the first Item in the Container. + * + * @see com.itmill.toolkit.data.Container.Ordered#firstItemId() + */ + public Object firstItemId() { + return ((Container.Ordered) items).firstItemId(); + } + + /** + * Gets the ID of the last Item in the Container. + * + * @see com.itmill.toolkit.data.Container.Ordered#lastItemId() + */ + public Object lastItemId() { + return ((Container.Ordered) items).lastItemId(); + } + + /** + * Tests if the Item corresponding to the given Item ID is the first Item in + * the Container. + * + * @see com.itmill.toolkit.data.Container.Ordered#isFirstId(java.lang.Object) + */ + public boolean isFirstId(Object itemId) { + return ((Container.Ordered) items).isFirstId(itemId); + } + + /** + * Tests if the Item corresponding to the given Item ID is the last Item in + * the Container. + * + * @see com.itmill.toolkit.data.Container.Ordered#isLastId(java.lang.Object) + */ + public boolean isLastId(Object itemId) { + return ((Container.Ordered) items).isLastId(itemId); + } + + /** + * Adds new item after the given item. + * + * @see com.itmill.toolkit.data.Container.Ordered#addItemAfter(java.lang.Object) + */ + public Object addItemAfter(Object previousItemId) + throws UnsupportedOperationException { + return ((Container.Ordered) items).addItemAfter(previousItemId); + } + + /** + * Adds new item after the given item. + * + * @see com.itmill.toolkit.data.Container.Ordered#addItemAfter(java.lang.Object, + * java.lang.Object) + */ + public Item addItemAfter(Object previousItemId, Object newItemId) + throws UnsupportedOperationException { + return ((Container.Ordered) items).addItemAfter(previousItemId, + newItemId); + } + + /** + * Gets the FieldFactory that is used to create editor for table cells. + * + * The FieldFactory is only used if the Table is editable. + * + * @return FieldFactory used to create the Field instances. + * @see #isEditable + */ + public FieldFactory getFieldFactory() { + return fieldFactory; + } + + /** + * Sets the FieldFactory that is used to create editor for table cells. + * + * The FieldFactory is only used if the Table is editable. By default the + * BaseFieldFactory is used. + * + * @param fieldFactory + * the field factory to set. + * @see #isEditable + * @see BaseFieldFactory + * + */ + public void setFieldFactory(FieldFactory fieldFactory) { + this.fieldFactory = fieldFactory; + + // Assure visual refresh + refreshCurrentPage(); + } + + /** + * Is table editable. + * + * If table is editable a editor of type Field is created for each table + * cell. The assigned FieldFactory is used to create the instances. + * + * To provide custom editors for table cells create a class implementins the + * FieldFactory interface, and assign it to table, and set the editable + * property to true. + * + * @return true if table is editable, false oterwise. + * @see Field + * @see FieldFactory + * + */ + public boolean isEditable() { + return editable; + } + + /** + * Sets the editable property. + * + * If table is editable a editor of type Field is created for each table + * cell. The assigned FieldFactory is used to create the instances. + * + * To provide custom editors for table cells create a class implementins the + * FieldFactory interface, and assign it to table, and set the editable + * property to true. + * + * @param editable + * true if table should be editable by user. + * @see Field + * @see FieldFactory + * + */ + public void setEditable(boolean editable) { + this.editable = editable; + + // Assure visual refresh + refreshCurrentPage(); + } + + /** + * Sorts the table. + * + * @throws UnsupportedOperationException + * if the container data source does not implement + * Container.Sortable + * @see com.itmill.toolkit.data.Container.Sortable#sort(java.lang.Object[], + * boolean[]) + * + */ + public void sort(Object[] propertyId, boolean[] ascending) + throws UnsupportedOperationException { + Container c = getContainerDataSource(); + if (c instanceof Container.Sortable) { + int pageIndex = getCurrentPageFirstItemIndex(); + ((Container.Sortable) c).sort(propertyId, ascending); + setCurrentPageFirstItemIndex(pageIndex); + } else if (c != null) { + throw new UnsupportedOperationException( + "Underlying Data does not allow sorting"); + } + } + + /** + * Sorts the table by currently selected sorting column. + * + * @throws UnsupportedOperationException + * if the container data source does not implement + * Container.Sortable + */ + public void sort() { + if (getSortContainerPropertyId() == null) { + return; + } + sort(new Object[] { sortContainerPropertyId }, + new boolean[] { sortAscending }); + } + + /** + * Gets the container property IDs, which can be used to sort the item. + * + * @see com.itmill.toolkit.data.Container.Sortable#getSortableContainerPropertyIds() + */ + public Collection getSortableContainerPropertyIds() { + Container c = getContainerDataSource(); + if (c instanceof Container.Sortable && !isSortDisabled()) { + return ((Container.Sortable) c).getSortableContainerPropertyIds(); + } else { + return new LinkedList(); + } + } + + /** + * Gets the currently sorted column property ID. + * + * @return the Container property id of the currently sorted column. + */ + public Object getSortContainerPropertyId() { + return sortContainerPropertyId; + } + + /** + * Sets the currently sorted column property id. + * + * @param propertyId + * the Container property id of the currently sorted column. + */ + public void setSortContainerPropertyId(Object propertyId) { + if ((sortContainerPropertyId != null && !sortContainerPropertyId + .equals(propertyId)) + || (sortContainerPropertyId == null && propertyId != null)) { + sortContainerPropertyId = propertyId; + sort(); + } + + // Assures the visual refresh + refreshCurrentPage(); + } + + /** + * Is the table currently sorted in ascending order. + * + * @return true if ascending, false if + * descending. + */ + public boolean isSortAscending() { + return sortAscending; + } + + /** + * Sets the table in ascending order. + * + * @param ascending + * true if ascending, false if + * descending. + */ + public void setSortAscending(boolean ascending) { + if (sortAscending != ascending) { + sortAscending = ascending; + sort(); + } + + // Assures the visual refresh + refreshCurrentPage(); + } + + /** + * Is sorting disabled altogether. + * + * True iff no sortable columns are given even in the case where data source + * would support this. + * + * @return True iff sorting is disabled. + */ + public boolean isSortDisabled() { + return sortDisabled; + } + + /** + * Disables the sorting altogether. + * + * To disable sorting altogether, set to true. In this case no sortable + * columns are given even in the case where datasource would support this. + * + * @param sortDisabled + * True iff sorting is disabled. + */ + public void setSortDisabled(boolean sortDisabled) { + if (this.sortDisabled != sortDisabled) { + this.sortDisabled = sortDisabled; + refreshCurrentPage(); + } + } + + /** + * Gets height property unit. + * + * @see com.itmill.toolkit.terminal.Sizeable#getHeightUnits() + */ + public int getHeightUnits() { + return heightUnit; + } + + /** + * Gets width property unit. + * + * @see com.itmill.toolkit.terminal.Sizeable#getWidthUnits() + */ + public int getWidthUnits() { + return widthUnit; + } + + /** + * Sets height units. + * + * @see com.itmill.toolkit.terminal.Sizeable#setHeightUnits(int) + */ + public void setHeightUnits(int units) { + heightUnit = units; + } + + /** + * Sets width units. Table supports only Sizeable.UNITS_PIXELS and + * Sizeable.UNITS_PERCENTAGE. Setting to any other throws + * IllegalArgumentException. + * + * @see com.itmill.toolkit.terminal.Sizeable#setWidthUnits(int) + */ + public void setWidthUnits(int units) { + if (units != Sizeable.UNITS_PIXELS + && units != Sizeable.UNITS_PERCENTAGE) { + throw new IllegalArgumentException(); + } + widthUnit = units; + } + + /** + * Gets height. + * + * @return height value as a positive integer or negative value if not + * assigned. + * @see com.itmill.toolkit.terminal.Sizeable#getHeight() + */ + public int getHeight() { + return height; + } + + /** + * Gets width. + * + * @return width value as positive integer or negative value if not + * assigned. + * @see com.itmill.toolkit.terminal.Sizeable#getWidth() + */ + public int getWidth() { + return width; + } + + /** + * Sets height. Use negative value to let the client decide the height. + * + * @param height + * the height to set. + */ + public void setHeight(int height) { + this.height = height; + requestRepaint(); + } + + /** + * Sets width. Use negative value to allow the client decide the width. + * + * @param width + * the width to set. + */ + public void setWidth(int width) { + this.width = width; + requestRepaint(); + } + + /** + * Table does not support lazy options loading mode. Setting this true will + * throw UnsupportedOperationException. + * + * @see com.itmill.toolkit.ui.Select#setLazyLoading(boolean) + */ + public void setLazyLoading(boolean useLazyLoading) { + if (useLazyLoading) { + throw new UnsupportedOperationException( + "Lazy options loading is not supported by Table."); + } + } + + /* + * (non-Javadoc) + * + * @see com.itmill.toolkit.terminal.Sizeable#setSizeFull() + */ + public void setSizeFull() { + setWidth(100); + setHeight(100); + setWidthUnits(UNITS_PERCENTAGE); + setHeightUnits(UNITS_PERCENTAGE); + } + + /* + * (non-Javadoc) + * + * @see com.itmill.toolkit.terminal.Sizeable#setSizeUndefined() + */ + public void setSizeUndefined() { + setWidth(-1); + setHeight(-1); + setWidthUnits(UNITS_PIXELS); + setHeightUnits(UNITS_PIXELS); + } } \ No newline at end of file diff --git a/src/com/itmill/toolkit/ui/TextField.java b/src/com/itmill/toolkit/ui/TextField.java index f2d15da712..c90af1058e 100644 --- a/src/com/itmill/toolkit/ui/TextField.java +++ b/src/com/itmill/toolkit/ui/TextField.java @@ -57,414 +57,425 @@ import com.itmill.toolkit.terminal.PaintTarget; */ public class TextField extends AbstractField { - /* Private members ************************************************* */ - - /** - * Value formatter used to format the string contents. - */ - private Format format; - - /** - * Number of visible columns in the TextField. - */ - private int columns = 0; - - /** - * Number of visible rows in a multiline TextField. Value 0 implies a - * single-line text-editor. - */ - private int rows = 0; - - /** - * Tells if word-wrapping should be used in multiline mode. - */ - private boolean wordwrap = true; - - /** - * Tells if input is used to enter sensitive information that is not echoed - * to display. Typically passwords. - */ - private boolean secret = false; - - /** - * Null representation. - */ - private String nullRepresentation = "null"; - - /** - * Is setting to null from non-null value allowed by setting with null - * representation . - */ - private boolean nullSettingAllowed = false; - - /* Constructors **************************************************** */ - - /** - * Constructs an empty TextField with no caption. - */ - public TextField() { - setValue(""); - } - - /** - * Constructs an empty TextField with given caption. - * - * @param caption - * the caption String for the editor. - */ - public TextField(String caption) { - setValue(""); - setCaption(caption); - } - - /** - * Constructs a new TextField that's bound to the specified - * Property and has no caption. - * - * @param dataSource - * the Property to be edited with this editor. - */ - public TextField(Property dataSource) { - setPropertyDataSource(dataSource); - } - - /** - * Constructs a new TextField that's bound to the specified - * Property and has the given caption String. - * - * @param caption - * the caption String for the editor. - * @param dataSource - * the Property to be edited with this editor. - */ - public TextField(String caption, Property dataSource) { - this(dataSource); - setCaption(caption); - } - - /** - * Constructs a new TextField with the given caption and - * initial text contents. The editor constructed this way will not be bound - * to a Property unless - * {@link com.itmill.toolkit.data.Property.Viewer#setPropertyDataSource(Property)} - * is called to bind it. - * - * @param caption - * the caption String for the editor. - * @param text - * the initial text content of the editor. - */ - public TextField(String caption, String value) { - setValue(value); - setCaption(caption); - } - - /* Component basic features ********************************************* */ - - /* - * Paints this component. Don't add a JavaDoc comment here, we use the - * default documentation from implemented interface. - */ - public void paintContent(PaintTarget target) throws PaintException { - super.paintContent(target); - - // Sets the secret attribute - if (this.isSecret()) - target.addAttribute("secret", true); - - // Adds the number of column and rows - int c = getColumns(); - int r = getRows(); - if (c != 0) - target.addAttribute("cols", String.valueOf(c)); - if (r != 0) { - target.addAttribute("rows", String.valueOf(r)); - target.addAttribute("multiline", true); - if (!wordwrap) - target.addAttribute("wordwrap", false); - } - - // Adds the content as variable - String value = getFormattedValue(); - if (value == null) - value = getNullRepresentation(); - if (value == null) - throw new IllegalStateException( - "Null values are not allowed if the null-representation is null"); - target.addVariable(this, "text", value); - } - - /** - * Gets the formatted dtring value. Sets the field value by using the - * assigned Format. - * - * @return the Formatted value. - * @see #setFormat(Format) - * @see Format - */ - protected String getFormattedValue() { - Object value = getValue(); - if (this.format != null && value != null) - try { - return this.format.format(value); - } catch (IllegalArgumentException ignored) { - // Ignored exception - } - if (value != null) - return value.toString(); - return null; - } - - /* - * Gets the components UIDL tag string. Don't add a JavaDoc comment here, we - * use the default documentation from implemented interface. - */ - public String getTag() { - return "textfield"; - } - - /* - * Invoked when a variable of the component changes. Don't add a JavaDoc - * comment here, we use the default documentation from implemented - * interface. - */ - public void changeVariables(Object source, Map variables) { - - // Sets the text - if (variables.containsKey("text") && !isReadOnly()) { - - // Only do the setting if the string representation of the value - // has been updated - String newValue = (String) variables.get("text"); - String oldValue = getFormattedValue(); - if (newValue != null - && (oldValue == null || isNullSettingAllowed()) - && newValue.equals(getNullRepresentation())) - newValue = null; - if (newValue != oldValue - && (newValue == null || !newValue.equals(oldValue))) - setValue(newValue, true); - } - - } - - /* Text field configuration ********************************************* */ - - /** - * Gets the number of columns in the editor. If the number of columns is set - * 0, the actual number of displayed columns is determined implicitly by the - * adapter. - * - * @return the number of columns in the editor. - */ - public int getColumns() { - return this.columns; - } - - /** - * Sets the number of columns in the editor. If the number of columns is set - * 0, the actual number of displayed columns is determined implicitly by the - * adapter. - * - * @param columns - * the number of columns to set. - */ - public void setColumns(int columns) { - if (columns < 0) - columns = 0; - this.columns = columns; - requestRepaint(); - } - - /** - * Gets the number of rows in the editor. If the number of rows is set to 0, - * the actual number of displayed rows is determined implicitly by the - * adapter. - * - * @return number of explicitly set rows. - */ - public int getRows() { - return this.rows; - } - - /** - * Sets the number of rows in the editor. If the number of rows is set to 0, - * the actual number of displayed rows is determined implicitly by the - * adapter. - * - * @param rows - * the number of rows for this editor. - */ - public void setRows(int rows) { - if (rows < 0) - rows = 0; - this.rows = rows; - requestRepaint(); - } - - /** - * Tests if the editor is in word-wrap mode. - * - * @return true if the component is in the word-wrap mode, - * false if not. - */ - public boolean isWordwrap() { - return this.wordwrap; - } - - /** - * Sets the editor's word-wrap mode on or off. - * - * @param wordwrap - * the boolean value specifying if the editor should be in - * word-wrap mode after the call or not. - */ - public void setWordwrap(boolean wordwrap) { - this.wordwrap = wordwrap; - } - - /* Property features **************************************************** */ - - /* - * Gets the edited property's type. Don't add a JavaDoc comment here, we use - * the default documentation from implemented interface. - */ - public Class getType() { - return String.class; - } - - /** - * Gets the secret property on and off. If a field is used to enter - * secretinformation the information is not echoed to display. - * - * @return true if the field is used to enter secret - * information, false otherwise. - */ - public boolean isSecret() { - return secret; - } - - /** - * Sets the secret property on and off. If a field is used to enter - * secretinformation the information is not echoed to display. - * - * @param secret - * the value specifying if the field is used to enter secret - * information. - */ - public void setSecret(boolean secret) { - this.secret = secret; - requestRepaint(); - } - - /** - * Gets the null-string representation. - * - *

- * The null-valued strings are represented on the user interface by - * replacing the null value with this string. If the null representation is - * set null (not 'null' string), painting null value throws exception. - *

- * - *

- * The default value is string 'null'. - *

- * - * @return the String Textual representation for null strings. - * @see TextField#isNullSettingAllowed() - */ - public String getNullRepresentation() { - return nullRepresentation; - } - - /** - * Is setting nulls with null-string representation allowed. - * - *

- * If this property is true, writing null-representation string to text - * field allways sets the field value to real null. If this property is - * false, null setting is not made, but the null values are maintained. - * Maintenance of null-values is made by only converting the textfield - * contents to real null, if the text field matches the null-string - * representation and the current value of the field is null. - *

- * - *

- * By default this setting is false - *

- * - * @return boolean Should the null-string represenation be allways converted - * to null-values. - * @see TextField#getNullRepresentation() - */ - public boolean isNullSettingAllowed() { - return nullSettingAllowed; - } - - /** - * Sets the null-string representation. - * - *

- * The null-valued strings are represented on the user interface by - * replacing the null value with this string. If the null representation is - * set null (not 'null' string), painting null value throws exception. - *

- * - *

- * The default value is string 'null' - *

- * - * @param nullRepresentation - * Textual representation for null strings. - * @see TextField#setNullSettingAllowed(boolean) - */ - public void setNullRepresentation(String nullRepresentation) { - this.nullRepresentation = nullRepresentation; - } - - /** - * Sets the null conversion mode. - * - *

- * If this property is true, writing null-representation string to text - * field allways sets the field value to real null. If this property is - * false, null setting is not made, but the null values are maintained. - * Maintenance of null-values is made by only converting the textfield - * contents to real null, if the text field matches the null-string - * representation and the current value of the field is null. - *

- * - *

- * By default this setting is false. - *

- * - * @param nullSettingAllowed - * Should the null-string represenation be allways converted to - * null-values. - * @see TextField#getNullRepresentation() - */ - public void setNullSettingAllowed(boolean nullSettingAllowed) { - this.nullSettingAllowed = nullSettingAllowed; - } - - /** - * Gets the value formatter of TextField. - * - * @return the Format used to format the value. - */ - public Format getFormat() { - return format; - } - - /** - * Gets the value formatter of TextField. - * - * @param format - * the Format used to format the value. Null disables the - * formatting. - */ - public void setFormat(Format format) { - this.format = format; - } + /* Private members ************************************************* */ + + /** + * Value formatter used to format the string contents. + */ + private Format format; + + /** + * Number of visible columns in the TextField. + */ + private int columns = 0; + + /** + * Number of visible rows in a multiline TextField. Value 0 implies a + * single-line text-editor. + */ + private int rows = 0; + + /** + * Tells if word-wrapping should be used in multiline mode. + */ + private boolean wordwrap = true; + + /** + * Tells if input is used to enter sensitive information that is not echoed + * to display. Typically passwords. + */ + private boolean secret = false; + + /** + * Null representation. + */ + private String nullRepresentation = "null"; + + /** + * Is setting to null from non-null value allowed by setting with null + * representation . + */ + private boolean nullSettingAllowed = false; + + /* Constructors **************************************************** */ + + /** + * Constructs an empty TextField with no caption. + */ + public TextField() { + setValue(""); + } + + /** + * Constructs an empty TextField with given caption. + * + * @param caption + * the caption String for the editor. + */ + public TextField(String caption) { + setValue(""); + setCaption(caption); + } + + /** + * Constructs a new TextField that's bound to the specified + * Property and has no caption. + * + * @param dataSource + * the Property to be edited with this editor. + */ + public TextField(Property dataSource) { + setPropertyDataSource(dataSource); + } + + /** + * Constructs a new TextField that's bound to the specified + * Property and has the given caption String. + * + * @param caption + * the caption String for the editor. + * @param dataSource + * the Property to be edited with this editor. + */ + public TextField(String caption, Property dataSource) { + this(dataSource); + setCaption(caption); + } + + /** + * Constructs a new TextField with the given caption and + * initial text contents. The editor constructed this way will not be bound + * to a Property unless + * {@link com.itmill.toolkit.data.Property.Viewer#setPropertyDataSource(Property)} + * is called to bind it. + * + * @param caption + * the caption String for the editor. + * @param text + * the initial text content of the editor. + */ + public TextField(String caption, String value) { + setValue(value); + setCaption(caption); + } + + /* Component basic features ********************************************* */ + + /* + * Paints this component. Don't add a JavaDoc comment here, we use the + * default documentation from implemented interface. + */ + public void paintContent(PaintTarget target) throws PaintException { + super.paintContent(target); + + // Sets the secret attribute + if (isSecret()) { + target.addAttribute("secret", true); + } + + // Adds the number of column and rows + int c = getColumns(); + int r = getRows(); + if (c != 0) { + target.addAttribute("cols", String.valueOf(c)); + } + if (r != 0) { + target.addAttribute("rows", String.valueOf(r)); + target.addAttribute("multiline", true); + if (!wordwrap) { + target.addAttribute("wordwrap", false); + } + } + + // Adds the content as variable + String value = getFormattedValue(); + if (value == null) { + value = getNullRepresentation(); + } + if (value == null) { + throw new IllegalStateException( + "Null values are not allowed if the null-representation is null"); + } + target.addVariable(this, "text", value); + } + + /** + * Gets the formatted dtring value. Sets the field value by using the + * assigned Format. + * + * @return the Formatted value. + * @see #setFormat(Format) + * @see Format + */ + protected String getFormattedValue() { + Object value = getValue(); + if (format != null && value != null) { + try { + return format.format(value); + } catch (IllegalArgumentException ignored) { + // Ignored exception + } + } + if (value != null) { + return value.toString(); + } + return null; + } + + /* + * Gets the components UIDL tag string. Don't add a JavaDoc comment here, we + * use the default documentation from implemented interface. + */ + public String getTag() { + return "textfield"; + } + + /* + * Invoked when a variable of the component changes. Don't add a JavaDoc + * comment here, we use the default documentation from implemented + * interface. + */ + public void changeVariables(Object source, Map variables) { + + // Sets the text + if (variables.containsKey("text") && !isReadOnly()) { + + // Only do the setting if the string representation of the value + // has been updated + String newValue = (String) variables.get("text"); + String oldValue = getFormattedValue(); + if (newValue != null + && (oldValue == null || isNullSettingAllowed()) + && newValue.equals(getNullRepresentation())) { + newValue = null; + } + if (newValue != oldValue + && (newValue == null || !newValue.equals(oldValue))) { + setValue(newValue, true); + } + } + + } + + /* Text field configuration ********************************************* */ + + /** + * Gets the number of columns in the editor. If the number of columns is set + * 0, the actual number of displayed columns is determined implicitly by the + * adapter. + * + * @return the number of columns in the editor. + */ + public int getColumns() { + return columns; + } + + /** + * Sets the number of columns in the editor. If the number of columns is set + * 0, the actual number of displayed columns is determined implicitly by the + * adapter. + * + * @param columns + * the number of columns to set. + */ + public void setColumns(int columns) { + if (columns < 0) { + columns = 0; + } + this.columns = columns; + requestRepaint(); + } + + /** + * Gets the number of rows in the editor. If the number of rows is set to 0, + * the actual number of displayed rows is determined implicitly by the + * adapter. + * + * @return number of explicitly set rows. + */ + public int getRows() { + return rows; + } + + /** + * Sets the number of rows in the editor. If the number of rows is set to 0, + * the actual number of displayed rows is determined implicitly by the + * adapter. + * + * @param rows + * the number of rows for this editor. + */ + public void setRows(int rows) { + if (rows < 0) { + rows = 0; + } + this.rows = rows; + requestRepaint(); + } + + /** + * Tests if the editor is in word-wrap mode. + * + * @return true if the component is in the word-wrap mode, + * false if not. + */ + public boolean isWordwrap() { + return wordwrap; + } + + /** + * Sets the editor's word-wrap mode on or off. + * + * @param wordwrap + * the boolean value specifying if the editor should be in + * word-wrap mode after the call or not. + */ + public void setWordwrap(boolean wordwrap) { + this.wordwrap = wordwrap; + } + + /* Property features **************************************************** */ + + /* + * Gets the edited property's type. Don't add a JavaDoc comment here, we use + * the default documentation from implemented interface. + */ + public Class getType() { + return String.class; + } + + /** + * Gets the secret property on and off. If a field is used to enter + * secretinformation the information is not echoed to display. + * + * @return true if the field is used to enter secret + * information, false otherwise. + */ + public boolean isSecret() { + return secret; + } + + /** + * Sets the secret property on and off. If a field is used to enter + * secretinformation the information is not echoed to display. + * + * @param secret + * the value specifying if the field is used to enter secret + * information. + */ + public void setSecret(boolean secret) { + this.secret = secret; + requestRepaint(); + } + + /** + * Gets the null-string representation. + * + *

+ * The null-valued strings are represented on the user interface by + * replacing the null value with this string. If the null representation is + * set null (not 'null' string), painting null value throws exception. + *

+ * + *

+ * The default value is string 'null'. + *

+ * + * @return the String Textual representation for null strings. + * @see TextField#isNullSettingAllowed() + */ + public String getNullRepresentation() { + return nullRepresentation; + } + + /** + * Is setting nulls with null-string representation allowed. + * + *

+ * If this property is true, writing null-representation string to text + * field allways sets the field value to real null. If this property is + * false, null setting is not made, but the null values are maintained. + * Maintenance of null-values is made by only converting the textfield + * contents to real null, if the text field matches the null-string + * representation and the current value of the field is null. + *

+ * + *

+ * By default this setting is false + *

+ * + * @return boolean Should the null-string represenation be allways converted + * to null-values. + * @see TextField#getNullRepresentation() + */ + public boolean isNullSettingAllowed() { + return nullSettingAllowed; + } + + /** + * Sets the null-string representation. + * + *

+ * The null-valued strings are represented on the user interface by + * replacing the null value with this string. If the null representation is + * set null (not 'null' string), painting null value throws exception. + *

+ * + *

+ * The default value is string 'null' + *

+ * + * @param nullRepresentation + * Textual representation for null strings. + * @see TextField#setNullSettingAllowed(boolean) + */ + public void setNullRepresentation(String nullRepresentation) { + this.nullRepresentation = nullRepresentation; + } + + /** + * Sets the null conversion mode. + * + *

+ * If this property is true, writing null-representation string to text + * field allways sets the field value to real null. If this property is + * false, null setting is not made, but the null values are maintained. + * Maintenance of null-values is made by only converting the textfield + * contents to real null, if the text field matches the null-string + * representation and the current value of the field is null. + *

+ * + *

+ * By default this setting is false. + *

+ * + * @param nullSettingAllowed + * Should the null-string represenation be allways converted + * to null-values. + * @see TextField#getNullRepresentation() + */ + public void setNullSettingAllowed(boolean nullSettingAllowed) { + this.nullSettingAllowed = nullSettingAllowed; + } + + /** + * Gets the value formatter of TextField. + * + * @return the Format used to format the value. + */ + public Format getFormat() { + return format; + } + + /** + * Gets the value formatter of TextField. + * + * @param format + * the Format used to format the value. Null disables the + * formatting. + */ + public void setFormat(Format format) { + this.format = format; + } } diff --git a/src/com/itmill/toolkit/ui/Tree.java b/src/com/itmill/toolkit/ui/Tree.java index a86717eb84..2042d4b312 100644 --- a/src/com/itmill/toolkit/ui/Tree.java +++ b/src/com/itmill/toolkit/ui/Tree.java @@ -59,957 +59,955 @@ import com.itmill.toolkit.terminal.Resource; * @since 3.0 */ public class Tree extends AbstractSelect implements Container.Hierarchical, - Action.Container { - - /* Static members ***************************************************** */ - - private static final Method EXPAND_METHOD; - - private static final Method COLLAPSE_METHOD; - - static { - try { - EXPAND_METHOD = ExpandListener.class.getDeclaredMethod( - "nodeExpand", new Class[] { ExpandEvent.class }); - COLLAPSE_METHOD = CollapseListener.class.getDeclaredMethod( - "nodeCollapse", new Class[] { CollapseEvent.class }); - } catch (java.lang.NoSuchMethodException e) { - // This should never happen - e.printStackTrace(); - throw new java.lang.RuntimeException( - "Internal error, please report"); - } - } - - /* Private members **************************************************** */ - - /** - * Set of expanded nodes. - */ - private final HashSet expanded = new HashSet(); - - /** - * List of action handlers. - */ - private LinkedList actionHandlers = null; - - /** - * Action mapper. - */ - private KeyMapper actionMapper = null; - - /** - * Is the tree selectable . - */ - private boolean selectable = true; - - /** - * Flag to indicate sub-tree loading - */ - private boolean partialUpdate = false; - - /** - * Holds a itemId which was recently expanded - */ - private Object expandedItemId; - - /** - * a flag which indicates initial paint. After this flag set true partial - * updates are allowed. - */ - private boolean initialPaint = true; - - /* Tree constructors ************************************************** */ - - /** - * Creates a new empty tree. - */ - public Tree() { - } - - /** - * Creates a new empty tree with caption. - * - * @param caption - */ - public Tree(String caption) { - setCaption(caption); - } - - /** - * Creates a new tree with caption and connect it to a Container. - * - * @param caption - * @param dataSource - */ - public Tree(String caption, Container dataSource) { - setCaption(caption); - setContainerDataSource(dataSource); - } - - /* Expanding and collapsing ******************************************* */ - - /** - * Check is an item is expanded - * - * @param itemId - * the item id. - * @return true iff the item is expanded. - */ - public boolean isExpanded(Object itemId) { - return this.expanded.contains(itemId); - } - - /** - * Expands an item. - * - * @param itemId - * the item id. - * @return True iff the expand operation succeeded - */ - public boolean expandItem(Object itemId) { - return expandItem(itemId, true); - } - - /** - * Expands an item. - * - * @param itemId - * the item id. - * @param sendChildTree - * flag to indicate if client needs subtree or not (may be cached) - * @return True iff the expand operation succeeded - */ - private boolean expandItem(Object itemId, boolean sendChildTree) { - - // Succeeds if the node is already expanded - if (isExpanded(itemId)) { - return true; - } - - // Nodes that can not have children are not expandable - if (!areChildrenAllowed(itemId)) { - return false; - } - - // Expands - this.expanded.add(itemId); - - this.expandedItemId = itemId; - if (this.initialPaint) { - requestRepaint(); - } else if(sendChildTree) { - requestPartialRepaint(); - } - fireExpandEvent(itemId); - - return true; - } - - public void requestRepaint() { - super.requestRepaint(); - this.partialUpdate = false; - } - - private void requestPartialRepaint() { - super.requestRepaint(); - this.partialUpdate = true; - } - - /** - * Expands the items recursively - * - * Expands all the children recursively starting from an item. Operation - * succeeds only if all expandable items are expanded. - * - * @param startItemId - * @return True iff the expand operation succeeded - */ - public boolean expandItemsRecursively(Object startItemId) { - - boolean result = true; - - // Initial stack - Stack todo = new Stack(); - todo.add(startItemId); - - // Expands recursively - while (!todo.isEmpty()) { - Object id = todo.pop(); - if (areChildrenAllowed(id) && !expandItem(id, false)) { - result = false; - } - if (hasChildren(id)) { - todo.addAll(getChildren(id)); - } - } - requestRepaint(); - return result; - } - - /** - * Collapses an item. - * - * @param itemId - * the item id. - * @return True iff the collapse operation succeeded - */ - public boolean collapseItem(Object itemId) { - - // Succeeds if the node is already collapsed - if (!isExpanded(itemId)) { - return true; - } - - // Collapse - this.expanded.remove(itemId); - requestRepaint(); - fireCollapseEvent(itemId); - - return true; - } - - /** - * Collapses the items recursively. - * - * Collapse all the children recursively starting from an item. Operation - * succeeds only if all expandable items are collapsed. - * - * @param startItemId - * @return True iff the collapse operation succeeded - */ - public boolean collapseItemsRecursively(Object startItemId) { - - boolean result = true; - - // Initial stack - Stack todo = new Stack(); - todo.add(startItemId); - - // Collapse recursively - while (!todo.isEmpty()) { - Object id = todo.pop(); - if (areChildrenAllowed(id) && !collapseItem(id)) { - result = false; - } - if (hasChildren(id)) { - todo.addAll(getChildren(id)); - } - } - - return result; - } - - /** - * Getter for property selectable. - * - *

- * The tree is selectable by default. - *

- * - * @return the Value of property selectable. - */ - public boolean isSelectable() { - return this.selectable; - } - - /** - * Setter for property selectable. - * - *

- * The tree is selectable by default. - *

- * - * @param selectable - * the New value of property selectable. - */ - public void setSelectable(boolean selectable) { - if (this.selectable != selectable) { - this.selectable = selectable; - requestRepaint(); - } - } - - /* Component API ****************************************************** */ - - /** - * Gets the UIDL tag corresponding to the component. - * - * @see com.itmill.toolkit.ui.AbstractComponent#getTag() - */ - public String getTag() { - return "tree"; - } - - /** - * Called when one or more variables handled by the implementing class are - * changed. - * - * @see com.itmill.toolkit.terminal.VariableOwner#changeVariables(Object - * source, Map variables) - */ - public void changeVariables(Object source, Map variables) { - - if (!isSelectable() && variables.containsKey("selected")) { - // Not-selectable is a special case, AbstractSelect does not support - // TODO could be optimized. - variables = new HashMap(variables); - variables.remove("selected"); - } - - // Collapses the nodes - if (variables.containsKey("collapse")) { - String[] keys = (String[]) variables.get("collapse"); - for (int i = 0; i < keys.length; i++) { - Object id = this.itemIdMapper.get(keys[i]); - if (id != null && isExpanded(id)) { - this.expanded.remove(id); - fireCollapseEvent(id); - } - } - } - - // Expands the nodes - if (variables.containsKey("expand")) { - boolean sendChildTree = false; - if(variables.containsKey("requestChildTree")) { - sendChildTree = true; - } - String[] keys = (String[]) variables.get("expand"); - for (int i = 0; i < keys.length; i++) { - Object id = this.itemIdMapper.get(keys[i]); - if (id != null) { - expandItem(id, sendChildTree); - } - } - } - - // Selections are handled by the select component - super.changeVariables(source, variables); - - // Actions - if (variables.containsKey("action")) { - - StringTokenizer st = new StringTokenizer((String) variables - .get("action"), ","); - if (st.countTokens() == 2) { - Object itemId = this.itemIdMapper.get(st.nextToken()); - Action action = (Action) this.actionMapper.get(st.nextToken()); - if (action != null && containsId(itemId) - && this.actionHandlers != null) { - for (Iterator i = this.actionHandlers.iterator(); i - .hasNext();) { - ((Action.Handler) i.next()).handleAction(action, this, - itemId); - } - } - } - } - } - - /** - * Paints any needed component-specific things to the given UIDL stream. - * - * @see com.itmill.toolkit.ui.AbstractComponent#paintContent(PaintTarget) - */ - public void paintContent(PaintTarget target) throws PaintException { - this.initialPaint = false; - - if (this.partialUpdate) { - target.addAttribute("partialUpdate", true); - target.addAttribute("rootKey", this.itemIdMapper - .key(this.expandedItemId)); - } else { - - // Focus control id - if (getFocusableId() > 0) { - target.addAttribute("focusid", getFocusableId()); - } - - // The tab ordering number - if (getTabIndex() > 0) { - target.addAttribute("tabindex", getTabIndex()); - } - - // Paint tree attributes - if (isSelectable()) { - target.addAttribute("selectmode", (isMultiSelect() ? "multi" - : "single")); - } else { - target.addAttribute("selectmode", "none"); - } - if (isNewItemsAllowed()) { - target.addAttribute("allownewitem", true); - } - - if (isNullSelectionAllowed()) { - target.addAttribute("nullselect", true); - } - - } - - // Initialize variables - Set actionSet = new LinkedHashSet(); - String[] selectedKeys; - if (isMultiSelect()) { - selectedKeys = new String[((Set) getValue()).size()]; - } else { - selectedKeys = new String[(getValue() == null ? 0 : 1)]; - } - int keyIndex = 0; - LinkedList expandedKeys = new LinkedList(); - - // Iterates through hierarchical tree using a stack of iterators - Stack iteratorStack = new Stack(); - Collection ids; - if (this.partialUpdate) { - ids = getChildren(this.expandedItemId); - } else { - ids = rootItemIds(); - } - - if (ids != null) { - iteratorStack.push(ids.iterator()); - } - - while (!iteratorStack.isEmpty()) { - - // Gets the iterator for current tree level - Iterator i = (Iterator) iteratorStack.peek(); - - // If the level is finished, back to previous tree level - if (!i.hasNext()) { - - // Removes used iterator from the stack - iteratorStack.pop(); - - // Closes node - if (!iteratorStack.isEmpty()) { - target.endTag("node"); - } - } - - // Adds the item on current level - else { - Object itemId = i.next(); - - // Starts the item / node - boolean isNode = areChildrenAllowed(itemId) - && hasChildren(itemId); - if (isNode) { - target.startTag("node"); - } else { - target.startTag("leaf"); - } - - // Adds the attributes - target.addAttribute("caption", getItemCaption(itemId)); - Resource icon = getItemIcon(itemId); - if (icon != null) { - target.addAttribute("icon", getItemIcon(itemId)); - } - String key = this.itemIdMapper.key(itemId); - target.addAttribute("key", key); - if (isSelected(itemId)) { - target.addAttribute("selected", true); - selectedKeys[keyIndex++] = key; - } - if (areChildrenAllowed(itemId) && isExpanded(itemId)) { - target.addAttribute("expanded", true); - expandedKeys.add(key); - } - - // Actions - if (this.actionHandlers != null) { - ArrayList keys = new ArrayList(); - for (Iterator ahi = this.actionHandlers.iterator(); ahi - .hasNext();) { - Action[] aa = ((Action.Handler) ahi.next()).getActions( - itemId, this); - if (aa != null) { - for (int ai = 0; ai < aa.length; ai++) { - String akey = this.actionMapper.key(aa[ai]); - actionSet.add(aa[ai]); - keys.add(akey); - } - } - } - target.addAttribute("al", keys.toArray()); - } - - // Adds the children if expanded, or close the tag - if (isExpanded(itemId) && hasChildren(itemId) - && areChildrenAllowed(itemId)) { - iteratorStack.push(getChildren(itemId).iterator()); - } else { - if (isNode) { - target.endTag("node"); - } else { - target.endTag("leaf"); - } - } - } - } - - // Actions - if (!actionSet.isEmpty()) { - target.addVariable(this, "action", ""); - target.startTag("actions"); - for (Iterator i = actionSet.iterator(); i.hasNext();) { - Action a = (Action) i.next(); - target.startTag("action"); - if (a.getCaption() != null) { - target.addAttribute("caption", a.getCaption()); - } - if (a.getIcon() != null) { - target.addAttribute("icon", a.getIcon()); - } - target.addAttribute("key", this.actionMapper.key(a)); - target.endTag("action"); - } - target.endTag("actions"); - } - - if (this.partialUpdate) { - this.partialUpdate = false; - } else { - // Selected - target.addVariable(this, "selected", selectedKeys); - - // Expand and collapse - target.addVariable(this, "expand", new String[] {}); - target.addVariable(this, "collapse", new String[] {}); - - // New items - target.addVariable(this, "newitem", new String[] {}); - } - } - - /* Container.Hierarchical API ***************************************** */ - - /** - * Tests if the Item with given ID can have any children. - * - * @see com.itmill.toolkit.data.Container.Hierarchical#areChildrenAllowed(Object) - */ - public boolean areChildrenAllowed(Object itemId) { - return ((Container.Hierarchical) this.items).areChildrenAllowed(itemId); - } - - /** - * Gets the IDs of all Items that are children of the specified Item. - * - * @see com.itmill.toolkit.data.Container.Hierarchical#getChildren(Object) - */ - public Collection getChildren(Object itemId) { - return ((Container.Hierarchical) this.items).getChildren(itemId); - } - - /** - * Gets the ID of the parent Item of the specified Item. - * - * @see com.itmill.toolkit.data.Container.Hierarchical#getParent(Object) - */ - public Object getParent(Object itemId) { - return ((Container.Hierarchical) this.items).getParent(itemId); - } - - /** - * Tests if the Item specified with itemId has any child - * Items, that is, is it a leaf Item. - * - * @see com.itmill.toolkit.data.Container.Hierarchical#hasChildren(Object) - */ - public boolean hasChildren(Object itemId) { - return ((Container.Hierarchical) this.items).hasChildren(itemId); - } - - /** - * Tests if the Item specified with itemId is a root Item. - * - * @see com.itmill.toolkit.data.Container.Hierarchical#isRoot(Object) - */ - public boolean isRoot(Object itemId) { - return ((Container.Hierarchical) this.items).isRoot(itemId); - } - - /** - * Gets the IDs of all Items in the container that don't have a parent. - * - * @see com.itmill.toolkit.data.Container.Hierarchical#rootItemIds() - */ - public Collection rootItemIds() { - return ((Container.Hierarchical) this.items).rootItemIds(); - } - - /** - * Sets the given Item's capability to have children. - * - * @see com.itmill.toolkit.data.Container.Hierarchical#setChildrenAllowed(Object, - * boolean) - */ - public boolean setChildrenAllowed(Object itemId, boolean areChildrenAllowed) { - boolean success = ((Container.Hierarchical) this.items) - .setChildrenAllowed(itemId, areChildrenAllowed); - if (success) { - fireValueChange(false); - } - return success; - } - - /** - * Sets the parent of an Item. - * - * @see com.itmill.toolkit.data.Container.Hierarchical#setParent(Object, - * Object) - */ - public boolean setParent(Object itemId, Object newParentId) { - boolean success = ((Container.Hierarchical) this.items).setParent( - itemId, newParentId); - if (success) { - requestRepaint(); - } - return success; - } - - /* Overriding select behavior******************************************** */ - - /** - * Sets the Container that serves as the data source of the viewer. - * - * @see com.itmill.toolkit.data.Container.Viewer#setContainerDataSource(Container) - */ - public void setContainerDataSource(Container newDataSource) { - - // Assure that the data source is ordered by making unordered - // containers ordered by wrapping them - if (Container.Hierarchical.class.isAssignableFrom(newDataSource - .getClass())) { - super.setContainerDataSource(newDataSource); - } else { - super.setContainerDataSource(new ContainerHierarchicalWrapper( - newDataSource)); - } - } - - /* Expand event and listener ****************************************** */ - - /** - * Event to fired when a node is expanded. ExapandEvent is fired when a node - * is to be expanded. it can me used to dynamically fill the sub-nodes of - * the node. - * - * @author IT Mill Ltd. - * @version - * @VERSION@ - * @since 3.0 - */ - public class ExpandEvent extends Component.Event { - - /** - * Serial generated by eclipse. - */ - private static final long serialVersionUID = 3832624001804481075L; - - private final Object expandedItemId; - - /** - * New instance of options change event - * - * @param source - * the Source of the event. - * @param expandedItemId - */ - public ExpandEvent(Component source, Object expandedItemId) { - super(source); - this.expandedItemId = expandedItemId; - } - - /** - * Node where the event occurred. - * - * @return the Source of the event. - */ - public Object getItemId() { - return this.expandedItemId; - } - } - - /** - * Expand event listener. - * - * @author IT Mill Ltd. - * @version - * @VERSION@ - * @since 3.0 - */ - public interface ExpandListener { - - /** - * A node has been expanded. - * - * @param event - * the Expand event. - */ - public void nodeExpand(ExpandEvent event); - } - - /** - * Adds the expand listener. - * - * @param listener - * the Listener to be added. - */ - public void addListener(ExpandListener listener) { - addListener(ExpandEvent.class, listener, EXPAND_METHOD); - } - - /** - * Removes the expand listener. - * - * @param listener - * the Listener to be removed. - */ - public void removeListener(ExpandListener listener) { - removeListener(ExpandEvent.class, listener, EXPAND_METHOD); - } - - /** - * Emits the expand event. - * - * @param itemId - * the item id. - */ - protected void fireExpandEvent(Object itemId) { - fireEvent(new ExpandEvent(this, itemId)); - } - - /* Collapse event ****************************************** */ - - /** - * Collapse event - * - * @author IT Mill Ltd. - * @version - * @VERSION@ - * @since 3.0 - */ - public class CollapseEvent extends Component.Event { - - /** - * Serial generated by eclipse. - */ - private static final long serialVersionUID = 3257009834783290160L; - - private final Object collapsedItemId; - - /** - * New instance of options change event. - * - * @param source - * the Source of the event. - * @param collapsedItemId - */ - public CollapseEvent(Component source, Object collapsedItemId) { - super(source); - this.collapsedItemId = collapsedItemId; - } - - /** - * Gets tge Collapsed Item id. - * - * @return the collapsed item id. - */ - public Object getItemId() { - return this.collapsedItemId; - } - } - - /** - * Collapse event listener. - * - * @author IT Mill Ltd. - * @version - * @VERSION@ - * @since 3.0 - */ - public interface CollapseListener { - - /** - * A node has been collapsed. - * - * @param event - * the Collapse event. - */ - public void nodeCollapse(CollapseEvent event); - } - - /** - * Adds the collapse listener. - * - * @param listener - * the Listener to be added. - */ - public void addListener(CollapseListener listener) { - addListener(CollapseEvent.class, listener, COLLAPSE_METHOD); - } - - /** - * Removes the collapse listener. - * - * @param listener - * the Listener to be removed. - */ - public void removeListener(CollapseListener listener) { - removeListener(CollapseEvent.class, listener, COLLAPSE_METHOD); - } - - /** - * Emits collapse event. - * - * @param itemId - * the item id. - */ - protected void fireCollapseEvent(Object itemId) { - fireEvent(new CollapseEvent(this, itemId)); - } - - /* Action container *************************************************** */ - - /** - * Adds an action handler. - * - * @see com.itmill.toolkit.event.Action.Container#addActionHandler(Action.Handler) - */ - public void addActionHandler(Action.Handler actionHandler) { - - if (actionHandler != null) { - - if (this.actionHandlers == null) { - this.actionHandlers = new LinkedList(); - this.actionMapper = new KeyMapper(); - } - - if (!this.actionHandlers.contains(actionHandler)) { - this.actionHandlers.add(actionHandler); - requestRepaint(); - } - } - } - - /** - * Removes an action handler. - * - * @see com.itmill.toolkit.event.Action.Container#removeActionHandler(Action.Handler) - */ - public void removeActionHandler(Action.Handler actionHandler) { - - if (this.actionHandlers != null - && this.actionHandlers.contains(actionHandler)) { - - this.actionHandlers.remove(actionHandler); - - if (this.actionHandlers.isEmpty()) { - this.actionHandlers = null; - this.actionMapper = null; - } - - requestRepaint(); - } - } - - /** - * Gets the visible item ids. - * - * @see com.itmill.toolkit.ui.Select#getVisibleItemIds() - */ - public Collection getVisibleItemIds() { - - LinkedList visible = new LinkedList(); - - // Iterates trough hierarchical tree using a stack of iterators - Stack iteratorStack = new Stack(); - Collection ids = rootItemIds(); - if (ids != null) { - iteratorStack.push(ids.iterator()); - } - while (!iteratorStack.isEmpty()) { - - // Gets the iterator for current tree level - Iterator i = (Iterator) iteratorStack.peek(); - - // If the level is finished, back to previous tree level - if (!i.hasNext()) { - - // Removes used iterator from the stack - iteratorStack.pop(); - } - - // Adds the item on current level - else { - Object itemId = i.next(); - - visible.add(itemId); - - // Adds children if expanded, or close the tag - if (isExpanded(itemId) && hasChildren(itemId)) { - iteratorStack.push(getChildren(itemId).iterator()); - } - } - } - - return visible; - } - - /** - * Tree does not support setNullSelectionItemId. - * - * @see com.itmill.toolkit.ui.AbstractSelect#setNullSelectionItemId(java.lang.Object) - */ - public void setNullSelectionItemId(Object nullSelectionItemId) - throws UnsupportedOperationException { - if (nullSelectionItemId != null) { - throw new UnsupportedOperationException(); - } - - } - - /** - * Adding new items is not supported. - * - * @throws UnsupportedOperationException - * if set to true. - * @see com.itmill.toolkit.ui.Select#setNewItemsAllowed(boolean) - */ - public void setNewItemsAllowed(boolean allowNewOptions) - throws UnsupportedOperationException { - if (allowNewOptions) { - throw new UnsupportedOperationException(); - } - } - - /** - * Focusing to this component is not supported. - * - * @throws UnsupportedOperationException - * if invoked. - * @see com.itmill.toolkit.ui.AbstractField#focus() - */ - public void focus() throws UnsupportedOperationException { - throw new UnsupportedOperationException(); - } - - /** - * Tree does not support lazy options loading mode. Setting this true will - * throw UnsupportedOperationException. - * - * @see com.itmill.toolkit.ui.Select#setLazyLoading(boolean) - */ - public void setLazyLoading(boolean useLazyLoading) { - if (useLazyLoading) { - throw new UnsupportedOperationException( - "Lazy options loading is not supported by Tree."); - } - } + Action.Container { + + /* Static members ***************************************************** */ + + private static final Method EXPAND_METHOD; + + private static final Method COLLAPSE_METHOD; + + static { + try { + EXPAND_METHOD = ExpandListener.class.getDeclaredMethod( + "nodeExpand", new Class[] { ExpandEvent.class }); + COLLAPSE_METHOD = CollapseListener.class.getDeclaredMethod( + "nodeCollapse", new Class[] { CollapseEvent.class }); + } catch (java.lang.NoSuchMethodException e) { + // This should never happen + e.printStackTrace(); + throw new java.lang.RuntimeException( + "Internal error, please report"); + } + } + + /* Private members **************************************************** */ + + /** + * Set of expanded nodes. + */ + private final HashSet expanded = new HashSet(); + + /** + * List of action handlers. + */ + private LinkedList actionHandlers = null; + + /** + * Action mapper. + */ + private KeyMapper actionMapper = null; + + /** + * Is the tree selectable . + */ + private boolean selectable = true; + + /** + * Flag to indicate sub-tree loading + */ + private boolean partialUpdate = false; + + /** + * Holds a itemId which was recently expanded + */ + private Object expandedItemId; + + /** + * a flag which indicates initial paint. After this flag set true partial + * updates are allowed. + */ + private boolean initialPaint = true; + + /* Tree constructors ************************************************** */ + + /** + * Creates a new empty tree. + */ + public Tree() { + } + + /** + * Creates a new empty tree with caption. + * + * @param caption + */ + public Tree(String caption) { + setCaption(caption); + } + + /** + * Creates a new tree with caption and connect it to a Container. + * + * @param caption + * @param dataSource + */ + public Tree(String caption, Container dataSource) { + setCaption(caption); + setContainerDataSource(dataSource); + } + + /* Expanding and collapsing ******************************************* */ + + /** + * Check is an item is expanded + * + * @param itemId + * the item id. + * @return true iff the item is expanded. + */ + public boolean isExpanded(Object itemId) { + return expanded.contains(itemId); + } + + /** + * Expands an item. + * + * @param itemId + * the item id. + * @return True iff the expand operation succeeded + */ + public boolean expandItem(Object itemId) { + return expandItem(itemId, true); + } + + /** + * Expands an item. + * + * @param itemId + * the item id. + * @param sendChildTree + * flag to indicate if client needs subtree or not (may be + * cached) + * @return True iff the expand operation succeeded + */ + private boolean expandItem(Object itemId, boolean sendChildTree) { + + // Succeeds if the node is already expanded + if (isExpanded(itemId)) { + return true; + } + + // Nodes that can not have children are not expandable + if (!areChildrenAllowed(itemId)) { + return false; + } + + // Expands + expanded.add(itemId); + + expandedItemId = itemId; + if (initialPaint) { + requestRepaint(); + } else if (sendChildTree) { + requestPartialRepaint(); + } + fireExpandEvent(itemId); + + return true; + } + + public void requestRepaint() { + super.requestRepaint(); + partialUpdate = false; + } + + private void requestPartialRepaint() { + super.requestRepaint(); + partialUpdate = true; + } + + /** + * Expands the items recursively + * + * Expands all the children recursively starting from an item. Operation + * succeeds only if all expandable items are expanded. + * + * @param startItemId + * @return True iff the expand operation succeeded + */ + public boolean expandItemsRecursively(Object startItemId) { + + boolean result = true; + + // Initial stack + Stack todo = new Stack(); + todo.add(startItemId); + + // Expands recursively + while (!todo.isEmpty()) { + Object id = todo.pop(); + if (areChildrenAllowed(id) && !expandItem(id, false)) { + result = false; + } + if (hasChildren(id)) { + todo.addAll(getChildren(id)); + } + } + requestRepaint(); + return result; + } + + /** + * Collapses an item. + * + * @param itemId + * the item id. + * @return True iff the collapse operation succeeded + */ + public boolean collapseItem(Object itemId) { + + // Succeeds if the node is already collapsed + if (!isExpanded(itemId)) { + return true; + } + + // Collapse + expanded.remove(itemId); + requestRepaint(); + fireCollapseEvent(itemId); + + return true; + } + + /** + * Collapses the items recursively. + * + * Collapse all the children recursively starting from an item. Operation + * succeeds only if all expandable items are collapsed. + * + * @param startItemId + * @return True iff the collapse operation succeeded + */ + public boolean collapseItemsRecursively(Object startItemId) { + + boolean result = true; + + // Initial stack + Stack todo = new Stack(); + todo.add(startItemId); + + // Collapse recursively + while (!todo.isEmpty()) { + Object id = todo.pop(); + if (areChildrenAllowed(id) && !collapseItem(id)) { + result = false; + } + if (hasChildren(id)) { + todo.addAll(getChildren(id)); + } + } + + return result; + } + + /** + * Getter for property selectable. + * + *

+ * The tree is selectable by default. + *

+ * + * @return the Value of property selectable. + */ + public boolean isSelectable() { + return selectable; + } + + /** + * Setter for property selectable. + * + *

+ * The tree is selectable by default. + *

+ * + * @param selectable + * the New value of property selectable. + */ + public void setSelectable(boolean selectable) { + if (this.selectable != selectable) { + this.selectable = selectable; + requestRepaint(); + } + } + + /* Component API ****************************************************** */ + + /** + * Gets the UIDL tag corresponding to the component. + * + * @see com.itmill.toolkit.ui.AbstractComponent#getTag() + */ + public String getTag() { + return "tree"; + } + + /** + * Called when one or more variables handled by the implementing class are + * changed. + * + * @see com.itmill.toolkit.terminal.VariableOwner#changeVariables(Object + * source, Map variables) + */ + public void changeVariables(Object source, Map variables) { + + if (!isSelectable() && variables.containsKey("selected")) { + // Not-selectable is a special case, AbstractSelect does not support + // TODO could be optimized. + variables = new HashMap(variables); + variables.remove("selected"); + } + + // Collapses the nodes + if (variables.containsKey("collapse")) { + String[] keys = (String[]) variables.get("collapse"); + for (int i = 0; i < keys.length; i++) { + Object id = itemIdMapper.get(keys[i]); + if (id != null && isExpanded(id)) { + expanded.remove(id); + fireCollapseEvent(id); + } + } + } + + // Expands the nodes + if (variables.containsKey("expand")) { + boolean sendChildTree = false; + if (variables.containsKey("requestChildTree")) { + sendChildTree = true; + } + String[] keys = (String[]) variables.get("expand"); + for (int i = 0; i < keys.length; i++) { + Object id = itemIdMapper.get(keys[i]); + if (id != null) { + expandItem(id, sendChildTree); + } + } + } + + // Selections are handled by the select component + super.changeVariables(source, variables); + + // Actions + if (variables.containsKey("action")) { + + StringTokenizer st = new StringTokenizer((String) variables + .get("action"), ","); + if (st.countTokens() == 2) { + Object itemId = itemIdMapper.get(st.nextToken()); + Action action = (Action) actionMapper.get(st.nextToken()); + if (action != null && containsId(itemId) + && actionHandlers != null) { + for (Iterator i = actionHandlers.iterator(); i.hasNext();) { + ((Action.Handler) i.next()).handleAction(action, this, + itemId); + } + } + } + } + } + + /** + * Paints any needed component-specific things to the given UIDL stream. + * + * @see com.itmill.toolkit.ui.AbstractComponent#paintContent(PaintTarget) + */ + public void paintContent(PaintTarget target) throws PaintException { + initialPaint = false; + + if (partialUpdate) { + target.addAttribute("partialUpdate", true); + target.addAttribute("rootKey", itemIdMapper.key(expandedItemId)); + } else { + + // Focus control id + if (getFocusableId() > 0) { + target.addAttribute("focusid", getFocusableId()); + } + + // The tab ordering number + if (getTabIndex() > 0) { + target.addAttribute("tabindex", getTabIndex()); + } + + // Paint tree attributes + if (isSelectable()) { + target.addAttribute("selectmode", (isMultiSelect() ? "multi" + : "single")); + } else { + target.addAttribute("selectmode", "none"); + } + if (isNewItemsAllowed()) { + target.addAttribute("allownewitem", true); + } + + if (isNullSelectionAllowed()) { + target.addAttribute("nullselect", true); + } + + } + + // Initialize variables + Set actionSet = new LinkedHashSet(); + String[] selectedKeys; + if (isMultiSelect()) { + selectedKeys = new String[((Set) getValue()).size()]; + } else { + selectedKeys = new String[(getValue() == null ? 0 : 1)]; + } + int keyIndex = 0; + LinkedList expandedKeys = new LinkedList(); + + // Iterates through hierarchical tree using a stack of iterators + Stack iteratorStack = new Stack(); + Collection ids; + if (partialUpdate) { + ids = getChildren(expandedItemId); + } else { + ids = rootItemIds(); + } + + if (ids != null) { + iteratorStack.push(ids.iterator()); + } + + while (!iteratorStack.isEmpty()) { + + // Gets the iterator for current tree level + Iterator i = (Iterator) iteratorStack.peek(); + + // If the level is finished, back to previous tree level + if (!i.hasNext()) { + + // Removes used iterator from the stack + iteratorStack.pop(); + + // Closes node + if (!iteratorStack.isEmpty()) { + target.endTag("node"); + } + } + + // Adds the item on current level + else { + Object itemId = i.next(); + + // Starts the item / node + boolean isNode = areChildrenAllowed(itemId) + && hasChildren(itemId); + if (isNode) { + target.startTag("node"); + } else { + target.startTag("leaf"); + } + + // Adds the attributes + target.addAttribute("caption", getItemCaption(itemId)); + Resource icon = getItemIcon(itemId); + if (icon != null) { + target.addAttribute("icon", getItemIcon(itemId)); + } + String key = itemIdMapper.key(itemId); + target.addAttribute("key", key); + if (isSelected(itemId)) { + target.addAttribute("selected", true); + selectedKeys[keyIndex++] = key; + } + if (areChildrenAllowed(itemId) && isExpanded(itemId)) { + target.addAttribute("expanded", true); + expandedKeys.add(key); + } + + // Actions + if (actionHandlers != null) { + ArrayList keys = new ArrayList(); + for (Iterator ahi = actionHandlers.iterator(); ahi + .hasNext();) { + Action[] aa = ((Action.Handler) ahi.next()).getActions( + itemId, this); + if (aa != null) { + for (int ai = 0; ai < aa.length; ai++) { + String akey = actionMapper.key(aa[ai]); + actionSet.add(aa[ai]); + keys.add(akey); + } + } + } + target.addAttribute("al", keys.toArray()); + } + + // Adds the children if expanded, or close the tag + if (isExpanded(itemId) && hasChildren(itemId) + && areChildrenAllowed(itemId)) { + iteratorStack.push(getChildren(itemId).iterator()); + } else { + if (isNode) { + target.endTag("node"); + } else { + target.endTag("leaf"); + } + } + } + } + + // Actions + if (!actionSet.isEmpty()) { + target.addVariable(this, "action", ""); + target.startTag("actions"); + for (Iterator i = actionSet.iterator(); i.hasNext();) { + Action a = (Action) i.next(); + target.startTag("action"); + if (a.getCaption() != null) { + target.addAttribute("caption", a.getCaption()); + } + if (a.getIcon() != null) { + target.addAttribute("icon", a.getIcon()); + } + target.addAttribute("key", actionMapper.key(a)); + target.endTag("action"); + } + target.endTag("actions"); + } + + if (partialUpdate) { + partialUpdate = false; + } else { + // Selected + target.addVariable(this, "selected", selectedKeys); + + // Expand and collapse + target.addVariable(this, "expand", new String[] {}); + target.addVariable(this, "collapse", new String[] {}); + + // New items + target.addVariable(this, "newitem", new String[] {}); + } + } + + /* Container.Hierarchical API ***************************************** */ + + /** + * Tests if the Item with given ID can have any children. + * + * @see com.itmill.toolkit.data.Container.Hierarchical#areChildrenAllowed(Object) + */ + public boolean areChildrenAllowed(Object itemId) { + return ((Container.Hierarchical) items).areChildrenAllowed(itemId); + } + + /** + * Gets the IDs of all Items that are children of the specified Item. + * + * @see com.itmill.toolkit.data.Container.Hierarchical#getChildren(Object) + */ + public Collection getChildren(Object itemId) { + return ((Container.Hierarchical) items).getChildren(itemId); + } + + /** + * Gets the ID of the parent Item of the specified Item. + * + * @see com.itmill.toolkit.data.Container.Hierarchical#getParent(Object) + */ + public Object getParent(Object itemId) { + return ((Container.Hierarchical) items).getParent(itemId); + } + + /** + * Tests if the Item specified with itemId has any child + * Items, that is, is it a leaf Item. + * + * @see com.itmill.toolkit.data.Container.Hierarchical#hasChildren(Object) + */ + public boolean hasChildren(Object itemId) { + return ((Container.Hierarchical) items).hasChildren(itemId); + } + + /** + * Tests if the Item specified with itemId is a root Item. + * + * @see com.itmill.toolkit.data.Container.Hierarchical#isRoot(Object) + */ + public boolean isRoot(Object itemId) { + return ((Container.Hierarchical) items).isRoot(itemId); + } + + /** + * Gets the IDs of all Items in the container that don't have a parent. + * + * @see com.itmill.toolkit.data.Container.Hierarchical#rootItemIds() + */ + public Collection rootItemIds() { + return ((Container.Hierarchical) items).rootItemIds(); + } + + /** + * Sets the given Item's capability to have children. + * + * @see com.itmill.toolkit.data.Container.Hierarchical#setChildrenAllowed(Object, + * boolean) + */ + public boolean setChildrenAllowed(Object itemId, boolean areChildrenAllowed) { + boolean success = ((Container.Hierarchical) items).setChildrenAllowed( + itemId, areChildrenAllowed); + if (success) { + fireValueChange(false); + } + return success; + } + + /** + * Sets the parent of an Item. + * + * @see com.itmill.toolkit.data.Container.Hierarchical#setParent(Object, + * Object) + */ + public boolean setParent(Object itemId, Object newParentId) { + boolean success = ((Container.Hierarchical) items).setParent(itemId, + newParentId); + if (success) { + requestRepaint(); + } + return success; + } + + /* Overriding select behavior******************************************** */ + + /** + * Sets the Container that serves as the data source of the viewer. + * + * @see com.itmill.toolkit.data.Container.Viewer#setContainerDataSource(Container) + */ + public void setContainerDataSource(Container newDataSource) { + + // Assure that the data source is ordered by making unordered + // containers ordered by wrapping them + if (Container.Hierarchical.class.isAssignableFrom(newDataSource + .getClass())) { + super.setContainerDataSource(newDataSource); + } else { + super.setContainerDataSource(new ContainerHierarchicalWrapper( + newDataSource)); + } + } + + /* Expand event and listener ****************************************** */ + + /** + * Event to fired when a node is expanded. ExapandEvent is fired when a node + * is to be expanded. it can me used to dynamically fill the sub-nodes of + * the node. + * + * @author IT Mill Ltd. + * @version + * @VERSION@ + * @since 3.0 + */ + public class ExpandEvent extends Component.Event { + + /** + * Serial generated by eclipse. + */ + private static final long serialVersionUID = 3832624001804481075L; + + private final Object expandedItemId; + + /** + * New instance of options change event + * + * @param source + * the Source of the event. + * @param expandedItemId + */ + public ExpandEvent(Component source, Object expandedItemId) { + super(source); + this.expandedItemId = expandedItemId; + } + + /** + * Node where the event occurred. + * + * @return the Source of the event. + */ + public Object getItemId() { + return expandedItemId; + } + } + + /** + * Expand event listener. + * + * @author IT Mill Ltd. + * @version + * @VERSION@ + * @since 3.0 + */ + public interface ExpandListener { + + /** + * A node has been expanded. + * + * @param event + * the Expand event. + */ + public void nodeExpand(ExpandEvent event); + } + + /** + * Adds the expand listener. + * + * @param listener + * the Listener to be added. + */ + public void addListener(ExpandListener listener) { + addListener(ExpandEvent.class, listener, EXPAND_METHOD); + } + + /** + * Removes the expand listener. + * + * @param listener + * the Listener to be removed. + */ + public void removeListener(ExpandListener listener) { + removeListener(ExpandEvent.class, listener, EXPAND_METHOD); + } + + /** + * Emits the expand event. + * + * @param itemId + * the item id. + */ + protected void fireExpandEvent(Object itemId) { + fireEvent(new ExpandEvent(this, itemId)); + } + + /* Collapse event ****************************************** */ + + /** + * Collapse event + * + * @author IT Mill Ltd. + * @version + * @VERSION@ + * @since 3.0 + */ + public class CollapseEvent extends Component.Event { + + /** + * Serial generated by eclipse. + */ + private static final long serialVersionUID = 3257009834783290160L; + + private final Object collapsedItemId; + + /** + * New instance of options change event. + * + * @param source + * the Source of the event. + * @param collapsedItemId + */ + public CollapseEvent(Component source, Object collapsedItemId) { + super(source); + this.collapsedItemId = collapsedItemId; + } + + /** + * Gets tge Collapsed Item id. + * + * @return the collapsed item id. + */ + public Object getItemId() { + return collapsedItemId; + } + } + + /** + * Collapse event listener. + * + * @author IT Mill Ltd. + * @version + * @VERSION@ + * @since 3.0 + */ + public interface CollapseListener { + + /** + * A node has been collapsed. + * + * @param event + * the Collapse event. + */ + public void nodeCollapse(CollapseEvent event); + } + + /** + * Adds the collapse listener. + * + * @param listener + * the Listener to be added. + */ + public void addListener(CollapseListener listener) { + addListener(CollapseEvent.class, listener, COLLAPSE_METHOD); + } + + /** + * Removes the collapse listener. + * + * @param listener + * the Listener to be removed. + */ + public void removeListener(CollapseListener listener) { + removeListener(CollapseEvent.class, listener, COLLAPSE_METHOD); + } + + /** + * Emits collapse event. + * + * @param itemId + * the item id. + */ + protected void fireCollapseEvent(Object itemId) { + fireEvent(new CollapseEvent(this, itemId)); + } + + /* Action container *************************************************** */ + + /** + * Adds an action handler. + * + * @see com.itmill.toolkit.event.Action.Container#addActionHandler(Action.Handler) + */ + public void addActionHandler(Action.Handler actionHandler) { + + if (actionHandler != null) { + + if (actionHandlers == null) { + actionHandlers = new LinkedList(); + actionMapper = new KeyMapper(); + } + + if (!actionHandlers.contains(actionHandler)) { + actionHandlers.add(actionHandler); + requestRepaint(); + } + } + } + + /** + * Removes an action handler. + * + * @see com.itmill.toolkit.event.Action.Container#removeActionHandler(Action.Handler) + */ + public void removeActionHandler(Action.Handler actionHandler) { + + if (actionHandlers != null && actionHandlers.contains(actionHandler)) { + + actionHandlers.remove(actionHandler); + + if (actionHandlers.isEmpty()) { + actionHandlers = null; + actionMapper = null; + } + + requestRepaint(); + } + } + + /** + * Gets the visible item ids. + * + * @see com.itmill.toolkit.ui.Select#getVisibleItemIds() + */ + public Collection getVisibleItemIds() { + + LinkedList visible = new LinkedList(); + + // Iterates trough hierarchical tree using a stack of iterators + Stack iteratorStack = new Stack(); + Collection ids = rootItemIds(); + if (ids != null) { + iteratorStack.push(ids.iterator()); + } + while (!iteratorStack.isEmpty()) { + + // Gets the iterator for current tree level + Iterator i = (Iterator) iteratorStack.peek(); + + // If the level is finished, back to previous tree level + if (!i.hasNext()) { + + // Removes used iterator from the stack + iteratorStack.pop(); + } + + // Adds the item on current level + else { + Object itemId = i.next(); + + visible.add(itemId); + + // Adds children if expanded, or close the tag + if (isExpanded(itemId) && hasChildren(itemId)) { + iteratorStack.push(getChildren(itemId).iterator()); + } + } + } + + return visible; + } + + /** + * Tree does not support setNullSelectionItemId. + * + * @see com.itmill.toolkit.ui.AbstractSelect#setNullSelectionItemId(java.lang.Object) + */ + public void setNullSelectionItemId(Object nullSelectionItemId) + throws UnsupportedOperationException { + if (nullSelectionItemId != null) { + throw new UnsupportedOperationException(); + } + + } + + /** + * Adding new items is not supported. + * + * @throws UnsupportedOperationException + * if set to true. + * @see com.itmill.toolkit.ui.Select#setNewItemsAllowed(boolean) + */ + public void setNewItemsAllowed(boolean allowNewOptions) + throws UnsupportedOperationException { + if (allowNewOptions) { + throw new UnsupportedOperationException(); + } + } + + /** + * Focusing to this component is not supported. + * + * @throws UnsupportedOperationException + * if invoked. + * @see com.itmill.toolkit.ui.AbstractField#focus() + */ + public void focus() throws UnsupportedOperationException { + throw new UnsupportedOperationException(); + } + + /** + * Tree does not support lazy options loading mode. Setting this true will + * throw UnsupportedOperationException. + * + * @see com.itmill.toolkit.ui.Select#setLazyLoading(boolean) + */ + public void setLazyLoading(boolean useLazyLoading) { + if (useLazyLoading) { + throw new UnsupportedOperationException( + "Lazy options loading is not supported by Tree."); + } + } } diff --git a/src/com/itmill/toolkit/ui/TwinColSelect.java b/src/com/itmill/toolkit/ui/TwinColSelect.java index 70bbf47098..aab5bf62c1 100644 --- a/src/com/itmill/toolkit/ui/TwinColSelect.java +++ b/src/com/itmill/toolkit/ui/TwinColSelect.java @@ -15,43 +15,43 @@ import com.itmill.toolkit.terminal.PaintTarget; */ public class TwinColSelect extends AbstractSelect { - /** - * - */ - public TwinColSelect() { - super(); - setMultiSelect(true); - } - - /** - * @param caption - */ - public TwinColSelect(String caption) { - super(caption); - setMultiSelect(true); - } - - /** - * @param caption - * @param dataSource - */ - public TwinColSelect(String caption, Container dataSource) { - super(caption, dataSource); - setMultiSelect(true); - } - - /** - * @param caption - * @param options - */ - public TwinColSelect(String caption, Collection options) { - super(caption, options); - setMultiSelect(true); - } - - public void paintContent(PaintTarget target) throws PaintException { - target.addAttribute("type", "twincol"); - super.paintContent(target); - } + /** + * + */ + public TwinColSelect() { + super(); + setMultiSelect(true); + } + + /** + * @param caption + */ + public TwinColSelect(String caption) { + super(caption); + setMultiSelect(true); + } + + /** + * @param caption + * @param dataSource + */ + public TwinColSelect(String caption, Container dataSource) { + super(caption, dataSource); + setMultiSelect(true); + } + + /** + * @param caption + * @param options + */ + public TwinColSelect(String caption, Collection options) { + super(caption, options); + setMultiSelect(true); + } + + public void paintContent(PaintTarget target) throws PaintException { + target.addAttribute("type", "twincol"); + super.paintContent(target); + } } diff --git a/src/com/itmill/toolkit/ui/Upload.java b/src/com/itmill/toolkit/ui/Upload.java index 94149ac7ef..a755b14137 100644 --- a/src/com/itmill/toolkit/ui/Upload.java +++ b/src/com/itmill/toolkit/ui/Upload.java @@ -28,7 +28,9 @@ package com.itmill.toolkit.ui; +import java.io.IOException; import java.io.InputStream; +import java.io.OutputStream; import java.lang.reflect.Method; import java.util.Map; @@ -36,9 +38,6 @@ import com.itmill.toolkit.terminal.PaintException; import com.itmill.toolkit.terminal.PaintTarget; import com.itmill.toolkit.terminal.UploadStream; -import java.io.IOException; -import java.io.OutputStream; - /** * Component for client file uploading. * @@ -49,751 +48,757 @@ import java.io.OutputStream; */ public class Upload extends AbstractComponent implements Component.Focusable { - /** - * Upload buffer size. - */ - private static final int BUFFER_SIZE = 64 * 1024; // 64k - - /** - * Should the field be focused on next repaint? - */ - private boolean focus = false; - - /** - * The tab order number of this field. - */ - private int tabIndex = 0; - - /** - * The output of the upload is redirected to this receiver. - */ - private Receiver receiver; - - private long focusableId = -1; - - private boolean isUploading; - - private long contentLength = -1; - - private int totalBytes; - - /** - * ProgressListener to which information about progress is sent during - * upload - */ - private ProgressListener progressListener; - - /* TODO: Add a default constructor, receive to temp file. */ - - /** - * Creates a new instance of Upload that redirects the uploaded data to - * given stream. - * - * @param caption - * @param uploadReceiver - */ - public Upload(String caption, Receiver uploadReceiver) { - this.focusableId = Window.getNewFocusableId(this); - setCaption(caption); - receiver = uploadReceiver; - } - - /** - * Gets the component type. - * - * @return Component type as string. - */ - public String getTag() { - return "upload"; - } - - public void receiveUpload(UploadStream upload) { - if (!isUploading) - throw new IllegalStateException("uploading not started"); - - // Gets file properties - String filename = upload.getContentName(); - String type = upload.getContentType(); - - fireStarted(filename, type); - - // Gets the output target stream - OutputStream out = receiver.receiveUpload(filename, type); - if (out == null) - throw new RuntimeException( - "Error getting outputstream from upload receiver"); - - InputStream in = upload.getStream(); - - if (null == in) { - // No file, for instance non-existent filename in html upload - fireUploadInterrupted(filename, type, 0); - endUpload(); - return; - } - - byte buffer[] = new byte[BUFFER_SIZE]; - int bytesRead = 0; - totalBytes = 0; - try { - while ((bytesRead = in.read(buffer)) > 0) { - out.write(buffer, 0, bytesRead); - totalBytes += bytesRead; - if (progressListener != null && contentLength > 0) { - // update progress if listener set and contentLength - // received - progressListener.updateProgress(totalBytes, contentLength); - } - } - - // upload successful - out.close(); - fireUploadSuccess(filename, type, totalBytes); - endUpload(); - requestRepaint(); - - } catch (IOException e) { - - // Download interrupted - fireUploadInterrupted(filename, type, totalBytes); - endUpload(); - } - } - - /** - * Invoked when the value of a variable has changed. - * - * @see com.itmill.toolkit.ui.AbstractComponent#changeVariables(java.lang.Object, - * java.util.Map) - */ - public void changeVariables(Object source, Map variables) { - // NOP - - } - - /** - * Paints the content of this component. - * - * @param target - * Target to paint the content on. - * @throws PaintException - * if the paint operation failed. - */ - public void paintContent(PaintTarget target) throws PaintException { - // The field should be focused - if (focus) - target.addAttribute("focus", true); - - // The tab ordering number - if (this.tabIndex >= 0) - target.addAttribute("tabindex", this.tabIndex); - - target.addAttribute("state", isUploading); - - target.addVariable(this, "fake", true); - - target.addUploadStreamVariable(this, "stream"); - } - - /** - * Interface that must be implemented by the upload receivers. - * - * @author IT Mill Ltd. - * @version - * @VERSION@ - * @since 3.0 - */ - public interface Receiver { - - /** - * Invoked when a new upload arrives. - * - * @param filename - * the desired filename of the upload, usually as specified - * by the client. - * @param MIMEType - * the MIME type of the uploaded file. - * @return Stream to which the uploaded file should be written. - */ - public OutputStream receiveUpload(String filename, String MIMEType); - } - - /* Upload events ************************************************ */ - - private static final Method UPLOAD_FINISHED_METHOD; - - private static final Method UPLOAD_FAILED_METHOD; - - private static final Method UPLOAD_SUCCEEDED_METHOD; - - private static final Method UPLOAD_STARTED_METHOD; - - static { - try { - UPLOAD_FINISHED_METHOD = FinishedListener.class.getDeclaredMethod( - "uploadFinished", new Class[] { FinishedEvent.class }); - UPLOAD_FAILED_METHOD = FailedListener.class.getDeclaredMethod( - "uploadFailed", new Class[] { FailedEvent.class }); - UPLOAD_STARTED_METHOD = StartedListener.class.getDeclaredMethod( - "uploadStarted", new Class[] { StartedEvent.class }); - UPLOAD_SUCCEEDED_METHOD = SucceededListener.class - .getDeclaredMethod("uploadSucceeded", - new Class[] { SucceededEvent.class }); - } catch (java.lang.NoSuchMethodException e) { - // This should never happen - throw new java.lang.RuntimeException("Internal error"); - } - } - - /** - * Upload.Received event is sent when the upload receives a file, regardless - * if the receival was successfull. - * - * @author IT Mill Ltd. - * @version - * @VERSION@ - * @since 3.0 - */ - public class FinishedEvent extends Component.Event { - - /** - * Serial generated by eclipse. - */ - private static final long serialVersionUID = 3257288015385670969L; - - /** - * Length of the received file. - */ - private long length; - - /** - * MIME type of the received file. - */ - private String type; - - /** - * Received file name. - */ - private String filename; - - /** - * - * @param source - * the source of the file. - * @param filename - * the received file name. - * @param MIMEType - * the MIME type of the received file. - * @param length - * the length of the received file. - */ - public FinishedEvent(Upload source, String filename, String MIMEType, - long length) { - super(source); - this.type = MIMEType; - this.filename = filename; - this.length = length; - } - - /** - * Uploads where the event occurred. - * - * @return the Source of the event. - */ - public Upload getUpload() { - return (Upload) getSource(); - } - - /** - * Gets the file name. - * - * @return the filename. - */ - public String getFilename() { - return filename; - } - - /** - * Gets the MIME Type of the file. - * - * @return the MIME type. - */ - public String getMIMEType() { - return type; - } - - /** - * Gets the length of the file. - * - * @return the length. - */ - public long getLength() { - return length; - } - - } - - /** - * Upload.Interrupted event is sent when the upload is received, but the - * reception is interrupted for some reason. - * - * @author IT Mill Ltd. - * @version - * @VERSION@ - * @since 3.0 - */ - public class FailedEvent extends FinishedEvent { - - /** - * Serial generated by eclipse. - */ - private static final long serialVersionUID = 3833746590157386293L; - - /** - * - * @param source - * @param filename - * @param MIMEType - * @param length - */ - public FailedEvent(Upload source, String filename, String MIMEType, - long length) { - super(source, filename, MIMEType, length); - } - - } - - /** - * Upload.Success event is sent when the upload is received successfully. - * - * @author IT Mill Ltd. - * @version - * @VERSION@ - * @since 3.0 - */ - public class SucceededEvent extends FinishedEvent { - - /** - * Serial generated by eclipse. - */ - private static final long serialVersionUID = 3256445798169524023L; - - /** - * - * @param source - * @param filename - * @param MIMEType - * @param length - */ - public SucceededEvent(Upload source, String filename, String MIMEType, - long length) { - super(source, filename, MIMEType, length); - } - - } - - /** - * Upload.Started event is sent when the upload is started to received. - * - * @author IT Mill Ltd. - * @version - * @VERSION@ - * @since 5.0 - */ - public class StartedEvent extends Component.Event { - - /** - * Serial generated by eclipse. - */ - private static final long serialVersionUID = -3984393770487403525L; - private String filename; - private String type; - - /** - * - * @param source - * @param filename - * @param MIMEType - * @param length - */ - public StartedEvent(Upload source, String filename, String MIMEType) { - super(source); - this.filename = filename; - this.type = MIMEType; - } - - /** - * Uploads where the event occurred. - * - * @return the Source of the event. - */ - public Upload getUpload() { - return (Upload) getSource(); - } - - /** - * Gets the file name. - * - * @return the filename. - */ - public String getFilename() { - return filename; - } - - /** - * Gets the MIME Type of the file. - * - * @return the MIME type. - */ - public String getMIMEType() { - return type; - } - - } - - /** - * Receives the events when the upload starts. - * - * @author IT Mill Ltd. - * @version - * @VERSION@ - * @since 5.0 - */ - public interface StartedListener { - - /** - * Upload has started. - * - * @param event - * the Upload started event. - */ - public void uploadStarted(StartedEvent event); - } - - /** - * Receives the events when the uploads are ready. - * - * @author IT Mill Ltd. - * @version - * @VERSION@ - * @since 3.0 - */ - public interface FinishedListener { - - /** - * Upload has finished. - * - * @param event - * the Upload finished event. - */ - public void uploadFinished(FinishedEvent event); - } - - /** - * Receives events when the uploads are finished, but unsuccessful. - * - * @author IT Mill Ltd. - * @version - * @VERSION@ - * @since 3.0 - */ - public interface FailedListener { - - /** - * Upload has finished unsuccessfully. - * - * @param event - * the Upload failed event. - */ - public void uploadFailed(FailedEvent event); - } - - /** - * Receives events when the uploads are successfully finished. - * - * @author IT Mill Ltd. - * @version - * @VERSION@ - * @since 3.0 - */ - public interface SucceededListener { - - /** - * Upload successfull.. - * - * @param event - * the Upload successfull event. - */ - public void uploadSucceeded(SucceededEvent event); - } - - /** - * Adds the upload started event listener. - * - * @param listener - * the Listener to be added. - */ - public void addListener(StartedListener listener) { - addListener(StartedEvent.class, listener, UPLOAD_STARTED_METHOD); - } - - /** - * Removes the upload started event listener. - * - * @param listener - * the Listener to be removed. - */ - public void removeListener(StartedListener listener) { - removeListener(FinishedEvent.class, listener, UPLOAD_STARTED_METHOD); - } - - /** - * Adds the upload received event listener. - * - * @param listener - * the Listener to be added. - */ - public void addListener(FinishedListener listener) { - addListener(FinishedEvent.class, listener, UPLOAD_FINISHED_METHOD); - } - - /** - * Removes the upload received event listener. - * - * @param listener - * the Listener to be removed. - */ - public void removeListener(FinishedListener listener) { - removeListener(FinishedEvent.class, listener, UPLOAD_FINISHED_METHOD); - } - - /** - * Adds the upload interrupted event listener. - * - * @param listener - * the Listener to be added. - */ - public void addListener(FailedListener listener) { - addListener(FailedEvent.class, listener, UPLOAD_FAILED_METHOD); - } - - /** - * Removes the upload interrupted event listener. - * - * @param listener - * the Listener to be removed. - */ - public void removeListener(FailedListener listener) { - removeListener(FinishedEvent.class, listener, UPLOAD_FAILED_METHOD); - } - - /** - * Adds the upload success event listener. - * - * @param listener - * the Listener to be added. - */ - public void addListener(SucceededListener listener) { - addListener(SucceededEvent.class, listener, UPLOAD_SUCCEEDED_METHOD); - } - - /** - * Removes the upload success event listener. - * - * @param listener - * the Listener to be removed. - */ - public void removeListener(SucceededListener listener) { - removeListener(SucceededEvent.class, listener, UPLOAD_SUCCEEDED_METHOD); - } - - /** - * Emit upload received event. - * - * @param filename - * @param MIMEType - * @param length - */ - protected void fireStarted(String filename, String MIMEType) { - fireEvent(new Upload.StartedEvent(this, filename, MIMEType)); - } - - /** - * Emit upload received event. - * - * @param filename - * @param MIMEType - * @param length - */ - protected void fireUploadReceived(String filename, String MIMEType, - long length) { - fireEvent(new Upload.FinishedEvent(this, filename, MIMEType, length)); - } - - /** - * Emits the upload interrupted event. - * - * @param filename - * @param MIMEType - * @param length - */ - protected void fireUploadInterrupted(String filename, String MIMEType, - long length) { - fireEvent(new Upload.FailedEvent(this, filename, MIMEType, length)); - } - - /** - * Emits the upload success event. - * - * @param filename - * @param MIMEType - * @param length - * - */ - protected void fireUploadSuccess(String filename, String MIMEType, - long length) { - fireEvent(new Upload.SucceededEvent(this, filename, MIMEType, length)); - } - - /** - * Returns the current receiver. - * - * @return the Receiver. - */ - public Receiver getReceiver() { - return receiver; - } - - /** - * Sets the receiver. - * - * @param receiver - * the receiver to set. - */ - public void setReceiver(Receiver receiver) { - this.receiver = receiver; - } - - /** - * Sets the focus to this component. - * - * @see com.itmill.toolkit.ui.Component.Focusable#focus() - */ - public void focus() { - Window w = getWindow(); - if (w != null) { - w.setFocusedComponent(this); - } - } - - /** - * Gets the Tabulator index of this Focusable component. - * - * @see com.itmill.toolkit.ui.Component.Focusable#getTabIndex() - */ - public int getTabIndex() { - return this.tabIndex; - } - - /** - * Sets the Tabulator index of this Focusable component. - * - * @see com.itmill.toolkit.ui.Component.Focusable#setTabIndex(int) - */ - public void setTabIndex(int tabIndex) { - this.tabIndex = tabIndex; - } - - /** - * Gets the unique ID of focusable. - * - * @see com.itmill.toolkit.ui.Component.Focusable#getFocusableId() - */ - public long getFocusableId() { - return this.focusableId; - } - - /** - * Sets the size of the file currently being uploaded. - * - * @param contentLength - */ - public void setUploadSize(long contentLength) { - this.contentLength = contentLength; - } - - /** - * Go into upload state. This is to prevent double uploading on same - * component. - */ - public void startUpload() { - if (isUploading) - throw new IllegalStateException("uploading already started"); - isUploading = true; - } - - /** - * Go into state where new uploading can begin. - */ - public void endUpload() { - isUploading = false; - contentLength = -1; - } - - public boolean isUploading() { - return isUploading; - } - - /** - * Gets read bytes of the file currently being uploaded. - * - * @return bytes - */ - public long getBytesRead() { - return totalBytes; - } - - /** - * Returns size of file currently being uploaded. Value sane only during - * upload. - * - * @return size in bytes - */ - public long getUploadSize() { - return contentLength; - } - - /** - * Sets listener to track progress of upload. - * - * @param progressListener - */ - public void setProgressListener(ProgressListener progressListener) { - this.progressListener = progressListener; - } - - /** - * Gets listener that tracks progress of upload. - * - * @return listener - * - */ - public ProgressListener getProgressListener() { - return this.progressListener; - } - - /** - * ProgressListener receives events to track progress of upload. - */ - public interface ProgressListener { - /** - * Updates progress to listener - * - * @param readBytes - * bytes transferred - * @param contentLength - * total size of file currently being uploaded, -1 if unknown - */ - public void updateProgress(long readBytes, long contentLength); - } + /** + * Upload buffer size. + */ + private static final int BUFFER_SIZE = 64 * 1024; // 64k + + /** + * Should the field be focused on next repaint? + */ + private boolean focus = false; + + /** + * The tab order number of this field. + */ + private int tabIndex = 0; + + /** + * The output of the upload is redirected to this receiver. + */ + private Receiver receiver; + + private long focusableId = -1; + + private boolean isUploading; + + private long contentLength = -1; + + private int totalBytes; + + /** + * ProgressListener to which information about progress is sent during + * upload + */ + private ProgressListener progressListener; + + /* TODO: Add a default constructor, receive to temp file. */ + + /** + * Creates a new instance of Upload that redirects the uploaded data to + * given stream. + * + * @param caption + * @param uploadReceiver + */ + public Upload(String caption, Receiver uploadReceiver) { + focusableId = Window.getNewFocusableId(this); + setCaption(caption); + receiver = uploadReceiver; + } + + /** + * Gets the component type. + * + * @return Component type as string. + */ + public String getTag() { + return "upload"; + } + + public void receiveUpload(UploadStream upload) { + if (!isUploading) { + throw new IllegalStateException("uploading not started"); + } + + // Gets file properties + String filename = upload.getContentName(); + String type = upload.getContentType(); + + fireStarted(filename, type); + + // Gets the output target stream + OutputStream out = receiver.receiveUpload(filename, type); + if (out == null) { + throw new RuntimeException( + "Error getting outputstream from upload receiver"); + } + + InputStream in = upload.getStream(); + + if (null == in) { + // No file, for instance non-existent filename in html upload + fireUploadInterrupted(filename, type, 0); + endUpload(); + return; + } + + byte buffer[] = new byte[BUFFER_SIZE]; + int bytesRead = 0; + totalBytes = 0; + try { + while ((bytesRead = in.read(buffer)) > 0) { + out.write(buffer, 0, bytesRead); + totalBytes += bytesRead; + if (progressListener != null && contentLength > 0) { + // update progress if listener set and contentLength + // received + progressListener.updateProgress(totalBytes, contentLength); + } + } + + // upload successful + out.close(); + fireUploadSuccess(filename, type, totalBytes); + endUpload(); + requestRepaint(); + + } catch (IOException e) { + + // Download interrupted + fireUploadInterrupted(filename, type, totalBytes); + endUpload(); + } + } + + /** + * Invoked when the value of a variable has changed. + * + * @see com.itmill.toolkit.ui.AbstractComponent#changeVariables(java.lang.Object, + * java.util.Map) + */ + public void changeVariables(Object source, Map variables) { + // NOP + + } + + /** + * Paints the content of this component. + * + * @param target + * Target to paint the content on. + * @throws PaintException + * if the paint operation failed. + */ + public void paintContent(PaintTarget target) throws PaintException { + // The field should be focused + if (focus) { + target.addAttribute("focus", true); + } + + // The tab ordering number + if (tabIndex >= 0) { + target.addAttribute("tabindex", tabIndex); + } + + target.addAttribute("state", isUploading); + + target.addVariable(this, "fake", true); + + target.addUploadStreamVariable(this, "stream"); + } + + /** + * Interface that must be implemented by the upload receivers. + * + * @author IT Mill Ltd. + * @version + * @VERSION@ + * @since 3.0 + */ + public interface Receiver { + + /** + * Invoked when a new upload arrives. + * + * @param filename + * the desired filename of the upload, usually as + * specified by the client. + * @param MIMEType + * the MIME type of the uploaded file. + * @return Stream to which the uploaded file should be written. + */ + public OutputStream receiveUpload(String filename, String MIMEType); + } + + /* Upload events ************************************************ */ + + private static final Method UPLOAD_FINISHED_METHOD; + + private static final Method UPLOAD_FAILED_METHOD; + + private static final Method UPLOAD_SUCCEEDED_METHOD; + + private static final Method UPLOAD_STARTED_METHOD; + + static { + try { + UPLOAD_FINISHED_METHOD = FinishedListener.class.getDeclaredMethod( + "uploadFinished", new Class[] { FinishedEvent.class }); + UPLOAD_FAILED_METHOD = FailedListener.class.getDeclaredMethod( + "uploadFailed", new Class[] { FailedEvent.class }); + UPLOAD_STARTED_METHOD = StartedListener.class.getDeclaredMethod( + "uploadStarted", new Class[] { StartedEvent.class }); + UPLOAD_SUCCEEDED_METHOD = SucceededListener.class + .getDeclaredMethod("uploadSucceeded", + new Class[] { SucceededEvent.class }); + } catch (java.lang.NoSuchMethodException e) { + // This should never happen + throw new java.lang.RuntimeException("Internal error"); + } + } + + /** + * Upload.Received event is sent when the upload receives a file, regardless + * if the receival was successfull. + * + * @author IT Mill Ltd. + * @version + * @VERSION@ + * @since 3.0 + */ + public class FinishedEvent extends Component.Event { + + /** + * Serial generated by eclipse. + */ + private static final long serialVersionUID = 3257288015385670969L; + + /** + * Length of the received file. + */ + private long length; + + /** + * MIME type of the received file. + */ + private String type; + + /** + * Received file name. + */ + private String filename; + + /** + * + * @param source + * the source of the file. + * @param filename + * the received file name. + * @param MIMEType + * the MIME type of the received file. + * @param length + * the length of the received file. + */ + public FinishedEvent(Upload source, String filename, String MIMEType, + long length) { + super(source); + type = MIMEType; + this.filename = filename; + this.length = length; + } + + /** + * Uploads where the event occurred. + * + * @return the Source of the event. + */ + public Upload getUpload() { + return (Upload) getSource(); + } + + /** + * Gets the file name. + * + * @return the filename. + */ + public String getFilename() { + return filename; + } + + /** + * Gets the MIME Type of the file. + * + * @return the MIME type. + */ + public String getMIMEType() { + return type; + } + + /** + * Gets the length of the file. + * + * @return the length. + */ + public long getLength() { + return length; + } + + } + + /** + * Upload.Interrupted event is sent when the upload is received, but the + * reception is interrupted for some reason. + * + * @author IT Mill Ltd. + * @version + * @VERSION@ + * @since 3.0 + */ + public class FailedEvent extends FinishedEvent { + + /** + * Serial generated by eclipse. + */ + private static final long serialVersionUID = 3833746590157386293L; + + /** + * + * @param source + * @param filename + * @param MIMEType + * @param length + */ + public FailedEvent(Upload source, String filename, String MIMEType, + long length) { + super(source, filename, MIMEType, length); + } + + } + + /** + * Upload.Success event is sent when the upload is received successfully. + * + * @author IT Mill Ltd. + * @version + * @VERSION@ + * @since 3.0 + */ + public class SucceededEvent extends FinishedEvent { + + /** + * Serial generated by eclipse. + */ + private static final long serialVersionUID = 3256445798169524023L; + + /** + * + * @param source + * @param filename + * @param MIMEType + * @param length + */ + public SucceededEvent(Upload source, String filename, String MIMEType, + long length) { + super(source, filename, MIMEType, length); + } + + } + + /** + * Upload.Started event is sent when the upload is started to received. + * + * @author IT Mill Ltd. + * @version + * @VERSION@ + * @since 5.0 + */ + public class StartedEvent extends Component.Event { + + /** + * Serial generated by eclipse. + */ + private static final long serialVersionUID = -3984393770487403525L; + private String filename; + private String type; + + /** + * + * @param source + * @param filename + * @param MIMEType + * @param length + */ + public StartedEvent(Upload source, String filename, String MIMEType) { + super(source); + this.filename = filename; + type = MIMEType; + } + + /** + * Uploads where the event occurred. + * + * @return the Source of the event. + */ + public Upload getUpload() { + return (Upload) getSource(); + } + + /** + * Gets the file name. + * + * @return the filename. + */ + public String getFilename() { + return filename; + } + + /** + * Gets the MIME Type of the file. + * + * @return the MIME type. + */ + public String getMIMEType() { + return type; + } + + } + + /** + * Receives the events when the upload starts. + * + * @author IT Mill Ltd. + * @version + * @VERSION@ + * @since 5.0 + */ + public interface StartedListener { + + /** + * Upload has started. + * + * @param event + * the Upload started event. + */ + public void uploadStarted(StartedEvent event); + } + + /** + * Receives the events when the uploads are ready. + * + * @author IT Mill Ltd. + * @version + * @VERSION@ + * @since 3.0 + */ + public interface FinishedListener { + + /** + * Upload has finished. + * + * @param event + * the Upload finished event. + */ + public void uploadFinished(FinishedEvent event); + } + + /** + * Receives events when the uploads are finished, but unsuccessful. + * + * @author IT Mill Ltd. + * @version + * @VERSION@ + * @since 3.0 + */ + public interface FailedListener { + + /** + * Upload has finished unsuccessfully. + * + * @param event + * the Upload failed event. + */ + public void uploadFailed(FailedEvent event); + } + + /** + * Receives events when the uploads are successfully finished. + * + * @author IT Mill Ltd. + * @version + * @VERSION@ + * @since 3.0 + */ + public interface SucceededListener { + + /** + * Upload successfull.. + * + * @param event + * the Upload successfull event. + */ + public void uploadSucceeded(SucceededEvent event); + } + + /** + * Adds the upload started event listener. + * + * @param listener + * the Listener to be added. + */ + public void addListener(StartedListener listener) { + addListener(StartedEvent.class, listener, UPLOAD_STARTED_METHOD); + } + + /** + * Removes the upload started event listener. + * + * @param listener + * the Listener to be removed. + */ + public void removeListener(StartedListener listener) { + removeListener(FinishedEvent.class, listener, UPLOAD_STARTED_METHOD); + } + + /** + * Adds the upload received event listener. + * + * @param listener + * the Listener to be added. + */ + public void addListener(FinishedListener listener) { + addListener(FinishedEvent.class, listener, UPLOAD_FINISHED_METHOD); + } + + /** + * Removes the upload received event listener. + * + * @param listener + * the Listener to be removed. + */ + public void removeListener(FinishedListener listener) { + removeListener(FinishedEvent.class, listener, UPLOAD_FINISHED_METHOD); + } + + /** + * Adds the upload interrupted event listener. + * + * @param listener + * the Listener to be added. + */ + public void addListener(FailedListener listener) { + addListener(FailedEvent.class, listener, UPLOAD_FAILED_METHOD); + } + + /** + * Removes the upload interrupted event listener. + * + * @param listener + * the Listener to be removed. + */ + public void removeListener(FailedListener listener) { + removeListener(FinishedEvent.class, listener, UPLOAD_FAILED_METHOD); + } + + /** + * Adds the upload success event listener. + * + * @param listener + * the Listener to be added. + */ + public void addListener(SucceededListener listener) { + addListener(SucceededEvent.class, listener, UPLOAD_SUCCEEDED_METHOD); + } + + /** + * Removes the upload success event listener. + * + * @param listener + * the Listener to be removed. + */ + public void removeListener(SucceededListener listener) { + removeListener(SucceededEvent.class, listener, UPLOAD_SUCCEEDED_METHOD); + } + + /** + * Emit upload received event. + * + * @param filename + * @param MIMEType + * @param length + */ + protected void fireStarted(String filename, String MIMEType) { + fireEvent(new Upload.StartedEvent(this, filename, MIMEType)); + } + + /** + * Emit upload received event. + * + * @param filename + * @param MIMEType + * @param length + */ + protected void fireUploadReceived(String filename, String MIMEType, + long length) { + fireEvent(new Upload.FinishedEvent(this, filename, MIMEType, length)); + } + + /** + * Emits the upload interrupted event. + * + * @param filename + * @param MIMEType + * @param length + */ + protected void fireUploadInterrupted(String filename, String MIMEType, + long length) { + fireEvent(new Upload.FailedEvent(this, filename, MIMEType, length)); + } + + /** + * Emits the upload success event. + * + * @param filename + * @param MIMEType + * @param length + * + */ + protected void fireUploadSuccess(String filename, String MIMEType, + long length) { + fireEvent(new Upload.SucceededEvent(this, filename, MIMEType, length)); + } + + /** + * Returns the current receiver. + * + * @return the Receiver. + */ + public Receiver getReceiver() { + return receiver; + } + + /** + * Sets the receiver. + * + * @param receiver + * the receiver to set. + */ + public void setReceiver(Receiver receiver) { + this.receiver = receiver; + } + + /** + * Sets the focus to this component. + * + * @see com.itmill.toolkit.ui.Component.Focusable#focus() + */ + public void focus() { + Window w = getWindow(); + if (w != null) { + w.setFocusedComponent(this); + } + } + + /** + * Gets the Tabulator index of this Focusable component. + * + * @see com.itmill.toolkit.ui.Component.Focusable#getTabIndex() + */ + public int getTabIndex() { + return tabIndex; + } + + /** + * Sets the Tabulator index of this Focusable component. + * + * @see com.itmill.toolkit.ui.Component.Focusable#setTabIndex(int) + */ + public void setTabIndex(int tabIndex) { + this.tabIndex = tabIndex; + } + + /** + * Gets the unique ID of focusable. + * + * @see com.itmill.toolkit.ui.Component.Focusable#getFocusableId() + */ + public long getFocusableId() { + return focusableId; + } + + /** + * Sets the size of the file currently being uploaded. + * + * @param contentLength + */ + public void setUploadSize(long contentLength) { + this.contentLength = contentLength; + } + + /** + * Go into upload state. This is to prevent double uploading on same + * component. + */ + public void startUpload() { + if (isUploading) { + throw new IllegalStateException("uploading already started"); + } + isUploading = true; + } + + /** + * Go into state where new uploading can begin. + */ + public void endUpload() { + isUploading = false; + contentLength = -1; + } + + public boolean isUploading() { + return isUploading; + } + + /** + * Gets read bytes of the file currently being uploaded. + * + * @return bytes + */ + public long getBytesRead() { + return totalBytes; + } + + /** + * Returns size of file currently being uploaded. Value sane only during + * upload. + * + * @return size in bytes + */ + public long getUploadSize() { + return contentLength; + } + + /** + * Sets listener to track progress of upload. + * + * @param progressListener + */ + public void setProgressListener(ProgressListener progressListener) { + this.progressListener = progressListener; + } + + /** + * Gets listener that tracks progress of upload. + * + * @return listener + * + */ + public ProgressListener getProgressListener() { + return progressListener; + } + + /** + * ProgressListener receives events to track progress of upload. + */ + public interface ProgressListener { + /** + * Updates progress to listener + * + * @param readBytes + * bytes transferred + * @param contentLength + * total size of file currently being uploaded, -1 if + * unknown + */ + public void updateProgress(long readBytes, long contentLength); + } } diff --git a/src/com/itmill/toolkit/ui/Window.java b/src/com/itmill/toolkit/ui/Window.java index 376e056756..237dc5c984 100644 --- a/src/com/itmill/toolkit/ui/Window.java +++ b/src/com/itmill/toolkit/ui/Window.java @@ -60,1256 +60,1259 @@ import com.itmill.toolkit.terminal.URIHandler; */ public class Window extends Panel implements URIHandler, ParameterHandler { - /** - * Window with no border. - */ - public static final int BORDER_NONE = 0; - - /** - * Window with only minimal border. - */ - public static final int BORDER_MINIMAL = 1; - - /** - * Window with default borders. - */ - public static final int BORDER_DEFAULT = 2; - - /** - * The terminal this window is attached to. - */ - private Terminal terminal = null; - - /** - * The application this window is attached to. - */ - private Application application = null; - - /** - * List of URI handlers for this window. - */ - private LinkedList uriHandlerList = null; - - /** - * List of parameter handlers for this window. - */ - private LinkedList parameterHandlerList = null; - - /** Set of subwindows */ - private final HashSet subwindows = new HashSet(); - - /** - * Explicitly specified theme of this window. If null, application theme is - * used. - */ - private String theme = null; - - /** - * Resources to be opened automatically on next repaint. - */ - private final LinkedList openList = new LinkedList(); - - /** - * The name of the window. - */ - private String name = null; - - /** - * Window border mode. - */ - private int border = BORDER_DEFAULT; - - /** - * Focused component. - */ - private Focusable focusedComponent; - - /** - * Distance of Window top border in pixels from top border of the containing - * (main window) or -1 if unspecified. - */ - private int positionY = -1; - - /** - * Distance of Window left border in pixels from left border of the - * containing (main window) or -1 if unspecified . - */ - private int positionX = -1; - - /** - * Distance scrolled from top in pixels. - */ - private int scrollTop = 0; - - /** - * Distance scrolled from left in pixels. - */ - private int scrollLeft = 0; - - private LinkedList notifications; - - /* ********************************************************************* */ - - /** - * Creates a new empty unnamed window with default layout. - * - *

- * To show the window in application, it must be added to application with - * Application.addWindow method. - *

- * - *

- * The windows are scrollable by default. - *

- * - * @param caption - * the Title of the window. - */ - public Window() { - this("", null); - } - - /** - * Creates a new empty window with default layout. - * - *

- * To show the window in application, it must be added to application with - * Application.addWindow method. - *

- * - *

- * The windows are scrollable by default. - *

- * - * @param caption - * the Title of the window. - */ - public Window(String caption) { - this(caption, null); - } - - /** - * Creates a new window. - * - *

- * To show the window in application, it must be added to application with - * Application.addWindow method. - *

- * - *

- * The windows are scrollable by default. - *

- * - * @param caption - * the Title of the window. - * @param layout - * the Layout of the window. - */ - public Window(String caption, Layout layout) { - super(caption, layout); - setScrollable(true); - } - - /** - * Gets the terminal type. - * - * @return the Value of property terminal. - */ - public Terminal getTerminal() { - return this.terminal; - } - - /* ********************************************************************* */ - - /** - * Gets the window of the component. Returns the window where this component - * belongs to. If the component does not yet belong to a window the returns - * null. - * - * @return the parent window of the component. - */ - public final Window getWindow() { - return this; - } - - /** - * Gets the application instance of the component. Returns the application - * where this component belongs to. If the component does not yet belong to - * a application the returns null. - * - * @return the parent application of the component. - */ - public final Application getApplication() { - if (getParent() == null) { - return this.application; - } - return ((Window) getParent()).getApplication(); - } - - /** - * Getter for property parent. - * - *

- * Parent is the visual parent of a component. Each component can belong to - * only one ComponentContainer at time. - *

- * - *

- * For windows attached directly to the application, parent is - * null. For windows inside other windows, parent is the - * window containing this window. - *

- * - * @return the Value of property parent. - */ - public final Component getParent() { - return super.getParent(); - } - - /** - * Setter for property parent. - * - *

- * Parent is the visual parent of a component. This is mostly called by - * containers add method and should not be called directly - *

- * - * @param parent - * the New value of property parent. - */ - public void setParent(Component parent) { - super.setParent(parent); - } - - /** - * Gets the component UIDL tag. - * - * @return the Component UIDL tag as string. - */ - public String getTag() { - return "window"; - } - - /* ********************************************************************* */ - - /** - * Adds the new URI handler to this window. - * - * @param handler - * the URI handler to add. - */ - public void addURIHandler(URIHandler handler) { - // TODO Subwindow support - - if (uriHandlerList == null) { - uriHandlerList = new LinkedList(); - } - synchronized (uriHandlerList) { - if (!uriHandlerList.contains(handler)) { - uriHandlerList.addLast(handler); - } - } - } - - /** - * Removes the given URI handler from this window. - * - * @param handler - * the URI handler to remove. - */ - public void removeURIHandler(URIHandler handler) { - // TODO Subwindow support - - if (handler == null || uriHandlerList == null) { - return; - } - synchronized (uriHandlerList) { - uriHandlerList.remove(handler); - if (uriHandlerList.isEmpty()) { - uriHandlerList = null; - } - } - } - - /** - * Handles uri recursively. - * - * @param context - * @param relativeUri - */ - public DownloadStream handleURI(URL context, String relativeUri) { - // TODO Subwindow support - - DownloadStream result = null; - if (uriHandlerList != null) { - Object[] handlers; - synchronized (uriHandlerList) { - handlers = uriHandlerList.toArray(); - } - for (int i = 0; i < handlers.length; i++) { - DownloadStream ds = ((URIHandler) handlers[i]).handleURI( - context, relativeUri); - if (ds != null) { - if (result != null) { - throw new RuntimeException("handleURI for " + context - + " uri: '" + relativeUri - + "' returns ambigious result."); - } - result = ds; - } - } - } - return result; - } - - /* ********************************************************************* */ - - /** - * Adds the new parameter handler to this window. - * - * @param handler - * the parameter handler to add. - */ - public void addParameterHandler(ParameterHandler handler) { - // TODO Subwindow support - if (parameterHandlerList == null) { - parameterHandlerList = new LinkedList(); - } - synchronized (parameterHandlerList) { - if (!parameterHandlerList.contains(handler)) { - parameterHandlerList.addLast(handler); - } - } - } - - /** - * Removes the given URI handler from this window. - * - * @param handler - * the parameter handler to remove. - */ - public void removeParameterHandler(ParameterHandler handler) { - // TODO Subwindow support - if (handler == null || parameterHandlerList == null) { - return; - } - synchronized (parameterHandlerList) { - parameterHandlerList.remove(handler); - if (parameterHandlerList.isEmpty()) { - parameterHandlerList = null; - } - } - } - - /* Documented by the interface */ - public void handleParameters(Map parameters) { - if (parameterHandlerList != null) { - Object[] handlers; - synchronized (parameterHandlerList) { - handlers = parameterHandlerList.toArray(); - } - for (int i = 0; i < handlers.length; i++) { - ((ParameterHandler) handlers[i]).handleParameters(parameters); - } - } - } - - /* ********************************************************************* */ - - /** - * Gets the theme for this window. - * - *

- * Subwindows do not support themes and thus return theme used by the parent - *

- * - * @return the Name of the theme used in window. If the theme for this - * individual window is not explicitly set, the application theme is - * used instead. If application is not assigned the - * terminal.getDefaultTheme is used. If terminal is not set, null is - * returned - */ - public String getTheme() { - if (getParent() != null) { - return ((Window) getParent()).getTheme(); - } - if (theme != null) { - return theme; - } - if ((application != null) && (application.getTheme() != null)) { - return application.getTheme(); - } - if (terminal != null) { - return terminal.getDefaultTheme(); - } - return null; - } - - /** - * Sets the theme for this window. - * - * Setting theme for subwindows is not supported. - * - * @param theme - * the New theme for this window. Null implies the default theme. - */ - public void setTheme(String theme) { - if (getParent() != null) { - throw new UnsupportedOperationException( - "Setting theme for sub-windws is not supported."); - } - this.theme = theme; - requestRepaint(); - } - - /** - * Paints the content of this component. - * - * @param event - * the Paint Event. - * @throws PaintException - * if the paint operation failed. - */ - public synchronized void paintContent(PaintTarget target) - throws PaintException { - - // Sets the window name - String name = getName(); - target.addAttribute("name", name == null ? "" : name); - - // Sets the window theme - String theme = getTheme(); - target.addAttribute("theme", theme == null ? "" : theme); - - // Marks the main window - if (getApplication() != null - && this == getApplication().getMainWindow()) { - target.addAttribute("main", true); - } - - // Open requested resource - synchronized (openList) { - if (!openList.isEmpty()) { - for (Iterator i = openList.iterator(); i.hasNext();) { - ((OpenResource) i.next()).paintContent(target); - } - openList.clear(); - } - } - - // Contents of the window panel is painted - super.paintContent(target); - - // Window position - target.addVariable(this, "positionx", getPositionX()); - target.addVariable(this, "positiony", getPositionY()); - - // Window position - target.addVariable(this, "scrolltop", getScrollTop()); - target.addVariable(this, "scrollleft", getScrollLeft()); - - // Window closing - target.addVariable(this, "close", false); - - // Sets the focused component - if (this.focusedComponent != null) { - target.addVariable(this, "focused", "" - + this.focusedComponent.getFocusableId()); - } else { - target.addVariable(this, "focused", ""); - } - - // Paint subwindows - for (Iterator i = subwindows.iterator(); i.hasNext();) { - Window w = (Window) i.next(); - w.paint(target); - } - - // Paint notifications - if (this.notifications != null) { - target.startTag("notifications"); - for (Iterator it = this.notifications.iterator(); it.hasNext();) { - Notification n = (Notification) it.next(); - target.startTag("notification"); - if (n.getCaption() != null) { - target.addAttribute("caption", n.getCaption()); - } - if (n.getMessage() != null) { - target.addAttribute("message", n.getMessage()); - } - target.addAttribute("position", n.getPosition()); - target.addAttribute("delay", n.getDelayMsec()); - if (n.getStyleName() != null) { - target.addAttribute("style", n.getStyleName()); - } - target.endTag("notification"); - } - target.endTag("notifications"); - this.notifications = null; - } - - } - - /* ********************************************************************* */ - - /** - * Opens the given resource in this window. - * - * @param resource - */ - public void open(Resource resource) { - synchronized (openList) { - if (!openList.contains(resource)) { - openList.add(new OpenResource(resource, null, -1, -1, - BORDER_DEFAULT)); - } - } - requestRepaint(); - } - - /* ********************************************************************* */ - - /** - * Opens the given resource in named terminal window. Empty or - * null window name results the resource to be opened in this - * window. - * - * @param resource - * the resource. - * @param windowName - * the name of the window. - */ - public void open(Resource resource, String windowName) { - synchronized (openList) { - if (!openList.contains(resource)) { - openList.add(new OpenResource(resource, windowName, -1, -1, - BORDER_DEFAULT)); - } - } - requestRepaint(); - } - - /* ********************************************************************* */ - - /** - * Opens the given resource in named terminal window with given size and - * border properties. Empty or null window name results the - * resource to be opened in this window. - * - * @param resource - * @param windowName - * @param width - * @param height - * @param border - */ - public void open(Resource resource, String windowName, int width, - int height, int border) { - synchronized (openList) { - if (!openList.contains(resource)) { - openList.add(new OpenResource(resource, windowName, width, - height, border)); - } - } - requestRepaint(); - } - - /* ********************************************************************* */ - - /** - * Returns the full url of the window, this returns window specific url even - * for the main window. - * - * @return the URL of the window. - */ - public URL getURL() { - - if (application == null) { - return null; - } - - try { - return new URL(application.getURL(), getName() + "/"); - } catch (MalformedURLException e) { - throw new RuntimeException("Internal problem, please report"); - } - } - - /** - * Gets the unique name of the window that indentifies it on the terminal. - * - *

- * Name identifies the URL used to access application-level windows, but is - * not used for windows inside other windows. all application-level windows - * can be accessed by their names in url - * http://host:port/foo/bar/ where - * http://host:port/foo/ is the application url as returned - * by getURL() and bar is the name of the window. Also note - * that not all windows should be added to application - one can also add - * windows inside other windows - these windows show as smaller windows - * inside those windows. - *

- * - * @return the Name of the Window. - */ - public String getName() { - return name; - } - - /** - * Returns the border. - * - * @return the border. - */ - public int getBorder() { - return border; - } - - /** - * Sets the border. - * - * @param border - * the border to set. - */ - public void setBorder(int border) { - this.border = border; - } - - /** - * Sets the application this window is connected to. - * - *

- * This method should not be invoked directly. Instead the - * {@link com.itmill.toolkit.Application#addWindow(Window)} method should be - * used to add the window to an application and - * {@link com.itmill.toolkit.Application#removeWindow(Window)} method for - * removing the window from the applicion. These methods call this method - * implicitly. - *

- * - *

- * The method invokes {@link Component#attach()} and - * {@link Component#detach()} methods when necessary. - *

- * - * @param application - * the application to set. - */ - public void setApplication(Application application) { - - // If the application is not changed, dont do nothing - if (application == this.application) { - return; - } - - // Sends detach event if the window is connected to application - if (this.application != null) { - detach(); - } - - // Connects to new parent - this.application = application; - - // Sends the attach event if connected to a window - if (application != null) { - attach(); - } - } - - /** - * Sets the name. - *

- * The name of the window must be unique inside the application. - *

- * - *

- * If the name is null, the the window is given name automatically when it - * is added to an application. - *

- * - * @param name - * the name to set. - */ - public void setName(String name) { - - // The name can not be changed in application - if (getApplication() != null) { - throw new IllegalStateException( - "Window name can not be changed while " - + "the window is in application"); - } - - this.name = name; - } - - /** - * Sets the terminal type. The terminal type is set by the the terminal - * adapter and may change from time to time. - * - * @param type - * the terminal type to set. - */ - public void setTerminal(Terminal type) { - this.terminal = type; - } - - /** - * Window only supports pixels as unit. - * - * @see com.itmill.toolkit.terminal.Sizeable#getHeightUnits() - */ - public void setHeightUnits(int units) { - if (units != Sizeable.UNITS_PIXELS) { - throw new IllegalArgumentException("Only pixels are supported"); - } - } - - /** - * Window only supports pixels as unit. - * - * @see com.itmill.toolkit.terminal.Sizeable#getWidthUnits() - */ - public void setWidthUnits(int units) { - if (units != Sizeable.UNITS_PIXELS) { - throw new IllegalArgumentException("Only pixels are supported"); - } - } - - /** - * Private data structure for storing opening window properties. - */ - private class OpenResource { - - private final Resource resource; - - private final String name; - - private final int width; - - private final int height; - - private final int border; - - /** - * Creates a new open resource. - * - * @param resource - * @param name - * @param width - * @param height - * @param border - */ - private OpenResource(Resource resource, String name, int width, - int height, int border) { - this.resource = resource; - this.name = name; - this.width = width; - this.height = height; - this.border = border; - } - - /** - * Paints the open-tag inside the window. - * - * @param target - * the Paint Event. - * @throws PaintException - * if the Paint Operation fails. - */ - private void paintContent(PaintTarget target) throws PaintException { - target.startTag("open"); - target.addAttribute("src", resource); - if (name != null && name.length() > 0) { - target.addAttribute("name", name); - } - if (width >= 0) { - target.addAttribute("width", width); - } - if (height >= 0) { - target.addAttribute("height", height); - } - switch (border) { - case Window.BORDER_MINIMAL: - target.addAttribute("border", "minimal"); - break; - case Window.BORDER_NONE: - target.addAttribute("border", "none"); - break; - } - - target.endTag("open"); - } - } - - /** - * Called when one or more variables handled by the implementing class are - * changed. - * - * @see com.itmill.toolkit.terminal.VariableOwner#changeVariables(java.lang.Object, - * java.util.Map) - */ - public void changeVariables(Object source, Map variables) { - super.changeVariables(source, variables); - - // Gets the focused component - String focusedId = (String) variables.get("focused"); - if (focusedId != null) { - try { - long id = Long.parseLong(focusedId); - this.focusedComponent = Window.getFocusableById(id); - } catch (NumberFormatException ignored) { - // We ignore invalid focusable ids - } - } - - // Positioning - Integer positionx = (Integer) variables.get("positionx"); - if (positionx != null) { - int x = positionx.intValue(); - setPositionX(x < 0 ? -1 : x); - } - Integer positiony = (Integer) variables.get("positiony"); - if (positiony != null) { - int y = positiony.intValue(); - setPositionY(y < 0 ? -1 : y); - } - - // Scroll position - Integer scrolltop = (Integer) variables.get("scrolltop"); - if (scrolltop != null) { - int top = scrolltop.intValue(); - setScrollTop(top < 0 ? 0 : top); - } - Integer scrollleft = (Integer) variables.get("scrollleft"); - if (scrollleft != null) { - int left = scrollleft.intValue(); - setScrollLeft(left < 0 ? 0 : left); - } - - // Closing - Boolean close = (Boolean) variables.get("close"); - if (close != null && close.booleanValue()) { - this.setVisible(false); - fireClose(); - } - } - - /** - * Gets the currently focused component in this window. - * - * @return the Focused component or null if none is focused. - */ - public Component.Focusable getFocusedComponent() { - return this.focusedComponent; - } - - /** - * Sets the currently focused component in this window. - * - * @param focusable - * the Focused component or null if none is focused. - */ - public void setFocusedComponent(Component.Focusable focusable) { - Application app = getApplication(); - if (app != null) { - app.setFocusedComponent(focusable); - this.focusedComponent = focusable; - } - } - - /* Focusable id generator ****************************************** */ - - private static long lastUsedFocusableId = 0; - - private static Map focusableComponents = new HashMap(); - - /** - * Gets an id for focusable component. - * - * @param focusable - * the focused component. - */ - public static long getNewFocusableId(Component.Focusable focusable) { - long newId = ++lastUsedFocusableId; - WeakReference ref = new WeakReference(focusable); - focusableComponents.put(new Long(newId), ref); - return newId; - } - - /** - * Maps the focusable id back to focusable component. - * - * @param focusableId - * the Focused Id. - * @return the focusable Id. - */ - public static Component.Focusable getFocusableById(long focusableId) { - WeakReference ref = (WeakReference) focusableComponents.get(new Long( - focusableId)); - if (ref != null) { - Object o = ref.get(); - if (o != null) { - return (Component.Focusable) o; - } - } - return null; - } - - /** - * Releases the focusable component id when not used anymore. - * - * @param focusableId - * the focusable Id to remove. - */ - public static void removeFocusableId(long focusableId) { - Long id = new Long(focusableId); - WeakReference ref = (WeakReference) focusableComponents.get(id); - ref.clear(); - focusableComponents.remove(id); - } - - /** - * Gets the distance of Window left border in pixels from left border of the - * containing (main window). - * - * @return the Distance of Window left border in pixels from left border of - * the containing (main window). or -1 if unspecified. - * @since 4.0.0 - */ - public int getPositionX() { - return positionX; - } - - /** - * Sets the distance of Window left border in pixels from left border of the - * containing (main window). - * - * @param positionX - * the Distance of Window left border in pixels from left border - * of the containing (main window). or -1 if unspecified. - * @since 4.0.0 - */ - public void setPositionX(int positionX) { - this.positionX = positionX; - } - - /** - * Gets the distance of Window top border in pixels from top border of the - * containing (main window). - * - * @return Distance of Window top border in pixels from top border of the - * containing (main window). or -1 if unspecified . - * - * @since 4.0.0 - */ - public int getPositionY() { - return positionY; - } - - /** - * Sets the distance of Window top border in pixels from top border of the - * containing (main window). - * - * @param positionY - * the Distance of Window top border in pixels from top border of - * the containing (main window). or -1 if unspecified - * - * @since 4.0.0 - */ - public void setPositionY(int positionY) { - this.positionY = positionY; - } - - private static final Method WINDOW_CLOSE_METHOD; - static { - try { - WINDOW_CLOSE_METHOD = CloseListener.class.getDeclaredMethod( - "windowClose", new Class[] { CloseEvent.class }); - } catch (java.lang.NoSuchMethodException e) { - // This should never happen - throw new java.lang.RuntimeException(); - } - } - - public class CloseEvent extends Component.Event { - - /** - * Serial generated by eclipse. - */ - private static final long serialVersionUID = -7235770057344367327L; - - /** - * - * @param source - */ - public CloseEvent(Component source) { - super(source); - } - - /** - * Gets the Window. - * - * @return the window. - */ - public Window getWindow() { - return (Window) getSource(); - } - } - - public interface CloseListener { - public void windowClose(CloseEvent e); - } - - /** - * Adds the listener. - * - * @param listener - * the listener to add. - */ - public void addListener(CloseListener listener) { - addListener(CloseEvent.class, listener, WINDOW_CLOSE_METHOD); - } - - /** - * Removes the listener. - * - * @param listener - * the listener to remove. - */ - public void removeListener(CloseListener listener) { - addListener(CloseEvent.class, listener, WINDOW_CLOSE_METHOD); - } - - protected void fireClose() { - fireEvent(new Window.CloseEvent(this)); - } - - /** - * Adds a new window inside another window. - * - *

- * Adding windows inside another window creates "subwindows". These windows - * should not be added to application directly and are not accessible - * directly with any url. Addding windows implicitly sets their parents. - *

- * - *

- * Only one level of subwindows are supported. Thus you can add windows - * inside such windows whose parent is null. - *

- * - * @param window - * @throws IllegalArgumentException - * if a window is added inside non-application level window. - * @throws NullPointerException - * if the given Window is null. - */ - public void addWindow(Window window) throws IllegalArgumentException, - NullPointerException { - - if (getParent() != null) { - throw new IllegalArgumentException( - "You can only add windows inside application-level windows"); - } - - if (window == null) { - throw new NullPointerException("Argument must not be null"); - } - - subwindows.add(window); - window.setParent(this); - requestRepaint(); - } - - /** - * Remove the given subwindow from this window. - * - * @param window - * Window to be removed. - */ - public void removeWindow(Window window) { - subwindows.remove(window); - window.setParent(null); - requestRepaint(); - - } - - /** - * Get the set of all child windows. - * - * @return Set of child windows. - */ - public Set getChildWindows() { - return Collections.unmodifiableSet(subwindows); - } - - /** - * Gets the current vertical scroll position of window. - * - * @return pixels scrolled from top - */ - public int getScrollTop() { - return scrollTop; - } - - /** - * Scrolls window to given position. - * - * @param scrollTop - * pixels to be scrolled from top - */ - public void setScrollTop(int scrollTop) { - this.scrollTop = scrollTop; - } - - /** - * Gets the current horizontal scroll position of window. - * - * @return pixels scrolled from left - */ - public int getScrollLeft() { - return scrollLeft; - } - - /** - * Scrolls window to given position. - * - * @param scrollLeft - * pixels to be scrolled from left - */ - public void setScrollLeft(int scrollLeft) { - this.scrollLeft = scrollLeft; - } - - public void showNotification(String message) { - addNotification(new Notification(message)); - } - - public void showNotification(String message, int type) { - addNotification(new Notification(message, type)); - } - - public void showNotification(String caption, String message, int type) { - addNotification(new Notification(caption, message, type)); - } - - public void showNotification(Notification notification) { - addNotification(notification); - } - - private void addNotification(Notification notification) { - if (this.notifications == null) { - this.notifications = new LinkedList(); - } - this.notifications.add(notification); - requestRepaint(); - } - - public class Notification { - public static final int TYPE_HUMANIZED_MESSAGE = 1; - public static final int TYPE_WARNING_MESSAGE = 2; - public static final int TYPE_ERROR_MESSAGE = 3; - public static final int TYPE_TRAY_NOTIFICATION = 4; - - public static final int POSITION_CENTERED = 1; - public static final int POSITION_CENTERED_TOP = 2; - public static final int POSITION_CENTERED_BOTTOM = 3; - public static final int POSITION_TOP_LEFT = 4; - public static final int POSITION_TOP_RIGHT = 5; - public static final int POSITION_BOTTOM_LEFT = 6; - public static final int POSITION_BOTTOM_RIGHT = 7; - - public static final int DELAY_FOREVER = -1; - public static final int DELAY_NONE = 0; - - private String caption; - private String message; - private Resource icon; - private int position = POSITION_CENTERED; - private int delayMsec = 0; - private String styleName; - - public Notification(String message) { - this(null, message, TYPE_HUMANIZED_MESSAGE); - } - - public Notification(String message, int type) { - this(null, message, type); - } - - public Notification(String caption, String message, int type) { - this.caption = caption; - this.message = message; - setType(type); - } - - private void setType(int type) { - switch (type) { - case TYPE_WARNING_MESSAGE: - delayMsec = 1500; - styleName = "warning"; - break; - case TYPE_ERROR_MESSAGE: - delayMsec = -1; - styleName = "error"; - break; - case TYPE_TRAY_NOTIFICATION: - delayMsec = 3000; - position = POSITION_BOTTOM_RIGHT; - styleName = "tray"; - - case TYPE_HUMANIZED_MESSAGE: - default: - break; - } - - } - - public String getCaption() { - return caption; - } - - public void setCaption(String caption) { - this.caption = caption; - } - - public String getMessage() { - return message; - } - - public void setMessage(String message) { - this.message = message; - } - - public int getPosition() { - return position; - } - - public void setPosition(int position) { - this.position = position; - } - - public Resource getIcon() { - return icon; - } - - public void setIcon(Resource icon) { - this.icon = icon; - } - - public int getDelayMsec() { - return delayMsec; - } - - public void setDelayMsec(int delayMsec) { - this.delayMsec = delayMsec; - } - - public void setStyleName(String styleName) { - this.styleName = styleName; - } - - public String getStyleName() { - return this.styleName; - } - } + /** + * Window with no border. + */ + public static final int BORDER_NONE = 0; + + /** + * Window with only minimal border. + */ + public static final int BORDER_MINIMAL = 1; + + /** + * Window with default borders. + */ + public static final int BORDER_DEFAULT = 2; + + /** + * The terminal this window is attached to. + */ + private Terminal terminal = null; + + /** + * The application this window is attached to. + */ + private Application application = null; + + /** + * List of URI handlers for this window. + */ + private LinkedList uriHandlerList = null; + + /** + * List of parameter handlers for this window. + */ + private LinkedList parameterHandlerList = null; + + /** Set of subwindows */ + private final HashSet subwindows = new HashSet(); + + /** + * Explicitly specified theme of this window. If null, application theme is + * used. + */ + private String theme = null; + + /** + * Resources to be opened automatically on next repaint. + */ + private final LinkedList openList = new LinkedList(); + + /** + * The name of the window. + */ + private String name = null; + + /** + * Window border mode. + */ + private int border = BORDER_DEFAULT; + + /** + * Focused component. + */ + private Focusable focusedComponent; + + /** + * Distance of Window top border in pixels from top border of the containing + * (main window) or -1 if unspecified. + */ + private int positionY = -1; + + /** + * Distance of Window left border in pixels from left border of the + * containing (main window) or -1 if unspecified . + */ + private int positionX = -1; + + /** + * Distance scrolled from top in pixels. + */ + private int scrollTop = 0; + + /** + * Distance scrolled from left in pixels. + */ + private int scrollLeft = 0; + + private LinkedList notifications; + + /* ********************************************************************* */ + + /** + * Creates a new empty unnamed window with default layout. + * + *

+ * To show the window in application, it must be added to application with + * Application.addWindow method. + *

+ * + *

+ * The windows are scrollable by default. + *

+ * + * @param caption + * the Title of the window. + */ + public Window() { + this("", null); + } + + /** + * Creates a new empty window with default layout. + * + *

+ * To show the window in application, it must be added to application with + * Application.addWindow method. + *

+ * + *

+ * The windows are scrollable by default. + *

+ * + * @param caption + * the Title of the window. + */ + public Window(String caption) { + this(caption, null); + } + + /** + * Creates a new window. + * + *

+ * To show the window in application, it must be added to application with + * Application.addWindow method. + *

+ * + *

+ * The windows are scrollable by default. + *

+ * + * @param caption + * the Title of the window. + * @param layout + * the Layout of the window. + */ + public Window(String caption, Layout layout) { + super(caption, layout); + setScrollable(true); + } + + /** + * Gets the terminal type. + * + * @return the Value of property terminal. + */ + public Terminal getTerminal() { + return terminal; + } + + /* ********************************************************************* */ + + /** + * Gets the window of the component. Returns the window where this component + * belongs to. If the component does not yet belong to a window the returns + * null. + * + * @return the parent window of the component. + */ + public final Window getWindow() { + return this; + } + + /** + * Gets the application instance of the component. Returns the application + * where this component belongs to. If the component does not yet belong to + * a application the returns null. + * + * @return the parent application of the component. + */ + public final Application getApplication() { + if (getParent() == null) { + return application; + } + return ((Window) getParent()).getApplication(); + } + + /** + * Getter for property parent. + * + *

+ * Parent is the visual parent of a component. Each component can belong to + * only one ComponentContainer at time. + *

+ * + *

+ * For windows attached directly to the application, parent is + * null. For windows inside other windows, parent is the + * window containing this window. + *

+ * + * @return the Value of property parent. + */ + public final Component getParent() { + return super.getParent(); + } + + /** + * Setter for property parent. + * + *

+ * Parent is the visual parent of a component. This is mostly called by + * containers add method and should not be called directly + *

+ * + * @param parent + * the New value of property parent. + */ + public void setParent(Component parent) { + super.setParent(parent); + } + + /** + * Gets the component UIDL tag. + * + * @return the Component UIDL tag as string. + */ + public String getTag() { + return "window"; + } + + /* ********************************************************************* */ + + /** + * Adds the new URI handler to this window. + * + * @param handler + * the URI handler to add. + */ + public void addURIHandler(URIHandler handler) { + // TODO Subwindow support + + if (uriHandlerList == null) { + uriHandlerList = new LinkedList(); + } + synchronized (uriHandlerList) { + if (!uriHandlerList.contains(handler)) { + uriHandlerList.addLast(handler); + } + } + } + + /** + * Removes the given URI handler from this window. + * + * @param handler + * the URI handler to remove. + */ + public void removeURIHandler(URIHandler handler) { + // TODO Subwindow support + + if (handler == null || uriHandlerList == null) { + return; + } + synchronized (uriHandlerList) { + uriHandlerList.remove(handler); + if (uriHandlerList.isEmpty()) { + uriHandlerList = null; + } + } + } + + /** + * Handles uri recursively. + * + * @param context + * @param relativeUri + */ + public DownloadStream handleURI(URL context, String relativeUri) { + // TODO Subwindow support + + DownloadStream result = null; + if (uriHandlerList != null) { + Object[] handlers; + synchronized (uriHandlerList) { + handlers = uriHandlerList.toArray(); + } + for (int i = 0; i < handlers.length; i++) { + DownloadStream ds = ((URIHandler) handlers[i]).handleURI( + context, relativeUri); + if (ds != null) { + if (result != null) { + throw new RuntimeException("handleURI for " + context + + " uri: '" + relativeUri + + "' returns ambigious result."); + } + result = ds; + } + } + } + return result; + } + + /* ********************************************************************* */ + + /** + * Adds the new parameter handler to this window. + * + * @param handler + * the parameter handler to add. + */ + public void addParameterHandler(ParameterHandler handler) { + // TODO Subwindow support + if (parameterHandlerList == null) { + parameterHandlerList = new LinkedList(); + } + synchronized (parameterHandlerList) { + if (!parameterHandlerList.contains(handler)) { + parameterHandlerList.addLast(handler); + } + } + } + + /** + * Removes the given URI handler from this window. + * + * @param handler + * the parameter handler to remove. + */ + public void removeParameterHandler(ParameterHandler handler) { + // TODO Subwindow support + if (handler == null || parameterHandlerList == null) { + return; + } + synchronized (parameterHandlerList) { + parameterHandlerList.remove(handler); + if (parameterHandlerList.isEmpty()) { + parameterHandlerList = null; + } + } + } + + /* Documented by the interface */ + public void handleParameters(Map parameters) { + if (parameterHandlerList != null) { + Object[] handlers; + synchronized (parameterHandlerList) { + handlers = parameterHandlerList.toArray(); + } + for (int i = 0; i < handlers.length; i++) { + ((ParameterHandler) handlers[i]).handleParameters(parameters); + } + } + } + + /* ********************************************************************* */ + + /** + * Gets the theme for this window. + * + *

+ * Subwindows do not support themes and thus return theme used by the parent + *

+ * + * @return the Name of the theme used in window. If the theme for this + * individual window is not explicitly set, the application theme is + * used instead. If application is not assigned the + * terminal.getDefaultTheme is used. If terminal is not set, null is + * returned + */ + public String getTheme() { + if (getParent() != null) { + return ((Window) getParent()).getTheme(); + } + if (theme != null) { + return theme; + } + if ((application != null) && (application.getTheme() != null)) { + return application.getTheme(); + } + if (terminal != null) { + return terminal.getDefaultTheme(); + } + return null; + } + + /** + * Sets the theme for this window. + * + * Setting theme for subwindows is not supported. + * + * @param theme + * the New theme for this window. Null implies the default + * theme. + */ + public void setTheme(String theme) { + if (getParent() != null) { + throw new UnsupportedOperationException( + "Setting theme for sub-windws is not supported."); + } + this.theme = theme; + requestRepaint(); + } + + /** + * Paints the content of this component. + * + * @param event + * the Paint Event. + * @throws PaintException + * if the paint operation failed. + */ + public synchronized void paintContent(PaintTarget target) + throws PaintException { + + // Sets the window name + String name = getName(); + target.addAttribute("name", name == null ? "" : name); + + // Sets the window theme + String theme = getTheme(); + target.addAttribute("theme", theme == null ? "" : theme); + + // Marks the main window + if (getApplication() != null + && this == getApplication().getMainWindow()) { + target.addAttribute("main", true); + } + + // Open requested resource + synchronized (openList) { + if (!openList.isEmpty()) { + for (Iterator i = openList.iterator(); i.hasNext();) { + ((OpenResource) i.next()).paintContent(target); + } + openList.clear(); + } + } + + // Contents of the window panel is painted + super.paintContent(target); + + // Window position + target.addVariable(this, "positionx", getPositionX()); + target.addVariable(this, "positiony", getPositionY()); + + // Window position + target.addVariable(this, "scrolltop", getScrollTop()); + target.addVariable(this, "scrollleft", getScrollLeft()); + + // Window closing + target.addVariable(this, "close", false); + + // Sets the focused component + if (focusedComponent != null) { + target.addVariable(this, "focused", "" + + focusedComponent.getFocusableId()); + } else { + target.addVariable(this, "focused", ""); + } + + // Paint subwindows + for (Iterator i = subwindows.iterator(); i.hasNext();) { + Window w = (Window) i.next(); + w.paint(target); + } + + // Paint notifications + if (notifications != null) { + target.startTag("notifications"); + for (Iterator it = notifications.iterator(); it.hasNext();) { + Notification n = (Notification) it.next(); + target.startTag("notification"); + if (n.getCaption() != null) { + target.addAttribute("caption", n.getCaption()); + } + if (n.getMessage() != null) { + target.addAttribute("message", n.getMessage()); + } + target.addAttribute("position", n.getPosition()); + target.addAttribute("delay", n.getDelayMsec()); + if (n.getStyleName() != null) { + target.addAttribute("style", n.getStyleName()); + } + target.endTag("notification"); + } + target.endTag("notifications"); + notifications = null; + } + + } + + /* ********************************************************************* */ + + /** + * Opens the given resource in this window. + * + * @param resource + */ + public void open(Resource resource) { + synchronized (openList) { + if (!openList.contains(resource)) { + openList.add(new OpenResource(resource, null, -1, -1, + BORDER_DEFAULT)); + } + } + requestRepaint(); + } + + /* ********************************************************************* */ + + /** + * Opens the given resource in named terminal window. Empty or + * null window name results the resource to be opened in this + * window. + * + * @param resource + * the resource. + * @param windowName + * the name of the window. + */ + public void open(Resource resource, String windowName) { + synchronized (openList) { + if (!openList.contains(resource)) { + openList.add(new OpenResource(resource, windowName, -1, -1, + BORDER_DEFAULT)); + } + } + requestRepaint(); + } + + /* ********************************************************************* */ + + /** + * Opens the given resource in named terminal window with given size and + * border properties. Empty or null window name results the + * resource to be opened in this window. + * + * @param resource + * @param windowName + * @param width + * @param height + * @param border + */ + public void open(Resource resource, String windowName, int width, + int height, int border) { + synchronized (openList) { + if (!openList.contains(resource)) { + openList.add(new OpenResource(resource, windowName, width, + height, border)); + } + } + requestRepaint(); + } + + /* ********************************************************************* */ + + /** + * Returns the full url of the window, this returns window specific url even + * for the main window. + * + * @return the URL of the window. + */ + public URL getURL() { + + if (application == null) { + return null; + } + + try { + return new URL(application.getURL(), getName() + "/"); + } catch (MalformedURLException e) { + throw new RuntimeException("Internal problem, please report"); + } + } + + /** + * Gets the unique name of the window that indentifies it on the terminal. + * + *

+ * Name identifies the URL used to access application-level windows, but is + * not used for windows inside other windows. all application-level windows + * can be accessed by their names in url + * http://host:port/foo/bar/ where + * http://host:port/foo/ is the application url as returned + * by getURL() and bar is the name of the window. Also note + * that not all windows should be added to application - one can also add + * windows inside other windows - these windows show as smaller windows + * inside those windows. + *

+ * + * @return the Name of the Window. + */ + public String getName() { + return name; + } + + /** + * Returns the border. + * + * @return the border. + */ + public int getBorder() { + return border; + } + + /** + * Sets the border. + * + * @param border + * the border to set. + */ + public void setBorder(int border) { + this.border = border; + } + + /** + * Sets the application this window is connected to. + * + *

+ * This method should not be invoked directly. Instead the + * {@link com.itmill.toolkit.Application#addWindow(Window)} method should be + * used to add the window to an application and + * {@link com.itmill.toolkit.Application#removeWindow(Window)} method for + * removing the window from the applicion. These methods call this method + * implicitly. + *

+ * + *

+ * The method invokes {@link Component#attach()} and + * {@link Component#detach()} methods when necessary. + *

+ * + * @param application + * the application to set. + */ + public void setApplication(Application application) { + + // If the application is not changed, dont do nothing + if (application == this.application) { + return; + } + + // Sends detach event if the window is connected to application + if (this.application != null) { + detach(); + } + + // Connects to new parent + this.application = application; + + // Sends the attach event if connected to a window + if (application != null) { + attach(); + } + } + + /** + * Sets the name. + *

+ * The name of the window must be unique inside the application. + *

+ * + *

+ * If the name is null, the the window is given name automatically when it + * is added to an application. + *

+ * + * @param name + * the name to set. + */ + public void setName(String name) { + + // The name can not be changed in application + if (getApplication() != null) { + throw new IllegalStateException( + "Window name can not be changed while " + + "the window is in application"); + } + + this.name = name; + } + + /** + * Sets the terminal type. The terminal type is set by the the terminal + * adapter and may change from time to time. + * + * @param type + * the terminal type to set. + */ + public void setTerminal(Terminal type) { + terminal = type; + } + + /** + * Window only supports pixels as unit. + * + * @see com.itmill.toolkit.terminal.Sizeable#getHeightUnits() + */ + public void setHeightUnits(int units) { + if (units != Sizeable.UNITS_PIXELS) { + throw new IllegalArgumentException("Only pixels are supported"); + } + } + + /** + * Window only supports pixels as unit. + * + * @see com.itmill.toolkit.terminal.Sizeable#getWidthUnits() + */ + public void setWidthUnits(int units) { + if (units != Sizeable.UNITS_PIXELS) { + throw new IllegalArgumentException("Only pixels are supported"); + } + } + + /** + * Private data structure for storing opening window properties. + */ + private class OpenResource { + + private final Resource resource; + + private final String name; + + private final int width; + + private final int height; + + private final int border; + + /** + * Creates a new open resource. + * + * @param resource + * @param name + * @param width + * @param height + * @param border + */ + private OpenResource(Resource resource, String name, int width, + int height, int border) { + this.resource = resource; + this.name = name; + this.width = width; + this.height = height; + this.border = border; + } + + /** + * Paints the open-tag inside the window. + * + * @param target + * the Paint Event. + * @throws PaintException + * if the Paint Operation fails. + */ + private void paintContent(PaintTarget target) throws PaintException { + target.startTag("open"); + target.addAttribute("src", resource); + if (name != null && name.length() > 0) { + target.addAttribute("name", name); + } + if (width >= 0) { + target.addAttribute("width", width); + } + if (height >= 0) { + target.addAttribute("height", height); + } + switch (border) { + case Window.BORDER_MINIMAL: + target.addAttribute("border", "minimal"); + break; + case Window.BORDER_NONE: + target.addAttribute("border", "none"); + break; + } + + target.endTag("open"); + } + } + + /** + * Called when one or more variables handled by the implementing class are + * changed. + * + * @see com.itmill.toolkit.terminal.VariableOwner#changeVariables(java.lang.Object, + * java.util.Map) + */ + public void changeVariables(Object source, Map variables) { + super.changeVariables(source, variables); + + // Gets the focused component + String focusedId = (String) variables.get("focused"); + if (focusedId != null) { + try { + long id = Long.parseLong(focusedId); + focusedComponent = Window.getFocusableById(id); + } catch (NumberFormatException ignored) { + // We ignore invalid focusable ids + } + } + + // Positioning + Integer positionx = (Integer) variables.get("positionx"); + if (positionx != null) { + int x = positionx.intValue(); + setPositionX(x < 0 ? -1 : x); + } + Integer positiony = (Integer) variables.get("positiony"); + if (positiony != null) { + int y = positiony.intValue(); + setPositionY(y < 0 ? -1 : y); + } + + // Scroll position + Integer scrolltop = (Integer) variables.get("scrolltop"); + if (scrolltop != null) { + int top = scrolltop.intValue(); + setScrollTop(top < 0 ? 0 : top); + } + Integer scrollleft = (Integer) variables.get("scrollleft"); + if (scrollleft != null) { + int left = scrollleft.intValue(); + setScrollLeft(left < 0 ? 0 : left); + } + + // Closing + Boolean close = (Boolean) variables.get("close"); + if (close != null && close.booleanValue()) { + setVisible(false); + fireClose(); + } + } + + /** + * Gets the currently focused component in this window. + * + * @return the Focused component or null if none is focused. + */ + public Component.Focusable getFocusedComponent() { + return focusedComponent; + } + + /** + * Sets the currently focused component in this window. + * + * @param focusable + * the Focused component or null if none is focused. + */ + public void setFocusedComponent(Component.Focusable focusable) { + Application app = getApplication(); + if (app != null) { + app.setFocusedComponent(focusable); + focusedComponent = focusable; + } + } + + /* Focusable id generator ****************************************** */ + + private static long lastUsedFocusableId = 0; + + private static Map focusableComponents = new HashMap(); + + /** + * Gets an id for focusable component. + * + * @param focusable + * the focused component. + */ + public static long getNewFocusableId(Component.Focusable focusable) { + long newId = ++lastUsedFocusableId; + WeakReference ref = new WeakReference(focusable); + focusableComponents.put(new Long(newId), ref); + return newId; + } + + /** + * Maps the focusable id back to focusable component. + * + * @param focusableId + * the Focused Id. + * @return the focusable Id. + */ + public static Component.Focusable getFocusableById(long focusableId) { + WeakReference ref = (WeakReference) focusableComponents.get(new Long( + focusableId)); + if (ref != null) { + Object o = ref.get(); + if (o != null) { + return (Component.Focusable) o; + } + } + return null; + } + + /** + * Releases the focusable component id when not used anymore. + * + * @param focusableId + * the focusable Id to remove. + */ + public static void removeFocusableId(long focusableId) { + Long id = new Long(focusableId); + WeakReference ref = (WeakReference) focusableComponents.get(id); + ref.clear(); + focusableComponents.remove(id); + } + + /** + * Gets the distance of Window left border in pixels from left border of the + * containing (main window). + * + * @return the Distance of Window left border in pixels from left border of + * the containing (main window). or -1 if unspecified. + * @since 4.0.0 + */ + public int getPositionX() { + return positionX; + } + + /** + * Sets the distance of Window left border in pixels from left border of the + * containing (main window). + * + * @param positionX + * the Distance of Window left border in pixels from left + * border of the containing (main window). or -1 if + * unspecified. + * @since 4.0.0 + */ + public void setPositionX(int positionX) { + this.positionX = positionX; + } + + /** + * Gets the distance of Window top border in pixels from top border of the + * containing (main window). + * + * @return Distance of Window top border in pixels from top border of the + * containing (main window). or -1 if unspecified . + * + * @since 4.0.0 + */ + public int getPositionY() { + return positionY; + } + + /** + * Sets the distance of Window top border in pixels from top border of the + * containing (main window). + * + * @param positionY + * the Distance of Window top border in pixels from top + * border of the containing (main window). or -1 if + * unspecified + * + * @since 4.0.0 + */ + public void setPositionY(int positionY) { + this.positionY = positionY; + } + + private static final Method WINDOW_CLOSE_METHOD; + static { + try { + WINDOW_CLOSE_METHOD = CloseListener.class.getDeclaredMethod( + "windowClose", new Class[] { CloseEvent.class }); + } catch (java.lang.NoSuchMethodException e) { + // This should never happen + throw new java.lang.RuntimeException(); + } + } + + public class CloseEvent extends Component.Event { + + /** + * Serial generated by eclipse. + */ + private static final long serialVersionUID = -7235770057344367327L; + + /** + * + * @param source + */ + public CloseEvent(Component source) { + super(source); + } + + /** + * Gets the Window. + * + * @return the window. + */ + public Window getWindow() { + return (Window) getSource(); + } + } + + public interface CloseListener { + public void windowClose(CloseEvent e); + } + + /** + * Adds the listener. + * + * @param listener + * the listener to add. + */ + public void addListener(CloseListener listener) { + addListener(CloseEvent.class, listener, WINDOW_CLOSE_METHOD); + } + + /** + * Removes the listener. + * + * @param listener + * the listener to remove. + */ + public void removeListener(CloseListener listener) { + addListener(CloseEvent.class, listener, WINDOW_CLOSE_METHOD); + } + + protected void fireClose() { + fireEvent(new Window.CloseEvent(this)); + } + + /** + * Adds a new window inside another window. + * + *

+ * Adding windows inside another window creates "subwindows". These windows + * should not be added to application directly and are not accessible + * directly with any url. Addding windows implicitly sets their parents. + *

+ * + *

+ * Only one level of subwindows are supported. Thus you can add windows + * inside such windows whose parent is null. + *

+ * + * @param window + * @throws IllegalArgumentException + * if a window is added inside non-application level window. + * @throws NullPointerException + * if the given Window is null. + */ + public void addWindow(Window window) throws IllegalArgumentException, + NullPointerException { + + if (getParent() != null) { + throw new IllegalArgumentException( + "You can only add windows inside application-level windows"); + } + + if (window == null) { + throw new NullPointerException("Argument must not be null"); + } + + subwindows.add(window); + window.setParent(this); + requestRepaint(); + } + + /** + * Remove the given subwindow from this window. + * + * @param window + * Window to be removed. + */ + public void removeWindow(Window window) { + subwindows.remove(window); + window.setParent(null); + requestRepaint(); + + } + + /** + * Get the set of all child windows. + * + * @return Set of child windows. + */ + public Set getChildWindows() { + return Collections.unmodifiableSet(subwindows); + } + + /** + * Gets the current vertical scroll position of window. + * + * @return pixels scrolled from top + */ + public int getScrollTop() { + return scrollTop; + } + + /** + * Scrolls window to given position. + * + * @param scrollTop + * pixels to be scrolled from top + */ + public void setScrollTop(int scrollTop) { + this.scrollTop = scrollTop; + } + + /** + * Gets the current horizontal scroll position of window. + * + * @return pixels scrolled from left + */ + public int getScrollLeft() { + return scrollLeft; + } + + /** + * Scrolls window to given position. + * + * @param scrollLeft + * pixels to be scrolled from left + */ + public void setScrollLeft(int scrollLeft) { + this.scrollLeft = scrollLeft; + } + + public void showNotification(String message) { + addNotification(new Notification(message)); + } + + public void showNotification(String message, int type) { + addNotification(new Notification(message, type)); + } + + public void showNotification(String caption, String message, int type) { + addNotification(new Notification(caption, message, type)); + } + + public void showNotification(Notification notification) { + addNotification(notification); + } + + private void addNotification(Notification notification) { + if (notifications == null) { + notifications = new LinkedList(); + } + notifications.add(notification); + requestRepaint(); + } + + public class Notification { + public static final int TYPE_HUMANIZED_MESSAGE = 1; + public static final int TYPE_WARNING_MESSAGE = 2; + public static final int TYPE_ERROR_MESSAGE = 3; + public static final int TYPE_TRAY_NOTIFICATION = 4; + + public static final int POSITION_CENTERED = 1; + public static final int POSITION_CENTERED_TOP = 2; + public static final int POSITION_CENTERED_BOTTOM = 3; + public static final int POSITION_TOP_LEFT = 4; + public static final int POSITION_TOP_RIGHT = 5; + public static final int POSITION_BOTTOM_LEFT = 6; + public static final int POSITION_BOTTOM_RIGHT = 7; + + public static final int DELAY_FOREVER = -1; + public static final int DELAY_NONE = 0; + + private String caption; + private String message; + private Resource icon; + private int position = POSITION_CENTERED; + private int delayMsec = 0; + private String styleName; + + public Notification(String message) { + this(null, message, TYPE_HUMANIZED_MESSAGE); + } + + public Notification(String message, int type) { + this(null, message, type); + } + + public Notification(String caption, String message, int type) { + this.caption = caption; + this.message = message; + setType(type); + } + + private void setType(int type) { + switch (type) { + case TYPE_WARNING_MESSAGE: + delayMsec = 1500; + styleName = "warning"; + break; + case TYPE_ERROR_MESSAGE: + delayMsec = -1; + styleName = "error"; + break; + case TYPE_TRAY_NOTIFICATION: + delayMsec = 3000; + position = POSITION_BOTTOM_RIGHT; + styleName = "tray"; + + case TYPE_HUMANIZED_MESSAGE: + default: + break; + } + + } + + public String getCaption() { + return caption; + } + + public void setCaption(String caption) { + this.caption = caption; + } + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } + + public int getPosition() { + return position; + } + + public void setPosition(int position) { + this.position = position; + } + + public Resource getIcon() { + return icon; + } + + public void setIcon(Resource icon) { + this.icon = icon; + } + + public int getDelayMsec() { + return delayMsec; + } + + public void setDelayMsec(int delayMsec) { + this.delayMsec = delayMsec; + } + + public void setStyleName(String styleName) { + this.styleName = styleName; + } + + public String getStyleName() { + return styleName; + } + } } -- 2.39.5