// ------------------- ShowUIDefaults.java ------------------------- /******************************************************************* =========================================== Camickr's ShowUIDefaults Properties Viewer =========================================== By Camickr Source Contributions by Dr. Lazlo Jamf, Thomas Kellerer, Brent Allen Parrish Compiled on 14 May 2008 This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. ********************************************************************/ import java.awt.*; import java.awt.event.*; import java.util.*; import javax.swing.*; import javax.swing.text.*; import javax.swing.plaf.*; import javax.swing.table.AbstractTableModel; import javax.swing.table.TableCellRenderer; import javax.swing.border.Border; /** * ShowUIDefaults class lists all of the various properties found in the * javax.swing.UIDefaults LAF collection and presents the data in a * javax.swing.JTable and categorized tabbed pane view. Provides support * for common data transfer operations (i.e. copy/paste) and features * four changeable LookAndFeels (LAF), * * * @param title java.lang.String sets the window titlebar string. * @author camickr */ public class ShowUIDefaults extends JFrame implements ActionListener { JFrame frame; JTabbedPane tabbedPane; JButton metal; JButton windows; JButton motif; JButton basic; JButton classic; JButton jamf; SampleRenderer sampleRenderer; /** * Class constructor sets this window's titlebar string; sets up the tabbed * pane layout; instantiates the javax.swing.JButton objects and * sets this instance's javax.swing.JFrame member. * */ public ShowUIDefaults(String title) { super(title); frame = this; getContentPane().setLayout( new BorderLayout() ); tabbedPane = getTabbedPane(); getContentPane().add( tabbedPane ); JPanel buttons = new JPanel(); buttons.setLayout( new GridLayout( 1, 5) ); getContentPane().add(buttons, BorderLayout.SOUTH); metal = new JButton( "Metal" ); metal.addActionListener( this ); buttons.add(metal); windows = new JButton( "Windows" ); windows.addActionListener( this ); buttons.add(windows); motif = new JButton( "Motif" ); motif.addActionListener( this ); buttons.add(motif); // Added classic LAF -Brent P. classic = new JButton( "Windows Classic" ); classic.addActionListener( this ); buttons.add(classic); jamf = new JButton( "Jamf's Listing" ); jamf.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { try { String[] args = {}; Listing.main(args); } catch(Exception ex) { System.out.println(ex.getMessage()); } } }); // End anonymous buttons.add(jamf); } /** * Handles events as specified by the java.awt.event.ActionListener * interface. * * @param e java.awt.event.ActionEvent. */ public void actionPerformed(ActionEvent e) { String laf = ""; Object o = e.getSource(); if (o.equals(metal)) laf = "javax.swing.plaf.metal.MetalLookAndFeel"; else if (o.equals(windows)) laf = "com.sun.java.swing.plaf.windows.WindowsLookAndFeel"; else if (o.equals(motif)) laf = "com.sun.java.swing.plaf.motif.MotifLookAndFeel"; else if (o.equals(classic)) laf = "com.sun.java.swing.plaf.windows.WindowsClassicLookAndFeel"; try { UIManager.setLookAndFeel(laf); } catch (Exception e2) { System.out.println(e2.getMessage()); e2.printStackTrace(); } getContentPane().remove(tabbedPane); tabbedPane = getTabbedPane(); getContentPane().add( tabbedPane ); SwingUtilities.updateComponentTreeUI(frame); frame.pack(); } /** * Parses the javax.swing.UIDefaults collection and returns the tabbed * pane view for this window. * * @return pane javax.swing.JTabbedPane of this instance's key/value pairs. */ private JTabbedPane getTabbedPane() { // Modified: Brent Allen Parrish // Added: Generic type hinting for collection objects Map components = new TreeMap(); UIDefaults defaults = UIManager.getDefaults(); // Build of Map of attributes for each component // Modified: Brent Allen Parrish // Added: Changed the name of the Enumeration variable from 'enum' // to 'enum1' because 'enum' is now a keyword in Java 6. for ( Enumeration enum1 = defaults.keys(); enum1.hasMoreElements(); ) { Object key = enum1.nextElement(); Object value = defaults.get( key ); Map componentMap = getComponentMap( components, key.toString() ); if ( componentMap != null ) { try { // Modified: Brent Allen Parrish // Added try/catch for java.lang.ClassCastException being thrown due // to bad comparisons between immutable and mutable objects, in this case, // java.lang.StringBuffer and java.lang.Comparable. if(key instanceof StringBuffer) { key = (Comparable) key.toString(); } componentMap.put( key, value ); } catch(ClassCastException cce) { System.out.println(cce.getMessage()); cce.printStackTrace(); } } } JTabbedPane pane = new JTabbedPane( SwingConstants.BOTTOM ); pane.setPreferredSize( new Dimension( 800, 400 ) ); addComponentTabs( pane, components ); return pane; } /** * Returns an java.util.Map object of this collection's components. * * @param components java.util.Map collection of components. * @param key java.lang.String of this instance's UIDefaults key value. * @return componentMap java.util.Map collection of mapped components. */ @SuppressWarnings(value = "unchecked") private Map getComponentMap( Map components, String key ) { if ( key.startsWith("class") | key.startsWith("javax") ) return null; // Component name is found before the first "." String componentName; int pos = key.indexOf( "." ); if (pos == -1) if (key.endsWith( "UI" ) ) componentName = key.substring( 0, key.length() - 2 ); else componentName = "System Colors"; else componentName = key.substring( 0, pos ); // Get the Map for this particular component Object componentMap = components.get(componentName ); if (componentMap == null) { componentMap = new TreeMap(); components.put( componentName, componentMap ); } return (Map)componentMap; } /** * Adds this window's component tabs and builds the table model of mapped components. * * @param pane javax.swing.JTabbedPane * @param components java.util.Map<Object, Object> */ private void addComponentTabs(JTabbedPane pane, Map components) { sampleRenderer = new SampleRenderer(); String[ ] colName = {"Key", "Value", "Sample"}; Set c = components.keySet(); for (Iterator ci = c.iterator(); ci.hasNext();) { String component = (String)ci.next(); Map attributes = (Map)components.get( component ); Object[ ][ ] rowData = new Object[ attributes.size() ][ 3 ]; int i = 0; Set a = attributes.keySet(); for(Iterator ai = a.iterator(); ai.hasNext(); i++) { String attribute = (String)ai.next(); rowData[ i ] [ 0 ] = attribute; Object o = attributes.get(attribute); if (o != null) { rowData[ i ] [ 1 ] = o.toString(); rowData[ i ] [ 2 ] = ""; if (o instanceof Font) rowData[ i ] [ 2 ] = (Font)o; if (o instanceof Color) rowData[ i ] [ 2 ] = (Color)o; if (o instanceof Icon) { // Modified: Brent Allen Parrish // Added: Added Dr. Lazlo Jamf's IconAdapter wrapper for objects // implementing the javax.swing.Icon interface and a try/catch // block for good measure. try { rowData[ i ] [ 2 ] = new IconAdapter((Icon)o, attribute); } catch(ClassCastException ignored) { return; } } if (o instanceof Border) { // Modified: Brent Allen Parrish // Added: Added Dr. Lazlo Jamf's BorderAdapter wrapper for objects // implementing the javax.swing.Border interface and a try/catch // block for good measure. try { rowData[ i ] [ 2 ] = new BorderAdapter((Border)o, attribute); } catch(ClassCastException ignored) { return; } } } else { rowData[ i ] [ 1 ] = ""; rowData[ i ] [ 2 ] = ""; } } // ----------------------------------------------------------- // Modified: Brent Allen Parrish // Added: UIDefaultsPopup menu for selecting and copying // text from the table cells. Added anonymous classes // to the JTable to enable copying and selection of table // cell text. // ----------------------------------------------------------- JTextField cellEditor = new JTextField(); UIDefaultsPopup popup = new UIDefaultsPopup(this, cellEditor); cellEditor.setComponentPopupMenu(popup); cellEditor.setEditable(false); // --------------------------end mod--------------------------- MyTableModel myModel = new MyTableModel( rowData, colName ); JTable table = new JTable( myModel ) { // ------------------------------------------------------- // Modified: Brent Allen Parrish // Enables table cell editing for copy/paste data transfer. // ------------------------------------------------------- public boolean isCellEditable(int rowIndex, int vColIndex) { return true; } // Selects this text when a user double-clicks a table cell. public boolean editCellAt(int row, int column, EventObject e) { boolean result = super.editCellAt(row, column, e); final Component editor = getEditorComponent(); if (editor != null && editor instanceof JTextComponent) { if (e == null) { ((JTextComponent)editor).selectAll(); } else { // Schedule a job for the dispatch thread if // java.awt.event.EventObject is null. SwingUtilities.invokeLater(new Runnable() { public void run() { ((JTextComponent)editor).selectAll(); } }); } } // ----------------------end mod----------------------- return result; } }; // End anonymous RowHeightResizer rhr = new UIDefaultsResizer(table); // Thomas Kellerer's resizer adapter table.setColumnSelectionAllowed(false); table.setRowSelectionAllowed(true); table.setDefaultRenderer(sampleRenderer.getClass(), sampleRenderer); table.getColumnModel().getColumn(0).setPreferredWidth(250); table.getColumnModel().getColumn(1).setPreferredWidth(500); table.getColumnModel().getColumn(2).setPreferredWidth(50); // Sets simple cell editor for copy/paste -Brent P. // --------------------------------------------------------------------------------- table.getColumnModel().getColumn(0).setCellEditor(new DefaultCellEditor(cellEditor)); table.getColumnModel().getColumn(1).setCellEditor(new DefaultCellEditor(cellEditor)); // --------------------------------------------------------------------------------- pane.addTab( component, new JScrollPane( table ) ); } } /** * MyTableModel class builds the javax.swing.JTable table model for this table. * * @param rowData java.lang.Object[][] matrix array of this row's data. * @param columnNames java.lang.String[] array of strings this column's data. */ class MyTableModel extends AbstractTableModel { private String[] columnNames; private Object[][] rowData; public MyTableModel(Object[][] rowData, String[] columnNames) { this.rowData = rowData; this.columnNames = columnNames; } public int getColumnCount() { return columnNames.length; } public int getRowCount() { return rowData.length; } public String getColumnName(int col) { return columnNames[col]; } public Object getValueAt(int row, int col) { return rowData[row][col]; } public Class getColumnClass(int c) { Object o; if ( c == 2 ) o = sampleRenderer; else o = getValueAt(0, c); return o.getClass(); } public void setValueAt(Object value, int row, int col) { rowData[row][col] = value; fireTableCellUpdated(row, col); } } /** * SampleRenderer class provides a renderer for painting this * javax.swing.JTable cell's font, color and icon objects. * Sub-classes javax.swing.JLabel. */ class SampleRenderer extends JLabel implements TableCellRenderer { /** * Class constructor calls parent constructor, sets the * horizontal alignment to centered and sets up the background. * * @see javax.swing.JLabel#setOpaque */ public SampleRenderer() { super(); setHorizontalAlignment( SwingConstants.CENTER ); setOpaque(true); //MUST do this for background to show up. } /** * Returns this table cell's renderer component. * * @param table javax.swing.JTable for which this component is being rendered. * @param sample javax.lang.Object for this current UIDefualts java.lang.Object. * @param isSelected boolean indicating this component's selected status. * @param hasFocus boolean indicating this component's focus state. * @param row int value indicates row position in this table. * @param column int value indicates column position in this table. * @return this java.awt.Component table cell renderer component. */ public Component getTableCellRendererComponent( JTable table, Object sample, boolean isSelected, boolean hasFocus, int row, int column ) { setBackground( null ); setIcon( null ); setText( "" ); if ( sample instanceof Color ) { setBackground( (Color)sample ); } if ( sample instanceof Font ) { setText( "Sample" ); setFont( (Font)sample ); } if ( sample instanceof Border ) { setBorder( (Border)sample ); } if ( sample instanceof Icon ) { setIcon((Icon)sample); } return this; } } /** * Starts the app synchronously on the EDT so this program can run in a * seperate thread. * * @param args java.lang.String array of commandline arguments. */ public static void main(String[] args) { // Schedule a job for the dispatch thread. EventQueue.invokeLater(new Runnable() { /** * Starts this application. * Implements java.lang.Runnable interface * which allows running this application in a seperate thread. */ public void run() { // Set the Look and Feel try { UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); } catch(Exception e) { } // The attributes of each component will be shown on a separate tab JFrame f = new ShowUIDefaults( "Camickr 1.0 UI Defaults Viewer" ); f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); f.pack(); // Centers window location within the viewing screen Dimension center = WindowUtil.centerWindow(null, f); f.setLocation(center.width, center.height); f.setVisible(true); } }); // End anonymous } } // End class