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.getContentPane().add(new ListDemo()); 94 frame.setPreferredSize(new Dimension(800, 600)); 95 frame.pack(); 96 frame.setLocationRelativeTo(null); 97 frame.setVisible(true); 98 } 99 100 /** 101 * ListDemo Constructor 102 */ 103 public ListDemo() { 104 setLayout(new BorderLayout()); 105 106 loadImages(); 107 108 JLabel description = new JLabel(resourceManager.getString("ListDemo.description")); 109 add(description, BorderLayout.NORTH); 110 111 JPanel centerPanel = new JPanel(); 112 centerPanel.setLayout(new BoxLayout(centerPanel, BoxLayout.X_AXIS)); 113 centerPanel.add(Box.createRigidArea(HGAP10)); 114 add(centerPanel, BorderLayout.CENTER); 115 116 JPanel listPanel = new JPanel(); 117 listPanel.setLayout(new BoxLayout(listPanel, BoxLayout.Y_AXIS)); 118 listPanel.add(Box.createRigidArea(VGAP10)); 119 120 centerPanel.add(listPanel); 121 centerPanel.add(Box.createRigidArea(HGAP30)); 122 123 // Create the list 124 list = new JList<>(); 125 list.setCellRenderer(new CompanyLogoListCellRenderer()); 126 listModel = new GeneratedListModel(); 127 list.setModel(listModel); 128 129 // Set the preferred row count. This affects the preferredSize 130 // of the JList when it's in a scrollpane. 131 list.setVisibleRowCount(22); 132 133 // Add list to a scrollpane 134 JScrollPane scrollPane = new JScrollPane(list); 135 listPanel.add(scrollPane); 136 listPanel.add(Box.createRigidArea(VGAP10)); 137 138 // Add the control panel (holds the prefix/suffix list and prefix/suffix checkboxes) 139 centerPanel.add(createControlPanel()); 140 141 // create prefixes and suffixes 142 addPrefix("Tera", true); 143 addPrefix("Micro", false); 144 addPrefix("Southern", false); 145 addPrefix("Net", true); 146 addPrefix("YoYo", true); 147 addPrefix("Northern", false); 148 addPrefix("Tele", false); 149 addPrefix("Eastern", false); 150 addPrefix("Neo", false); 151 addPrefix("Digi", false); 152 addPrefix("National", false); 153 addPrefix("Compu", true); 154 addPrefix("Meta", true); 155 addPrefix("Info", false); 156 addPrefix("Western", false); 157 addPrefix("Data", false); 158 addPrefix("Atlantic", false); 159 addPrefix("Advanced", false); 160 addPrefix("Euro", false); 161 addPrefix("Pacific", false); 162 addPrefix("Mobile", false); 163 addPrefix("In", false); 164 addPrefix("Computa", false); 165 addPrefix("Digital", false); 166 addPrefix("Analog", false); 167 168 addSuffix("Tech", true); 169 addSuffix("Soft", true); 170 addSuffix("Telecom", true); 171 addSuffix("Solutions", false); 172 addSuffix("Works", true); 173 addSuffix("Dyne", false); 174 addSuffix("Services", false); 175 addSuffix("Vers", false); 176 addSuffix("Devices", false); 177 addSuffix("Software", false); 178 addSuffix("Serv", false); 179 addSuffix("Systems", true); 180 addSuffix("Dynamics", true); 181 addSuffix("Net", false); 182 addSuffix("Sys", false); 183 addSuffix("Computing", false); 184 addSuffix("Scape", false); 185 addSuffix("Com", false); 186 addSuffix("Ware", false); 187 addSuffix("Widgets", false); 188 addSuffix("Media", false); 189 addSuffix("Computer", false); 190 addSuffix("Hardware", false); 191 addSuffix("Gizmos", false); 192 addSuffix("Concepts", false); 193 } 194 195 private JPanel createControlPanel() { 196 JPanel controlPanel = new JPanel() { 197 private final Insets insets = new Insets(0, 4, 10, 10); 198 199 @Override 200 public Insets getInsets() { 201 return insets; 202 } 203 }; 204 controlPanel.setLayout(new BoxLayout(controlPanel, BoxLayout.X_AXIS)); 205 206 JPanel prefixPanel = new JPanel(); 207 prefixPanel.setLayout(new BoxLayout(prefixPanel, BoxLayout.Y_AXIS)); 208 prefixPanel.add(new JLabel(resourceManager.getString("ListDemo.prefixes"))); 209 210 JPanel suffixPanel = new JPanel(); 211 suffixPanel.setLayout(new BoxLayout(suffixPanel, BoxLayout.Y_AXIS)); 212 suffixPanel.add(new JLabel(resourceManager.getString("ListDemo.suffixes"))); 213 214 prefixList = new JPanel() { 215 private final Insets insets = new Insets(0, 4, 0, 0); 216 217 @Override 218 public Insets getInsets() { 219 return insets; 220 } 221 }; 222 prefixList.setLayout(new BoxLayout(prefixList, BoxLayout.Y_AXIS)); 223 JScrollPane scrollPane = new JScrollPane(prefixList); 224 scrollPane.getVerticalScrollBar().setUnitIncrement(10); 225 prefixPanel.add(scrollPane); 226 prefixPanel.add(Box.createRigidArea(HGAP10)); 227 228 suffixList = new JPanel() { 229 private final Insets insets = new Insets(0, 4, 0, 0); 230 231 @Override 232 public Insets getInsets() { 233 return insets; 234 } 235 }; 236 suffixList.setLayout(new BoxLayout(suffixList, BoxLayout.Y_AXIS)); 237 scrollPane = new JScrollPane(suffixList); 238 scrollPane.getVerticalScrollBar().setUnitIncrement(10); 239 suffixPanel.add(scrollPane); 240 suffixPanel.add(Box.createRigidArea(HGAP10)); 241 242 controlPanel.add(prefixPanel); 243 controlPanel.add(Box.createRigidArea(HGAP15)); 244 controlPanel.add(suffixPanel); 245 return controlPanel; 246 } 247 248 private final FocusListener listFocusListener = new FocusAdapter() { 249 @Override 250 public void focusGained(FocusEvent e) { 251 JComponent c = (JComponent) e.getComponent(); 252 c.scrollRectToVisible(new Rectangle(0, 0, c.getWidth(), c.getHeight())); 253 } 254 }; 255 256 private void addPrefix(String prefix, boolean selected) { 257 if (prefixAction == null) { 258 prefixAction = new UpdatePrefixListAction(listModel); 259 } 260 final JCheckBox cb = (JCheckBox) prefixList.add(new JCheckBox(prefix)); 261 cb.setSelected(selected); 262 cb.addActionListener(prefixAction); 263 if (selected) { 264 listModel.addPrefix(prefix); 265 } 266 cb.addFocusListener(listFocusListener); 267 } 268 269 private void addSuffix(String suffix, boolean selected) { 270 if (suffixAction == null) { 271 suffixAction = new UpdateSuffixListAction(listModel); 272 } 273 final JCheckBox cb = (JCheckBox) suffixList.add(new JCheckBox(suffix)); 274 cb.setSelected(selected); 275 cb.addActionListener(suffixAction); 276 if (selected) { 277 listModel.addSuffix(suffix); 278 } 279 cb.addFocusListener(listFocusListener); 280 } 281 282 private static class UpdatePrefixListAction extends AbstractAction { 283 284 private final GeneratedListModel listModel; 285 286 protected UpdatePrefixListAction(GeneratedListModel listModel) { 287 this.listModel = listModel; 288 } 289 290 @Override 291 public void actionPerformed(ActionEvent e) { 292 JCheckBox cb = (JCheckBox) e.getSource(); 293 if (cb.isSelected()) { 294 listModel.addPrefix(cb.getText()); 295 } else { 296 listModel.removePrefix(cb.getText()); 297 } 298 } 299 } 300 301 private static class UpdateSuffixListAction extends AbstractAction { 302 303 private final GeneratedListModel listModel; 304 305 protected UpdateSuffixListAction(GeneratedListModel listModel) { 306 this.listModel = listModel; 307 } 308 309 @Override 310 public void actionPerformed(ActionEvent e) { 311 JCheckBox cb = (JCheckBox) e.getSource(); 312 if (cb.isSelected()) { 313 listModel.addSuffix(cb.getText()); 314 } else { 315 listModel.removeSuffix(cb.getText()); 316 } 317 } 318 } 319 320 private static class GeneratedListModel extends AbstractListModel<String> { 321 322 private Permuter permuter; 323 324 private final Vector<String> prefix = new Vector<>(); 325 private final Vector<String> suffix = new Vector<>(); 326 327 private void update() { 328 permuter = new Permuter(getSize()); 329 fireContentsChanged(this, 0, getSize()); 330 } 331 332 public void addPrefix(String s) { 333 if (!prefix.contains(s)) { 334 prefix.addElement(s); 335 update(); 336 } 337 } 338 339 public void removePrefix(String s) { 340 prefix.removeElement(s); 341 update(); 342 } 343 344 public void addSuffix(String s) { 345 if (!suffix.contains(s)) { 346 suffix.addElement(s); 347 update(); 348 } 349 } 350 351 public void removeSuffix(String s) { 352 suffix.removeElement(s); 353 update(); 354 } 355 356 @Override 357 public int getSize() { 358 return prefix.size() * suffix.size(); 359 } 360 361 @Override 362 public String getElementAt(int index) { 363 if (permuter == null) { 364 update(); 365 } 366 // morph the index to another int -- this has the benefit of 367 // causing the list to look random. 368 int j = permuter.map(index); 369 int ps = prefix.size(); 370 int ss = suffix.size(); 371 return prefix.elementAt(j % ps) + suffix.elementAt((j / ps) % ss); 372 } 373 } 374 375 private final ImageIcon[] images = new ImageIcon[7]; 376 377 void loadImages() { 378 images[0] = resourceManager.createImageIcon("red.gif", resourceManager.getString("ListDemo.red")); 379 images[1] = resourceManager.createImageIcon("blue.gif", resourceManager.getString("ListDemo.blue")); 380 images[2] = resourceManager.createImageIcon("yellow.gif", resourceManager.getString("ListDemo.yellow")); 381 images[3] = resourceManager.createImageIcon("green.gif", resourceManager.getString("ListDemo.green")); 382 images[4] = resourceManager.createImageIcon("gray.gif", resourceManager.getString("ListDemo.gray")); 383 images[5] = resourceManager.createImageIcon("cyan.gif", resourceManager.getString("ListDemo.cyan")); 384 images[6] = resourceManager.createImageIcon("magenta.gif", resourceManager.getString("ListDemo.magenta")); 385 } 386 387 private class CompanyLogoListCellRenderer extends DefaultListCellRenderer { 388 389 @Override 390 public Component getListCellRendererComponent( 391 JList<?> list, 392 Object value, 393 int index, 394 boolean isSelected, 395 boolean cellHasFocus) { 396 Component retValue = super.getListCellRendererComponent( 397 list, value, index, isSelected, cellHasFocus 398 ); 399 setIcon(images[index % 7]); 400 return retValue; 401 } 402 } 403} 404