1   /****************************************************************************
2    **
3    ** This file is part of yFiles-2.6. 
4    ** 
5    ** yWorks proprietary/confidential. Use is subject to license terms.
6    **
7    ** Redistribution of this file or of an unauthorized byte-code version
8    ** of this file is strictly forbidden.
9    **
10   ** Copyright (c) 2000-2008 by yWorks GmbH, Vor dem Kreuzberg 28, 
11   ** 72070 Tuebingen, Germany. All rights reserved.
12   **
13   ***************************************************************************/
14  package demo.view.anim;
15  
16  import y.io.GMLIOHandler;
17  import y.io.IOHandler;
18  import y.io.YGFIOHandler;
19  import y.option.CompoundEditor;
20  import y.option.ConstraintManager;
21  import y.option.DefaultEditorFactory;
22  import y.option.Editor;
23  import y.option.EnumOptionItem;
24  import y.option.GuiFactory;
25  import y.option.ItemEditor;
26  import y.option.OptionGroup;
27  import y.option.OptionHandler;
28  import y.option.OptionItem;
29  import y.util.D;
30  import y.view.Graph2D;
31  import y.view.Graph2DView;
32  import y.view.ViewAnimationFactory;
33  
34  import javax.swing.AbstractAction;
35  import javax.swing.Action;
36  import javax.swing.BorderFactory;
37  import javax.swing.DefaultListCellRenderer;
38  import javax.swing.JButton;
39  import javax.swing.JComponent;
40  import javax.swing.JList;
41  import javax.swing.JPanel;
42  import javax.swing.JTable;
43  import javax.swing.ListCellRenderer;
44  import javax.swing.table.DefaultTableCellRenderer;
45  import javax.swing.table.TableCellRenderer;
46  import java.awt.BorderLayout;
47  import java.awt.Color;
48  import java.awt.Component;
49  import java.awt.FlowLayout;
50  import java.awt.GridBagConstraints;
51  import java.awt.GridBagLayout;
52  import java.awt.event.ActionEvent;
53  import java.io.IOException;
54  import java.net.URL;
55  import java.net.URLDecoder;
56  import java.util.HashMap;
57  import java.util.Iterator;
58  import java.util.Map;
59  
60  /**
61   * Provides the GUI and option handling for <code>AnimationEffectsDemo</code>.
62   * Cannot be used for anything else.
63   *
64   * @see AnimationEffectsDemo
65   */
66  abstract class AnimationEffectsDemoBase
67  {
68    static final byte NO_ANIM  = (byte)0;
69  
70    static final byte BLUR_IN  = (byte)11;
71    static final byte FADE_IN  = (byte)12;
72    static final byte IMPLODE  = (byte)13;
73    static final byte WHIRL_IN = (byte)14;
74  
75    static final byte EXTRACT   = (byte)15;
76  
77    static final byte BLUR_OUT  = (byte)21;
78    static final byte FADE_OUT  = (byte)22;
79    static final byte EXPLODE   = (byte)23;
80    static final byte WHIRL_OUT = (byte)24;
81  
82    static final byte RETRACT   = (byte)25;
83  
84    static final byte TRAVERSE_EDGE  = (byte)31;
85    static final byte ZOOM           = (byte)32;
86    static final byte MOVE_CAMERA    = (byte)33;
87    static final byte MORPH          = (byte)34;
88    static final byte RESIZE         = (byte)35;
89    static final byte BLINK          = (byte)36;
90    static final byte ANIMATED_LOAD  = (byte)37;
91    static final byte ANIMATED_CLEAR = (byte)38;
92  
93  
94    static final String DEMO_NAME;
95    static
96    {
97      String name = AnimationEffectsDemo.class.getName();
98      name = name.substring(name.lastIndexOf('.')+1);
99      DEMO_NAME = name;
100   }
101 
102 
103   final Graph2DView view;
104   final GuiFactory i18n;
105   final OptionHandler oh;
106   boolean compoundAction;
107 
108   private final boolean wantsRadioButtons;
109 
110   /**
111    * Creates a new AnimationEffectsDemoBase.
112    * @param i18n   localization data
113    * @param wantsRadioButtons
114    */
115   AnimationEffectsDemoBase( final GuiFactory i18n,
116                             final boolean wantsRadioButtons )
117   {
118     this.wantsRadioButtons = wantsRadioButtons;
119     this.view = new Graph2DView();
120     this.i18n = i18n;
121     this.oh = createOptionHandler();
122     this.compoundAction = false;
123   }
124 
125   abstract void animate();
126 
127   void selectAllEdges()
128   {
129     final Graph2D graph = view.getGraph2D();
130     graph.setSelected(graph.edges(), true);
131   }
132 
133   void openGraph( final String resource )
134   {
135     final URL url = getClass().getResource(resource);
136     if (url != null)
137     {
138       final Graph2D graph = view.getGraph2D();
139       graph.clear();
140 
141       try
142       {
143         final String name = URLDecoder.decode(url.getFile(), "UTF-8");
144         getIoHandlerByExt(name).read(graph, name);
145       }
146       catch (IOException ioe)
147       {
148         D.show(ioe);
149       }
150 
151       view.fitContent();
152     }
153     else
154     {
155       final java.io.File file = new java.io.File(resource);
156       if (file.exists())
157       {
158         final Graph2D graph = view.getGraph2D();
159         graph.clear();
160 
161         try
162         {
163           final String name = file.getAbsolutePath();
164           getIoHandlerByExt(name).read(graph, name);
165         }
166         catch (IOException ioe)
167         {
168           D.show(ioe);
169         }
170 
171         view.fitContent();
172       }
173       else
174       {
175         try
176         {
177           throw new Exception("Cannot locate file: " + resource);
178         }
179         catch (Exception ex)
180         {
181           D.show(ex);
182         }
183       }
184     }
185   }
186 
187   void localizeAction( final Action action, final String key )
188   {
189     action.putValue(Action.NAME, i18n.getString(key));
190     action.putValue(Action.SHORT_DESCRIPTION,
191                     i18n.getString(key + ".shortDescription"));
192     final java.net.URL iconUrl =
193             getClass().getResource(i18n.getString(key + ".smallIcon"));
194     if (iconUrl != null)
195     {
196       action.putValue(Action.SMALL_ICON, new javax.swing.ImageIcon(iconUrl));
197     }
198   }
199 
200 
201   /**
202    * Creates an OptionHandler.
203    */
204   private OptionHandler createOptionHandler()
205   {
206     final OptionHandler oh = new OptionHandler(DEMO_NAME);
207 
208     final ConstraintManager cm = new ConstraintManager(oh);
209 
210     OptionGroup group;
211     OptionGroup section;
212     OptionItem item;
213 
214 
215     final Byte noAnim       = new Byte(NO_ANIM);
216 
217 
218     oh.useSection("elements");
219     section = new OptionGroup();
220     section.setAttribute(OptionGroup.ATTRIBUTE_TITLE, "elements");
221 
222     final Byte blurIn  = new Byte(BLUR_IN);
223     final Byte fadeIn  = new Byte(FADE_IN);
224     final Byte implode = new Byte(IMPLODE);
225     final Byte whirlIn = new Byte(WHIRL_IN);
226 
227     final Byte blurOut  = new Byte(BLUR_OUT);
228     final Byte fadeOut  = new Byte(FADE_OUT);
229     final Byte explode  = new Byte(EXPLODE);
230     final Byte whirlOut = new Byte(WHIRL_OUT);
231 
232     final Byte extract  = new Byte(EXTRACT);
233     final Byte retract  = new Byte(RETRACT);
234 
235     final ElementsRenderer elementsRenderer = new ElementsRenderer();
236     item = oh.addEnum("createNode", new Byte[] {noAnim, blurIn,  fadeIn,  implode, whirlIn}, 4);
237     item.setAttribute(EnumOptionItem.ATTRIBUTE_RENDERER, elementsRenderer);
238     section.addItem(item);
239     item = oh.addEnum("deleteNode", new Byte[] {noAnim, blurOut, fadeOut, explode, whirlOut}, 1);
240     item.setAttribute(EnumOptionItem.ATTRIBUTE_RENDERER, elementsRenderer);
241     section.addItem(item);
242     item = oh.addEnum("createEdge", new Byte[] {noAnim, blurIn,  fadeIn,  implode, extract}, 2);
243     item.setAttribute(EnumOptionItem.ATTRIBUTE_RENDERER, elementsRenderer);
244     section.addItem(item);
245     item = oh.addEnum("deleteEdge", new Byte[] {noAnim, blurOut, fadeOut, explode, retract}, 4);
246     item.setAttribute(EnumOptionItem.ATTRIBUTE_RENDERER, elementsRenderer);
247     section.addItem(item);
248 
249     oh.useSection("misc");
250     section = new OptionGroup();
251 
252     final Byte animatedClear = new Byte(ANIMATED_CLEAR);
253     final Byte animatedLoad  = new Byte(ANIMATED_LOAD);
254     final Byte traverseEdge  = new Byte(TRAVERSE_EDGE);
255     final Byte zoom          = new Byte(ZOOM);
256     final Byte moveCamera    = new Byte(MOVE_CAMERA);
257     final Byte morph         = new Byte(MORPH);
258     final Byte resize        = new Byte(RESIZE);
259     final Byte blink         = new Byte(BLINK);
260 
261     item = oh.addEnum("animation", new Byte[]{
262             animatedLoad, animatedClear,
263             traverseEdge, zoom, moveCamera,
264             morph, resize, blink
265     }, 2);
266     item.setAttribute(DefaultEditorFactory.ATTRIBUTE_CONTROLLER_ID,
267                       DEMO_NAME + "Base.animation");
268     item.setAttribute(EnumOptionItem.ATTRIBUTE_RENDERER,
269                       new AnimationRenderer());
270     item.setAttribute(DefaultEditorFactory.ATTRIBUTE_ENUM_STYLE,
271                       wantsRadioButtons
272                       ? DefaultEditorFactory.STYLE_RADIO_BUTTONS
273                       : DefaultEditorFactory.STYLE_COMBO_BOX);
274     section.addItem(item);
275 
276     final OrderRenderer orderRenderer = new OrderRenderer();
277     final Object[] order = {
278             ViewAnimationFactory.LEFT_TO_RIGHT,
279             ViewAnimationFactory.RIGHT_TO_LEFT,
280             ViewAnimationFactory.CLOCKWISE,
281             ViewAnimationFactory.COUNTER_CLOCKWISE
282     };
283 
284     group = new OptionGroup();
285     group.setAttribute(OptionGroup.ATTRIBUTE_TITLE, "misc_animation_properties");
286     group.setAttribute(DefaultEditorFactory.ATTRIBUTE_CONTROLLER_ID,
287                        DEMO_NAME + "Base.animation");
288     group.setAttribute(DefaultEditorFactory.ATTRIBUTE_CARD_ID, animatedLoad.toString());
289     item = oh.addEnum("animateLoad_graph", new String[]{"big", "small"}, 0);
290     item.setAttribute(DefaultEditorFactory.ATTRIBUTE_ENUM_STYLE,
291                       DefaultEditorFactory.STYLE_RADIO_BUTTONS);
292     group.addItem(item);
293     item = oh.addEnum("animateLoad_nodeOrder", order, 0);
294     item.setAttribute(EnumOptionItem.ATTRIBUTE_RENDERER, orderRenderer);
295     group.addItem(item);
296     group.addItem(oh.addBool("animateLoad_obeyEdgeDirection", false));
297     group.addItem(oh.addDouble("animateLoad_ratio", 0.15, 0.1, 1.0));
298     cm.setEnabledOnValueEquals("animation", animatedLoad, group);
299 
300     group = new OptionGroup();
301     group.setAttribute(OptionGroup.ATTRIBUTE_TITLE, "misc_animation_properties");
302     group.setAttribute(DefaultEditorFactory.ATTRIBUTE_CONTROLLER_ID,
303                        DEMO_NAME + "Base.animation");
304     group.setAttribute(DefaultEditorFactory.ATTRIBUTE_CARD_ID, animatedClear.toString());
305     item = oh.addEnum("animateClear_nodeOrder", order, 0);
306     item.setAttribute(EnumOptionItem.ATTRIBUTE_RENDERER, orderRenderer);
307     group.addItem(item);
308     group.addItem(oh.addBool("animateClear_obeyEdgeDirection", false));
309     group.addItem(oh.addDouble("animateClear_ratio", 0.15, 0.1, 1.0));
310     cm.setEnabledOnValueEquals("animation", animatedClear, group);
311 
312     group = new OptionGroup();
313     group.setAttribute(OptionGroup.ATTRIBUTE_TITLE, "misc_animation_properties");
314     group.setAttribute(DefaultEditorFactory.ATTRIBUTE_CONTROLLER_ID,
315                        DEMO_NAME + "Base.animation");
316     group.setAttribute(DefaultEditorFactory.ATTRIBUTE_CARD_ID, traverseEdge.toString());
317 
318     group.addItem(oh.addColor("colorVisited", Color.RED, true, true, false, false));
319     group.addItem(oh.addColor("colorUnvisited", Color.BLACK, true, true, false, false));
320     cm.setEnabledOnValueEquals("animation", traverseEdge, group);
321     addItems(group, section);
322 
323     group = new OptionGroup();
324     group.setAttribute(OptionGroup.ATTRIBUTE_TITLE, "misc_animation_properties");
325     group.setAttribute(DefaultEditorFactory.ATTRIBUTE_CONTROLLER_ID,
326                        DEMO_NAME + "Base.animation");
327     group.setAttribute(DefaultEditorFactory.ATTRIBUTE_CARD_ID, zoom.toString());
328 
329     group.addItem(oh.addDouble("zoom_factor", 1.0, 0.1, 16.0));
330     cm.setEnabledOnValueEquals("animation", zoom, group);
331 
332     group = new OptionGroup();
333     group.setAttribute(OptionGroup.ATTRIBUTE_TITLE, "misc_animation_properties");
334     group.setAttribute(DefaultEditorFactory.ATTRIBUTE_CONTROLLER_ID,
335                        DEMO_NAME + "Base.animation");
336     group.setAttribute(DefaultEditorFactory.ATTRIBUTE_CARD_ID, morph.toString());
337 
338     group.addItem(oh.addDouble("translateX", 50));
339     group.addItem(oh.addDouble("translateY", 50));
340     group.addItem(oh.addDouble("width", 100));
341     group.addItem(oh.addDouble("height", 25));
342     group.addItem(oh.addColor("fillColor", Color.RED, true, true, false, false));
343     group.addItem(oh.addColor("fillColor2", Color.GREEN, true, true, false, false));
344     group.addItem(oh.addColor("lineColor", Color.BLACK, true, true, false, false));
345     cm.setEnabledOnValueEquals("animation", morph, group);
346     addItems(group, section);
347 
348     group = new OptionGroup();
349     group.setAttribute(OptionGroup.ATTRIBUTE_TITLE, "misc_animation_properties");
350     group.setAttribute(DefaultEditorFactory.ATTRIBUTE_CONTROLLER_ID,
351                        DEMO_NAME + "Base.animation");
352     group.setAttribute(DefaultEditorFactory.ATTRIBUTE_CARD_ID, resize.toString());
353 
354     group.addItem(oh.addDouble("resize_width", 100));
355     group.addItem(oh.addDouble("resize_height", 100));
356     cm.setEnabledOnValueEquals("animation", resize, group);
357     addItems(group, section);
358 
359     group = new OptionGroup();
360     group.setAttribute(OptionGroup.ATTRIBUTE_TITLE, "misc_animation_properties");
361     group.setAttribute(DefaultEditorFactory.ATTRIBUTE_CONTROLLER_ID,
362                        DEMO_NAME + "Base.animation");
363     group.setAttribute(DefaultEditorFactory.ATTRIBUTE_CARD_ID, blink.toString());
364 
365     group.addItem(oh.addInt("repetitions", 1, 1, 25));
366     cm.setEnabledOnValueEquals("animation", blink, group);
367     addItems(group, section);
368 
369     oh.useSection("global");
370     oh.addDouble("speed", 1.0, 0.25, 4.0, 2);
371 
372     return oh;
373   }
374 
375   private JComponent createControlPane()
376   {
377     final DefaultEditorFactory editorFactory = new DefaultEditorFactory();
378     editorFactory.setGuiFactory(i18n);
379 
380     final Map attributes = new HashMap();
381     final Editor editor = editorFactory.createEditor(oh, attributes);
382     setAutoAdopt(true, editor);
383     setAutoCommit(true, editor);
384 
385     final JPanel buttonPane = new JPanel(new FlowLayout(FlowLayout.LEADING));
386     buttonPane.add(new JButton(createAnimateAction()));
387 
388     JPanel spacer = new JPanel();
389     final JPanel pane = new JPanel(new GridBagLayout());
390 
391     int row = 0;
392 
393     final GridBagConstraints gbc = new GridBagConstraints();
394     gbc.fill = GridBagConstraints.HORIZONTAL;
395     gbc.anchor = GridBagConstraints.WEST;
396 
397     {
398       final CompoundEditor ce = (CompoundEditor)editor;
399       for (int i = 0, n = ce.editorCount()-2; i < n; ++i)
400       {
401         gbc.gridy = row++;
402         pane.add(ce.getEditor(i).getComponent(), gbc);
403       }
404       // special case for last two editors:
405       // misc section and animation speed setting
406       {
407         final GridBagConstraints compoundConstraints = new GridBagConstraints();
408         final JPanel compoundPane = new JPanel(new GridBagLayout());
409         compoundPane.setBorder(
410                 BorderFactory.createTitledBorder(
411                         i18n.getString(DEMO_NAME + ".GROUP.misc")));
412 
413         compoundConstraints.fill = GridBagConstraints.HORIZONTAL;
414         compoundConstraints.anchor = GridBagConstraints.NORTHWEST;
415         compoundConstraints.gridy = 0;
416         compoundConstraints.gridwidth = 2;
417         compoundConstraints.weightx = 1.0;
418         compoundPane.add(ce.getEditor(ce.editorCount()-2).getComponent(),
419                          compoundConstraints);
420 
421         compoundConstraints.fill = GridBagConstraints.BOTH;
422         compoundConstraints.anchor = GridBagConstraints.WEST;
423         compoundConstraints.gridy = 1;
424         compoundConstraints.weighty = 1.0;
425         compoundPane.add(spacer, compoundConstraints);
426 
427         compoundConstraints.gridy = 2;
428         compoundConstraints.gridwidth = 1;
429         compoundConstraints.anchor = GridBagConstraints.SOUTHWEST;
430         compoundPane.add(buttonPane, compoundConstraints);
431 
432         compoundConstraints.gridx = 1;
433         compoundPane.add(ce.getEditor(ce.editorCount()-1).getComponent(),
434                          compoundConstraints);
435 
436         gbc.gridy = row++;
437         pane.add(compoundPane, gbc);
438       }
439     }
440 
441     spacer = new JPanel();
442     gbc.fill = GridBagConstraints.BOTH;
443     gbc.gridy = row;
444     gbc.weighty = 0.75;
445     pane.add(spacer, gbc);
446 
447     return pane;
448   }
449 
450   JComponent createContentPane()
451   {
452     final JPanel pane = new JPanel(new BorderLayout());
453     pane.add(createControlPane(), BorderLayout.WEST);
454     pane.add(view, BorderLayout.CENTER);
455     return pane;
456   }
457 
458   private Action createAnimateAction()
459   {
460     final Action action = new AbstractAction()
461     {
462       public void actionPerformed( final ActionEvent e )
463       {
464         animate();
465       }
466     };
467     localizeAction(action, DEMO_NAME + ".action.Animate");
468 
469     return action;
470   }
471 
472   private IOHandler getIoHandlerByExt( final String filename )
473   {
474     if (filename.endsWith(".gml"))
475     {
476       return new GMLIOHandler();
477     }
478     else if (filename.endsWith(".ygf"))
479     {
480       return new YGFIOHandler();
481     }
482     else
483     {
484       throw new IllegalArgumentException("Unsupported file format: " + filename);
485     }
486   }
487 
488 
489   private static void addItems( final OptionGroup src, final OptionGroup tgt )
490   {
491     for (Iterator it = src.items(); it.hasNext();)
492     {
493       tgt.addItem((OptionItem)it.next());
494     }
495   }
496 
497   /**
498    * Sets the <code>autoCommit</code> property to the specified value,
499    * if the specified editor support setting said property.
500    */
501   private static void setAutoCommit( final boolean autoCommit,
502                                      final Editor editor )
503   {
504     if ( editor instanceof CompoundEditor )
505     {
506       for ( Iterator it = ((CompoundEditor)editor).editors(); it.hasNext(); )
507       {
508         setAutoCommit( autoCommit, (Editor)it.next() );
509       }
510     }
511     if ( editor instanceof ItemEditor )
512     {
513       ((ItemEditor)editor).setAutoCommit( autoCommit );
514     }
515   }
516 
517   /**
518    * Sets the <code>autoAdopt</code> property for all items of the specified
519    * option handler.
520    */
521   private static void setAutoAdopt( final boolean autoAdopt,
522                                     final Editor editor )
523   {
524     if ( editor instanceof CompoundEditor )
525     {
526       for ( Iterator it = ((CompoundEditor)editor).editors(); it.hasNext(); )
527       {
528         setAutoAdopt( autoAdopt, (Editor)it.next() );
529       }
530     }
531     if ( editor instanceof ItemEditor )
532     {
533       ((ItemEditor)editor).setAutoAdopt( autoAdopt );
534     }
535   }
536 
537 
538   private abstract class I18nRenderer
539           implements ListCellRenderer, TableCellRenderer
540   {
541     private final DefaultListCellRenderer listDelegate;
542     private final DefaultTableCellRenderer tableDelegate;
543 
544     I18nRenderer()
545     {
546       this.listDelegate  = new DefaultListCellRenderer();
547       this.tableDelegate = new DefaultTableCellRenderer();
548     }
549 
550     public Component getListCellRendererComponent( final JList list,
551                                                    final Object value,
552                                                    final int index,
553                                                    final boolean isSelected,
554                                                    final boolean hasFocus )
555     {
556       return listDelegate.getListCellRendererComponent(list, toString(value),
557                                                        index,
558                                                        isSelected, hasFocus);
559     }
560 
561     public Component getTableCellRendererComponent( final JTable table,
562                                                     final Object value,
563                                                     final boolean isSelected,
564                                                     final boolean hasFocus,
565                                                     final int row,
566                                                     final int column )
567     {
568       return tableDelegate.getTableCellRendererComponent(table, toString(value),
569                                                          isSelected, hasFocus,
570                                                          row, column);
571     }
572 
573     abstract String toString( final Object value );
574   }
575 
576   private final class ElementsRenderer extends I18nRenderer
577   {
578     String toString( final Object animation )
579     {
580       switch (((Byte)animation).byteValue())
581       {
582         case NO_ANIM:
583           return i18n.getString(DEMO_NAME + ".elements.VALUE.noAnimation");
584         case BLUR_IN:
585           return i18n.getString(DEMO_NAME + ".elements.VALUE.blurIn");
586         case FADE_IN:
587           return i18n.getString(DEMO_NAME + ".elements.VALUE.fadeIn");
588         case IMPLODE:
589           return i18n.getString(DEMO_NAME + ".elements.VALUE.implode");
590         case WHIRL_IN:
591           return i18n.getString(DEMO_NAME + ".elements.VALUE.whirlIn");
592         case EXTRACT:
593           return i18n.getString(DEMO_NAME + ".elements.VALUE.extract");
594         case BLUR_OUT:
595           return i18n.getString(DEMO_NAME + ".elements.VALUE.blurOut");
596         case FADE_OUT:
597           return i18n.getString(DEMO_NAME + ".elements.VALUE.fadeOut");
598         case EXPLODE:
599           return i18n.getString(DEMO_NAME + ".elements.VALUE.explode");
600         case WHIRL_OUT:
601           return i18n.getString(DEMO_NAME + ".elements.VALUE.whirlOut");
602         case RETRACT:
603           return i18n.getString(DEMO_NAME + ".elements.VALUE.retract");
604         default:
605           // this should never happen
606           return "";
607       }
608     }
609   }
610 
611   private final class AnimationRenderer extends I18nRenderer
612   {
613     String toString( final Object animation )
614     {
615       switch (((Byte)animation).byteValue())
616       {
617         case NO_ANIM:
618           return i18n.getString(DEMO_NAME + ".misc.animation.VALUE.noAnimation");
619         case TRAVERSE_EDGE:
620           return i18n.getString(DEMO_NAME + ".misc.animation.VALUE.traverseEdge");
621         case ZOOM:
622           return i18n.getString(DEMO_NAME + ".misc.animation.VALUE.zoom");
623         case MOVE_CAMERA:
624           return i18n.getString(DEMO_NAME + ".misc.animation.VALUE.moveCamera");
625         case MORPH:
626           return i18n.getString(DEMO_NAME + ".misc.animation.VALUE.morph");
627         case RESIZE:
628           return i18n.getString(DEMO_NAME + ".misc.animation.VALUE.resize");
629         case BLINK:
630           return i18n.getString(DEMO_NAME + ".misc.animation.VALUE.blink");
631         case ANIMATED_LOAD:
632           return i18n.getString(DEMO_NAME + ".misc.animation.VALUE.animatedLoad");
633         case ANIMATED_CLEAR:
634           return i18n.getString(DEMO_NAME + ".misc.animation.VALUE.animatedClear");
635         default:
636           return i18n.getString(DEMO_NAME + ".misc.animation.VALUE.noAnimation");
637       }
638     }
639   }
640 
641   private final class OrderRenderer extends I18nRenderer
642   {
643     String toString( final Object nodeOrder )
644     {
645       if (nodeOrder == ViewAnimationFactory.LEFT_TO_RIGHT)
646       {
647         return i18n.getString("ViewAnimationFactory.LEFT_TO_RIGHT");
648       }
649       if (nodeOrder == ViewAnimationFactory.RIGHT_TO_LEFT)
650       {
651         return i18n.getString("ViewAnimationFactory.RIGHT_TO_LEFT");
652       }
653       if (nodeOrder == ViewAnimationFactory.CLOCKWISE)
654       {
655         return i18n.getString("ViewAnimationFactory.CLOCKWISE");
656       }
657       if (nodeOrder == ViewAnimationFactory.COUNTER_CLOCKWISE)
658       {
659         return i18n.getString("ViewAnimationFactory.COUNTER_CLOCKWISE");
660       }
661       // this should never happen
662       return null;
663     }
664   }
665 }
666