1 /*
   2  * Copyright (c) 2010, 2016, 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 input mappings for handling key, mouse, etc events.
  68      *
  69      * @param control The control that this skin should be installed onto.
  70      */
  71     public CellSkinBase(final C control) {
  72         super (control);
  73 
  74         /**
  75          * The Cell does not typically want to block mouse events from going down
  76          * to the virtualized controls holding the cell. For example mouse clicks
  77          * on cells should also pass down to the ListView holding the cells.
  78          */
  79         consumeMouseEvents(false);
  80     }
  81 
  82 
  83 
  84     /***************************************************************************
  85      *                                                                         *
  86      * Properties                                                              *
  87      *                                                                         *
  88      **************************************************************************/
  89 
  90     /**
  91      * The default cell size. For vertical ListView or a TreeView or TableView
  92      * this is the height, for a horizontal ListView this is the width. This
  93      * is settable from CSS
  94      */
  95     private DoubleProperty cellSize;
  96 
  97     public final double getCellSize() {
  98         return cellSize == null ? DEFAULT_CELL_SIZE : cellSize.get();
  99     }
 100 
 101     public final ReadOnlyDoubleProperty cellSizeProperty() {
 102         return cellSizePropertyImpl();
 103     }
 104 
 105     private DoubleProperty cellSizePropertyImpl() {
 106         if (cellSize == null) {
 107             cellSize = new StyleableDoubleProperty(DEFAULT_CELL_SIZE) {
 108 
 109                 @Override
 110                 public void applyStyle(StyleOrigin origin, Number value) {
 111                     double size = value == null ? DEFAULT_CELL_SIZE : value.doubleValue();
 112                     // guard against a 0 or negative size
 113                     super.applyStyle(origin, size <= 0 ? DEFAULT_CELL_SIZE : size);
 114                 }
 115 
 116 
 117                 @Override public void set(double value) {
 118 //                    // Commented this out due to RT-19794, because otherwise
 119 //                    // cellSizeSet would be false when the default caspian.css
 120 //                    // cell size was set. This would lead to
 121 //                    // ListCellSkin.computePrefHeight computing the pref height
 122 //                    // of the cell (which is about 22px), rather than use the
 123 //                    // value provided by caspian.css (which is 24px).
 124 //                    // cellSizeSet = true;//value != DEFAULT_CELL_SIZE;
 125                     super.set(value);
 126                     getSkinnable().requestLayout();
 127                 }
 128 
 129                 @Override public Object getBean() {
 130                     return CellSkinBase.this;
 131                 }
 132 
 133                 @Override public String getName() {
 134                     return "cellSize";
 135                 }
 136 
 137                 @Override public CssMetaData<Cell<?>, Number> getCssMetaData() {
 138                     return StyleableProperties.CELL_SIZE;
 139                 }
 140             };
 141         }
 142         return cellSize;
 143     }
 144 
 145 
 146 
 147     /***************************************************************************
 148      *                                                                         *
 149      *                         Stylesheet Handling                             *
 150      *                                                                         *
 151      **************************************************************************/
 152 
 153     static final double DEFAULT_CELL_SIZE = 24.0;
 154 
 155      /*
 156       * Super-lazy instantiation pattern from Bill Pugh.
 157       */
 158      private static class StyleableProperties {
 159          private final static CssMetaData<Cell<?>,Number> CELL_SIZE =
 160                 new CssMetaData<Cell<?>,Number>("-fx-cell-size",
 161                  SizeConverter.getInstance(), DEFAULT_CELL_SIZE) {
 162 
 163             @Override
 164             public boolean isSettable(Cell<?> n) {
 165                 final CellSkinBase<?> skin = (CellSkinBase<?>) n.getSkin();
 166                 return skin.cellSize == null || !skin.cellSize.isBound();
 167             }
 168 
 169             @Override
 170             public StyleableProperty<Number> getStyleableProperty(Cell<?> n) {
 171                 final CellSkinBase<?> skin = (CellSkinBase<?>) n.getSkin();
 172                 return (StyleableProperty<Number>)(WritableValue<Number>)skin.cellSizePropertyImpl();
 173             }
 174         };
 175 
 176          private static final List<CssMetaData<? extends Styleable, ?>> STYLEABLES;
 177          static {
 178 
 179             final List<CssMetaData<? extends Styleable, ?>> styleables =
 180                 new ArrayList<CssMetaData<? extends Styleable, ?>>(SkinBase.getClassCssMetaData());
 181             styleables.add(CELL_SIZE);
 182             STYLEABLES = Collections.unmodifiableList(styleables);
 183 
 184          }
 185     }
 186 
 187     /**
 188      * Returns the CssMetaData associated with this class, which may include the
 189      * CssMetaData of its superclasses.
 190      */
 191     public static List<CssMetaData<? extends Styleable, ?>> getClassCssMetaData() {
 192         return StyleableProperties.STYLEABLES;
 193     }
 194 
 195     /** {@inheritDoc} */
 196     @Override public List<CssMetaData<? extends Styleable, ?>> getCssMetaData() {
 197         return getClassCssMetaData();
 198     }
 199 
 200 }