1 /*
2 * Copyright (c) 2011, 2017, 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
809 if (tabHeaderSkin.isVisible() && (measureClosingTabs || ! tabHeaderSkin.isClosing)) {
810 width += tabHeaderSkin.prefWidth(height);
811 }
812 }
813 return snapSize(width) + snappedLeftInset() + snappedRightInset();
814 }
815
816 @Override protected double computePrefHeight(double width) {
817 double height = 0.0F;
818 for (Node child : getChildren()) {
819 TabHeaderSkin tabHeaderSkin = (TabHeaderSkin)child;
820 height = Math.max(height, tabHeaderSkin.prefHeight(width));
821 }
822 return snapSize(height) + snappedTopInset() + snappedBottomInset();
823 }
824
825 @Override protected void layoutChildren() {
826 if (tabsFit()) {
827 setScrollOffset(0.0);
828 } else {
829 if (!removeTab.isEmpty()) {
830 double offset = 0;
831 double w = tabHeaderArea.getWidth() - snapSize(controlButtons.prefWidth(-1)) - firstTabIndent() - SPACER;
832 Iterator<Node> i = getChildren().iterator();
833 while (i.hasNext()) {
834 TabHeaderSkin tabHeader = (TabHeaderSkin)i.next();
835 double tabHeaderPrefWidth = snapSize(tabHeader.prefWidth(-1));
836 if (removeTab.contains(tabHeader)) {
837 if (offset < w) {
838 isSelectingTab = true;
839 }
840 i.remove();
841 removeTab.remove(tabHeader);
842 if (removeTab.isEmpty()) {
843 break;
844 }
845 }
846 offset += tabHeaderPrefWidth;
847 }
848 // } else {
849 // isSelectingTab = true;
850 }
851 }
852
853 if (isSelectingTab) {
854 ensureSelectedTabIsVisible();
855 isSelectingTab = false;
856 } else {
857 validateScrollOffset();
858 }
859
860 Side tabPosition = getSkinnable().getSide();
861 double tabBackgroundHeight = snapSize(prefHeight(-1));
862 double tabX = (tabPosition.equals(Side.LEFT) || tabPosition.equals(Side.BOTTOM)) ?
863 snapSize(getWidth()) - getScrollOffset() : getScrollOffset();
864
865 updateHeaderClip();
866 for (Node node : getChildren()) {
867 TabHeaderSkin tabHeader = (TabHeaderSkin)node;
868
869 // size and position the header relative to the other headers
870 double tabHeaderPrefWidth = snapSize(tabHeader.prefWidth(-1) * tabHeader.animationTransition.get());
871 double tabHeaderPrefHeight = snapSize(tabHeader.prefHeight(-1));
872 tabHeader.resize(tabHeaderPrefWidth, tabHeaderPrefHeight);
873
874 // This ensures that the tabs are located in the correct position
875 // when there are tabs of differing heights.
876 double startY = tabPosition.equals(Side.BOTTOM) ?
877 0 : tabBackgroundHeight - tabHeaderPrefHeight - snappedBottomInset();
878 if (tabPosition.equals(Side.LEFT) || tabPosition.equals(Side.BOTTOM)) {
973 }
974 clipHeight = headersPrefHeight;
975 } else {
976 // If x = 0 the header region's drop shadow is clipped.
977 x = -shadowRadius;
978 clipWidth = (headersPrefWidth < maxWidth ? headersPrefWidth : maxWidth) + shadowRadius;
979 clipHeight = headersPrefHeight;
980 }
981
982 headerClip.setX(x);
983 headerClip.setY(y);
984 headerClip.setWidth(clipWidth);
985 headerClip.setHeight(clipHeight);
986 }
987
988 private void addTab(Tab tab, int addToIndex) {
989 TabHeaderSkin tabHeaderSkin = new TabHeaderSkin(tab);
990 headersRegion.getChildren().add(addToIndex, tabHeaderSkin);
991 }
992
993 private List<TabHeaderSkin> removeTab = new ArrayList<>();
994 private void removeTab(Tab tab) {
995 TabHeaderSkin tabHeaderSkin = getTabHeaderSkin(tab);
996 if (tabHeaderSkin != null) {
997 if (tabsFit()) {
998 headersRegion.getChildren().remove(tabHeaderSkin);
999 } else {
1000 // The tab will be removed during layout because
1001 // we need its width to compute the scroll offset.
1002 removeTab.add(tabHeaderSkin);
1003 tabHeaderSkin.removeListeners(tab);
1004 }
1005 }
1006 }
1007
1008 private TabHeaderSkin getTabHeaderSkin(Tab tab) {
1009 for (Node child: headersRegion.getChildren()) {
1010 TabHeaderSkin tabHeaderSkin = (TabHeaderSkin)child;
1011 if (tabHeaderSkin.getTab().equals(tab)) {
1012 return tabHeaderSkin;
1013 }
1014 }
1015 return null;
1016 }
1017
1018 private boolean tabsFit() {
1019 double headerPrefWidth = snapSize(headersRegion.prefWidth(-1));
1020 double controlTabWidth = snapSize(controlButtons.prefWidth(-1));
1021 double visibleWidth = headerPrefWidth + controlTabWidth + firstTabIndent() + SPACER;
1022 return visibleWidth < getWidth();
1023 }
1024
|
1 /*
2 * Copyright (c) 2011, 2018, 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
809 if (tabHeaderSkin.isVisible() && (measureClosingTabs || ! tabHeaderSkin.isClosing)) {
810 width += tabHeaderSkin.prefWidth(height);
811 }
812 }
813 return snapSize(width) + snappedLeftInset() + snappedRightInset();
814 }
815
816 @Override protected double computePrefHeight(double width) {
817 double height = 0.0F;
818 for (Node child : getChildren()) {
819 TabHeaderSkin tabHeaderSkin = (TabHeaderSkin)child;
820 height = Math.max(height, tabHeaderSkin.prefHeight(width));
821 }
822 return snapSize(height) + snappedTopInset() + snappedBottomInset();
823 }
824
825 @Override protected void layoutChildren() {
826 if (tabsFit()) {
827 setScrollOffset(0.0);
828 } else {
829 if (isSelectingTab) {
830 ensureSelectedTabIsVisible();
831 } else {
832 validateScrollOffset();
833 }
834 }
835 isSelectingTab = false;
836
837 Side tabPosition = getSkinnable().getSide();
838 double tabBackgroundHeight = snapSize(prefHeight(-1));
839 double tabX = (tabPosition.equals(Side.LEFT) || tabPosition.equals(Side.BOTTOM)) ?
840 snapSize(getWidth()) - getScrollOffset() : getScrollOffset();
841
842 updateHeaderClip();
843 for (Node node : getChildren()) {
844 TabHeaderSkin tabHeader = (TabHeaderSkin)node;
845
846 // size and position the header relative to the other headers
847 double tabHeaderPrefWidth = snapSize(tabHeader.prefWidth(-1) * tabHeader.animationTransition.get());
848 double tabHeaderPrefHeight = snapSize(tabHeader.prefHeight(-1));
849 tabHeader.resize(tabHeaderPrefWidth, tabHeaderPrefHeight);
850
851 // This ensures that the tabs are located in the correct position
852 // when there are tabs of differing heights.
853 double startY = tabPosition.equals(Side.BOTTOM) ?
854 0 : tabBackgroundHeight - tabHeaderPrefHeight - snappedBottomInset();
855 if (tabPosition.equals(Side.LEFT) || tabPosition.equals(Side.BOTTOM)) {
950 }
951 clipHeight = headersPrefHeight;
952 } else {
953 // If x = 0 the header region's drop shadow is clipped.
954 x = -shadowRadius;
955 clipWidth = (headersPrefWidth < maxWidth ? headersPrefWidth : maxWidth) + shadowRadius;
956 clipHeight = headersPrefHeight;
957 }
958
959 headerClip.setX(x);
960 headerClip.setY(y);
961 headerClip.setWidth(clipWidth);
962 headerClip.setHeight(clipHeight);
963 }
964
965 private void addTab(Tab tab, int addToIndex) {
966 TabHeaderSkin tabHeaderSkin = new TabHeaderSkin(tab);
967 headersRegion.getChildren().add(addToIndex, tabHeaderSkin);
968 }
969
970 private void removeTab(Tab tab) {
971 TabHeaderSkin tabHeaderSkin = getTabHeaderSkin(tab);
972 if (tabHeaderSkin != null) {
973 headersRegion.getChildren().remove(tabHeaderSkin);
974 }
975 }
976
977 private TabHeaderSkin getTabHeaderSkin(Tab tab) {
978 for (Node child: headersRegion.getChildren()) {
979 TabHeaderSkin tabHeaderSkin = (TabHeaderSkin)child;
980 if (tabHeaderSkin.getTab().equals(tab)) {
981 return tabHeaderSkin;
982 }
983 }
984 return null;
985 }
986
987 private boolean tabsFit() {
988 double headerPrefWidth = snapSize(headersRegion.prefWidth(-1));
989 double controlTabWidth = snapSize(controlButtons.prefWidth(-1));
990 double visibleWidth = headerPrefWidth + controlTabWidth + firstTabIndent() + SPACER;
991 return visibleWidth < getWidth();
992 }
993
|