View Javadoc
1   /*
2    * ObjectLab, http://www.objectlab.co.uk/open is supporting JTreeMap.
3    *
4    * Based in London, we are world leaders in the design and development
5    * of bespoke applications for the securities financing markets.
6    *
7    * <a href="http://www.objectlab.co.uk/open">Click here to learn more</a>
8    *           ___  _     _           _   _          _
9    *          / _ \| |__ (_) ___  ___| |_| |    __ _| |__
10   *         | | | | '_ \| |/ _ \/ __| __| |   / _` | '_ \
11   *         | |_| | |_) | |  __/ (__| |_| |__| (_| | |_) |
12   *          \___/|_.__// |\___|\___|\__|_____\__,_|_.__/
13   *                   |__/
14   *
15   *                     www.ObjectLab.co.uk
16   *
17   * $Id$
18   *
19   * Copyright 2006 the original author or authors.
20   *
21   * Licensed under the Apache License, Version 2.0 (the "License"); you may not
22   * use this file except in compliance with the License. You may obtain a copy of
23   * the License at
24   *
25   * http://www.apache.org/licenses/LICENSE-2.0
26   *
27   * Unless required by applicable law or agreed to in writing, software
28   * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
29   * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
30   * License for the specific language governing permissions and limitations under
31   * the License.
32   */
33  package net.sf.jtreemap.swing.example;
34  
35  import java.awt.BorderLayout;
36  import java.awt.CardLayout;
37  import java.awt.Color;
38  import java.awt.Container;
39  import java.awt.Dimension;
40  import java.awt.Font;
41  import java.awt.GridBagConstraints;
42  import java.awt.event.ActionEvent;
43  import java.awt.event.ActionListener;
44  import java.awt.event.WindowEvent;
45  import java.io.File;
46  import java.io.IOException;
47  import java.text.ParseException;
48  import java.util.LinkedHashMap;
49  import java.util.Locale;
50  
51  import javax.swing.BorderFactory;
52  import javax.swing.JComboBox;
53  import javax.swing.JFileChooser;
54  import javax.swing.JFrame;
55  import javax.swing.JLabel;
56  import javax.swing.JMenu;
57  import javax.swing.JMenuBar;
58  import javax.swing.JMenuItem;
59  import javax.swing.JOptionPane;
60  import javax.swing.JPanel;
61  import javax.swing.JScrollPane;
62  import javax.swing.JSplitPane;
63  import javax.swing.JTree;
64  import javax.swing.KeyStroke;
65  import javax.swing.border.EtchedBorder;
66  import javax.swing.border.TitledBorder;
67  import javax.swing.event.TreeSelectionEvent;
68  import javax.swing.event.TreeSelectionListener;
69  import javax.swing.filechooser.FileFilter;
70  import javax.swing.tree.DefaultTreeModel;
71  
72  import lombok.extern.slf4j.Slf4j;
73  import net.sf.jtreemap.swing.JTreeMap;
74  import net.sf.jtreemap.swing.SplitByNumber;
75  import net.sf.jtreemap.swing.SplitBySlice;
76  import net.sf.jtreemap.swing.SplitBySortedWeight;
77  import net.sf.jtreemap.swing.SplitByWeight;
78  import net.sf.jtreemap.swing.SplitSquarified;
79  import net.sf.jtreemap.swing.SplitStrategy;
80  import net.sf.jtreemap.swing.TreeMapNode;
81  import net.sf.jtreemap.swing.provider.ColorProvider;
82  import net.sf.jtreemap.swing.provider.HSBTreeMapColorProvider;
83  import net.sf.jtreemap.swing.provider.RandomColorProvider;
84  import net.sf.jtreemap.swing.provider.RedGreenColorProvider;
85  import net.sf.jtreemap.swing.provider.ZoomPopupMenu;
86  
87  /**
88   * Test of JTreeMap
89   *
90   * @author Laurent Dutheil
91   */
92  @Slf4j
93  public class JTreeMapExample extends JFrame implements ActionListener {
94      private static final long serialVersionUID = 2813934810390001709L;
95      private static final double CONSTRAINT_WEIGHTX = 0.5;
96      private static final int SCROLLPANE_WIDTH = 140;
97      private static final int APPLICATION_HEIGHT = 400;
98      private static final int APPLICATION_WIDTH = 600;
99      private static final int DEFAULT_FONT_SIZE = 16;
100     private static final String EXIT = "Exit";
101     private static final String OPEN_TM3_FILE = "Open TM3 File";
102     private static final String OPEN_XML_FILE = "Open Xml File";
103     private final JTreeMap jTreeMap;
104     private JTree treeView = new JTree();
105     private BuilderTM3 builderTM3;
106     private CardLayout cardLayout;
107     private JComboBox cmbColorProvider;
108     private JComboBox cmbStrategy;
109     private JComboBox cmbValue;
110     private JComboBox cmbWeight;
111     private final LinkedHashMap<String, ColorProvider> colorProviders = new LinkedHashMap<String, ColorProvider>();
112     private JPanel panelLegend;
113     private JPanel panelTM3;
114     private TreeMapNode root;
115     private final LinkedHashMap<String, SplitStrategy> strategies = new LinkedHashMap<String, SplitStrategy>();
116     private DefaultTreeModel treeModel;
117 
118     /**
119      * Constructor
120      */
121     public JTreeMapExample() {
122         root = DemoUtil.buildDemoRoot();
123 
124         jTreeMap = new JTreeMap(this.root, treeView);
125         jTreeMap.setFont(new Font(null, Font.BOLD, DEFAULT_FONT_SIZE));
126         jTreeMap.setPreferredSize(new Dimension(APPLICATION_WIDTH, APPLICATION_HEIGHT));
127         jTreeMap.setBorder(BorderFactory.createEtchedBorder(EtchedBorder.LOWERED));
128 
129         /* uncomment if you want to keep proportions on zooming */
130         // jTreeMap.setZoomKeepProportion(true);
131         /*
132          * uncomment if you want to change the max border between two nodes of
133          * the same level
134          */
135         // TreeMapNode.setBorder(5);
136         // add a popup menu to zoom the JTreeMap
137         new ZoomPopupMenu(this.jTreeMap);
138 
139         // init GUI
140         try {
141             initGUI();
142         } catch (final Exception ex) {
143             log.error("Issue", ex);
144         }
145     }
146 
147     /**
148      * main
149      *
150      * @param args
151      *            command line
152      */
153     public static void main(final String[] args) {
154         final JTreeMapExample example = new JTreeMapExample();
155         example.setVisible(true);
156         example.pack();
157     }
158 
159     /*
160      * (non-Javadoc)
161      *
162      * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent)
163      */
164     @Override
165     public void actionPerformed(final ActionEvent e) {
166         // Action performed for the File Menu @see addMenu()
167 
168         final String command = e.getActionCommand();
169 
170         if (OPEN_XML_FILE.equals(command)) {
171             final JFileChooser chooser = new JFileChooser(System.getProperty("user.home"));
172             final FileFilter filter = new XMLFileFilter();
173             chooser.setFileFilter(filter);
174             final int returnVal = chooser.showOpenDialog(this);
175             if (returnVal == JFileChooser.APPROVE_OPTION) {
176                 setXmlFile(chooser.getSelectedFile().getPath());
177             }
178             // create new colorProviders for the new TreeMap
179             createColorProviders();
180             // then update the lengend panel
181             updateLegendPanel();
182         } else if (OPEN_TM3_FILE.equals(command)) {
183             final JFileChooser chooser = new JFileChooser(System.getProperty("user.home"));
184             final FileFilter filter = new TM3FileFilter();
185             chooser.setFileFilter(filter);
186             final int returnVal = chooser.showOpenDialog(this);
187             if (returnVal == JFileChooser.APPROVE_OPTION) {
188                 setTm3File(chooser.getSelectedFile().getPath());
189             }
190             // create new colorProviders for the new TreeMap
191             createColorProviders();
192             // then update the lengend panel
193             updateLegendPanel();
194 
195         } else if (EXIT.equals(command)) {
196             windowClosingEvent(null);
197         }
198     }
199 
200     /**
201      * Set the tm3 file
202      *
203      * @param path
204      *            the path of the tm3 file
205      */
206     public void setTm3File(final String path) {
207         try {
208             builderTM3 = new BuilderTM3(new File(path));
209             root = builderTM3.getRoot();
210 
211             jTreeMap.setRoot(this.root);
212             treeModel.setRoot(this.root);
213 
214             setTM3Fields();
215             panelTM3.setVisible(true);
216         } catch (final IOException e) {
217             log.error("IO Issue", e);
218             JOptionPane.showMessageDialog(this, e.getMessage(), "File error", JOptionPane.ERROR_MESSAGE);
219         }
220     }
221 
222     /**
223      * Set the xml file corresponding to the TreeMap.dtd
224      *
225      * @param xmlFileName
226      *            xml file name
227      */
228     public void setXmlFile(final String xmlFileName) {
229         try {
230             final BuilderXML bXml = new BuilderXML(xmlFileName);
231             root = bXml.getRoot();
232 
233             jTreeMap.setRoot(this.root);
234             treeModel.setRoot(this.root);
235 
236             panelTM3.setVisible(false);
237         } catch (final ParseException e) {
238             log.error("Parse Issue", e);
239             JOptionPane.showMessageDialog(this, e.getMessage(), "File error", JOptionPane.ERROR_MESSAGE);
240         }
241 
242     }
243 
244     /**
245      * Code to execute before closing the window
246      *
247      * @param e
248      *            WindowEvent
249      */
250     protected void windowClosingEvent(final WindowEvent e) {
251         System.exit(0);
252     }
253 
254     private void addMenu() {
255         final JMenuBar menuBar = new JMenuBar();
256         final JMenu menu = new JMenu("File");
257 
258         JMenuItem item = new JMenuItem(OPEN_XML_FILE);
259         item.addActionListener(this);
260         item.setAccelerator(KeyStroke.getKeyStroke('O', java.awt.event.InputEvent.ALT_MASK));
261         menu.add(item);
262 
263         item = new JMenuItem(OPEN_TM3_FILE);
264         item.addActionListener(this);
265         item.setAccelerator(KeyStroke.getKeyStroke('T', java.awt.event.InputEvent.ALT_MASK));
266         menu.add(item);
267 
268         item = new JMenuItem(EXIT);
269         item.setAccelerator(KeyStroke.getKeyStroke('X', java.awt.event.InputEvent.ALT_MASK));
270         item.addActionListener(this);
271         menu.add(item);
272 
273         menuBar.add(menu);
274         setJMenuBar(menuBar);
275     }
276 
277     /**
278      * Add a splitPane with a treeview on the left and the JTreeMap on the right
279      */
280     private void addPanelCenter(final Container parent) {
281         final JSplitPane splitPaneCenter = new JSplitPane();
282         splitPaneCenter.setBorder(BorderFactory.createEmptyBorder());
283         parent.add(splitPaneCenter, BorderLayout.CENTER);
284 
285         final JScrollPane jScrollPane1 = new JScrollPane();
286         splitPaneCenter.setTopComponent(jScrollPane1);
287         splitPaneCenter.setBottomComponent(this.jTreeMap);
288 
289         treeModel = new DefaultTreeModel(this.root);
290         treeView = new JTree(this.treeModel);
291         jTreeMap.setTreeView(treeView);
292         jScrollPane1.getViewport().add(this.treeView);
293         jScrollPane1.setPreferredSize(new Dimension(SCROLLPANE_WIDTH, jTreeMap.getRoot().getHeight()));
294         treeView.addTreeSelectionListener(new TreeSelectionListener() {
295             @Override
296             public void valueChanged(final TreeSelectionEvent e) {
297                 // for each selected elements ont the treeView, we zoom the
298                 // JTreeMap
299                 TreeMapNode dest = (TreeMapNode) JTreeMapExample.this.treeView.getLastSelectedPathComponent();
300 
301                 // if the element is a leaf, we select the parent
302                 if (dest != null && dest.isLeaf()) {
303                     dest = (TreeMapNode) dest.getParent();
304                 }
305                 if (dest == null) {
306                     return;
307                 }
308 
309                 JTreeMapExample.this.jTreeMap.zoom(dest);
310                 JTreeMapExample.this.jTreeMap.repaint();
311             }
312         });
313     }
314 
315     /**
316      * Add a pane to choose the weight and the value for TM3 file
317      */
318     private void addPanelEast(final Container parent) {
319         GridBagConstraints gridBagConstraints;
320         panelTM3 = new JPanel();
321         parent.add(this.panelTM3, BorderLayout.EAST);
322 
323         final JPanel choicePanel = new JPanel();
324         choicePanel.setLayout(new java.awt.GridBagLayout());
325         choicePanel.setBorder(new TitledBorder("Choose the TM3 fields"));
326         panelTM3.add(choicePanel);
327 
328         final JLabel lblWeight = new JLabel(" weight : ");
329         gridBagConstraints = new java.awt.GridBagConstraints();
330         gridBagConstraints.gridx = 0;
331         gridBagConstraints.gridy = 0;
332         gridBagConstraints.anchor = java.awt.GridBagConstraints.EAST;
333         choicePanel.add(lblWeight, gridBagConstraints);
334 
335         cmbWeight = new JComboBox();
336         gridBagConstraints = new java.awt.GridBagConstraints();
337         gridBagConstraints.gridx = 1;
338         gridBagConstraints.gridy = 0;
339         gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
340         gridBagConstraints.weightx = CONSTRAINT_WEIGHTX;
341         choicePanel.add(this.cmbWeight, gridBagConstraints);
342         cmbWeight.addActionListener(new ActionListener() {
343             @Override
344             public void actionPerformed(final ActionEvent e) {
345                 final JComboBox cmb = (JComboBox) e.getSource();
346                 final String field = (String) cmb.getSelectedItem();
347                 JTreeMapExample.this.builderTM3.setWeights(field);
348                 JTreeMapExample.this.repaint();
349             }
350         });
351 
352         final JLabel lblValue = new JLabel(" value : ");
353         gridBagConstraints = new java.awt.GridBagConstraints();
354         gridBagConstraints.gridx = 0;
355         gridBagConstraints.gridy = 1;
356         gridBagConstraints.anchor = java.awt.GridBagConstraints.EAST;
357         gridBagConstraints.weighty = 1.0;
358         choicePanel.add(lblValue, gridBagConstraints);
359 
360         cmbValue = new JComboBox();
361         gridBagConstraints = new java.awt.GridBagConstraints();
362         gridBagConstraints.gridx = 1;
363         gridBagConstraints.gridy = 1;
364         gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
365         gridBagConstraints.weightx = CONSTRAINT_WEIGHTX;
366         gridBagConstraints.weighty = 1.0;
367         choicePanel.add(this.cmbValue, gridBagConstraints);
368         cmbValue.addActionListener(new ActionListener() {
369             @Override
370             public void actionPerformed(final ActionEvent e) {
371                 final JComboBox cmb = (JComboBox) e.getSource();
372                 final String field = (String) cmb.getSelectedItem();
373                 JTreeMapExample.this.builderTM3.setValues(field);
374                 createColorProviders();
375                 updateLegendPanel();
376                 JTreeMapExample.this.repaint();
377             }
378         });
379 
380         panelTM3.setVisible(false);
381     }
382 
383     /**
384      * add a combobox with all strategies
385      */
386     private void addPanelNorth(final Container parent) {
387         final JPanel panelNorth = new JPanel();
388         panelNorth.setBorder(BorderFactory.createEmptyBorder());
389         final JLabel lblStrategy = new JLabel();
390         lblStrategy.setText("Strategy :");
391         parent.add(panelNorth, BorderLayout.NORTH);
392         panelNorth.add(lblStrategy);
393         cmbStrategy = new JComboBox();
394         panelNorth.add(this.cmbStrategy);
395 
396         createStrategies();
397 
398         cmbStrategy.addActionListener(new ActionListener() {
399             @Override
400             public void actionPerformed(final ActionEvent e) {
401                 updateStrategy();
402             }
403         });
404     }
405 
406     /**
407      * add a combobox with all color providers and the legend panel
408      */
409     private void addPanelSouth(final Container parent) {
410         final JPanel southPanel = new JPanel();
411         southPanel.setLayout(new BorderLayout());
412         final JPanel jPanelLegendNorth = new JPanel();
413         final JLabel lblColorProvider = new JLabel();
414         lblColorProvider.setText("Color Provider :");
415         jPanelLegendNorth.add(lblColorProvider);
416         cmbColorProvider = new JComboBox();
417         jPanelLegendNorth.add(this.cmbColorProvider);
418         southPanel.add(jPanelLegendNorth, BorderLayout.NORTH);
419         panelLegend = new JPanel();
420         southPanel.add(this.panelLegend, BorderLayout.CENTER);
421         parent.add(southPanel, BorderLayout.SOUTH);
422         cardLayout = new CardLayout();
423         panelLegend.setLayout(this.cardLayout);
424 
425         createColorProviders();
426 
427         for (final String key : colorProviders.keySet()) {
428             cmbColorProvider.addItem(key);
429         }
430 
431         cmbColorProvider.addActionListener(new ActionListener() {
432             @Override
433             public void actionPerformed(final ActionEvent e) {
434                 if (JTreeMapExample.this.cmbColorProvider.getSelectedIndex() > -1) {
435                     updateLegendPanel();
436                 }
437             }
438         });
439 
440         cmbColorProvider.setSelectedIndex(0);
441     }
442 
443     protected void createColorProviders() {
444         colorProviders.put("Red Green", new RedGreenColorProvider(this.jTreeMap));
445         colorProviders.put("Random", new RandomColorProvider(jTreeMap));
446         colorProviders.put("HSB linear",
447                 new HSBTreeMapColorProvider(jTreeMap, HSBTreeMapColorProvider.ColorDistributionTypes.LINEAR, Color.GREEN, Color.RED));
448         colorProviders.put("HSB log",
449                 new HSBTreeMapColorProvider(jTreeMap, HSBTreeMapColorProvider.ColorDistributionTypes.LOG, Color.GREEN, Color.RED));
450         colorProviders.put("HSB SquareRoot",
451                 new HSBTreeMapColorProvider(jTreeMap, HSBTreeMapColorProvider.ColorDistributionTypes.SQUARE_ROOT, Color.GREEN, Color.RED));
452         colorProviders.put("HSB CubicRoot",
453                 new HSBTreeMapColorProvider(jTreeMap, HSBTreeMapColorProvider.ColorDistributionTypes.CUBIC_ROOT, Color.GREEN, Color.RED));
454         colorProviders.put("HSB exp",
455                 new HSBTreeMapColorProvider(jTreeMap, HSBTreeMapColorProvider.ColorDistributionTypes.EXP, Color.GREEN, Color.RED));
456         for (final String key : colorProviders.keySet()) {
457             final ColorProvider cp = colorProviders.get(key);
458             panelLegend.add(cp.getLegendPanel(), key);
459         }
460     }
461 
462     private void createStrategies() {
463         strategies.put("Squarified", new SplitSquarified());
464         strategies.put("Sorted Weight", new SplitBySortedWeight());
465         strategies.put("Weight", new SplitByWeight());
466         strategies.put("Slice", new SplitBySlice());
467         strategies.put("Equal Weight", new SplitByNumber());
468         cmbStrategy.removeAllItems();
469         for (final String key : strategies.keySet()) {
470             cmbStrategy.addItem(key);
471         }
472     }
473 
474     /**
475      * init the window
476      *
477      * @throws Exception
478      */
479     private void initGUI() throws Exception {
480         setTitle("JTreeMap Example");
481 
482         addWindowListener(new java.awt.event.WindowAdapter() {
483             @Override
484             public void windowClosing(final WindowEvent e) {
485                 windowClosingEvent(e);
486             }
487         });
488 
489         // a File menu to import other files
490         addMenu();
491 
492         // panel to choose the strategy
493         addPanelNorth(this.getContentPane());
494         // splitPane with treeView on the left and JTreeMap on the right
495         addPanelCenter(this.getContentPane());
496         // panel to choose the color provider
497         addPanelSouth(this.getContentPane());
498         // panel to choose the fields for a TM3 file
499         addPanelEast(this.getContentPane());
500 
501         // update the chosen strategy
502         updateStrategy();
503         // update the chosen color provider
504         updateLegendPanel();
505     }
506 
507     private void setTM3Fields() {
508         final String[] numberFields = builderTM3.getNumberFields();
509         final String[] cmbValues = new String[numberFields.length + 1];
510         cmbValues[0] = "";
511         for (int i = 1; i < cmbValues.length; i++) {
512             cmbValues[i] = numberFields[i - 1];
513         }
514         cmbWeight.removeAllItems();
515         cmbValue.removeAllItems();
516         for (final String item : cmbValues) {
517             cmbWeight.addItem(item);
518             cmbValue.addItem(item);
519         }
520     }
521 
522     protected void updateLegendPanel() {
523         final String key = (String) cmbColorProvider.getSelectedItem();
524         final ColorProvider cp = colorProviders.get(key);
525         if (cp != null) {
526             jTreeMap.setColorProvider(cp);
527             cardLayout.show(this.panelLegend, key);
528         }
529         JTreeMapExample.this.repaint();
530     }
531 
532     void updateStrategy() {
533         final String key = (String) cmbStrategy.getSelectedItem();
534         final SplitStrategy strat = strategies.get(key);
535         jTreeMap.setStrategy(strat);
536         jTreeMap.repaint();
537     }
538 
539     static class TM3FileFilter extends FileFilter {
540         // return true if should accept a given file
541         @Override
542         public boolean accept(final File f) {
543             if (f.isDirectory()) {
544                 return true;
545             }
546             final String path = f.getPath().toLowerCase(Locale.getDefault());
547             if (path.endsWith(".tm3")) {
548                 return true;
549             }
550             return false;
551         }
552 
553         // return a description of files
554         @Override
555         public String getDescription() {
556             return "TM3 file (*.tm3)";
557         }
558     }
559 
560     static class XMLFileFilter extends FileFilter {
561         // return true if should accept a given file
562         @Override
563         public boolean accept(final File f) {
564             if (f.isDirectory()) {
565                 return true;
566             }
567             final String path = f.getPath().toLowerCase(Locale.getDefault());
568             if (path.endsWith(".xml")) {
569                 return true;
570             }
571             return false;
572         }
573 
574         // return a description of files
575         @Override
576         public String getDescription() {
577             return "XML file (*.xml)";
578         }
579     }
580 }
581 /*
582  *                 ObjectLab is supporing JTreeMap
583  *
584  * Based in London, we are world leaders in the design and development
585  * of bespoke applications for the securities financing markets.
586  *
587  * <a href="http://www.objectlab.co.uk/open">Click here to learn more about us</a>
588  *           ___  _     _           _   _          _
589  *          / _ \| |__ (_) ___  ___| |_| |    __ _| |__
590  *         | | | | '_ \| |/ _ \/ __| __| |   / _` | '_ \
591  *         | |_| | |_) | |  __/ (__| |_| |__| (_| | |_) |
592  *          \___/|_.__// |\___|\___|\__|_____\__,_|_.__/
593  *                   |__/
594  *
595  *                     www.ObjectLab.co.uk
596  */