View Javadoc

1   /*
2      Copyright 2002-2006 Martin van den Bemt
3   
4      Licensed under the Apache License, Version 2.0 (the "License");
5      you may not use this file except in compliance with the License.
6      You may obtain a copy of the License at
7   
8          http://www.apache.org/licenses/LICENSE-2.0
9   
10     Unless required by applicable law or agreed to in writing, software
11     distributed under the License is distributed on an "AS IS" BASIS,
12     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13     See the License for the specific language governing permissions and
14     limitations under the License.
15  */
16  package org.xulux.guilayer.swing.widgets;
17  
18  import java.awt.Container;
19  import java.awt.Dimension;
20  import java.util.StringTokenizer;
21  
22  import javax.swing.JTextField;
23  import javax.swing.text.JTextComponent;
24  
25  import org.xulux.api.dataprovider.IConverter;
26  import org.xulux.api.dataprovider.IDataProvider;
27  import org.xulux.api.dataprovider.IField;
28  import org.xulux.api.dataprovider.IMapping;
29  import org.xulux.api.dataprovider.InvalidValueException;
30  import org.xulux.api.gui.IInvalidValueStrategy;
31  import org.xulux.api.gui.IXuluxListener;
32  import org.xulux.core.XuluxContext;
33  import org.xulux.dataprovider.Dictionary;
34  import org.xulux.gui.utils.ColorUtils;
35  import org.xulux.guilayer.swing.SwingWidget;
36  import org.xulux.guilayer.swing.listeners.PrePostFieldListener;
37  import org.xulux.utils.BooleanUtils;
38  import org.xulux.utils.ClassLoaderUtils;
39  
40  /**
41   * Represents an entry field
42   *
43   * @author <a href="mailto:martin@mvdb.net">Martin van den Bemt</a>
44   * @version $Id: Entry.java,v 1.1 2005/12/18 12:58:18 mvdb Exp $
45   */
46  public class Entry extends SwingWidget {
47      /**
48       * The dimensions
49       */
50      private Dimension size;
51      /**
52       * is setValue called ?
53       */
54      protected boolean setValueCalled = false;
55  
56      /**
57       * A textcomponent allows overriding by
58       * similar classes.
59       */
60      protected JTextComponent textComponent;
61  
62      /**
63       * The focuslistener
64       */
65      protected PrePostFieldListener focusListener;
66      /**
67       * the immidiatelistener
68       */
69      protected PrePostFieldListener immidiateListener;
70      /**
71       * the value class
72       */
73      protected Class valueClass;
74  
75      /**
76       * Constructor for Entry.
77       * @param name the name of the entry
78       */
79      public Entry(String name) {
80          super(name);
81      }
82  
83      /**
84       * @see org.xulux.api.gui.IWidget#destroy()
85       */
86      public void destroy() {
87          processDestroy();
88          removeAllRules();
89          if (textComponent != null) {
90              textComponent.removeAll();
91              Container container = textComponent.getParent();
92              if (container != null) {
93                  container.remove(textComponent);
94              }
95              textComponent = null;
96          }
97          if (getPart() != null) {
98            getPart().removeWidget(this, this);
99          }
100         initialized = false;
101     }
102 
103     /**
104      * @see org.xulux.api.gui.IWidget#getNativeWidget()
105      */
106     public Object getNativeWidget() {
107         if (!initialized) {
108             initialize();
109         }
110         return textComponent;
111     }
112 
113     /**
114      * @see org.xulux.api.gui.IWidget#setProperty(java.lang.String, java.lang.Object)
115      */
116     public void setProperty(String key, Object value) {
117       if (key != null) {
118         key = key.toLowerCase();
119       }
120       if (key != null && key.equals("valueclass")) {
121           setLazyProperty(key, value);
122           if (value != null) {
123             if (value instanceof String) {
124               this.valueClass = ClassLoaderUtils.getClass((String) value);
125             } else if (value instanceof Class) {
126               this.valueClass = (Class) value;
127             } else {
128               this.valueClass = value.getClass();
129             }
130           } else {
131             this.valueClass = null;
132           }
133       } else {
134           super.setProperty(key, value);
135       }
136     }
137 
138     /**
139      * @see org.xulux.api.gui.IWidget#initialize()
140      */
141     public void initialize() {
142         if (this.initialized) {
143             return;
144         }
145         this.initialized = true;
146         this.setValueCalled = true;
147         textComponent = (JTextComponent) processNativeWidget(new JTextField());
148         if (isImmidiate()) {
149             if (this.immidiateListener == null) {
150                 IXuluxListener listener = getPart().getFieldEventHandler(this);
151                 if (listener != null) {
152                     this.immidiateListener = (PrePostFieldListener) listener;
153                 } else {
154                     this.immidiateListener = new PrePostFieldListener(this);
155                 }
156             }
157         }
158         if (isVisible()) {
159             if (focusListener == null) {
160                 IXuluxListener listener = getPart().getFieldEventHandler(this);
161                 if (listener == null) {
162                     focusListener = (PrePostFieldListener) listener;
163                 } else {
164                     focusListener = new PrePostFieldListener(this);
165                 }
166                 textComponent.addFocusListener(focusListener);
167             }
168         }
169         initInitialValue();
170         initializeValue();
171         refresh();
172         processInit();
173         this.setValueCalled = false;
174     }
175 
176     /**
177      * Initializes the initial value, if any.
178      *
179      */
180     protected void initInitialValue() {
181         String iv = getProperty("initialvalue");
182         if (iv != null) {
183             String ivType = getProperty("initialvalue.type");
184             if (ivType != null && ivType.equals("field")) {
185                 IMapping mapping = XuluxContext.getDictionary().getDefaultProvider().getMapping(getPart().getBean());
186                 if (mapping != null) {
187                     IField field = mapping.getField(iv);
188                     if (field != null) {
189                         this.value = field.getValue(getPart().getBean());
190                         textComponent.setText(String.valueOf(this.value));
191                     }
192                 }
193             } else if (ivType == null || ivType.equals("string")) {
194                 this.value = iv;
195                 textComponent.setText(iv);
196             }
197         }
198     }
199 
200 
201     /**
202      * @see org.xulux.api.gui.IWidget#refresh()
203      */
204     public void refresh() {
205         isRefreshing = true;
206         initialize();
207         initializeValue();
208         textComponent.setEnabled(isEnabled());
209         textComponent.setVisible(isVisible());
210         textComponent.setPreferredSize(this.size);
211         String backgroundColor = null;
212         if (isRequired() && isEnabled()) {
213             backgroundColor = getProperty("required-background-color");
214         } else if (!isEnabled()) {
215             backgroundColor = getProperty("disabled-background-color");
216         }
217         if (backgroundColor == null) {
218             backgroundColor = getProperty("default-background-color");
219         }
220         if (backgroundColor != null) {
221             textComponent.setBackground(ColorUtils.getSwingColor(backgroundColor));
222         }
223 
224         String foreGroundColor = null;
225         if (isRequired() && isEnabled()) {
226             foreGroundColor = getProperty("required-foreground-color");
227         } else if (!isEnabled()) {
228             foreGroundColor = getProperty("disabled-foreground-color");
229             if (foreGroundColor != null) {
230                 textComponent.setDisabledTextColor(ColorUtils.getSwingColor(foreGroundColor));
231                 foreGroundColor = null;
232             }
233         }
234         if (foreGroundColor == null) {
235             foreGroundColor = getProperty("default-foreground-color");
236         }
237         if (foreGroundColor != null) {
238             textComponent.setForeground(ColorUtils.getSwingColor(foreGroundColor));
239         }
240         if (getField() != null && getField().startsWith("?")) {
241             initializeValue();
242         }
243         if (getProperty("enabled.depends") != null) {
244             String value = getProperty("enabled.depends");
245             Object depValue = getPart().getWidget(value).getValue();
246             if (depValue != null) {
247                 setEnabled(BooleanUtils.toBoolean(depValue.toString()));
248             } else {
249                 setEnabled(false);
250             }
251         }
252         textComponent.repaint();
253         textComponent.setCaretPosition(0);
254         isRefreshing = false;
255     }
256 
257     /**
258      * @see org.xulux.api.gui.IWidget#getValue()
259      */
260     public Object getValue() {
261         if (getField() != null) {
262           if (getProperty("converter.class") != null) {
263               IConverter converter = (IConverter) ClassLoaderUtils.getObjectFromClassString(getProperty("converter.class"));
264               if (converter != null) {
265                   return converter.getBeanValue(this.value);
266               }
267           }
268         }
269         return this.value;
270     }
271 
272     /**
273      * Lets changes reflect onscreen.
274      * @param value
275      * @todo Make this all utility classes, since this is a lot of code reproducing !
276     
277      */
278     protected void initializeValue() {
279         if (getProvider() != null) {
280             IDataProvider pr = XuluxContext.getDictionary().getProvider(getProvider());
281             IMapping mapping = null;
282             if (pr.needsPartValue()) {
283                 if (getField() != null) {
284               		mapping = pr.getMapping(getPart().getBean());
285                 }
286             } else {
287               	mapping = pr.getMapping(this.value);
288             }
289             IField field = null;
290             if (mapping != null) {
291 	            if (getField() != null) {
292 	                field = mapping.getField(getField());
293 	            } else {
294                     field = mapping.getField(this.value);
295 	            }
296             }
297             if (field != null) {
298               if (pr.needsPartValue()) {
299                 textComponent.setText((String) field.getValue(getPart().getBean()));
300               } else {
301                 String val = (String) field.getValue(this.value);
302                 if (val == null) {
303                     val = "";
304                 }
305                 textComponent.setText(val);
306               }
307             } else {
308               textComponent.setText("");
309             }
310             return;
311         } else if (getField() == null) {
312             if (getValue() != null) {
313                 if (getProperty("entryfields") != null) {
314                     String entryFields = getProperty("entryfields");
315                     String entryValue = "";
316                     IMapping mapping = XuluxContext.getDictionary().getDefaultProvider().getMapping(getValue());
317                     StringTokenizer stn = new StringTokenizer(entryFields, ",");
318                     while (stn.hasMoreTokens()) {
319                         String token = stn.nextToken();
320                         String strPart = "";
321                         IField iField = mapping.getField(token);
322                         if (iField != null) {
323                             strPart = iField.getValue(getValue()).toString();
324                         } else {
325                             //allow seperators in the field list.
326                             strPart = token;
327                         }
328                         entryValue += strPart;
329                     }
330                     textComponent.setText(String.valueOf(entryValue));
331                     return;
332                 }
333                 IConverter converter = null;
334                 if (getProperty("converter.class") != null) {
335                     converter = (IConverter) ClassLoaderUtils.getObjectFromClassString(getProperty("converter.class"));
336                 } else {
337                     converter = Dictionary.getConverter(getValue());
338                 }
339                 if (converter != null) {
340                     textComponent.setText((String) converter.getGuiValue(getValue()));
341                 } else {
342                     textComponent.setText(String.valueOf(getValue()));
343                 }
344             } else {
345                 textComponent.setText("");
346             }
347             return;
348         }
349         Object bean = null;
350         String tmpField = null;
351         if (getField().startsWith("?")) {
352             int dotIndex = getField().indexOf('.');
353             if (dotIndex != -1) {
354                 bean = getPart().getWidget(getField().substring(1, dotIndex)).getValue();
355                 if (bean == null) {
356                     textComponent.setText("");
357                     return;
358                 } else {
359                   tmpField = getField().substring(dotIndex+1);
360                 }
361             }
362         }
363         if (bean == null) {
364             bean = getPart().getBean();
365         }
366         IMapping map = XuluxContext.getDictionary().getDefaultProvider().getMapping(bean);
367         if (map == null) {
368             textComponent.setText("");
369             return;
370         }
371         IField field = null;
372         if (tmpField == null) {
373           field = map.getField(getField());
374         } else {
375           field = map.getField(tmpField);
376         }
377         if (field == null) {
378             System.out.println("Field " + getField() + " is not present in the dictionary");
379             System.out.println("NyxWidget : " + getName());
380             textComponent.setText("");
381             return;
382         }
383         Object beanValue = field.getValue(bean);
384         this.value = beanValue;
385         if (this.value == null) {
386             textComponent.setText("");
387         } else {
388             // we assume toString method here.
389             // @todo Implement fields some more so it can be a combination of fields that turn up here.
390 
391             // If this is not an array, do a toString
392             if (!this.value.getClass().isArray()) {
393                 IConverter converter = Dictionary.getConverter(this.value);
394                 if (converter != null) {
395                     textComponent.setText((String) converter.getGuiValue(this.value));
396                 } else {
397                     textComponent.setText(this.value.toString());
398                 }
399             } else {
400                 textComponent.setText("Invalid : Array");
401             }
402         }
403     }
404 
405     /**
406      * @see org.xulux.api.gui.IWidget#setValue(java.lang.Object)
407      */
408     public void setValue(Object object) {
409         if (this.valueClass == null && getProperty("valueclass") != null) {
410             this.valueClass = ClassLoaderUtils.getClass(getProperty("valueclass"));
411         }
412         // if there is no field present
413         // we set the value passed in
414         // and check to see if the field
415         // needs updating or not.
416         if (getProvider() != null) {
417           IDataProvider pr = XuluxContext.getDictionary().getProvider(getProvider());
418           IMapping mapping = null;
419           IField field = null;
420           if (!(object instanceof String) && this.value == null) {
421             this.value = object;
422           } else {
423             mapping = pr.getMapping(this.value);
424             if (getField() != null) {
425                 field = mapping.getField(getField());
426             } else {
427                 field = mapping.getField(this.value);
428             }
429             try {
430               field.setValue(this.value, object);
431               setValidValue(true);
432             } catch(InvalidValueException ive) {
433                 IInvalidValueStrategy strategy = getPart().getInvalidValueStrategy();
434                 if (strategy != null) {
435                     strategy.handleInvalidValueException(this, ive);
436                 }
437             }
438           }
439         } else if (getField() == null) {
440             if (object != null) {
441                 if (valueClass != null && !valueClass.isAssignableFrom(object.getClass())) {
442                     IConverter converter = null;
443                     if (getProperty("converter.class") != null) {
444                         converter = (IConverter) ClassLoaderUtils.getObjectFromClassString(getProperty("converter.class"));
445                     } else {
446                         converter = Dictionary.getConverter(valueClass);
447                     }
448                     if (converter != null) {
449                         object = converter.getBeanValue(object);
450                     }
451                 }
452             }
453             if (object != this.value) {
454                 this.previousValue = this.value;
455             }
456             this.value = object;
457         } else {
458             IMapping map = XuluxContext.getDictionary().getDefaultProvider().getMapping(getPart().getBean());
459             if (map != null) {
460                 IField field = map.getField(getField());
461                 // set the previous value
462                 if (field != null) {
463                     this.previousValue = field.getValue(getPart().getBean());
464                     IConverter converter = Dictionary.getConverter(field.getType());
465                     if (converter != null) {
466                         object = converter.getBeanValue(object);
467                     }
468                     field.setValue(getPart().getBean(), object);
469                 }
470             }
471         }
472         if (initialized) {
473             initializeValue();
474         }
475     }
476 
477     /**
478      * @see org.xulux.api.gui.IWidget#clear()
479      */
480     public void clear() {
481         this.value = null;
482         if (textComponent != null) {
483             textComponent.setText("");
484         }
485         if (initialized) {
486             refresh();
487         }
488     }
489 
490     /**
491      * @see org.xulux.api.gui.IWidget#getGuiValue()
492      */
493     public Object getGuiValue() {
494         if (!initialized) {
495             initialize();
496         }
497         return textComponent.getText();
498     }
499 
500     /**
501      * @see org.xulux.api.gui.IWidget#canContainValue()
502      */
503     public boolean canContainValue() {
504         return true;
505     }
506 
507     /**
508      * @see org.xulux.api.gui.IWidget#isValueEmpty()
509      */
510     public boolean isValueEmpty() {
511         if (getGuiValue() == null || getGuiValue().equals("")) {
512             return true;
513         }
514         return false;
515     }
516 
517     /**
518      * @see org.xulux.api.gui.IWidget#addXuluxListener(org.xulux.api.gui.IXuluxListener)
519      */
520     public void addXuluxListener(IXuluxListener listener) {
521     }
522 
523 }