summaryrefslogtreecommitdiffstats
path: root/src/com/vaadin/ui/CustomComponent.java
blob: 21eda0890982417b2d1a9d1d8e6d9fcaeded16ed (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
/* 
@VaadinApache2LicenseForJavaFiles@
 */

package com.vaadin.ui;

import java.io.Serializable;
import java.util.Iterator;

import com.vaadin.terminal.PaintException;
import com.vaadin.terminal.PaintTarget;
import com.vaadin.terminal.gwt.client.ui.VCustomComponent;
import com.vaadin.ui.ClientWidget.LoadStyle;

/**
 * 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 Vaadin Ltd.
 * @version
 * @VERSION@
 * @since 3.0
 */
@SuppressWarnings("serial")
@ClientWidget(value = VCustomComponent.class, loadStyle = LoadStyle.EAGER)
public class CustomComponent extends AbstractComponentContainer {

    /**
     * The root component implementing the custom component.
     */
    private Component root = null;

    /**
     * Type of the component.
     */
    private String componentType = null;

    /**
     * Constructs a 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() {
        // expand horizontally by default
        setWidth(100, UNITS_PERCENTAGE);
    }

    /**
     * Constructs a 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) {
        this();
        setCompositionRoot(compositionRoot);
    }

    /**
     * Returns the composition root.
     * 
     * @return the Component Composition root.
     */
    protected 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 void setCompositionRoot(Component compositionRoot) {
        if (compositionRoot != root) {
            if (root != null) {
                // remove old component
                super.removeComponent(root);
            }
            if (compositionRoot != null) {
                // set new component
                super.addComponent(compositionRoot);
            }
            root = compositionRoot;
            requestRepaint();
        }
    }

    /* Basic component features ------------------------------------------ */

    @Override
    public void paintContent(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 (getComponentType() != null) {
            target.addAttribute("type", getComponentType());
        }
        root.paint(target);
    }

    /**
     * Gets the component type.
     * 
     * The component type is textual type of the component. This is included in
     * the UIDL as component tag attribute.
     * 
     * @deprecated not more useful as the whole tag system has been removed
     * 
     * @return the component type.
     */
    @Deprecated
    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.
     * 
     * @deprecated not more useful as the whole tag system has been removed
     * 
     * @param componentType
     *            the componentType to set.
     */
    @Deprecated
    public void setComponentType(String componentType) {
        this.componentType = componentType;
    }

    private class ComponentIterator implements Iterator<Component>,
            Serializable {
        boolean first = getCompositionRoot() != null;

        public boolean hasNext() {
            return first;
        }

        public Component next() {
            first = false;
            return root;
        }

        public void remove() {
            throw new UnsupportedOperationException();
        }
    }

    public Iterator<Component> getComponentIterator() {
        return new ComponentIterator();
    }

    /**
     * Gets the number of contained components. Consistent with the iterator
     * returned by {@link #getComponentIterator()}.
     * 
     * @return the number of contained components (zero or one)
     */
    public int getComponentCount() {
        return (root != null ? 1 : 0);
    }

    /**
     * This method is not supported by CustomComponent.
     * 
     * @see com.vaadin.ui.ComponentContainer#replaceComponent(com.vaadin.ui.Component,
     *      com.vaadin.ui.Component)
     */
    public void replaceComponent(Component oldComponent, Component newComponent) {
        throw new UnsupportedOperationException();
    }

    /**
     * This method is not supported by CustomComponent. Use
     * {@link CustomComponent#setCompositionRoot(Component)} to set
     * CustomComponents "child".
     * 
     * @see com.vaadin.ui.AbstractComponentContainer#addComponent(com.vaadin.ui.Component)
     */
    @Override
    public void addComponent(Component c) {
        throw new UnsupportedOperationException();
    }

    /**
     * This method is not supported by CustomComponent.
     * 
     * @see com.vaadin.ui.AbstractComponentContainer#moveComponentsFrom(com.vaadin.ui.ComponentContainer)
     */
    @Override
    public void moveComponentsFrom(ComponentContainer source) {
        throw new UnsupportedOperationException();
    }

    /**
     * This method is not supported by CustomComponent.
     * 
     * @see com.vaadin.ui.AbstractComponentContainer#removeAllComponents()
     */
    @Override
    public void removeAllComponents() {
        throw new UnsupportedOperationException();
    }

    /**
     * This method is not supported by CustomComponent.
     * 
     * @see com.vaadin.ui.AbstractComponentContainer#removeComponent(com.vaadin.ui.Component)
     */
    @Override
    public void removeComponent(Component c) {
        throw new UnsupportedOperationException();
    }

}