1 /*
   2  * Copyright (c) 2010, 2014, 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.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package com.sun.javafx.scene.control.skin;
  27 
  28 import java.util.ArrayList;
  29 import java.util.Collections;
  30 import java.util.List;
  31 
  32 import com.sun.javafx.scene.control.behavior.BehaviorBase;
  33 
  34 import javafx.scene.control.Cell;
  35 import javafx.css.StyleableDoubleProperty;
  36 import javafx.css.CssMetaData;
  37 import javafx.css.StyleOrigin;
  38 
  39 import com.sun.javafx.css.converters.SizeConverter;
  40 
  41 import javafx.beans.property.DoubleProperty;
  42 import javafx.beans.property.ReadOnlyDoubleProperty;
  43 import javafx.beans.value.WritableValue;
  44 import javafx.css.Styleable;
  45 import javafx.css.StyleableProperty;
  46 import javafx.scene.control.SkinBase;
  47 
  48 
  49 /**
  50  * A base skin implementation, specifically for ListCellSkin and TreeCellSkin.
  51  * This might not be a suitable base class for TreeCellSkin or some other
  52  * such skins.
  53  */
  54 public class CellSkinBase<C extends Cell, B extends BehaviorBase<C>> extends LabeledSkinBase<C, B> {
  55     /**
  56      * The default cell size. For vertical ListView or a TreeView or TableView
  57      * this is the height, for a horizontal ListView this is the width. This
  58      * is settable from CSS
  59      */
  60     private DoubleProperty cellSize;
  61 
  62     public final double getCellSize() {
  63         return cellSize == null ? DEFAULT_CELL_SIZE : cellSize.get();
  64     }
  65 
  66     public final ReadOnlyDoubleProperty cellSizeProperty() {
  67         return cellSizePropertyImpl();
  68     }
  69 
  70     private DoubleProperty cellSizePropertyImpl() {
  71         if (cellSize == null) {
  72             cellSize = new StyleableDoubleProperty(DEFAULT_CELL_SIZE) {
  73 
  74                 @Override
  75                 public void applyStyle(StyleOrigin origin, Number value) {
  76                     double size = value == null ? DEFAULT_CELL_SIZE : value.doubleValue();
  77                     // guard against a 0 or negative size
  78                     super.applyStyle(origin, size <= 0 ? DEFAULT_CELL_SIZE : size);
  79                 }
  80 
  81 
  82                 @Override public void set(double value) {
  83 //                    // Commented this out due to RT-19794, because otherwise
  84 //                    // cellSizeSet would be false when the default caspian.css
  85 //                    // cell size was set. This would lead to 
  86 //                    // ListCellSkin.computePrefHeight computing the pref height
  87 //                    // of the cell (which is about 22px), rather than use the 
  88 //                    // value provided by caspian.css (which is 24px).
  89 //                    // cellSizeSet = true;//value != DEFAULT_CELL_SIZE;
  90                     super.set(value);
  91                     getSkinnable().requestLayout();
  92                 }
  93                 
  94                 @Override public Object getBean() {
  95                     return CellSkinBase.this;
  96                 }
  97 
  98                 @Override public String getName() {
  99                     return "cellSize";
 100                 }
 101 
 102                 @Override public CssMetaData<Cell<?>, Number> getCssMetaData() {
 103                     return StyleableProperties.CELL_SIZE;
 104                 }
 105             }; 
 106         }
 107         return cellSize;
 108     }
 109 
 110     public CellSkinBase(final C control, final B behavior) {
 111         super (control, behavior);
 112 
 113         /**
 114          * The Cell does not typically want to block mouse events from going down
 115          * to the virtualized controls holding the cell. For example mouse clicks
 116          * on cells should also pass down to the ListView holding the cells.
 117          */
 118         consumeMouseEvents(false);
 119     }
 120 
 121 
 122     
 123     /***************************************************************************
 124      *                                                                         *
 125      *                         Stylesheet Handling                             *
 126      *                                                                         *
 127      **************************************************************************/
 128 
 129     static final double DEFAULT_CELL_SIZE = 24.0;
 130 
 131      /**
 132       * Super-lazy instantiation pattern from Bill Pugh.
 133       * @treatAsPrivate implementation detail
 134       */
 135      private static class StyleableProperties {
 136          private final static CssMetaData<Cell<?>,Number> CELL_SIZE =
 137                 new CssMetaData<Cell<?>,Number>("-fx-cell-size",
 138                  SizeConverter.getInstance(), DEFAULT_CELL_SIZE) {
 139 
 140             @Override
 141             public boolean isSettable(Cell<?> n) {
 142                 final CellSkinBase<?,?> skin = (CellSkinBase<?,?>) n.getSkin();
 143                 return skin.cellSize == null || !skin.cellSize.isBound();
 144             }
 145 
 146             @Override
 147             public StyleableProperty<Number> getStyleableProperty(Cell<?> n) {
 148                 final CellSkinBase<?,?> skin = (CellSkinBase<?,?>) n.getSkin();
 149                 return (StyleableProperty<Number>)(WritableValue<Number>)skin.cellSizePropertyImpl();
 150             }
 151         };
 152 
 153          private static final List<CssMetaData<? extends Styleable, ?>> STYLEABLES;
 154          static {
 155 
 156             final List<CssMetaData<? extends Styleable, ?>> styleables = 
 157                 new ArrayList<CssMetaData<? extends Styleable, ?>>(SkinBase.getClassCssMetaData());
 158             styleables.add(CELL_SIZE);
 159             STYLEABLES = Collections.unmodifiableList(styleables);
 160 
 161          }
 162     }
 163 
 164     /**
 165      * @return The CssMetaData associated with this class, which may include the
 166      * CssMetaData of its super classes.
 167      */
 168     public static List<CssMetaData<? extends Styleable, ?>> getClassCssMetaData() {
 169         return StyleableProperties.STYLEABLES;
 170     }
 171 
 172     /**
 173      * {@inheritDoc}
 174      */
 175     @Override
 176     public List<CssMetaData<? extends Styleable, ?>> getCssMetaData() {
 177         return getClassCssMetaData();
 178     }
 179 
 180 }