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
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
|
/* *************************************************************************
IT Mill Toolkit
Development of Browser User Interfaces 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.pdf. Use of this product might
require purchasing a commercial license from IT Mill Ltd. For guidelines
on usage, see 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.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;
/**
* 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.
*
* <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() {
}
/**
* 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) {
setCompositionRoot(compositionRoot);
}
/**
* Returns the composition root.
*
* @return the 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);
}
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) {
}
}
|