1 /*
   2  * Copyright (c) 2010, 2015, 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 javafx.scene.control.skin;
  27 
  28 import java.util.ArrayList;
  29 import java.util.Collections;
  30 import java.util.List;
  31 
  32 import javafx.scene.Node;
  33 import javafx.scene.control.Cell;
  34 import javafx.css.StyleableDoubleProperty;
  35 import javafx.css.CssMetaData;
  36 import javafx.css.StyleOrigin;
  37 
  38 import javafx.css.converter.SizeConverter;
  39 
  40 import javafx.beans.property.DoubleProperty;
  41 import javafx.beans.property.ReadOnlyDoubleProperty;
  42 import javafx.beans.value.WritableValue;
  43 import javafx.css.Styleable;
  44 import javafx.css.StyleableProperty;
  45 import javafx.scene.control.Control;
  46 import javafx.scene.control.SkinBase;
  47 
  48 /**
  49  * Default skin implementation for the {@link Cell} control, and subclasses such
  50  * as {@link javafx.scene.control.ListCell}, {@link javafx.scene.control.TreeCell},
  51  * etc.
  52  *
  53  * @see Cell
  54  * @since 9
  55  */
  56 public class CellSkinBase<C extends Cell> extends LabeledSkinBase<C> {
  57 
  58     /***************************************************************************
  59      *                                                                         *
  60      * Constructors                                                            *
  61      *                                                                         *
  62      **************************************************************************/
  63 
  64     /**
  65      * Creates a new CellSkinBase instance, installing the necessary child
  66      * nodes into the Control {@link Control#getChildren() children} list, as
  67      * well as the necessary {@link Node#getInputMap() input mappings} for
  68      * handling key, mouse, etc events.
  69      *
  70      * @param control The control that this skin should be installed onto.
  71      */
  72     public CellSkinBase(final C control) {
  73         super (control);
  74 
  75         /**
  76          * The Cell does not typically want to block mouse events from going down
  77          * to the virtualized controls holding the cell. For example mouse clicks
  78          * on cells should also pass down to the ListView holding the cells.
  79          */
  80         consumeMouseEvents(false);
  81     }
  82 
  83 
  84 
  85     /***************************************************************************
  86      *                                                                         *
  87      * Properties                                                              *
  88      *                                                                         *
  89      **************************************************************************/
  90 
  91     /**
  92      * The default cell size. For vertical ListView or a TreeView or TableView
  93      * this is the height, for a horizontal ListView this is the width. This
  94      * is settable from CSS
  95      */
  96     private DoubleProperty cellSize;
  97 
  98     public final double getCellSize() {
  99         return cellSize == null ? DEFAULT_CELL_SIZE : cellSize.get();
 100     }
 101 
 102     public final ReadOnlyDoubleProperty cellSizeProperty() {
 103         return cellSizePropertyImpl();
 104     }
 105 
 106     private DoubleProperty cellSizePropertyImpl() {
 107         if (cellSize == null) {
 108             cellSize = new StyleableDoubleProperty(DEFAULT_CELL_SIZE) {
 109 
 110                 @Override
 111                 public void applyStyle(StyleOrigin origin, Number value) {
 112                     double size = value == null ? DEFAULT_CELL_SIZE : value.doubleValue();
 113                     // guard against a 0 or negative size
 114                     super.applyStyle(origin, size <= 0 ? DEFAULT_CELL_SIZE : size);
 115                 }
 116 
 117 
 118                 @Override public void set(double value) {
 119 //                    // Commented this out due to RT-19794, because otherwise
 120 //                    // cellSizeSet would be false when the default caspian.css
 121 //                    // cell size was set. This would lead to
 122 //                    // ListCellSkin.computePrefHeight computing the pref height
 123 //                    // of the cell (which is about 22px), rather than use the
 124 //                    // value provided by caspian.css (which is 24px).
 125 //                    // cellSizeSet = true;//value != DEFAULT_CELL_SIZE;
 126                     super.set(value);
 127                     getSkinnable().requestLayout();
 128                 }
 129 
 130                 @Override public Object getBean() {
 131                     return CellSkinBase.this;
 132                 }
 133 
 134                 @Override public String getName() {
 135                     return "cellSize";
 136                 }
 137 
 138                 @Override public CssMetaData<Cell<?>, Number> getCssMetaData() {
 139                     return StyleableProperties.CELL_SIZE;
 140                 }
 141             };
 142         }
 143         return cellSize;
 144     }
 145 
 146 
 147 
 148     /***************************************************************************
 149      *                                                                         *
 150      *                         Stylesheet Handling                             *
 151      *                                                                         *
 152      **************************************************************************/
 153 
 154     static final double DEFAULT_CELL_SIZE = 24.0;
 155 
 156      /**
 157       * Super-lazy instantiation pattern from Bill Pugh.
 158       * @treatAsPrivate implementation detail
 159       */
 160      private static class StyleableProperties {
 161          private final static CssMetaData<Cell<?>,Number> CELL_SIZE =
 162                 new CssMetaData<Cell<?>,Number>("-fx-cell-size",
 163                  SizeConverter.getInstance(), DEFAULT_CELL_SIZE) {
 164 
 165             @Override
 166             public boolean isSettable(Cell<?> n) {
 167                 final CellSkinBase<?> skin = (CellSkinBase<?>) n.getSkin();
 168                 return skin.cellSize == null || !skin.cellSize.isBound();
 169             }
 170 
 171             @Override
 172             public StyleableProperty<Number> getStyleableProperty(Cell<?> n) {
 173                 final CellSkinBase<?> skin = (CellSkinBase<?>) n.getSkin();
 174                 return (StyleableProperty<Number>)(WritableValue<Number>)skin.cellSizePropertyImpl();
 175             }
 176         };
 177 
 178          private static final List<CssMetaData<? extends Styleable, ?>> STYLEABLES;
 179          static {
 180 
 181             final List<CssMetaData<? extends Styleable, ?>> styleables =
 182                 new ArrayList<CssMetaData<? extends Styleable, ?>>(SkinBase.getClassCssMetaData());
 183             styleables.add(CELL_SIZE);
 184             STYLEABLES = Collections.unmodifiableList(styleables);
 185 
 186          }
 187     }
 188 
 189     /**
 190      * Returns the CssMetaData associated with this class, which may include the
 191      * CssMetaData of its super classes.
 192      */
 193     public static List<CssMetaData<? extends Styleable, ?>> getClassCssMetaData() {
 194         return StyleableProperties.STYLEABLES;
 195     }
 196 
 197     /** {@inheritDoc} */
 198     @Override public List<CssMetaData<? extends Styleable, ?>> getCssMetaData() {
 199         return getClassCssMetaData();
 200     }
 201 
 202 }