Source Code Cross Referenced for JGraphEditorComboBox.java in  » Graphic-Library » jgraphpad » com » jgraph » editor » factory » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Graphic Library » jgraphpad » com.jgraph.editor.factory 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /* 
002:         * $Id: JGraphEditorComboBox.java,v 1.2 2007/03/25 13:13:16 gaudenz Exp $
003:         * Copyright (c) 2001-2005, Gaudenz Alder
004:         * 
005:         * All rights reserved.
006:         * 
007:         * See LICENSE file for license details. If you are unable to locate
008:         * this file please contact info (at) jgraph (dot) com.
009:         */
010:        package com.jgraph.editor.factory;
011:
012:        import java.awt.Color;
013:        import java.awt.Component;
014:        import java.awt.Dimension;
015:        import java.awt.Graphics;
016:        import java.awt.Point;
017:        import java.awt.event.ActionEvent;
018:        import java.awt.event.ActionListener;
019:        import java.awt.geom.Rectangle2D;
020:        import java.util.Hashtable;
021:        import java.util.LinkedList;
022:        import java.util.List;
023:        import java.util.Map;
024:
025:        import javax.swing.BorderFactory;
026:        import javax.swing.Icon;
027:        import javax.swing.JComboBox;
028:        import javax.swing.JComponent;
029:        import javax.swing.JLabel;
030:        import javax.swing.JList;
031:        import javax.swing.ListCellRenderer;
032:        import javax.swing.border.Border;
033:
034:        import org.jgraph.JGraph;
035:        import org.jgraph.graph.AttributeMap;
036:        import org.jgraph.graph.CellView;
037:        import org.jgraph.graph.CellViewRenderer;
038:        import org.jgraph.graph.DefaultGraphModel;
039:        import org.jgraph.graph.EdgeRenderer;
040:        import org.jgraph.graph.EdgeView;
041:        import org.jgraph.graph.GraphConstants;
042:        import org.jgraph.graph.VertexView;
043:        import org.w3c.dom.Node;
044:
045:        import com.jgraph.editor.JGraphEditorAction;
046:
047:        /**
048:         * Combo box for selecting cell styles. The class provides a series of factory
049:         * methods to be added to an editor factory. The following methods are provided:
050:         * {@link BorderComboFactoryMethod}, {@link LineDecorationComboFactoryMethod}
051:         * and {@link LineWidthComboFactoryMethod}.
052:         */
053:        public class JGraphEditorComboBox extends JComboBox {
054:
055:            /**
056:             * Default array of borders.
057:             */
058:            public static Border[] defaultBorders = new Border[] {
059:                    BorderFactory.createRaisedBevelBorder(),
060:                    BorderFactory.createLoweredBevelBorder(),
061:                    BorderFactory.createEtchedBorder(),
062:                    BorderFactory.createLineBorder(Color.black) };
063:
064:            /**
065:             * Default array of widths.
066:             */
067:            public static float[] defaultWidths = new float[] { 1, 2, 3, 4, 5,
068:                    6, 8 };
069:
070:            /**
071:             * Default array of patterns.
072:             */
073:            protected static float[][] defaultPatterns = new float[][] {
074:                    new float[] { 1, 1 }, new float[] { 2, 2 },
075:                    new float[] { 4, 2 }, new float[] { 4, 4 },
076:                    new float[] { 8, 2 }, new float[] { 8, 4 },
077:                    new float[] { 4, 4, 16, 4 } };
078:
079:            /**
080:             * Default array of fillable arrows.
081:             */
082:            public static int[] defaultFillableDecorations = new int[] {
083:                    GraphConstants.ARROW_CLASSIC,
084:                    GraphConstants.ARROW_TECHNICAL,
085:                    GraphConstants.ARROW_DIAMOND, GraphConstants.ARROW_CIRCLE };
086:
087:            /**
088:             * Default array or arrows.
089:             */
090:            public static int[] defaultDecorations = new int[] {
091:                    GraphConstants.ARROW_CLASSIC, GraphConstants.ARROW_SIMPLE,
092:                    GraphConstants.ARROW_TECHNICAL,
093:                    GraphConstants.ARROW_DIAMOND, GraphConstants.ARROW_CIRCLE,
094:                    GraphConstants.ARROW_LINE, GraphConstants.ARROW_DOUBLELINE };
095:
096:            /**
097:             * Shared graph instance for rendering.
098:             */
099:            protected static JGraph backingGraph = new JGraph(
100:                    new DefaultGraphModel());
101:
102:            /**
103:             * Initial view attributes for restoring.
104:             */
105:            protected AttributeMap initialAttributes;
106:
107:            /**
108:             * Constructs a new combo box for the specified attribute maps. Uses an edge
109:             * view for preview of <code>edgePreview</code> is true, otherwise a
110:             * vertex view is used.
111:             * 
112:             * @param attributes
113:             *            The array of attributes for the combo box entries.
114:             * @param edgePreview
115:             *            Whether to use an edge for preview.
116:             */
117:            public JGraphEditorComboBox(Map[] attributes, boolean edgePreview) {
118:                this (attributes, null, edgePreview);
119:            }
120:
121:            /**
122:             * Constructs a new combo box for the specified attribute maps. Uses an edge
123:             * view for preview if <code>edgePreview</code> is true, otherwise a
124:             * vertex view is used.
125:             * 
126:             * @param attributes
127:             *            The array of attributes for the combo box entries.
128:             * @param view
129:             *            The cell view to use for previewing the attributes.
130:             * @param edgePreview
131:             *            Whether to use an edge for preview.
132:             */
133:            public JGraphEditorComboBox(Map[] attributes, CellView view,
134:                    boolean edgePreview) {
135:                super (attributes);
136:                setOpaque(false);
137:                if (view == null)
138:                    view = (edgePreview) ? createEdgeView()
139:                            : createVertexView();
140:                initialAttributes = new AttributeMap(view.getAttributes());
141:                GraphConstants.setRemoveAll(initialAttributes, true);
142:                setRenderer(new CellViewRendererBridge(view));
143:                setMinimumSize(new Dimension(44, 20));
144:                setPreferredSize(new Dimension(44, 20));
145:                setMaximumSize(new Dimension(44, 20));
146:            }
147:
148:            /**
149:             * Returns a new vertex to be used for preview. This implementation returns
150:             * a {@link VertexView} with a string user object.
151:             * 
152:             * @return Returns a new vertex view for preview.
153:             */
154:            protected CellView createVertexView() {
155:                VertexView view = new VertexView("");
156:                Dimension dim = getVertexViewSize();
157:                Rectangle2D bounds = new Rectangle2D.Double(0, 0, dim.width,
158:                        dim.height);
159:                GraphConstants.setBounds(view.getAttributes(), bounds);
160:                return view;
161:            }
162:
163:            /**
164:             * Hook for subclassers to modify the size of the vertex view.
165:             * 
166:             * @return Returns the size of the vertex view.
167:             */
168:            protected Dimension getVertexViewSize() {
169:                return new Dimension(18, 18);
170:            }
171:
172:            /**
173:             * Returns a new edge to be used for preview. This implementation returns a
174:             * {@link JGraphComboEdgeView} with a string user object and a set of
175:             * default points.
176:             * 
177:             * @return Returns a new edge view for preview.
178:             */
179:            protected CellView createEdgeView() {
180:                EdgeView view = new JGraphComboEdgeView(" ");
181:                List points = new LinkedList();
182:                points.add(new Point(2, 6));
183:                points.add(new Point(14, 6));
184:                GraphConstants.setPoints(view.getAttributes(), points);
185:                GraphConstants.setBeginSize(view.getAttributes(), 8);
186:                GraphConstants.setEndSize(view.getAttributes(), 8);
187:                return view;
188:            }
189:
190:            /**
191:             * Returns the backing graph which is used for rendering previews.
192:             * 
193:             * @return Returns the backing graph.
194:             */
195:            public static JGraph getBackingGraph() {
196:                return backingGraph;
197:            }
198:
199:            /**
200:             * Sets the backing graph which should be used for rendering previews.
201:             * 
202:             * @param backingGraph
203:             *            The backing graph to set.
204:             */
205:            public static void setBackingGraph(JGraph backingGraph) {
206:                JGraphEditorComboBox.backingGraph = backingGraph;
207:            }
208:
209:            /**
210:             * This class returns the renderer of the view configured for the selected
211:             * combo box item. Note: If the map contains an icon then this renderer (a
212:             * JLabel) with the icon is returned.
213:             */
214:            public class CellViewRendererBridge extends JLabel implements 
215:                    ListCellRenderer {
216:
217:                /**
218:                 * Reference to the view this renderer bridge uses for rendering.
219:                 */
220:                protected CellView view = null;
221:
222:                /**
223:                 * Constructs a new renderer bridge using <code>view</code> to render
224:                 * the list entries.
225:                 * 
226:                 * @param view
227:                 *            The view to renderer the list entries with.
228:                 */
229:                public CellViewRendererBridge(CellView view) {
230:                    setHorizontalAlignment(CENTER);
231:                    setVerticalAlignment(CENTER);
232:                    this .view = view;
233:                }
234:
235:                /**
236:                 * Returns a configured renderer for the specified value.
237:                 * 
238:                 * @param list
239:                 *            The list that contains the entry.
240:                 * @param value
241:                 *            The value to be rendered.
242:                 * @param index
243:                 *            The index of the value.
244:                 * @param isSelected
245:                 *            Whether the value should be rendered as selected.
246:                 * @param hasFocus
247:                 *            Whether the value should be renderer as focused.
248:                 * @return Returns a renderer for the specified value.
249:                 */
250:                public Component getListCellRendererComponent(JList list,
251:                        Object value, int index, boolean isSelected,
252:                        boolean hasFocus) {
253:                    Icon icon = null;
254:                    if (value instanceof  Map) {
255:                        Map map = (Map) value;
256:                        icon = GraphConstants.getIcon(map);
257:                        if (icon == null) {
258:                            view.getAllAttributes().clear();
259:                            view.changeAttributes(backingGraph
260:                                    .getGraphLayoutCache(), initialAttributes);
261:                            view.changeAttributes(backingGraph
262:                                    .getGraphLayoutCache(), map);
263:                        }
264:                    }
265:                    if (icon != null) {
266:                        setIcon(icon);
267:                        return this ;
268:                    } else {
269:                        Component r = view.getRendererComponent(backingGraph,
270:                                isSelected, hasFocus, false);
271:                        if (r instanceof  JComponent) {
272:                            final JComponent c = (JComponent) r;
273:                            final Dimension d = new Dimension((int) view
274:                                    .getBounds().getWidth(), (int) view
275:                                    .getBounds().getHeight());
276:
277:                            // Returns an outer renderer that may be freely sized by the
278:                            // combo rendering process. The component paints the cell
279:                            // view renderer at the size of the contained cell view.
280:                            JComponent wrapper = new JComponent() {
281:
282:                                /**
283:                                 * Paints the cell view renderer at the correct size.
284:                                 * 
285:                                 * @param g
286:                                 *            The graphics to paint the inner renderer
287:                                 *            on.
288:                                 */
289:                                public void paint(Graphics g) {
290:                                    c.setBounds(0, 0, d.width, d.height);
291:                                    c.paint(g);
292:                                }
293:
294:                            };
295:                            wrapper.setMinimumSize(d);
296:                            wrapper.setPreferredSize(d);
297:                            return wrapper;
298:                        }
299:                        return r;
300:                    }
301:                }
302:            }
303:
304:            /**
305:             * This class provides a an edge view with a special renderer.
306:             */
307:            protected static class JGraphComboEdgeView extends EdgeView {
308:
309:                /**
310:                 * Holds the custom renderer.
311:                 */
312:                protected static CellViewRenderer renderer = new JGraphComboEdgeRenderer();
313:
314:                /**
315:                 * Constructs an empty vertex view.
316:                 */
317:                public JGraphComboEdgeView() {
318:                    super ();
319:                }
320:
321:                /**
322:                 * Constructs a new combo edge view for the specified cell.
323:                 * 
324:                 * @param cell
325:                 *            The cell to create the edge view for.
326:                 */
327:                public JGraphComboEdgeView(Object cell) {
328:                    super (cell);
329:                }
330:
331:                /**
332:                 * Returns the custom renderer for this view.
333:                 * 
334:                 * @return Returns the custom renderer.
335:                 */
336:                public CellViewRenderer getRenderer() {
337:                    return renderer;
338:                }
339:
340:            }
341:
342:            /**
343:             * This class removes the translate call in the paint method. This is
344:             * required to render a list cell.
345:             */
346:            protected static class JGraphComboEdgeRenderer extends EdgeRenderer {
347:
348:                /**
349:                 * Overrides parent method to avoid translating the graphics before
350:                 * painting.
351:                 * 
352:                 * @param g
353:                 *            The graphics object to avoid translation for.
354:                 */
355:                protected void translateGraphics(Graphics g) {
356:                    // do not translate
357:                }
358:            }
359:
360:            /**
361:             * Provides a factory method to construct a border combo box.
362:             */
363:            public static class BorderComboFactoryMethod extends
364:                    JGraphEditorFactoryMethod {
365:
366:                /**
367:                 * Defines the default name for factory methods of this kind.
368:                 */
369:                public static String NAME = "createBorderCombo";
370:
371:                /**
372:                 * Constructs a new border combo factory method using {@link #NAME}.
373:                 */
374:                public BorderComboFactoryMethod() {
375:                    super (NAME);
376:                }
377:
378:                /**
379:                 * Returns a new border combo box for <code>configuration</code>.
380:                 * 
381:                 * @param configuration
382:                 *            The configuration to use for creating the combo box.
383:                 */
384:                public Component createInstance(Node configuration) {
385:                    Map[] attrs = new Hashtable[defaultBorders.length + 1];
386:                    attrs[0] = new Hashtable();
387:                    GraphConstants
388:                            .setRemoveAttributes(attrs[0], new Object[] {
389:                                    GraphConstants.BORDER,
390:                                    GraphConstants.BORDERCOLOR });
391:                    for (int i = 0; i < defaultBorders.length; i++) {
392:                        attrs[i + 1] = new Hashtable(2);
393:                        GraphConstants.setBorder(attrs[i + 1],
394:                                defaultBorders[i]);
395:                    }
396:                    JGraphEditorComboBox comboBox = new JGraphEditorComboBox(
397:                            attrs, false);
398:                    comboBox.addActionListener(new ComboBoxListener());
399:                    comboBox.setFocusable(false);
400:                    return comboBox;
401:                }
402:
403:            }
404:
405:            /**
406:             * Provides a factory method to construct a linewidth combo box.
407:             */
408:            public static class LineWidthComboFactoryMethod extends
409:                    JGraphEditorFactoryMethod {
410:
411:                /**
412:                 * Defines the default name for factory methods of this kind.
413:                 */
414:                public static String NAME = "createLineWidthCombo";
415:
416:                /**
417:                 * Constructs a new line width combo factory method using {@link #NAME}.
418:                 */
419:                public LineWidthComboFactoryMethod() {
420:                    super (NAME);
421:                }
422:
423:                /**
424:                 * Returns a new linewidth combo box for <code>configuration</code>.
425:                 * 
426:                 * @param configuration
427:                 *            The configuration to use for creating the combo box.
428:                 */
429:                public Component createInstance(Node configuration) {
430:                    Map[] attrs = new Hashtable[defaultWidths.length];
431:                    for (int i = 0; i < defaultWidths.length; i++) {
432:                        attrs[i] = new Hashtable(2);
433:                        GraphConstants.setLineWidth(attrs[i], defaultWidths[i]);
434:                    }
435:                    JGraphEditorComboBox comboBox = new JGraphEditorComboBox(
436:                            attrs, true);
437:                    comboBox.addActionListener(new ComboBoxListener());
438:                    comboBox.setFocusable(false);
439:                    return comboBox;
440:                }
441:
442:            }
443:
444:            /**
445:             * Provides a factory method to construct a dashpattern combo box.
446:             */
447:            public static class DashPatternComboFactoryMethod extends
448:                    JGraphEditorFactoryMethod {
449:
450:                /**
451:                 * Defines the default name for factory methods of this kind.
452:                 */
453:                public static String NAME = "createDashPatternCombo";
454:
455:                /**
456:                 * Constructs a new dash pattern combo factory method using
457:                 * {@link #NAME}.
458:                 */
459:                public DashPatternComboFactoryMethod() {
460:                    super (NAME);
461:                }
462:
463:                /**
464:                 * Returns a new dashpattern combo box for <code>configuration</code>.
465:                 * 
466:                 * @param configuration
467:                 *            The configuration to use for creating the combo box.
468:                 */
469:                public Component createInstance(Node configuration) {
470:                    Map[] attrs = new Hashtable[defaultPatterns.length + 1];
471:                    attrs[0] = new Hashtable();
472:                    GraphConstants.setRemoveAttributes(attrs[0],
473:                            new Object[] { GraphConstants.DASHPATTERN });
474:                    for (int i = 0; i < defaultPatterns.length; i++) {
475:                        attrs[i + 1] = new Hashtable(2);
476:                        GraphConstants.setDashPattern(attrs[i + 1],
477:                                defaultPatterns[i]);
478:                    }
479:                    JGraphEditorComboBox comboBox = new JGraphEditorComboBox(
480:                            attrs, true);
481:                    comboBox.addActionListener(new ComboBoxListener());
482:                    comboBox.setFocusable(false);
483:                    return comboBox;
484:                }
485:
486:            }
487:
488:            /**
489:             * Provides a factory method to construct a line decoration combo box.
490:             */
491:            public static class LineDecorationComboFactoryMethod extends
492:                    JGraphEditorFactoryMethod {
493:
494:                /**
495:                 * Defines the default name for factory methods of this kind.
496:                 */
497:                public static String NAME = "createLineDecorationCombo";
498:
499:                /**
500:                 * Constructs a new line decoration combo factory method using
501:                 * {@link #NAME}.
502:                 */
503:                public LineDecorationComboFactoryMethod() {
504:                    super (NAME);
505:                }
506:
507:                /**
508:                 * Returns a new line decoration combo box for
509:                 * <code>configuration</code>.
510:                 * 
511:                 * @param configuration
512:                 *            The configuration to use for creating the combo box.
513:                 */
514:                public Component createInstance(Node configuration) {
515:                    int all = defaultDecorations.length
516:                            + defaultFillableDecorations.length;
517:                    Map[] attrs = new Hashtable[2 * all + 1];
518:                    attrs[0] = new Hashtable();
519:                    GraphConstants.setRemoveAttributes(attrs[0], new Object[] {
520:                            GraphConstants.LINEBEGIN, GraphConstants.LINEEND,
521:                            GraphConstants.BEGINFILL, GraphConstants.ENDFILL });
522:
523:                    // Adds end decorations, not-filled and filled
524:                    for (int i = 0; i < defaultPatterns.length; i++) {
525:                        Map m = attrs[i + 1] = new Hashtable(2);
526:                        GraphConstants.setLineEnd(m, defaultDecorations[i]);
527:                        GraphConstants.setEndFill(m, false);
528:                    }
529:                    for (int i = 0; i < defaultFillableDecorations.length; i++) {
530:                        Map m = attrs[defaultDecorations.length + i + 1] = new Hashtable(
531:                                2);
532:                        GraphConstants.setLineEnd(m,
533:                                defaultFillableDecorations[i]);
534:                        GraphConstants.setEndFill(m, true);
535:                    }
536:
537:                    // Adds begin decorations, not-filled and filled
538:                    for (int i = 0; i < defaultPatterns.length; i++) {
539:                        Map m = attrs[all + i + 1] = new Hashtable(2);
540:                        GraphConstants.setLineBegin(m, defaultDecorations[i]);
541:                        GraphConstants.setBeginFill(m, false);
542:                    }
543:                    for (int i = 0; i < defaultFillableDecorations.length; i++) {
544:                        Map m = attrs[defaultDecorations.length + all + i + 1] = new Hashtable(
545:                                2);
546:                        GraphConstants.setLineBegin(m,
547:                                defaultFillableDecorations[i]);
548:                        GraphConstants.setBeginFill(m, true);
549:                    }
550:
551:                    // Constructs and returns the combo box
552:                    JGraphEditorComboBox comboBox = new JGraphEditorComboBox(
553:                            attrs, true);
554:                    comboBox.addActionListener(new ComboBoxListener());
555:                    comboBox.setFocusable(false);
556:                    return comboBox;
557:                }
558:
559:            }
560:
561:            /**
562:             * This class edits the selection of the focused graph according to the
563:             * selected combo box item.
564:             */
565:            public static class ComboBoxListener implements  ActionListener {
566:
567:                /**
568:                 * Redirects selection of a combo box item to changing the respective
569:                 * attrbiutes on the focused graph.
570:                 * 
571:                 * @param e
572:                 *            The object that describes the event.
573:                 */
574:                public void actionPerformed(ActionEvent e) {
575:                    JComboBox sender = (JComboBox) e.getSource();
576:
577:                    // Gets focused component before showing dialogs.
578:                    Component component = JGraphEditorAction
579:                            .getPermanentFocusOwner();
580:                    Object userObject = getSelection(sender);
581:                    if (userObject instanceof  Map) {
582:
583:                        // Edits cells in the focused graph
584:                        if (component instanceof  JGraph) {
585:                            JGraph graph = (JGraph) component;
586:                            graph.getGraphLayoutCache().edit(
587:                                    graph.getSelectionCells(),
588:                                    new Hashtable((Map) userObject));
589:                        }
590:                    }
591:                }
592:
593:                /**
594:                 * Hook for subclassers to process the selection and return and map for
595:                 * the default implementation to process.
596:                 * 
597:                 * @param box
598:                 *            The combo box to return the selected item for.
599:                 * @return Returns the selected item in <code>box</code>.
600:                 */
601:                protected Object getSelection(JComboBox box) {
602:                    return box.getSelectedItem();
603:                }
604:
605:            }
606:
607:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.