001 /* 002 * $Id: CellContext.java 3424 2009-07-30 10:53:39Z kleopatra $ 003 * 004 * Copyright 2006 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 package org.jdesktop.swingx.renderer; 022 023 import java.awt.Color; 024 import java.io.Serializable; 025 026 import javax.swing.Icon; 027 import javax.swing.JComponent; 028 import javax.swing.UIManager; 029 import javax.swing.border.Border; 030 import javax.swing.border.EmptyBorder; 031 032 /** 033 * Encapsulates a snapshop of cell content and default display context 034 * for usage by a <code>ComponentProvider</code>. 035 * <p> 036 * 037 * One part is the super-set of properties that's traditionally passed into the 038 * core renderers' (Table-, List-, Tree-) getXXCellRendererComponent. Raw 039 * properties which define the context are 040 * 041 * <ul> 042 * <li> selected 043 * <li> focused 044 * <li> expanded 045 * <li> leaf 046 * </ul> 047 * 048 * Similarl to a ComponentAdapter, the properties are a super-set of those for 049 * a concrete component type. It's up to sub-classes (once the generics will be removed, until 050 * then the DefaultXXRenderers - PENDING JW: undecided - even after the generics removal, the 051 * param list in the subclasses are the same) fill any reasonable 052 * defaults for those not applicable to the specific component context. 053 * 054 * With those raw properties given, a CellContext looks up and returns dependent visual 055 * properties as appropriate for the concrete component. Typically, they are taken 056 * from the component if supported, or requested from the UIManager. 057 * Dependent properties are 058 * 059 * <ul> 060 * <li> foreground and background color 061 * <li> border 062 * <li> icon (relevant for trees only) 063 * <li> editable 064 * </ul> 065 * 066 * For a backdoor, the cell location (in horizontal and vertical view coordinates) 067 * and the originating component is accessible as well. Note that they are not necessarily 068 * valid for the "life" component. It's not recommened to actually use them. If needed, 069 * that's probably a sign the api is lacking :-) 070 * <p> 071 * 072 * PENDING JW: the generic parameterization is useful to have a type-safe 073 * installContext but introduces a bunch of generic warnings. Not enough reason to 074 * go for, so will be removed in future versions (see Issue 1042-swingx) 075 * 076 * <ul> 077 * 078 * <li>PENDING: still incomplete? how about Font? 079 * <li>PENDING: protected methods? Probably need to open up - derived 080 * properties should be accessible in client code. 081 * </ul> 082 * 083 * @author Jeanette Winzenburg 084 */ 085 public class CellContext implements Serializable { 086 087 /** the default border for unfocused cells. */ 088 protected static Border noFocusBorder = new EmptyBorder(1, 1, 1, 1); 089 090 /** ?? the default border for unfocused cells. ?? */ 091 private static final Border SAFE_NO_FOCUS_BORDER = new EmptyBorder(1, 1, 1, 092 1); 093 094 /** 095 * Returns the shared border for unfocused cells. 096 * <p> 097 * PENDING: ?? copied from default renderers - why is it done like this? 098 * 099 * @return the border for unfocused cells. 100 */ 101 private static Border getNoFocusBorder() { 102 if (System.getSecurityManager() != null) { 103 return SAFE_NO_FOCUS_BORDER; 104 } else { 105 return noFocusBorder; 106 } 107 } 108 109 /** PENDING JW: maybe make this a WeakReference? Would be a more robust fix for Issue #1040-swingx. */ 110 protected transient JComponent component; 111 112 /** PENDING JW: maybe make this a WeakReference? Would be a more robust fix for Issue #1040-swingx. */ 113 protected transient Object value; 114 115 protected transient int row; 116 117 protected transient int column; 118 119 protected transient boolean selected; 120 121 protected transient boolean focused; 122 123 protected transient boolean expanded; 124 125 protected transient boolean leaf; 126 127 protected transient boolean dropOn; 128 129 // --------------------------- install context 130 131 132 /** 133 * Sets the state of the cell's context. Convenience method for subclasses. 134 * 135 * @param value the content value of the cell 136 * @param row the cell's row index in view coordinates 137 * @param column the cell's column index in view coordinates 138 * @param selected the cell's selected state 139 * @param focused the cell's focused state 140 * @param expanded the cell's expanded state 141 * @param leaf the cell's leaf state 142 */ 143 protected void installState(Object value, int row, int column, 144 boolean selected, boolean focused, boolean expanded, boolean leaf) { 145 this.value = value; 146 this.row = row; 147 this.column = column; 148 this.selected = selected; 149 this.focused = focused; 150 this.expanded = expanded; 151 this.leaf = leaf; 152 } 153 154 /** 155 * Replaces the value of this cell context with the given parameter and returns 156 * the replaced value. 157 * 158 * @param value the new value of the cell context 159 * @return the replaced value of the cell context 160 */ 161 public Object replaceValue(Object value) { 162 Object old = getValue(); 163 this.value = value; 164 return old; 165 } 166 167 // -------------------- accessors of installed state 168 169 /** 170 * Returns the component the cell resides on, may be null. Subclasses are 171 * expected to override and return the component type they are handling. 172 * 173 * @return the component the cell resides on, may be null. 174 */ 175 public JComponent getComponent() { 176 return component; 177 } 178 179 /** 180 * Returns the value of the cell as set in the install. 181 * 182 * @return the content value of the cell. 183 */ 184 public Object getValue() { 185 return value; 186 } 187 188 /** 189 * Returns the cell's row index in view coordinates as set in the install. 190 * 191 * @return the cell's row index. 192 */ 193 public int getRow() { 194 return row; 195 } 196 197 /** 198 * Returns the cell's column index in view coordinates as set in the 199 * install. 200 * 201 * @return the cell's column index. 202 */ 203 public int getColumn() { 204 return column; 205 } 206 207 /** 208 * Returns the selected state as set in the install. 209 * 210 * @return the cell's selected state. 211 */ 212 public boolean isSelected() { 213 return selected; 214 } 215 216 /** 217 * Returns the focused state as set in the install. 218 * 219 * @return the cell's focused state. 220 */ 221 public boolean isFocused() { 222 return focused; 223 } 224 225 /** 226 * Returns the expanded state as set in the install. 227 * 228 * @return the cell's expanded state. 229 */ 230 public boolean isExpanded() { 231 return expanded; 232 } 233 234 /** 235 * Returns the leaf state as set in the install. 236 * 237 * @return the cell's leaf state. 238 */ 239 public boolean isLeaf() { 240 return leaf; 241 } 242 243 // -------------------- accessors for derived state 244 /** 245 * Returns the cell's editability. Subclasses should override to return a 246 * reasonable cell-related state. 247 * <p> 248 * 249 * Here: false. 250 * 251 * @return the cell's editable property. 252 */ 253 public boolean isEditable() { 254 return false; 255 } 256 257 /** 258 * Returns the icon. Subclasses should override to return a reasonable 259 * cell-related state. 260 * <p> 261 * 262 * Here: <code>null</code>. 263 * 264 * @return the cell's icon. 265 */ 266 public Icon getIcon() { 267 return null; 268 } 269 270 /** 271 * Returns a boolean indicating if the cell is a drop location with any of the dropOn 272 * modes. It's up to subclasses to implement. 273 * <p> 274 * 275 * Here: false. 276 * 277 * @return true if the current cell is a drop location with any of the dropOn modes, 278 * false otherwise 279 */ 280 protected boolean isDropOn() { 281 return dropOn; 282 } 283 284 /** 285 * Returns the foreground color of the renderered component or null if the 286 * component is null 287 * <p> 288 * 289 * PENDING: fallback to UI properties if comp == null? 290 * 291 * @return the foreground color of the rendered component. 292 */ 293 protected Color getForeground() { 294 if (isDropOn()) { 295 return getSelectionForeground(); 296 } 297 return getComponent() != null ? getComponent().getForeground() : null; 298 } 299 300 /** 301 * Returns the background color of the renderered component or null if the 302 * component is null 303 * <p> 304 * 305 * PENDING: fallback to UI properties if comp == null? 306 * 307 * @return the background color of the rendered component. 308 */ 309 protected Color getBackground() { 310 if (isDropOn()) { 311 return getSelectionBackground(); 312 } 313 return getComponent() != null ? getComponent().getBackground() : null; 314 } 315 316 /** 317 * Returns the default selection background color of the renderered 318 * component. Typically, the color is LF specific. It's up to subclasses to 319 * look it up. Here: returns null. 320 * <p> 321 * 322 * PENDING: return UI properties here? 323 * 324 * @return the selection background color of the rendered component. 325 */ 326 protected Color getSelectionBackground() { 327 return null; 328 } 329 330 /** 331 * Returns the default selection foreground color of the renderered 332 * component. Typically, the color is LF specific. It's up to subclasses to 333 * look it up. Here: returns null. 334 * <p> 335 * 336 * PENDING: return UI properties here? 337 * 338 * @return the selection foreground color of the rendered component. 339 */ 340 protected Color getSelectionForeground() { 341 return null; 342 } 343 344 /** 345 * Returns the default focus border of the renderered component. Typically, 346 * the border is LF specific. 347 * 348 * @return the focus border of the rendered component. 349 */ 350 protected Border getFocusBorder() { 351 Border border = null; 352 if (isSelected()) { 353 border = UIManager 354 .getBorder(getUIKey("focusSelectedCellHighlightBorder")); 355 } 356 if (border == null) { 357 border = UIManager.getBorder(getUIKey("focusCellHighlightBorder")); 358 } 359 return border; 360 } 361 362 /** 363 * Returns the default border of the renderered component depending on cell 364 * state. Typically, the border is LF specific. 365 * <p> 366 * 367 * Here: returns the focus border if the cell is focused, the context 368 * defined no focus border otherwise. 369 * 370 * @return the default border of the rendered component. 371 */ 372 protected Border getBorder() { 373 if (isFocused()) { 374 return getFocusBorder(); 375 } 376 return getNoFocusBorder(); 377 } 378 379 /** 380 * Returns the default focused foreground color of the renderered component. 381 * Typically, the color is LF specific. 382 * 383 * @return the focused foreground color of the rendered component. 384 */ 385 protected Color getFocusForeground() { 386 return UIManager.getColor(getUIKey("focusCellForeground")); 387 } 388 389 /** 390 * Returns the default focused background color of the renderered component. 391 * Typically, the color is LF specific. 392 * 393 * @return the focused background color of the rendered component. 394 */ 395 protected Color getFocusBackground() { 396 return UIManager.getColor(getUIKey("focusCellBackground")); 397 } 398 399 protected Color getDropCellForeground() { 400 return UIManager.getColor(getUIKey("dropCellForeground")); 401 } 402 403 protected Color getDropCellBackground() { 404 return UIManager.getColor(getUIKey("dropCellBackground")); 405 } 406 // ----------------------- convenience 407 408 /** 409 * Convenience method to build a component type specific lookup key for the 410 * UIManager. 411 * 412 * @param key the general part of the key 413 * @return a composed key build of a component type prefix and the input. 414 */ 415 protected String getUIKey(String key) { 416 return getUIPrefix() + key; 417 } 418 419 /** 420 * Returns the component type specific prefix of keys for lookup in the 421 * UIManager. Subclasses must override, here: returns the empty String. 422 * 423 * @return the component type specific prefix. 424 */ 425 protected String getUIPrefix() { 426 return ""; 427 } 428 429 }