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