001/* 002 * $Id$ 003 * 004 * Copyright 2009 Sun Microsystems, Inc., 4150 Network Circle, 005 * Santa Clara, California 95054, U.S.A. All rights reserved. 006 * 007 * This library is free software; you can redistribute it and/or 008 * modify it under the terms of the GNU Lesser General Public 009 * License as published by the Free Software Foundation; either 010 * version 2.1 of the License, or (at your option) any later version. 011 * 012 * This library is distributed in the hope that it will be useful, 013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 015 * Lesser General Public License for more details. 016 * 017 * You should have received a copy of the GNU Lesser General Public 018 * License along with this library; if not, write to the Free Software 019 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 020 * 021 */ 022package org.jdesktop.swingx.plaf.synth; 023 024import java.awt.Color; 025import java.awt.Graphics; 026import java.beans.PropertyChangeEvent; 027import java.beans.PropertyChangeListener; 028 029import javax.swing.JComponent; 030import javax.swing.plaf.ComponentUI; 031import javax.swing.plaf.UIResource; 032import javax.swing.plaf.synth.ColorType; 033import javax.swing.plaf.synth.Region; 034import javax.swing.plaf.synth.SynthConstants; 035import javax.swing.plaf.synth.SynthContext; 036import javax.swing.plaf.synth.SynthLookAndFeel; 037import javax.swing.plaf.synth.SynthStyle; 038 039import org.jdesktop.swingx.SwingXUtilities; 040import org.jdesktop.swingx.plaf.basic.core.BasicXListUI; 041 042/** 043 * TODO add type doc 044 * 045 * @author Jeanette Winzenburg 046 */ 047public class SynthXListUI extends BasicXListUI 048 // PENDING JW: SynthUI is sun package (here: used by c&p'ed SynthBorder) - replace? 049 // maybe not: SynthLookUp looks up styles from delegates of type SynthUI only 050 implements SynthConstants, SynthUI /*, PropertyChangeListener */{ 051 052 private SynthStyle style; 053 @SuppressWarnings("unused") 054 private boolean useListColors; 055 @SuppressWarnings("unused") 056 private boolean useUIBorder; 057 058 /** 059 * Returns a new instance of SynthXListUI. SynthXListUI delegates are 060 * allocated one per JList. 061 * 062 * @return A new ListUI implementation for the Synth look and feel. 063 */ 064 public static ComponentUI createUI(JComponent list) { 065 return new SynthXListUI(); 066 } 067 068 /** 069 * {@inheritDoc} <p> 070 * Overridden to fill background, Synth-style. 071 */ 072 @Override 073 public void update(Graphics g, JComponent c) { 074 SynthContext context = getContext(c); 075 SynthUtils.update(context, g); 076 paintBorder(context, g, 0, 0, c.getWidth(), c.getHeight()); 077 paint(g, c); 078 } 079 080 081 /** 082 * {@inheritDoc} <p> 083 * Overridden to update style if appropriate. 084 */ 085 @Override 086 protected PropertyChangeListener createPropertyChangeListener() { 087 PropertyChangeListener l = new PropertyChangeHandler() { 088 089 @Override 090 public void propertyChange(PropertyChangeEvent e) { 091 if (SynthUtils.shouldUpdateStyle(e)) { 092 updateStyle(); 093 } 094 super.propertyChange(e); 095 } 096 097 }; 098 return l; 099 } 100 101 /** 102 * {@inheritDoc} <p> 103 * Overridden to install properties, Synth-style. 104 */ 105 @Override 106 protected void installDefaults() { 107 // never happens - the delegate renderer is always not-null and 108 // not a ui-resource 109// if (list.getCellRenderer() == null || 110// (list.getCellRenderer() instanceof UIResource)) { 111// list.setCellRenderer(new SynthListCellRenderer()); 112// } 113 updateStyle(); 114 } 115 116 private void updateStyle() { 117 // compare local reference to style from factory 118 // nothing to do if same 119 if (style == getStyle()) return; 120 // check if this is called from init or from later update 121 // if from later updates, need to cleanup old 122 boolean refresh = style != null; 123 if (refresh) { 124 style.uninstallDefaults(getContext(ENABLED)); 125 } 126 // update local reference 127 style = getStyle(); 128 // special case border 129 installSynthBorder(); 130 // install defaults 131 style.installDefaults(getContext(ENABLED)); 132 // install selected properties 133 SynthContext selectedContext = getContext(SELECTED); 134 Color sbg = list.getSelectionBackground(); 135 if (sbg == null || sbg instanceof UIResource) { 136 list.setSelectionBackground(style.getColor( 137 selectedContext, ColorType.TEXT_BACKGROUND)); 138 } 139 140 Color sfg = list.getSelectionForeground(); 141 if (sfg == null || sfg instanceof UIResource) { 142 list.setSelectionForeground(style.getColor( 143 selectedContext, ColorType.TEXT_FOREGROUND)); 144 } 145 // install cell height 146 int height = style.getInt(selectedContext, "List.cellHeight", -1); 147 if (height != -1) { 148 list.setFixedCellHeight(height); 149 } 150 // we do this because ... ?? 151 if (refresh) { 152 uninstallKeyboardActions(); 153 installKeyboardActions(); 154 } 155 // install currently unused properties of this delegate 156 useListColors = style.getBoolean(selectedContext, 157 "List.rendererUseListColors", true); 158 useUIBorder = style.getBoolean(selectedContext, 159 "List.rendererUseUIBorder", true); 160 161 } 162 163 /** 164 * Installs a SynthBorder from the current style, if ui-installable. 165 * 166 * @param context the context 167 */ 168 protected void installSynthBorder() { 169 if (SwingXUtilities.isUIInstallable(list.getBorder())) { 170 list.setBorder(new SynthBorder(this, style.getInsets(getContext(ENABLED), null))); 171 } 172 } 173 174 /** 175 * {@inheritDoc} <p> 176 * Overridden to uninstall properties, Synth-style, after calling super. 177 */ 178 @Override 179 protected void uninstallDefaults() { 180 super.uninstallDefaults(); 181 style.uninstallDefaults(getContext(ENABLED)); 182 style = null; 183 } 184 185 186 /** 187 * Paints border with the context's style's painter. 188 * Implemented for SynthUI interface. 189 */ 190 @Override 191 public void paintBorder(SynthContext context, Graphics g, int x, int y, 192 int w, int h) { 193 SynthUtils.getPainter(context).paintListBorder(context, g, x, y, w, h); 194 } 195 196 /** 197 * {@inheritDoc} <p> 198 * 199 * Returns a context for the component's current state. 200 * Implemented for SynthUI interface. <p> 201 * 202 * PENDING JW: not entirely sure if allowed ... but need to replace SynthUI anyway?. 203 * 204 * @throws IllegalArgumentException if the component is not controlled by this 205 * delegate 206 */ 207 @Override 208 public SynthContext getContext(JComponent c) { 209 if (c != list) throw new IllegalArgumentException("must be ui-delegate for component"); 210 return getContext(); 211 } 212 213 /** 214 * Returns the context based on current state. 215 * @return 216 */ 217 private SynthContext getContext() { 218 return getContext(getComponentState()); 219 } 220 221 /** 222 * Returns the current component state for the controlled list. 223 * @return 224 */ 225 private int getComponentState() { 226 return SynthUtils.getComponentState(list); 227 } 228 229 /** 230 * Returns a Context with the given component state. 231 * 232 * @param state 233 * @return 234 */ 235 private SynthContext getContext(int state) { 236 return SynthUtils.getContext(list, getRegion(), style, state); 237 } 238 239 private Region getRegion() { 240 return XRegion.getXRegion(list, true); 241 } 242 243 244 /** 245 * Returns the style for this component from the style factory. 246 * @return 247 */ 248 private SynthStyle getStyle() { 249 return SynthLookAndFeel.getStyleFactory().getStyle(list, getRegion()); 250 } 251 252 253// private class SynthListCellRenderer extends DefaultListCellRenderer.UIResource { 254// public String getName() { 255// return "List.cellRenderer"; 256// } 257// 258// public void setBorder(Border b) { 259// if (useUIBorder || b instanceof SynthBorder) { 260// super.setBorder(b); 261// } 262// } 263// 264// public Component getListCellRendererComponent(JList list, Object value, 265// int index, boolean isSelected, boolean cellHasFocus) { 266// if (!useListColors && (isSelected || cellHasFocus)) { 267// SynthLookAndFeel.setSelectedUI((SynthLabelUI)SynthLookAndFeel. 268// getUIOfType(getUI(), SynthLabelUI.class), 269// isSelected, cellHasFocus, list.isEnabled(), false); 270// } 271// else { 272// SynthLookAndFeel.resetSelectedUI(); 273// } 274// 275// super.getListCellRendererComponent(list, value, index, 276// isSelected, cellHasFocus); 277// return this; 278// } 279// 280// public void paint(Graphics g) { 281// super.paint(g); 282// SynthLookAndFeel.resetSelectedUI(); 283// } 284// } 285 286 287}