1 /*
   2  *
   3  * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
   4  *
   5  * Redistribution and use in source and binary forms, with or without
   6  * modification, are permitted provided that the following conditions
   7  * are met:
   8  *
   9  *   - Redistributions of source code must retain the above copyright
  10  *     notice, this list of conditions and the following disclaimer.
  11  *
  12  *   - Redistributions in binary form must reproduce the above copyright
  13  *     notice, this list of conditions and the following disclaimer in the
  14  *     documentation and/or other materials provided with the distribution.
  15  *
  16  *   - Neither the name of Oracle nor the names of its
  17  *     contributors may be used to endorse or promote products derived
  18  *     from this software without specific prior written permission.
  19  *
  20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
  21  * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
  22  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  23  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
  24  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  25  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  26  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
  27  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
  28  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
  29  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  30  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  31  */
  32 
  33 
  34 import javax.swing.*;
  35 import javax.swing.event.*;
  36 import javax.swing.text.*;
  37 import javax.swing.border.*;
  38 import javax.swing.colorchooser.*;
  39 import javax.swing.filechooser.*;
  40 import javax.accessibility.*;
  41 
  42 import java.awt.*;
  43 import java.awt.event.*;
  44 import java.beans.*;
  45 import java.util.*;
  46 import java.io.*;
  47 import java.applet.*;
  48 import java.net.*;
  49 
  50 /**
  51  * List Demo. This demo shows that it is not
  52  * always necessary to have an array of objects
  53  * as big as the size of the list stored.
  54  *
  55  * Indeed, in this example, there is no array
  56  * kept for the list data, rather it is generated
  57  * on the fly as only those elements are needed.
  58  *
  59  * @author Jeff Dinkins
  60  */
  61 public class ListDemo extends DemoModule {
  62     JList<String> list;
  63 
  64     JPanel prefixList;
  65     JPanel suffixList;
  66 
  67     Action prefixAction;
  68     Action suffixAction;
  69 
  70     GeneratedListModel listModel;
  71 
  72     Vector<JCheckBox> checkboxes = new Vector<>();
  73 
  74     /**
  75      * main method allows us to run as a standalone demo.
  76      */
  77     public static void main(String[] args) {
  78         ListDemo demo = new ListDemo(null);
  79         demo.mainImpl();
  80     }
  81 
  82     /**
  83      * ListDemo Constructor
  84      */
  85     public ListDemo(SwingSet2 swingset) {
  86         super(swingset, "ListDemo", "toolbar/JList.gif");
  87 
  88         loadImages();
  89 
  90         JLabel description = new JLabel(getString("ListDemo.description"));
  91         getDemoPanel().add(description, BorderLayout.NORTH);
  92 
  93         JPanel centerPanel = new JPanel();
  94         centerPanel.setLayout(new BoxLayout(centerPanel, BoxLayout.X_AXIS));
  95         centerPanel.add(Box.createRigidArea(HGAP10));
  96         getDemoPanel().add(centerPanel, BorderLayout.CENTER);
  97 
  98         JPanel listPanel = new JPanel();
  99         listPanel.setLayout(new BoxLayout(listPanel, BoxLayout.Y_AXIS));
 100         listPanel.add(Box.createRigidArea(VGAP10));
 101 
 102         centerPanel.add(listPanel);
 103         centerPanel.add(Box.createRigidArea(HGAP30));
 104 
 105         // Create the list
 106         list = new JList<>();
 107         list.setCellRenderer(new CompanyLogoListCellRenderer());
 108         listModel = new GeneratedListModel(this);
 109         list.setModel(listModel);
 110 
 111         // Set the preferred row count. This affects the preferredSize
 112         // of the JList when it's in a scrollpane.
 113         list.setVisibleRowCount(22);
 114 
 115         // Add list to a scrollpane
 116         JScrollPane scrollPane = new JScrollPane(list);
 117         listPanel.add(scrollPane);
 118         listPanel.add(Box.createRigidArea(VGAP10));
 119 
 120         // Add the control panel (holds the prefix/suffix list and prefix/suffix checkboxes)
 121         centerPanel.add(createControlPanel());
 122 
 123         // create prefixes and suffixes
 124         addPrefix("Tera", true);
 125         addPrefix("Micro", false);
 126         addPrefix("Southern", false);
 127         addPrefix("Net", true);
 128         addPrefix("YoYo", true);
 129         addPrefix("Northern", false);
 130         addPrefix("Tele", false);
 131         addPrefix("Eastern", false);
 132         addPrefix("Neo", false);
 133         addPrefix("Digi", false);
 134         addPrefix("National", false);
 135         addPrefix("Compu", true);
 136         addPrefix("Meta", true);
 137         addPrefix("Info", false);
 138         addPrefix("Western", false);
 139         addPrefix("Data", false);
 140         addPrefix("Atlantic", false);
 141         addPrefix("Advanced", false);
 142         addPrefix("Euro", false);
 143         addPrefix("Pacific", false);
 144         addPrefix("Mobile", false);
 145         addPrefix("In", false);
 146         addPrefix("Computa", false);
 147         addPrefix("Digital", false);
 148         addPrefix("Analog", false);
 149 
 150         addSuffix("Tech", true);
 151         addSuffix("Soft", true);
 152         addSuffix("Telecom", true);
 153         addSuffix("Solutions", false);
 154         addSuffix("Works", true);
 155         addSuffix("Dyne", false);
 156         addSuffix("Services", false);
 157         addSuffix("Vers", false);
 158         addSuffix("Devices", false);
 159         addSuffix("Software", false);
 160         addSuffix("Serv", false);
 161         addSuffix("Systems", true);
 162         addSuffix("Dynamics", true);
 163         addSuffix("Net", false);
 164         addSuffix("Sys", false);
 165         addSuffix("Computing", false);
 166         addSuffix("Scape", false);
 167         addSuffix("Com", false);
 168         addSuffix("Ware", false);
 169         addSuffix("Widgets", false);
 170         addSuffix("Media", false);
 171         addSuffix("Computer", false);
 172         addSuffix("Hardware", false);
 173         addSuffix("Gizmos", false);
 174         addSuffix("Concepts", false);
 175     }
 176 
 177     void updateDragEnabled(boolean dragEnabled) {
 178         list.setDragEnabled(dragEnabled);
 179     }
 180 
 181     public JPanel createControlPanel() {
 182         JPanel controlPanel = new JPanel() {
 183             Insets insets = new Insets(0, 4, 10, 10);
 184             public Insets getInsets() {
 185                 return insets;
 186             }
 187         };
 188         controlPanel.setLayout(new BoxLayout(controlPanel, BoxLayout.X_AXIS));
 189 
 190         JPanel prefixPanel = new JPanel();
 191         prefixPanel.setLayout(new BoxLayout(prefixPanel, BoxLayout.Y_AXIS));
 192         prefixPanel.add(new JLabel(getString("ListDemo.prefixes")));
 193 
 194         JPanel suffixPanel = new JPanel();
 195         suffixPanel.setLayout(new BoxLayout(suffixPanel, BoxLayout.Y_AXIS));
 196         suffixPanel.add(new JLabel(getString("ListDemo.suffixes")));
 197 
 198         prefixList = new JPanel() {
 199             Insets insets = new Insets(0, 4, 0, 0);
 200             public Insets getInsets() {
 201                 return insets;
 202             }
 203         };
 204         prefixList.setLayout(new BoxLayout(prefixList, BoxLayout.Y_AXIS));
 205         JScrollPane scrollPane = new JScrollPane(prefixList);
 206         scrollPane.getVerticalScrollBar().setUnitIncrement(10);
 207         prefixPanel.add(scrollPane);
 208         prefixPanel.add(Box.createRigidArea(HGAP10));
 209 
 210         suffixList = new JPanel() {
 211             Insets insets = new Insets(0, 4, 0, 0);
 212             public Insets getInsets() {
 213                 return insets;
 214             }
 215         };
 216         suffixList.setLayout(new BoxLayout(suffixList, BoxLayout.Y_AXIS));
 217         scrollPane = new JScrollPane(suffixList);
 218         scrollPane.getVerticalScrollBar().setUnitIncrement(10);
 219         suffixPanel.add(scrollPane);
 220         suffixPanel.add(Box.createRigidArea(HGAP10));
 221 
 222         controlPanel.add(prefixPanel);
 223         controlPanel.add(Box.createRigidArea(HGAP15));
 224         controlPanel.add(suffixPanel);
 225         return controlPanel;
 226     }
 227 
 228     private FocusListener listFocusListener = new FocusAdapter() {
 229         public void focusGained(FocusEvent e) {
 230             JComponent c = (JComponent)e.getComponent();
 231             c.scrollRectToVisible(new Rectangle(0, 0, c.getWidth(), c.getHeight()));
 232         }
 233     };
 234 
 235     public void addPrefix(String prefix, boolean selected) {
 236         if(prefixAction == null) {
 237             prefixAction = new UpdatePrefixListAction(listModel);
 238         }
 239         final JCheckBox cb = (JCheckBox) prefixList.add(new JCheckBox(prefix));
 240         checkboxes.addElement(cb);
 241         cb.setSelected(selected);
 242         cb.addActionListener(prefixAction);
 243         if(selected) {
 244             listModel.addPrefix(prefix);
 245         }
 246         cb.addFocusListener(listFocusListener);
 247     }
 248 
 249     public void addSuffix(String suffix, boolean selected) {
 250         if(suffixAction == null) {
 251             suffixAction = new UpdateSuffixListAction(listModel);
 252         }
 253         final JCheckBox cb = (JCheckBox) suffixList.add(new JCheckBox(suffix));
 254         checkboxes.addElement(cb);
 255         cb.setSelected(selected);
 256         cb.addActionListener(suffixAction);
 257         if(selected) {
 258             listModel.addSuffix(suffix);
 259         }
 260         cb.addFocusListener(listFocusListener);
 261     }
 262 
 263     class UpdatePrefixListAction extends AbstractAction {
 264         GeneratedListModel listModel;
 265         protected UpdatePrefixListAction(GeneratedListModel listModel) {
 266             this.listModel = listModel;
 267         }
 268 
 269         public void actionPerformed(ActionEvent e) {
 270             JCheckBox cb = (JCheckBox) e.getSource();
 271             if(cb.isSelected()) {
 272                 listModel.addPrefix(cb.getText());
 273             } else {
 274                 listModel.removePrefix(cb.getText());
 275             }
 276         }
 277     }
 278 
 279     class UpdateSuffixListAction extends AbstractAction {
 280         GeneratedListModel listModel;
 281         protected UpdateSuffixListAction(GeneratedListModel listModel) {
 282             this.listModel = listModel;
 283         }
 284 
 285         public void actionPerformed(ActionEvent e) {
 286             JCheckBox cb = (JCheckBox) e.getSource();
 287             if(cb.isSelected()) {
 288                 listModel.addSuffix(cb.getText());
 289             } else {
 290                 listModel.removeSuffix(cb.getText());
 291             }
 292         }
 293     }
 294 
 295 
 296     class GeneratedListModel extends AbstractListModel<String> {
 297         ListDemo demo;
 298         Permuter permuter;
 299 
 300         public Vector<String> prefix = new Vector<>();
 301         public Vector<String> suffix = new Vector<>();
 302 
 303         public GeneratedListModel (ListDemo demo) {
 304             this.demo = demo;
 305         }
 306 
 307         private void update() {
 308             permuter = new Permuter(getSize());
 309             fireContentsChanged(this, 0, getSize());
 310         }
 311 
 312         public void addPrefix(String s) {
 313             if(!prefix.contains(s)) {
 314                 prefix.addElement(s);
 315                 update();
 316             }
 317         }
 318 
 319         public void removePrefix(String s) {
 320             prefix.removeElement(s);
 321             update();
 322         }
 323 
 324         public void addSuffix(String s) {
 325             if(!suffix.contains(s)) {
 326                 suffix.addElement(s);
 327                 update();
 328             }
 329         }
 330 
 331         public void removeSuffix(String s) {
 332             suffix.removeElement(s);
 333             update();
 334         }
 335 
 336         public int getSize() {
 337             return prefix.size() * suffix.size();
 338         }
 339 
 340         public String getElementAt(int index) {
 341             if(permuter == null) {
 342                 update();
 343             }
 344             // morph the index to another int -- this has the benefit of
 345             // causing the list to look random.
 346             int j = permuter.map(index);
 347             int ps = prefix.size();
 348             int ss = suffix.size();
 349             return (String) prefix.elementAt(j%ps) + (String) suffix.elementAt((j/ps)%ss);
 350         }
 351     }
 352 
 353     ImageIcon[] images = new ImageIcon[7];
 354     void loadImages() {
 355             images[0] = createImageIcon("list/red.gif",  getString("ListDemo.red"));
 356             images[1] = createImageIcon("list/blue.gif",  getString("ListDemo.blue"));
 357             images[2] = createImageIcon("list/yellow.gif",  getString("ListDemo.yellow"));
 358             images[3] = createImageIcon("list/green.gif",  getString("ListDemo.green"));
 359             images[4] = createImageIcon("list/gray.gif",  getString("ListDemo.gray"));
 360             images[5] = createImageIcon("list/cyan.gif",  getString("ListDemo.cyan"));
 361             images[6] = createImageIcon("list/magenta.gif",  getString("ListDemo.magenta"));
 362     }
 363 
 364     class CompanyLogoListCellRenderer extends DefaultListCellRenderer {
 365        public Component getListCellRendererComponent(
 366             JList<?> list,
 367             Object value,
 368             int index,
 369             boolean isSelected,
 370             boolean cellHasFocus)
 371         {
 372             Component retValue = super.getListCellRendererComponent(
 373                 list, value, index, isSelected, cellHasFocus
 374             );
 375             setIcon(images[index%7]);
 376             return retValue;
 377         }
 378     }
 379 }