001/* 002 * $Id: HighlightPredicate.java 3935 2011-03-02 19:06:41Z kschaefe $ 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 */ 021package org.jdesktop.swingx.decorator; 022 023import java.awt.Component; 024import java.awt.Insets; 025import java.awt.Point; 026import java.awt.Rectangle; 027import java.math.BigDecimal; 028import java.util.ArrayList; 029import java.util.Arrays; 030import java.util.Collection; 031import java.util.List; 032 033import javax.swing.AbstractButton; 034import javax.swing.Icon; 035import javax.swing.JComponent; 036import javax.swing.JLabel; 037import javax.swing.SwingConstants; 038import javax.swing.SwingUtilities; 039 040import org.jdesktop.swingx.rollover.RolloverProducer; 041import org.jdesktop.swingx.util.Contract; 042 043/** 044 * A controller which decides whether or not a visual decoration should 045 * be applied to the given Component in the given ComponentAdapter state. 046 * This is a on/off <b>decision</b> only, the actual decoration is 047 * left to the AbstractHighlighter which typically respects this predicate. <p> 048 * 049 * Note: implementations should be immutable because <code>Highlighter</code>s 050 * guarantee to notify listeners on any state change which might effect the highlight. 051 * They can't comply to that contract if predicate internal state changes under their 052 * feet. If dynamic predicate state is required, the safe alternative is to create 053 * and set a new predicate.<p> 054 * 055 * 056 * @author Jeanette Winzenburg 057 * 058 * @see AbstractHighlighter 059 */ 060public interface HighlightPredicate { 061 062 /** 063 * Returns a boolean to indicate whether the component should be 064 * highlighted.<p> 065 * 066 * Note: both parameters should be considered strictly read-only! 067 * 068 * @param renderer the cell renderer component that is to be decorated, 069 * must not be null 070 * @param adapter the ComponentAdapter for this decorate operation, 071 * most not be null 072 * @return a boolean to indicate whether the component should be highlighted. 073 */ 074 boolean isHighlighted(Component renderer, ComponentAdapter adapter); 075 076 077//--------------------- implemented Constants 078 /** 079 * Unconditional true. 080 */ 081 public static final HighlightPredicate ALWAYS = new HighlightPredicate() { 082 083 /** 084 * {@inheritDoc} <p> 085 * 086 * Implemented to return true always. 087 */ 088 @Override 089 public boolean isHighlighted(Component renderer, ComponentAdapter adapter) { 090 return true; 091 } 092 093 }; 094 095 /** 096 * Unconditional false. 097 */ 098 public static final HighlightPredicate NEVER = new HighlightPredicate() { 099 100 /** 101 * {@inheritDoc} <p> 102 * 103 * Implemented to return false always. 104 */ 105 @Override 106 public boolean isHighlighted(Component renderer, ComponentAdapter adapter) { 107 return false; 108 } 109 110 }; 111 112 /** 113 * Rollover Row. 114 */ 115 public static final HighlightPredicate ROLLOVER_ROW = new HighlightPredicate() { 116 117 /** 118 * @inheritDoc 119 * Implemented to return true if the adapter's component is enabled and 120 * the row of its rollover property equals the adapter's row, returns 121 * false otherwise. 122 * 123 * @see org.jdesktop.swingx.rollover.RolloverProducer 124 */ 125 @Override 126 public boolean isHighlighted(Component renderer, ComponentAdapter adapter) { 127 if (!adapter.getComponent().isEnabled()) return false; 128 Point p = (Point) adapter.getComponent().getClientProperty( 129 RolloverProducer.ROLLOVER_KEY); 130 return p != null && p.y == adapter.row; 131 } 132 133 }; 134 135 /** 136 * Rollover Column. 137 */ 138 public static final HighlightPredicate ROLLOVER_COLUMN = new HighlightPredicate() { 139 140 /** 141 * @inheritDoc 142 * Implemented to return true if the adapter's component is enabled and 143 * the column of its rollover property equals the adapter's columns, returns 144 * false otherwise. 145 * 146 * @see org.jdesktop.swingx.rollover.RolloverProducer 147 */ 148 @Override 149 public boolean isHighlighted(Component renderer, ComponentAdapter adapter) { 150 if (!adapter.getComponent().isEnabled()) return false; 151 Point p = (Point) adapter.getComponent().getClientProperty( 152 RolloverProducer.ROLLOVER_KEY); 153 return p != null && p.x == adapter.column; 154 } 155 156 }; 157 /** 158 * Rollover Cell. 159 */ 160 public static final HighlightPredicate ROLLOVER_CELL = new HighlightPredicate() { 161 162 /** 163 * @inheritDoc 164 * Implemented to return true if the adapter's component is enabled and 165 * the column of its rollover property equals the adapter's columns, returns 166 * false otherwise. 167 * 168 * @see org.jdesktop.swingx.rollover.RolloverProducer 169 */ 170 @Override 171 public boolean isHighlighted(Component renderer, ComponentAdapter adapter) { 172 if (!adapter.getComponent().isEnabled()) return false; 173 Point p = (Point) adapter.getComponent().getClientProperty( 174 RolloverProducer.ROLLOVER_KEY); 175 return p != null && p.y == adapter.row && p.x == adapter.column; 176 } 177 178 }; 179 180 /** 181 * Is editable. 182 */ 183 public static final HighlightPredicate EDITABLE = new HighlightPredicate() { 184 /** 185 * {@inheritDoc} <p> 186 * 187 * Implemented to return true is the given adapter isEditable, false otherwise. 188 */ 189 @Override 190 public boolean isHighlighted(Component renderer, ComponentAdapter adapter) { 191 return adapter.isEditable(); 192 } 193 }; 194 195 /** 196 * Convenience for read-only (same as !editable). 197 */ 198 public static final HighlightPredicate READ_ONLY = new HighlightPredicate() { 199 /** 200 * {@inheritDoc} <p> 201 * 202 * Implemented to return false is the given adapter isEditable, true otherwise. 203 */ 204 @Override 205 public boolean isHighlighted(Component renderer, ComponentAdapter adapter) { 206 return !adapter.isEditable(); 207 } 208 }; 209 210 /** 211 * Leaf predicate. 212 */ 213 public static final HighlightPredicate IS_LEAF = new HighlightPredicate() { 214 /** 215 * {@inheritDoc} <p> 216 * 217 * Implemented to return true if the given adapter isLeaf, false otherwise. 218 */ 219 @Override 220 public boolean isHighlighted(Component renderer, ComponentAdapter adapter) { 221 return adapter.isLeaf(); 222 } 223 }; 224 225 /** 226 * Folder predicate - convenience: same as !IS_LEAF. 227 */ 228 public static final HighlightPredicate IS_FOLDER = new HighlightPredicate() { 229 /** 230 * {@inheritDoc} <p> 231 * 232 * Implemented to return false if the given adapter isLeaf, true otherwise. 233 */ 234 @Override 235 public boolean isHighlighted(Component renderer, ComponentAdapter adapter) { 236 return !adapter.isLeaf(); 237 } 238 }; 239 240 /** 241 * Selected predicate. 242 */ 243 public static final HighlightPredicate IS_SELECTED = new HighlightPredicate() { 244 245 @Override 246 public boolean isHighlighted(Component renderer, 247 ComponentAdapter adapter) { 248 return adapter.isSelected(); 249 } 250 251 }; 252 253 /** 254 * Determines if the displayed text is truncated. 255 * 256 * @author Karl Schaefer 257 */ 258 public static final HighlightPredicate IS_TEXT_TRUNCATED = new HighlightPredicate() { 259 @Override 260 public boolean isHighlighted(Component renderer, ComponentAdapter adapter) { 261 JComponent c = renderer instanceof JComponent ? (JComponent) renderer : null; 262 String text = adapter.getString(); 263 Icon icon = null; 264 //defaults from JLabel 265 int verticalAlignment = SwingConstants.CENTER; 266 int horizontalAlignment = SwingConstants.LEADING; 267 int verticalTextPosition = SwingConstants.CENTER; 268 int horizontalTextPosition = SwingConstants.TRAILING; 269 int gap = 0; 270 271 if (renderer instanceof JLabel) { 272 icon = ((JLabel) renderer).getIcon(); 273 gap = ((JLabel) renderer).getIconTextGap(); 274 } else if (renderer instanceof AbstractButton) { 275 icon = ((AbstractButton) renderer).getIcon(); 276 gap = ((AbstractButton) renderer).getIconTextGap(); 277 } 278 279 Rectangle cellBounds = adapter.getCellBounds(); 280 if (c != null && c.getBorder() != null) { 281 Insets insets = c.getBorder().getBorderInsets(c); 282 cellBounds.width -= insets.left + insets.right; 283 cellBounds.height -= insets.top + insets.bottom; 284 } 285 286 String result = SwingUtilities.layoutCompoundLabel(c, renderer 287 .getFontMetrics(renderer.getFont()), text, icon, verticalAlignment, 288 horizontalAlignment, verticalTextPosition, horizontalTextPosition, cellBounds, 289 new Rectangle(), new Rectangle(), gap); 290 291 return !text.equals(result); 292 } 293 }; 294 295 /** 296 * Focus predicate. 297 */ 298 public static final HighlightPredicate HAS_FOCUS = new HighlightPredicate() { 299 /** 300 * {@inheritDoc} <p> 301 * 302 * Implemented to return truw if the given adapter hasFocus, false otherwise. 303 */ 304 @Override 305 public boolean isHighlighted(Component renderer, ComponentAdapter adapter) { 306 return adapter.hasFocus(); 307 } 308 }; 309 /** 310 * Even rows. 311 * 312 * PENDING: this is zero based (that is "really" even 0, 2, 4 ..), differing 313 * from the old AlternateRowHighlighter. 314 * 315 */ 316 public static final HighlightPredicate EVEN = new HighlightPredicate() { 317 318 @Override 319 public boolean isHighlighted(Component renderer, ComponentAdapter adapter) { 320 return adapter.row % 2 == 0; 321 } 322 323 }; 324 325 /** 326 * Odd rows. 327 * 328 * PENDING: this is zero based (that is 1, 3, 4 ..), differs from 329 * the old implementation which was one based? 330 * 331 */ 332 public static final HighlightPredicate ODD = new HighlightPredicate() { 333 334 @Override 335 public boolean isHighlighted(Component renderer, ComponentAdapter adapter) { 336 return !EVEN.isHighlighted(renderer, adapter); 337 } 338 339 }; 340 341 /** 342 * Negative BigDecimals. 343 */ 344 public static final HighlightPredicate BIG_DECIMAL_NEGATIVE = new HighlightPredicate() { 345 346 @Override 347 public boolean isHighlighted(Component renderer, 348 ComponentAdapter adapter) { 349 return (adapter.getValue() instanceof BigDecimal) 350 && ((BigDecimal) adapter.getValue()).compareTo(BigDecimal.ZERO) < 0; 351 } 352 353 }; 354 355 /** 356 * Negative Number. 357 */ 358 public static final HighlightPredicate INTEGER_NEGATIVE = new HighlightPredicate() { 359 360 @Override 361 public boolean isHighlighted(Component renderer, 362 ComponentAdapter adapter) { 363 return (adapter.getValue() instanceof Number) 364 && ((Number) adapter.getValue()).intValue() < 0; 365 } 366 367 }; 368 369 // PENDING: these general type empty arrays don't really belong here? 370 public static final HighlightPredicate[] EMPTY_PREDICATE_ARRAY = new HighlightPredicate[0]; 371 public static final Object[] EMPTY_OBJECT_ARRAY = new Object[0]; 372 public static final Integer[] EMPTY_INTEGER_ARRAY = new Integer[0]; 373 374//----------------- logical implementations amongst HighlightPredicates 375 376 /** 377 * Negation of a HighlightPredicate. 378 */ 379 public static class NotHighlightPredicate implements HighlightPredicate { 380 381 private HighlightPredicate predicate; 382 383 /** 384 * Instantiates a not against the given predicate. 385 * @param predicate the predicate to negate, must not be null. 386 * @throws NullPointerException if the predicate is null 387 */ 388 public NotHighlightPredicate(HighlightPredicate predicate) { 389 if (predicate == null) 390 throw new NullPointerException("predicate must not be null"); 391 this.predicate = predicate; 392 } 393 394 /** 395 * {@inheritDoc} 396 * Implemented to return the negation of the given predicate. 397 */ 398 @Override 399 public boolean isHighlighted(Component renderer, ComponentAdapter adapter) { 400 return !predicate.isHighlighted(renderer, adapter); 401 } 402 403 /** 404 * @return the contained HighlightPredicate. 405 */ 406 public HighlightPredicate getHighlightPredicate() { 407 return predicate; 408 } 409 410 } 411 412 /** 413 * Ands a list of predicates. 414 */ 415 public static class AndHighlightPredicate implements HighlightPredicate { 416 417 private List<HighlightPredicate> predicate; 418 419 /** 420 * Instantiates a predicate which ands all given predicates. 421 * @param predicate zero or more not null predicates to and 422 * @throws NullPointerException if the predicate is null 423 */ 424 public AndHighlightPredicate(HighlightPredicate... predicate) { 425 this.predicate = Arrays.asList(Contract.asNotNull(predicate, "predicate must not be null")); 426 } 427 428 /** 429 * Instantiates a predicate which ANDs all contained predicates. 430 * @param list a collection with zero or more not null predicates to AND 431 * @throws NullPointerException if the collection is null 432 */ 433 public AndHighlightPredicate(Collection<HighlightPredicate> list) { 434 this.predicate = new ArrayList<HighlightPredicate>(Contract.asNotNull(list, "predicate list must not be null")); 435 } 436 437 /** 438 * {@inheritDoc} 439 * Implemented to return false if any of the contained predicates is 440 * false or if there are no predicates. 441 */ 442 @Override 443 public boolean isHighlighted(Component renderer, ComponentAdapter adapter) { 444 for (HighlightPredicate hp : predicate) { 445 if (!hp.isHighlighted(renderer, adapter)) return false; 446 } 447 return !predicate.isEmpty(); 448 } 449 450 /** 451 * @return the contained HighlightPredicates. 452 */ 453 public HighlightPredicate[] getHighlightPredicates() { 454 if (predicate.isEmpty()) return EMPTY_PREDICATE_ARRAY; 455 return predicate.toArray(new HighlightPredicate[predicate.size()]); 456 } 457 458 459 } 460 461 /** 462 * Or's a list of predicates. 463 */ 464 public static class OrHighlightPredicate implements HighlightPredicate { 465 466 private List<HighlightPredicate> predicate; 467 468 /** 469 * Instantiates a predicate which ORs all given predicates. 470 * @param predicate zero or more not null predicates to OR 471 * @throws NullPointerException if the predicate is null 472 */ 473 public OrHighlightPredicate(HighlightPredicate... predicate) { 474 this.predicate = Arrays.asList(Contract.asNotNull(predicate, "predicate must not be null")); 475 } 476 477 /** 478 * Instantiates a predicate which ORs all contained predicates. 479 * @param list a collection with zero or more not null predicates to OR 480 * @throws NullPointerException if the collection is null 481 */ 482 public OrHighlightPredicate(Collection<HighlightPredicate> list) { 483 this.predicate = new ArrayList<HighlightPredicate>(Contract.asNotNull(list, "predicate list must not be null")); 484 } 485 486 /** 487 * {@inheritDoc} 488 * Implemented to return true if any of the contained predicates is 489 * true. 490 */ 491 @Override 492 public boolean isHighlighted(Component renderer, ComponentAdapter adapter) { 493 for (HighlightPredicate hp : predicate) { 494 if (hp.isHighlighted(renderer, adapter)) return true; 495 } 496 return false; 497 } 498 /** 499 * @return all registered predicates 500 */ 501 public HighlightPredicate[] getHighlightPredicates() { 502 if (predicate.isEmpty()) return EMPTY_PREDICATE_ARRAY; 503 return predicate.toArray(new HighlightPredicate[predicate.size()]); 504 } 505 506 } 507 508//------------------------ coordinates 509 510 public static class RowGroupHighlightPredicate implements HighlightPredicate { 511 512 private int linesPerGroup; 513 514 /** 515 * Instantiates a predicate with the given grouping. 516 * 517 * @param linesPerGroup number of lines constituting a group, must 518 * be > 0 519 * @throws IllegalArgumentException if linesPerGroup < 1 520 */ 521 public RowGroupHighlightPredicate(int linesPerGroup) { 522 if (linesPerGroup < 1) 523 throw new IllegalArgumentException("a group contain at least 1 row, was: " + linesPerGroup); 524 this.linesPerGroup = linesPerGroup; 525 } 526 527 /** 528 * {@inheritDoc} 529 * Implemented to return true if the adapter's row falls into a 530 * odd group number. 531 */ 532 @Override 533 public boolean isHighlighted(Component renderer, ComponentAdapter adapter) { 534 // JW: oddness check is okay - adapter.row must be a valid view coordinate 535 return (adapter.row / linesPerGroup) % 2 == 1; 536 } 537 538 /** 539 * 540 * @return the number of lines per group. 541 */ 542 public int getLinesPerGroup() { 543 return linesPerGroup; 544 } 545 546 } 547 548 /** 549 * A HighlightPredicate based on column index. 550 * 551 */ 552 public static class ColumnHighlightPredicate implements HighlightPredicate { 553 List<Integer> columnList; 554 555 /** 556 * Instantiates a predicate which returns true for the 557 * given columns in model coordinates. 558 * 559 * @param columns the columns to highlight in model coordinates. 560 */ 561 public ColumnHighlightPredicate(int... columns) { 562 columnList = new ArrayList<Integer>(); 563 for (int i = 0; i < columns.length; i++) { 564 columnList.add(columns[i]); 565 } 566 } 567 568 /** 569 * {@inheritDoc} 570 * 571 * This implementation returns true if the adapter's column 572 * is contained in this predicates list. 573 * 574 */ 575 @Override 576 public boolean isHighlighted(Component renderer, ComponentAdapter adapter) { 577 int modelIndex = adapter.convertColumnIndexToModel(adapter.column); 578 return columnList.contains(modelIndex); 579 } 580 581 /** 582 * PENDING JW: get array of int instead of Integer? 583 * 584 * @return the columns indices in model coordinates to highlight 585 */ 586 public Integer[] getColumns() { 587 if (columnList.isEmpty()) return EMPTY_INTEGER_ARRAY; 588 return columnList.toArray(new Integer[columnList.size()]); 589 } 590 591 } 592 593 594 /** 595 * A HighlightPredicate based on column identifier. 596 * 597 */ 598 public static class IdentifierHighlightPredicate implements HighlightPredicate { 599 List<Object> columnList; 600 601 /** 602 * Instantiates a predicate which returns true for the 603 * given column identifiers. 604 * 605 * @param columns the identitiers of the columns to highlight. 606 */ 607 public IdentifierHighlightPredicate(Object... columns) { 608 columnList = new ArrayList<Object>(); 609 for (int i = 0; i < columns.length; i++) { 610 columnList.add(columns[i]); 611 } 612 } 613 614 /** 615 * {@inheritDoc} 616 * 617 * This implementation returns true if the adapter's column 618 * is contained in this predicates list. 619 * 620 */ 621 @Override 622 public boolean isHighlighted(Component renderer, ComponentAdapter adapter) { 623 int modelIndex = adapter.convertColumnIndexToModel(adapter.column); 624 Object identifier = adapter.getColumnIdentifierAt(modelIndex); 625 return identifier != null ? columnList.contains(identifier) : false; 626 } 627 628 /** 629 * @return the identifiers 630 */ 631 public Object[] getIdentifiers() { 632 if (columnList.isEmpty()) return EMPTY_OBJECT_ARRAY; 633 return columnList.toArray(new Object[0]); 634 } 635 636 } 637 638 639 640 /** 641 * A {@code HighlightPredicate} based on adapter depth. 642 * 643 * @author Karl Schaefer 644 */ 645 public static class DepthHighlightPredicate implements HighlightPredicate { 646 private List<Integer> depthList; 647 648 /** 649 * Instantiates a predicate which returns true for the 650 * given depths. 651 * 652 * @param depths the depths to highlight 653 */ 654 public DepthHighlightPredicate(int... depths) { 655 depthList = new ArrayList<Integer>(); 656 for (int i = 0; i < depths.length; i++) { 657 depthList.add(depths[i]); 658 } 659 } 660 661 /** 662 * {@inheritDoc} 663 * 664 * This implementation returns true if the adapter's depth is contained 665 * in this predicates list. 666 * 667 */ 668 @Override 669 public boolean isHighlighted(Component renderer, 670 ComponentAdapter adapter) { 671 int depth = adapter.getDepth(); 672 return depthList.contains(depth); 673 } 674 675 /** 676 * @return array of numbers representing different depths 677 */ 678 public Integer[] getDepths() { 679 if (depthList.isEmpty()) return EMPTY_INTEGER_ARRAY; 680 return depthList.toArray(new Integer[depthList.size()]); 681 } 682 683 } 684 685 //--------------------- value testing 686 687 /** 688 * Predicate testing the componentAdapter value against a fixed 689 * Object. 690 */ 691 public static class EqualsHighlightPredicate implements HighlightPredicate { 692 693 private Object compareValue; 694 695 /** 696 * Instantitates a predicate with null compare value. 697 * 698 */ 699 public EqualsHighlightPredicate() { 700 this(null); 701 } 702 /** 703 * Instantiates a predicate with the given compare value. 704 * PENDING JW: support array? 705 * @param compareValue the fixed value to compare the 706 * adapter against. 707 */ 708 public EqualsHighlightPredicate(Object compareValue) { 709 this.compareValue = compareValue; 710 } 711 712 /** 713 * {@inheritDoc} 714 * 715 * Implemented to return true if the adapter value equals the 716 * this predicate's compare value. 717 */ 718 @Override 719 public boolean isHighlighted(Component renderer, ComponentAdapter adapter) { 720 if (compareValue == null) return adapter.getValue() == null; 721 return compareValue.equals(adapter.getValue()); 722 } 723 724 /** 725 * @return the value this predicate checks against. 726 */ 727 public Object getCompareValue() { 728 return compareValue; 729 } 730 731 } 732 733 /** 734 * Predicate testing the componentAdapter value type against a given 735 * Class. 736 */ 737 public static class TypeHighlightPredicate implements HighlightPredicate { 738 739 private Class<?> clazz; 740 741 /** 742 * Instantiates a predicate with Object.clazz. This is essentially the 743 * same as testing the adapter's value against null. 744 * 745 */ 746 public TypeHighlightPredicate() { 747 this(Object.class); 748 } 749 750 /** 751 * Instantiates a predicate with the given compare class.<p> 752 * 753 * PENDING JW: support array? 754 * 755 * @param compareValue the fixed class to compare the 756 * adapter value against, must not be null 757 * 758 * @throws NullPointerException if the class is null. 759 */ 760 public TypeHighlightPredicate(Class<?> compareValue) { 761 this.clazz = Contract.asNotNull(compareValue, "compare class must not be null"); 762 } 763 764 /** 765 * {@inheritDoc} 766 * 767 * Implemented to return true if the adapter value is an instance 768 * of this predicate's class type. 769 */ 770 @Override 771 public boolean isHighlighted(Component renderer, ComponentAdapter adapter) { 772 return adapter.getValue() != null ? 773 clazz.isAssignableFrom(adapter.getValue().getClass()) : false; 774 } 775 776 /** 777 * @return type of predicate compare class 778 */ 779 public Class<?> getType() { 780 return clazz; 781 } 782 783 } 784 785 /** 786 * Predicate testing the componentAdapter column type against a given 787 * Class. 788 */ 789 public static class ColumnTypeHighlightPredicate implements HighlightPredicate { 790 791 private Class<?> clazz; 792 793 /** 794 * Instantitates a predicate with Object.class. <p> 795 * 796 * PENDING JW: this constructor is not very useful ... concrete implementations of 797 * ComponentAdapter are required to return a not-null from their 798 * getColumnClass() methods). 799 * 800 */ 801 public ColumnTypeHighlightPredicate() { 802 this(Object.class); 803 } 804 805 /** 806 * Instantitates a predicate with the given compare class. 807 * 808 * @param compareValue the fixed class to compare the 809 * adapter's column class against, must not be null 810 * 811 * @throws NullPointerException if the class is null. 812 * 813 */ 814 public ColumnTypeHighlightPredicate(Class<?> compareValue) { 815 this.clazz = Contract.asNotNull(compareValue, "compare class must not be null"); 816 } 817 818 /** 819 * @inheritDoc 820 * 821 * Implemented to return true if the adapter value is an instance 822 * of this predicate's class type. 823 */ 824 @Override 825 public boolean isHighlighted(Component renderer, ComponentAdapter adapter) { 826 return clazz.isAssignableFrom(adapter.getColumnClass()); 827 } 828 829 public Class<?> getType() { 830 return clazz; 831 } 832 833 } 834}