1 /* 2 * Copyright (c) 2011, 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 com.sun.javafx.scene.control.Properties; 29 import javafx.beans.InvalidationListener; 30 import javafx.beans.WeakInvalidationListener; 31 import javafx.beans.property.BooleanProperty; 32 import javafx.beans.property.ReadOnlyDoubleProperty; 33 import javafx.scene.Node; 34 import javafx.scene.control.Accordion; 35 import javafx.scene.control.Control; 36 import javafx.scene.control.IndexedCell; 37 import javafx.scene.shape.Rectangle; 38 39 /** 40 * Base skin for table cell controls, for example: 41 * {@link javafx.scene.control.TableCell} and {@link javafx.scene.control.TreeTableCell}. 42 * 43 * @see javafx.scene.control.TableCell 44 * @see javafx.scene.control.TreeTableCell 45 * @since 9 46 */ 47 public abstract class TableCellSkinBase<C extends IndexedCell> extends CellSkinBase<C> { 48 49 /*************************************************************************** 50 * * 51 * Private Fields * 52 * * 53 **************************************************************************/ 54 55 boolean isDeferToParentForPrefWidth = false; 56 57 58 59 /*************************************************************************** 60 * * 61 * Constructors * 62 * * 63 **************************************************************************/ 64 65 /** 66 * Creates a new TableCellSkinBase instance, installing the necessary child 67 * nodes into the Control {@link Control#getChildren() children} list, as 68 * well as the necessary {@link Node#getInputMap() input mappings} for 69 * handling key, mouse, etc events. 70 * 71 * @param control The control that this skin should be installed onto. 72 */ 73 public TableCellSkinBase(final C control) { 74 super(control); 75 76 // RT-22038 77 Rectangle clip = new Rectangle(); 78 clip.widthProperty().bind(control.widthProperty()); 79 clip.heightProperty().bind(control.heightProperty()); 80 getSkinnable().setClip(clip); 81 // --- end of RT-22038 82 83 ReadOnlyDoubleProperty columnWidthProperty = columnWidthProperty(); 84 if (columnWidthProperty != null) { 85 columnWidthProperty.addListener(weakColumnWidthListener); 86 } 87 88 registerChangeListener(control.visibleProperty(), e -> getSkinnable().setVisible(columnVisibleProperty().get())); 89 90 if (control.getProperties().containsKey(Properties.DEFER_TO_PARENT_PREF_WIDTH)) { 91 isDeferToParentForPrefWidth = true; 92 } 93 } 94 95 96 97 /*************************************************************************** 98 * * 99 * Listeners * 100 * * 101 **************************************************************************/ 102 103 private InvalidationListener columnWidthListener = valueModel -> getSkinnable().requestLayout(); 104 105 private WeakInvalidationListener weakColumnWidthListener = 106 new WeakInvalidationListener(columnWidthListener); 107 108 109 110 /*************************************************************************** 111 * * 112 * Abstract Methods * 113 * * 114 **************************************************************************/ 115 116 // Equivalent to tableColumn.widthProperty() 117 abstract ReadOnlyDoubleProperty columnWidthProperty(); 118 119 // Equivalent to tableColumn.visibleProperty() 120 abstract BooleanProperty columnVisibleProperty(); 121 122 123 124 /*************************************************************************** 125 * * 126 * Public Methods * 127 * * 128 **************************************************************************/ 129 130 /** {@inheritDoc} */ 131 @Override public void dispose() { 132 ReadOnlyDoubleProperty columnWidthProperty = columnWidthProperty(); 133 if (columnWidthProperty != null) { 134 columnWidthProperty.removeListener(weakColumnWidthListener); 135 } 136 137 super.dispose(); 138 } 139 140 /** {@inheritDoc} */ 141 @Override protected void layoutChildren(final double x, final double y, 142 final double w, final double h) { 143 // fit the cell within this space 144 // FIXME the subtraction of bottom padding isn't right here - but it 145 // results in better visuals, so I'm leaving it in place for now. 146 layoutLabelInArea(x, y, w, h - getSkinnable().getPadding().getBottom()); 147 } 148 149 /** {@inheritDoc} */ 150 @Override protected double computePrefWidth(double height, double topInset, double rightInset, double bottomInset, double leftInset) { 151 if (isDeferToParentForPrefWidth) { 152 return super.computePrefWidth(height, topInset, rightInset, bottomInset, leftInset); 153 } 154 return columnWidthProperty().get(); 155 } 156 }