ListDemo.java revision 13978:1993af50385d
1/*
2 * Copyright (c) 2007, 2016, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 */
23package com.sun.swingset3.demos.list;
24
25import java.awt.*;
26import java.awt.event.ActionEvent;
27import java.awt.event.FocusAdapter;
28import java.awt.event.FocusEvent;
29import java.awt.event.FocusListener;
30import java.util.Vector;
31import javax.swing.*;
32
33import com.sun.swingset3.DemoProperties;
34import com.sun.swingset3.demos.ResourceManager;
35
36/**
37 * List Demo. This demo shows that it is not always necessary to have an array
38 * of objects as big as the size of the list stored.
39 *
40 * Indeed, in this example, there is no array kept for the list data, rather it
41 * is generated on the fly as only those elements are needed.
42 *
43 * @version 1.17 11/17/05
44 * @author Jeff Dinkins
45 */
46@DemoProperties(
47        value = "JList Demo",
48        category = "Data",
49        description = "Demonstrates JList, a component which supports display/editing of a data list",
50        sourceFiles = {
51            "com/sun/swingset3/demos/list/ListDemo.java",
52            "com/sun/swingset3/demos/list/Permuter.java",
53            "com/sun/swingset3/demos/ResourceManager.java",
54            "com/sun/swingset3/demos/list/resources/ListDemo.properties",
55            "com/sun/swingset3/demos/list/resources/images/blue.gif",
56            "com/sun/swingset3/demos/list/resources/images/cyan.gif",
57            "com/sun/swingset3/demos/list/resources/images/gray.gif",
58            "com/sun/swingset3/demos/list/resources/images/green.gif",
59            "com/sun/swingset3/demos/list/resources/images/ListDemo.gif",
60            "com/sun/swingset3/demos/list/resources/images/magenta.gif",
61            "com/sun/swingset3/demos/list/resources/images/red.gif",
62            "com/sun/swingset3/demos/list/resources/images/yellow.gif"
63        }
64)
65public final class ListDemo extends JPanel {
66
67    private static final Dimension HGAP10 = new Dimension(10, 1);
68    private static final Dimension VGAP10 = new Dimension(1, 10);
69    private static final Dimension HGAP15 = new Dimension(15, 1);
70    private static final Dimension HGAP30 = new Dimension(30, 1);
71
72    private final ResourceManager resourceManager = new ResourceManager(this.getClass());
73    public static final String DEMO_TITLE = ListDemo.class.getAnnotation(DemoProperties.class).value();
74
75    private final JList<String> list;
76
77    private JPanel prefixList;
78    private JPanel suffixList;
79
80    private Action prefixAction;
81    private Action suffixAction;
82
83    private final GeneratedListModel listModel;
84
85    /**
86     * main method allows us to run as a standalone demo.
87     *
88     * @param args
89     */
90    public static void main(String[] args) {
91        JFrame frame = new JFrame(DEMO_TITLE);
92
93        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
94        frame.getContentPane().add(new ListDemo());
95        frame.setPreferredSize(new Dimension(800, 600));
96        frame.pack();
97        frame.setLocationRelativeTo(null);
98        frame.setVisible(true);
99    }
100
101    /**
102     * ListDemo Constructor
103     */
104    public ListDemo() {
105        setLayout(new BorderLayout());
106
107        loadImages();
108
109        JLabel description = new JLabel(resourceManager.getString("ListDemo.description"));
110        add(description, BorderLayout.NORTH);
111
112        JPanel centerPanel = new JPanel();
113        centerPanel.setLayout(new BoxLayout(centerPanel, BoxLayout.X_AXIS));
114        centerPanel.add(Box.createRigidArea(HGAP10));
115        add(centerPanel, BorderLayout.CENTER);
116
117        JPanel listPanel = new JPanel();
118        listPanel.setLayout(new BoxLayout(listPanel, BoxLayout.Y_AXIS));
119        listPanel.add(Box.createRigidArea(VGAP10));
120
121        centerPanel.add(listPanel);
122        centerPanel.add(Box.createRigidArea(HGAP30));
123
124        // Create the list
125        list = new JList<>();
126        list.setCellRenderer(new CompanyLogoListCellRenderer());
127        listModel = new GeneratedListModel();
128        list.setModel(listModel);
129
130        // Set the preferred row count. This affects the preferredSize
131        // of the JList when it's in a scrollpane.
132        list.setVisibleRowCount(22);
133
134        // Add list to a scrollpane
135        JScrollPane scrollPane = new JScrollPane(list);
136        listPanel.add(scrollPane);
137        listPanel.add(Box.createRigidArea(VGAP10));
138
139        // Add the control panel (holds the prefix/suffix list and prefix/suffix checkboxes)
140        centerPanel.add(createControlPanel());
141
142        // create prefixes and suffixes
143        addPrefix("Tera", true);
144        addPrefix("Micro", false);
145        addPrefix("Southern", false);
146        addPrefix("Net", true);
147        addPrefix("YoYo", true);
148        addPrefix("Northern", false);
149        addPrefix("Tele", false);
150        addPrefix("Eastern", false);
151        addPrefix("Neo", false);
152        addPrefix("Digi", false);
153        addPrefix("National", false);
154        addPrefix("Compu", true);
155        addPrefix("Meta", true);
156        addPrefix("Info", false);
157        addPrefix("Western", false);
158        addPrefix("Data", false);
159        addPrefix("Atlantic", false);
160        addPrefix("Advanced", false);
161        addPrefix("Euro", false);
162        addPrefix("Pacific", false);
163        addPrefix("Mobile", false);
164        addPrefix("In", false);
165        addPrefix("Computa", false);
166        addPrefix("Digital", false);
167        addPrefix("Analog", false);
168
169        addSuffix("Tech", true);
170        addSuffix("Soft", true);
171        addSuffix("Telecom", true);
172        addSuffix("Solutions", false);
173        addSuffix("Works", true);
174        addSuffix("Dyne", false);
175        addSuffix("Services", false);
176        addSuffix("Vers", false);
177        addSuffix("Devices", false);
178        addSuffix("Software", false);
179        addSuffix("Serv", false);
180        addSuffix("Systems", true);
181        addSuffix("Dynamics", true);
182        addSuffix("Net", false);
183        addSuffix("Sys", false);
184        addSuffix("Computing", false);
185        addSuffix("Scape", false);
186        addSuffix("Com", false);
187        addSuffix("Ware", false);
188        addSuffix("Widgets", false);
189        addSuffix("Media", false);
190        addSuffix("Computer", false);
191        addSuffix("Hardware", false);
192        addSuffix("Gizmos", false);
193        addSuffix("Concepts", false);
194    }
195
196    private JPanel createControlPanel() {
197        JPanel controlPanel = new JPanel() {
198            private final Insets insets = new Insets(0, 4, 10, 10);
199
200            @Override
201            public Insets getInsets() {
202                return insets;
203            }
204        };
205        controlPanel.setLayout(new BoxLayout(controlPanel, BoxLayout.X_AXIS));
206
207        JPanel prefixPanel = new JPanel();
208        prefixPanel.setLayout(new BoxLayout(prefixPanel, BoxLayout.Y_AXIS));
209        prefixPanel.add(new JLabel(resourceManager.getString("ListDemo.prefixes")));
210
211        JPanel suffixPanel = new JPanel();
212        suffixPanel.setLayout(new BoxLayout(suffixPanel, BoxLayout.Y_AXIS));
213        suffixPanel.add(new JLabel(resourceManager.getString("ListDemo.suffixes")));
214
215        prefixList = new JPanel() {
216            private final Insets insets = new Insets(0, 4, 0, 0);
217
218            @Override
219            public Insets getInsets() {
220                return insets;
221            }
222        };
223        prefixList.setLayout(new BoxLayout(prefixList, BoxLayout.Y_AXIS));
224        JScrollPane scrollPane = new JScrollPane(prefixList);
225        scrollPane.getVerticalScrollBar().setUnitIncrement(10);
226        prefixPanel.add(scrollPane);
227        prefixPanel.add(Box.createRigidArea(HGAP10));
228
229        suffixList = new JPanel() {
230            private final Insets insets = new Insets(0, 4, 0, 0);
231
232            @Override
233            public Insets getInsets() {
234                return insets;
235            }
236        };
237        suffixList.setLayout(new BoxLayout(suffixList, BoxLayout.Y_AXIS));
238        scrollPane = new JScrollPane(suffixList);
239        scrollPane.getVerticalScrollBar().setUnitIncrement(10);
240        suffixPanel.add(scrollPane);
241        suffixPanel.add(Box.createRigidArea(HGAP10));
242
243        controlPanel.add(prefixPanel);
244        controlPanel.add(Box.createRigidArea(HGAP15));
245        controlPanel.add(suffixPanel);
246        return controlPanel;
247    }
248
249    private final FocusListener listFocusListener = new FocusAdapter() {
250        @Override
251        public void focusGained(FocusEvent e) {
252            JComponent c = (JComponent) e.getComponent();
253            c.scrollRectToVisible(new Rectangle(0, 0, c.getWidth(), c.getHeight()));
254        }
255    };
256
257    private void addPrefix(String prefix, boolean selected) {
258        if (prefixAction == null) {
259            prefixAction = new UpdatePrefixListAction(listModel);
260        }
261        final JCheckBox cb = (JCheckBox) prefixList.add(new JCheckBox(prefix));
262        cb.setSelected(selected);
263        cb.addActionListener(prefixAction);
264        if (selected) {
265            listModel.addPrefix(prefix);
266        }
267        cb.addFocusListener(listFocusListener);
268    }
269
270    private void addSuffix(String suffix, boolean selected) {
271        if (suffixAction == null) {
272            suffixAction = new UpdateSuffixListAction(listModel);
273        }
274        final JCheckBox cb = (JCheckBox) suffixList.add(new JCheckBox(suffix));
275        cb.setSelected(selected);
276        cb.addActionListener(suffixAction);
277        if (selected) {
278            listModel.addSuffix(suffix);
279        }
280        cb.addFocusListener(listFocusListener);
281    }
282
283    private static class UpdatePrefixListAction extends AbstractAction {
284
285        private final GeneratedListModel listModel;
286
287        protected UpdatePrefixListAction(GeneratedListModel listModel) {
288            this.listModel = listModel;
289        }
290
291        @Override
292        public void actionPerformed(ActionEvent e) {
293            JCheckBox cb = (JCheckBox) e.getSource();
294            if (cb.isSelected()) {
295                listModel.addPrefix(cb.getText());
296            } else {
297                listModel.removePrefix(cb.getText());
298            }
299        }
300    }
301
302    private static class UpdateSuffixListAction extends AbstractAction {
303
304        private final GeneratedListModel listModel;
305
306        protected UpdateSuffixListAction(GeneratedListModel listModel) {
307            this.listModel = listModel;
308        }
309
310        @Override
311        public void actionPerformed(ActionEvent e) {
312            JCheckBox cb = (JCheckBox) e.getSource();
313            if (cb.isSelected()) {
314                listModel.addSuffix(cb.getText());
315            } else {
316                listModel.removeSuffix(cb.getText());
317            }
318        }
319    }
320
321    private static class GeneratedListModel extends AbstractListModel<String> {
322
323        private Permuter permuter;
324
325        private final Vector<String> prefix = new Vector<>();
326        private final Vector<String> suffix = new Vector<>();
327
328        private void update() {
329            permuter = new Permuter(getSize());
330            fireContentsChanged(this, 0, getSize());
331        }
332
333        public void addPrefix(String s) {
334            if (!prefix.contains(s)) {
335                prefix.addElement(s);
336                update();
337            }
338        }
339
340        public void removePrefix(String s) {
341            prefix.removeElement(s);
342            update();
343        }
344
345        public void addSuffix(String s) {
346            if (!suffix.contains(s)) {
347                suffix.addElement(s);
348                update();
349            }
350        }
351
352        public void removeSuffix(String s) {
353            suffix.removeElement(s);
354            update();
355        }
356
357        @Override
358        public int getSize() {
359            return prefix.size() * suffix.size();
360        }
361
362        @Override
363        public String getElementAt(int index) {
364            if (permuter == null) {
365                update();
366            }
367            // morph the index to another int -- this has the benefit of
368            // causing the list to look random.
369            int j = permuter.map(index);
370            int ps = prefix.size();
371            int ss = suffix.size();
372            return prefix.elementAt(j % ps) + suffix.elementAt((j / ps) % ss);
373        }
374    }
375
376    private final ImageIcon[] images = new ImageIcon[7];
377
378    void loadImages() {
379        images[0] = resourceManager.createImageIcon("red.gif", resourceManager.getString("ListDemo.red"));
380        images[1] = resourceManager.createImageIcon("blue.gif", resourceManager.getString("ListDemo.blue"));
381        images[2] = resourceManager.createImageIcon("yellow.gif", resourceManager.getString("ListDemo.yellow"));
382        images[3] = resourceManager.createImageIcon("green.gif", resourceManager.getString("ListDemo.green"));
383        images[4] = resourceManager.createImageIcon("gray.gif", resourceManager.getString("ListDemo.gray"));
384        images[5] = resourceManager.createImageIcon("cyan.gif", resourceManager.getString("ListDemo.cyan"));
385        images[6] = resourceManager.createImageIcon("magenta.gif", resourceManager.getString("ListDemo.magenta"));
386    }
387
388    private class CompanyLogoListCellRenderer extends DefaultListCellRenderer {
389
390        @Override
391        public Component getListCellRendererComponent(
392                JList<?> list,
393                Object value,
394                int index,
395                boolean isSelected,
396                boolean cellHasFocus) {
397            Component retValue = super.getListCellRendererComponent(
398                    list, value, index, isSelected, cellHasFocus
399            );
400            setIcon(images[index % 7]);
401            return retValue;
402        }
403    }
404}
405