--- old/modules/javafx.controls/src/main/java/javafx/scene/control/skin/NestedTableColumnHeader.java 2016-09-27 17:05:30.000000000 +1300 +++ new/modules/javafx.controls/src/main/java/javafx/scene/control/skin/NestedTableColumnHeader.java 2016-09-27 17:05:30.000000000 +1300 @@ -114,17 +114,16 @@ * Creates a new NestedTableColumnHeader instance to visually represent the given * {@link TableColumnBase} instance. * - * @param skin The skin used by the UI control. * @param tc The table column to be visually represented by this instance. */ - public NestedTableColumnHeader(final TableViewSkinBase skin, final TableColumnBase tc) { - super(skin, tc); + public NestedTableColumnHeader(final TableColumnBase tc) { + super(tc); getStyleClass().setAll(DEFAULT_STYLE_CLASS); setFocusTraversable(false); // init UI - label = new TableColumnHeader(skin, getTableColumn()); + label = new TableColumnHeader(getTableColumn()); label.setTableHeaderRow(getTableHeaderRow()); label.setParentHeader(getParentHeader()); label.setNestedColumnHeader(this); @@ -133,8 +132,6 @@ changeListenerHandler.registerChangeListener(getTableColumn().textProperty(), e -> label.setVisible(getTableColumn().getText() != null && ! getTableColumn().getText().isEmpty())); } - - changeListenerHandler.registerChangeListener(TableSkinUtils.columnResizePolicyProperty(skin), e -> updateContent()); } @@ -169,7 +166,7 @@ if (me.getClickCount() == 2 && me.isPrimaryButtonDown()) { // the user wants to resize the column such that its // width is equal to the widest element in the column - TableSkinUtils.resizeColumnToFitContent(header.getTableViewSkin(), column, -1); + TableSkinUtils.resizeColumnToFitContent(header.getTableSkin(), column, -1); } else { // rather than refer to the rect variable, we just grab // it from the source to prevent a small memory leak. @@ -367,8 +364,8 @@ */ protected TableColumnHeader createTableColumnHeader(TableColumnBase col) { return col.getColumns().isEmpty() ? - new TableColumnHeader(getTableViewSkin(), col) : - new NestedTableColumnHeader(getTableViewSkin(), col); + new TableColumnHeader(col) : + new NestedTableColumnHeader(col); } @@ -382,6 +379,11 @@ @Override void setTableHeaderRow(TableHeaderRow header) { super.setTableHeaderRow(header); + // it's only now that a skin might be available + if (getTableSkin() != null) { + changeListenerHandler.registerChangeListener(TableSkinUtils.columnResizePolicyProperty(getTableSkin()), e -> updateContent()); + } + label.setTableHeaderRow(header); // tell all children columns what TableHeader they belong to @@ -413,8 +415,8 @@ void updateTableColumnHeaders() { // watching for changes to the view columns in either table or tableColumn. - if (getTableColumn() == null && getTableViewSkin() != null) { - setColumns(TableSkinUtils.getColumns(getTableViewSkin())); + if (getTableColumn() == null && getTableSkin() != null) { + setColumns(TableSkinUtils.getColumns(getTableSkin())); } else if (getTableColumn() != null) { setColumns(getTableColumn().getColumns()); } @@ -571,20 +573,19 @@ return; } - final TableViewSkinBase skin = getTableViewSkin(); - boolean isConstrainedResize = false; - Callback columnResizePolicy = TableSkinUtils.columnResizePolicyProperty(skin).get(); + TableViewSkinBase tableSkin = getTableSkin(); + Callback columnResizePolicy = TableSkinUtils.columnResizePolicyProperty(tableSkin).get(); if (columnResizePolicy != null) { isConstrainedResize = - skin instanceof TableViewSkin ? TableView.CONSTRAINED_RESIZE_POLICY.equals(columnResizePolicy) : - skin instanceof TreeTableViewSkin ? TreeTableView.CONSTRAINED_RESIZE_POLICY.equals(columnResizePolicy) : + tableSkin instanceof TableViewSkin ? TableView.CONSTRAINED_RESIZE_POLICY.equals(columnResizePolicy) : + tableSkin instanceof TreeTableViewSkin ? TreeTableView.CONSTRAINED_RESIZE_POLICY.equals(columnResizePolicy) : false; } // RT-32547 - don't show resize cursor when in constrained resize mode // and there is only one column - if (isConstrainedResize && TableSkinUtils.getVisibleLeafColumns(skin).size() == 1) { + if (isConstrainedResize && TableSkinUtils.getVisibleLeafColumns(tableSkin).size() == 1) { return; } @@ -651,7 +652,7 @@ draggedX = -draggedX; } double delta = draggedX - lastX; - boolean allowed = TableSkinUtils.resizeColumn(getTableViewSkin(), col, delta); + boolean allowed = TableSkinUtils.resizeColumn(getTableSkin(), col, delta); if (allowed) { lastX = draggedX; } --- old/modules/javafx.controls/src/main/java/javafx/scene/control/skin/TableColumnHeader.java 2016-09-27 17:05:31.000000000 +1300 +++ new/modules/javafx.controls/src/main/java/javafx/scene/control/skin/TableColumnHeader.java 2016-09-27 17:05:31.000000000 +1300 @@ -74,7 +74,8 @@ /** - * Region responsible for painting a single column header. + * Region responsible for painting a single column header. A subcomponent used by + * subclasses of {@link TableViewSkinBase}. * * @since 9 */ @@ -103,7 +104,7 @@ private boolean autoSizeComplete = false; private double dragOffset; - private final TableViewSkinBase> skin; +// TableViewSkinBase tableSkin; private NestedTableColumnHeader nestedColumnHeader; private TableHeaderRow tableHeaderRow; private NestedTableColumnHeader parentHeader; @@ -131,7 +132,7 @@ // the line drawn in the table when a user presses and moves a column header // to indicate where the column will be dropped. This is provided by the // table skin, but manipulated by the header - final Region columnReorderLine; + Region columnReorderLine; @@ -145,14 +146,10 @@ * Creates a new TableColumnHeader instance to visually represent the given * {@link TableColumnBase} instance. * - * @param skin The skin used by the UI control. * @param tc The table column to be visually represented by this instance. */ - public TableColumnHeader(final TableViewSkinBase skin, final TableColumnBase tc) { - this.skin = skin; + public TableColumnHeader(final TableColumnBase tc) { setTableColumn(tc); - this.columnReorderLine = skin.getColumnReorderLine(); - setFocusTraversable(false); updateColumnIndex(); @@ -163,12 +160,6 @@ changeListenerHandler.registerChangeListener(sceneProperty(), e -> updateScene()); if (getTableColumn() != null) { - updateSortPosition(); - TableSkinUtils.getSortOrder(skin).addListener(weakSortOrderListener); - TableSkinUtils.getVisibleLeafColumns(skin).addListener(weakVisibleLeafColumnsListener); - } - - if (getTableColumn() != null) { changeListenerHandler.registerChangeListener(tc.idProperty(), e -> setId(tc.getId())); changeListenerHandler.registerChangeListener(tc.styleProperty(), e -> setStyle(tc.getStyle())); changeListenerHandler.registerChangeListener(tc.widthProperty(), e -> { @@ -182,7 +173,7 @@ changeListenerHandler.registerChangeListener(tc.sortableProperty(), e -> { // we need to notify all headers that a sortable state has changed, // in case the sort grid in other columns needs to be updated. - if (TableSkinUtils.getSortOrder(skin).contains(getTableColumn())) { + if (TableSkinUtils.getSortOrder(getTableSkin()).contains(getTableColumn())) { NestedTableColumnHeader root = getTableHeaderRow().getRootHeader(); updateAllHeaders(root); } @@ -246,7 +237,7 @@ // pass focus to the table, so that the user immediately sees // the focus rectangle around the table control. - header.getTableViewSkin().getSkinnable().requestFocus(); + header.getTableSkin().getSkinnable().requestFocus(); if (me.isPrimaryButtonDown() && header.isColumnReorderingEnabled()) { header.columnReorderingStarted(me.getX()); @@ -443,15 +434,35 @@ * * **************************************************************************/ - TableViewSkinBase> getTableViewSkin() { - return skin; - } - NestedTableColumnHeader getNestedColumnHeader() { return nestedColumnHeader; } void setNestedColumnHeader(NestedTableColumnHeader nch) { nestedColumnHeader = nch; } TableHeaderRow getTableHeaderRow() { return tableHeaderRow; } - void setTableHeaderRow(TableHeaderRow thr) { tableHeaderRow = thr; } + void setTableHeaderRow(TableHeaderRow thr) { + tableHeaderRow = thr; + updateTableSkin(); + } + + private void updateTableSkin() { + // when we get the table header row, we are also given the skin, + // so this is the time to look up listeners, etc. + if (tableHeaderRow == null) return; + + TableViewSkinBase tableSkin = getTableSkin(); + if (tableSkin == null) return; + + this.columnReorderLine = tableSkin.getColumnReorderLine(); + + if (getTableColumn() != null) { + updateSortPosition(); + TableSkinUtils.getSortOrder(tableSkin).addListener(weakSortOrderListener); + TableSkinUtils.getVisibleLeafColumns(tableSkin).addListener(weakVisibleLeafColumnsListener); + } + } + + TableViewSkinBase getTableSkin() { + return tableHeaderRow == null ? null : tableHeaderRow.tableSkin; + } NestedTableColumnHeader getParentHeader() { return parentHeader; } void setParentHeader(NestedTableColumnHeader ph) { parentHeader = ph; } @@ -499,10 +510,10 @@ } void dispose() { - TableViewSkinBase skin = getTableViewSkin(); - if (skin != null) { - TableSkinUtils.getVisibleLeafColumns(skin).removeListener(weakVisibleLeafColumnsListener); - TableSkinUtils.getSortOrder(skin).removeListener(weakSortOrderListener); + TableViewSkinBase tableSkin = getTableSkin(); + if (tableSkin != null) { + TableSkinUtils.getVisibleLeafColumns(tableSkin).removeListener(weakVisibleLeafColumnsListener); + TableSkinUtils.getSortOrder(tableSkin).removeListener(weakSortOrderListener); } changeListenerHandler.dispose(); @@ -517,7 +528,7 @@ private boolean isColumnReorderingEnabled() { // we only allow for column reordering if there are more than one column, - return !Properties.IS_TOUCH_SUPPORTED && TableSkinUtils.getVisibleLeafColumns(getTableViewSkin()).size() > 1; + return !Properties.IS_TOUCH_SUPPORTED && TableSkinUtils.getVisibleLeafColumns(getTableSkin()).size() > 1; } private void initUI() { @@ -550,7 +561,7 @@ // if the prefWidth has been set, we do _not_ autosize columns if (prefWidth == DEFAULT_COLUMN_WIDTH) { - TableSkinUtils.resizeColumnToFitContent(getTableViewSkin(), column, cellsToMeasure); + TableSkinUtils.resizeColumnToFitContent(getTableSkin(), column, cellsToMeasure); // getTableViewSkin().resizeColumnToFitContent(column, cellsToMeasure); } } @@ -579,7 +590,7 @@ } // RT-28016: if the tablecolumn is not a visible leaf column, we should ignore this - int visibleLeafIndex = TableSkinUtils.getVisibleLeafIndex(skin,getTableColumn()); + int visibleLeafIndex = TableSkinUtils.getVisibleLeafIndex(getTableSkin(), getTableColumn()); if (visibleLeafIndex == -1) return; final int sortColumnCount = getVisibleSortOrderColumnCount(); @@ -735,7 +746,7 @@ private ObservableList> getColumns(TableColumnBase column) { return column.getParentColumn() == null ? - TableSkinUtils.getColumns(getTableViewSkin()) : + TableSkinUtils.getColumns(getTableSkin()) : column.getParentColumn().getColumns(); } @@ -758,15 +769,15 @@ private void updateColumnIndex() { // TableView tv = getTableView(); - TableViewSkinBase skin = getTableViewSkin(); TableColumnBase tc = getTableColumn(); - columnIndex = skin == null || tc == null ? -1 :TableSkinUtils.getVisibleLeafIndex(skin,tc); + TableViewSkinBase tableSkin = getTableSkin(); + columnIndex = tableSkin == null || tc == null ? -1 :TableSkinUtils.getVisibleLeafIndex(tableSkin,tc); // update the pseudo class state regarding whether this is the last // visible cell (i.e. the right-most). isLastVisibleColumn = getTableColumn() != null && columnIndex != -1 && - columnIndex == TableSkinUtils.getVisibleLeafColumns(skin).size() - 1; + columnIndex == TableSkinUtils.getVisibleLeafColumns(tableSkin).size() - 1; pseudoClassStateChanged(PSEUDO_CLASS_LAST_VISIBLE, isLastVisibleColumn); } @@ -779,7 +790,7 @@ // final int sortPos = getTable().getSortOrder().indexOf(column); // final boolean isSortColumn = sortPos != -1; - final ObservableList> sortOrder = TableSkinUtils.getSortOrder(skin); + final ObservableList> sortOrder = TableSkinUtils.getSortOrder(getTableSkin()); // addColumn is true e.g. when the user is holding down Shift if (addColumn) { @@ -859,7 +870,7 @@ } private List getVisibleSortOrderColumns() { - final ObservableList> sortOrder = TableSkinUtils.getSortOrder(skin); + final ObservableList> sortOrder = TableSkinUtils.getSortOrder(getTableSkin()); List visibleSortOrderColumns = new ArrayList<>(); for (int i = 0; i < sortOrder.size(); i++) { @@ -922,7 +933,7 @@ final double x = getParentHeader().sceneToLocal(sceneX, sceneY).getX(); // calculate where the ghost column header should be - double dragX = getTableViewSkin().getSkinnable().sceneToLocal(sceneX, sceneY).getX() - dragOffset; + double dragX = getTableSkin().getSkinnable().sceneToLocal(sceneX, sceneY).getX() - dragOffset; getTableHeaderRow().setDragHeaderX(dragX); double startX = 0; @@ -970,7 +981,7 @@ double lineX = getTableHeaderRow().sceneToLocal(hoverHeader.localToScene(hoverHeader.getBoundsInLocal())).getMinX(); lineX = lineX + ((beforeMidPoint) ? (0) : (hoverHeader.getWidth())); - if (lineX >= -0.5 && lineX <= getTableViewSkin().getSkinnable().getWidth()) { + if (lineX >= -0.5 && lineX <= getTableSkin().getSkinnable().getWidth()) { columnReorderLine.setTranslateX(lineX); // then if this is the first event, we set the property to true --- old/modules/javafx.controls/src/main/java/javafx/scene/control/skin/TableHeaderRow.java 2016-09-27 17:05:32.000000000 +1300 +++ new/modules/javafx.controls/src/main/java/javafx/scene/control/skin/TableHeaderRow.java 2016-09-27 17:05:32.000000000 +1300 @@ -85,7 +85,7 @@ ControlResources.getString("TableView.nestedColumnControlMenuSeparator"); private final VirtualFlow flow; - private final TableViewSkinBase tableSkin; + final TableViewSkinBase tableSkin; private Map columnMenuItems = new HashMap(); private double scrollX; private double tableWidth; @@ -413,7 +413,7 @@ * @return A new NestedTableColumnHeader instance. */ protected NestedTableColumnHeader createRootHeader() { - return new NestedTableColumnHeader(tableSkin, null); + return new NestedTableColumnHeader(null); }