aboutsummaryrefslogtreecommitdiffstats
path: root/src/com/itmill/toolkit/ui/CustomComponent.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/com/itmill/toolkit/ui/CustomComponent.java')
-rw-r--r--src/com/itmill/toolkit/ui/CustomComponent.java387
1 files changed, 387 insertions, 0 deletions
diff --git a/src/com/itmill/toolkit/ui/CustomComponent.java b/src/com/itmill/toolkit/ui/CustomComponent.java
new file mode 100644
index 0000000000..1df4abc134
--- /dev/null
+++ b/src/com/itmill/toolkit/ui/CustomComponent.java
@@ -0,0 +1,387 @@
+/* *************************************************************************
+
+ IT Mill Toolkit
+
+ Development of Browser User Intarfaces Made Easy
+
+ Copyright (C) 2000-2006 IT Mill Ltd
+
+ *************************************************************************
+
+ This product is distributed under commercial license that can be found
+ from the product package on license/license.txt. Use of this product might
+ require purchasing a commercial license from IT Mill Ltd. For guidelines
+ on usage, see license/licensing-guidelines.html
+
+ *************************************************************************
+
+ For more information, contact:
+
+ IT Mill Ltd phone: +358 2 4802 7180
+ Ruukinkatu 2-4 fax: +358 2 4802 7181
+ 20540, Turku email: info@itmill.com
+ Finland company www: www.itmill.com
+
+ Primary source for information and releases: www.itmill.com
+
+ ********************************************************************** */
+
+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;
+import java.util.Set;
+
+import com.itmill.toolkit.Application;
+import com.itmill.toolkit.terminal.PaintException;
+import com.itmill.toolkit.terminal.PaintTarget;
+import com.itmill.toolkit.terminal.Resource;
+import com.itmill.toolkit.terminal.VariableOwner;
+
+/** Custom component provides simple implementation of Component interface for
+ * creation of new UI components by composition of existing components.
+ * <p>The component is used by inheriting the CustomComponent class and setting
+ * composite root inside the Custom component. The composite root itself
+ * can contain more components, but their interfaces are hidden from the
+ * users.</p>
+ *
+ * @author IT Mill Ltd.
+ * @version @VERSION@
+ * @since 3.0
+ */
+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;
+
+ /** Dependencies of the component, or null */
+ private HashSet dependencies = 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;
+
+ /** Construct new custom component.
+ *
+ * <p>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.</p>
+ */
+ public CustomComponent() {
+ }
+
+ /** Construct new custom component.
+ *
+ * <p>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.</p>
+ *
+ * @param compositionRoot The root of the composition component tree.
+ */
+ public CustomComponent(Component compositionRoot) {
+ setCompositionRoot(compositionRoot);
+ }
+
+ /** Returns the composition root.
+ * @return Component Composition root
+ */
+ protected final Component getCompositionRoot() {
+ return root;
+ }
+
+ /** Sets the compositions root.
+ * <p>The composition root must be set to non-null value before the
+ * component can be used. The composition root can only be set once.</p>
+ * @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 ------------------------------------------ */
+
+ public void attach() {
+ if (root != null)
+ root.attach();
+ }
+
+ public void detach() {
+ if (root != null)
+ root.detach();
+ }
+
+ public Application getApplication() {
+ if (parent == null)
+ return null;
+ return parent.getApplication();
+ }
+
+ /** The caption of the custom component is by default the the
+ * caption of the root component, or null if the root is not set
+ */
+ public String getCaption() {
+ if (root == null)
+ return null;
+ return root.getCaption();
+ }
+
+ /** The icon of the custom component is by default the the
+ * icon of the root component, or null if the root is not set
+ */
+ public Resource getIcon() {
+ if (root == null)
+ return null;
+ return root.getIcon();
+ }
+
+ /** The icon of the custom component is by default the the
+ * locale of the parent or null if the parent is not set.
+ */
+ public Locale getLocale() {
+ if (parent == null)
+ return null;
+ return parent.getLocale();
+ }
+
+ public Component getParent() {
+ return parent;
+ }
+
+ /** Custom component does not implement custom styles by default and
+ * this function returns null.
+ */
+ public String getStyle() {
+ return null;
+ }
+
+ public Window getWindow() {
+ if (parent == null)
+ return null;
+ return parent.getWindow();
+ }
+
+ /** Custom component is allways enabled by default */
+ 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.
+ */
+ public boolean isImmediate() {
+ return false;
+ }
+
+ /** The custom components are not readonly by default. */
+ public boolean isReadOnly() {
+ return false;
+ }
+
+ 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) {
+ }
+
+ 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();
+ }
+
+ /** Changing the read-only mode of the component is not supported by default.
+ */
+ public void setReadOnly(boolean readOnly) {
+ }
+
+ /** Changing the style of the component is not supported by default.
+ */
+ public void setStyle(String style) {
+ }
+
+ 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;
+ }
+
+ /** The custom component does not have any variables by default */
+ public void changeVariables(Object source, Map variables) {
+ }
+
+ public void dependsOn(VariableOwner depended) {
+ if (depended == null)
+ return;
+ if (dependencies == null)
+ dependencies = new HashSet();
+ dependencies.add(depended);
+ }
+
+ public Set getDirectDependencies() {
+ return dependencies;
+ }
+
+ public void removeDirectDependency(VariableOwner depended) {
+ if (dependencies == null)
+ return;
+ dependencies.remove(depended);
+ if (dependencies.isEmpty())
+ dependencies = null;
+ }
+
+ /* Event functions are not implemented by default -------------------- */
+
+ /** Custom component does not implement any component events by default */
+ public void addListener(Component.Listener listener) {
+ }
+
+ /** Custom component does not implement any component events by default */
+ 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.
+ *
+ * Returns the componentType.
+ * @return String
+ */
+ 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;
+ }
+
+}