blob: 163d3671ab98a8d8dd681745bcee7795307f4e90 [file] [log] [blame]
<?xml version="1.0" encoding="UTF-8"?>
<!--
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to you under the Apache License,
Version 2.0 (the "License"); you may not use this file except in
compliance with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<document id="tab-panes">
<properties>
<title>Tab Panes</title>
<explore>TabPane</explore>
</properties>
<body>
<p>
Functionally, tab panes are similar to card panes in that they show only one of a
collection of components at a time. Unlike card panes, tab panes include built-in
support for navigating between the components, which are called "tabs". The following
example demonstrates the use of the <tt>TabPane</tt> component:
</p>
<application class="org.apache.pivot.wtk.ScriptApplication"
width="680" height="480">
<libraries>
<library>core</library>
<library>wtk</library>
<library>wtk-terra</library>
<library>tutorials</library>
</libraries>
<startup-properties>
<src>/org/apache/pivot/tutorials/navigation/tab_panes.bxml</src>
</startup-properties>
</application>
<p>
The BXML source that produces this example is as follows. The tab pane contains three
tabs, each of which are flow panes containing bordered labels at different sizes. Like
<tt>CardPane</tt>, the preferred size of a tab pane is the maximum of the preferred
widths and heights of the tabs, plus the size of the area allocated to the tab
navigation, and each tab is sized to fill the entire space allocated to the tabs. The
tab pane itself is contained in a flow pane so that changes to its preferred size are
easily visible.
</p>
<p>
Note that, like the <a href="forms.html">Form</a> container, <tt>TabPane</tt> defines
attributes that a caller can set to customize the appearance of the tab.
<tt>TabPane</tt> currently defines two attributes: "label" and "icon" (additional
attributes may be added in the future to support closeable tabs or other such features).
Also note that disabling a tab component also disables its corresponding tab button,
preventing the user from navigating to that tab:
</p>
<source type="xml" location="org/apache/pivot/tutorials/navigation/tab_panes.bxml">
<![CDATA[
<navigation:TabPanes title="Tab Panes" maximized="true"
xmlns:bxml="http://pivot.apache.org/bxml"
xmlns:content="org.apache.pivot.wtk.content"
xmlns:navigation="org.apache.pivot.tutorials.navigation"
xmlns="org.apache.pivot.wtk">
<bxml:define>
<Prompt bxml:id="confirmCloseTabPrompt" title="Confirm Close Tab"
message="Really close this tab?"
options="['Cancel', 'OK']" selectedOptionIndex="1"/>
</bxml:define>
<TablePane styles="{padding:8, horizontalSpacing:6}">
<columns>
<TablePane.Column width="1*"/>
<TablePane.Column/>
</columns>
<TablePane.Row height="1*">
<Border styles="{padding:12}">
<BoxPane>
<TabPane bxml:id="tabPane">
<corner>
<BoxPane bxml:id="cornerBoxPane" styles="{horizontalAlignment:'right'}">
<TextInput textSize="10"/>
</BoxPane>
</corner>
<BoxPane styles="{horizontalAlignment:'center', verticalAlignment:'center'}">
<TabPane.tabData>
<content:ButtonData icon="/org/apache/pivot/tutorials/bell.png"
text="Bell"/>
</TabPane.tabData>
<Border styles="{padding:2}">
<Label text="240x180" preferredWidth="240" preferredHeight="180"
styles="{horizontalAlignment:'center', verticalAlignment:'center'}"/>
</Border>
</BoxPane>
<BoxPane styles="{horizontalAlignment:'center', verticalAlignment:'center'}">
<TabPane.tabData>
<content:ButtonData icon="/org/apache/pivot/tutorials/clock.png"
text="Clock"/>
</TabPane.tabData>
<Border styles="{padding:2}">
<Label text="320x240" preferredWidth="320" preferredHeight="240"
styles="{horizontalAlignment:'center', verticalAlignment:'center'}"/>
</Border>
</BoxPane>
<BoxPane styles="{horizontalAlignment:'center', verticalAlignment:'center'}">
<TabPane.tabData>
<content:ButtonData icon="/org/apache/pivot/tutorials/house.png"
text="House"/>
</TabPane.tabData>
<Border styles="{padding:2}">
<Label text="480x360" preferredWidth="480" preferredHeight="360"
styles="{horizontalAlignment:'center', verticalAlignment:'center'}"/>
</Border>
</BoxPane>
<BoxPane enabled="false">
<TabPane.tabData>
<content:ButtonData icon="/org/apache/pivot/tutorials/star.png"
text="Star"/>
</TabPane.tabData>
<Border styles="{padding:2}">
<Label text="480x360 (disabled)" preferredWidth="480" preferredHeight="360"
styles="{horizontalAlignment:'center', verticalAlignment:'center'}"/>
</Border>
</BoxPane>
</TabPane>
</BoxPane>
</Border>
<Border styles="{padding:2}">
<BoxPane orientation="vertical" styles="{padding:4, spacing:6}">
<Checkbox bxml:id="closeableCheckbox" buttonData="Closeable"/>
<Checkbox bxml:id="collapsibleCheckbox" buttonData="Collapsible"/>
<Label text="Tab orientation:"/>
<bxml:define>
<ButtonGroup bxml:id="tabOrientation"/>
</bxml:define>
<RadioButton bxml:id="horizontalRadioButton" buttonData="Horizontal" selected="true"
buttonGroup="$tabOrientation"/>
<RadioButton bxml:id="verticalRadioButton" buttonData="Vertical"
buttonGroup="$tabOrientation"/>
</BoxPane>
</Border>
</TablePane.Row>
</TablePane>
</navigation:TabPanes>
]]>
</source>
<p>
The default tab pane skin provides some styles for customizing the appearance and
behavior of the tab pane: "collapsible" and "tabOrientation". The "collapsible" style
is a boolean that controls how the tab pane responds to clicks on the tab buttons. When
set to <tt>true</tt>, clicking on the selected tab causes the tab pane to "collapse"
such that only the tab buttons remain visible. This is handy in situations where screen
real estate is at a premium, or when the content of the tab pane may be only
periodically relevant to the user but should still be conveniently accessible. The
"tabOrientation" style controls how the buttons themselves are laid out - either
horizontally or vertically.
</p>
<p>
The Java source for this example is as follows. It is fairly simple, consisting mostly
of event handling code for the radio buttons and checkbox:
</p>
<source type="java" location="org/apache/pivot/tutorials/navigation/TabPanes.java">
<![CDATA[
package org.apache.pivot.tutorials.navigation;
import java.net.URL;
import org.apache.pivot.beans.Bindable;
import org.apache.pivot.collections.Map;
import org.apache.pivot.util.Resources;
import org.apache.pivot.util.Vote;
import org.apache.pivot.wtk.Button;
import org.apache.pivot.wtk.ButtonStateListener;
import org.apache.pivot.wtk.Checkbox;
import org.apache.pivot.wtk.BoxPane;
import org.apache.pivot.wtk.Orientation;
import org.apache.pivot.wtk.Prompt;
import org.apache.pivot.wtk.RadioButton;
import org.apache.pivot.wtk.Sheet;
import org.apache.pivot.wtk.SheetCloseListener;
import org.apache.pivot.wtk.TabPane;
import org.apache.pivot.wtk.TabPaneListener;
import org.apache.pivot.wtk.Window;
public class TabPanes extends Window implements Bindable {
private Prompt confirmCloseTabPrompt = null;
private TabPane tabPane = null;
private Checkbox closeableCheckbox = null;
private Checkbox collapsibleCheckbox = null;
private RadioButton horizontalRadioButton = null;
private RadioButton verticalRadioButton = null;
private BoxPane cornerBoxPane = null;
private boolean confirmCloseTab = true;
@Override
public void initialize(Map<String, Object> namespace, URL location, Resources resources) {
confirmCloseTabPrompt = (Prompt)namespace.get("confirmCloseTabPrompt");
tabPane = (TabPane)namespace.get("tabPane");
closeableCheckbox = (Checkbox)namespace.get("closeableCheckbox");
collapsibleCheckbox = (Checkbox)namespace.get("collapsibleCheckbox");
horizontalRadioButton = (RadioButton)namespace.get("horizontalRadioButton");
verticalRadioButton = (RadioButton)namespace.get("verticalRadioButton");
cornerBoxPane = (BoxPane)namespace.get("cornerBoxPane");
tabPane.getTabPaneListeners().add(new TabPaneListener.Adapter() {
@Override
public Vote previewRemoveTabs(final TabPane tabPane, final int index, final int count) {
Vote vote;
if (confirmCloseTab) {
confirmCloseTabPrompt.open(TabPanes.this, new SheetCloseListener() {
@Override
public void sheetClosed(Sheet sheet) {
if (confirmCloseTabPrompt.getResult()
&& confirmCloseTabPrompt.getSelectedOptionIndex() == 1) {
confirmCloseTab = false;
int n = tabPane.getTabs().getLength();
if (index < n - 1) {
tabPane.setSelectedIndex(index + 1);
} else {
tabPane.setSelectedIndex(index - 1);
}
tabPane.getTabs().remove(index, count);
confirmCloseTab = true;
}
}
});
vote = Vote.DENY;
} else {
vote = Vote.APPROVE;
}
return vote;
}
});
ButtonStateListener checkboxStateListener = new ButtonStateListener() {
@Override
public void stateChanged(Button button, Button.State previousState) {
updateTabPane();
}
};
closeableCheckbox.getButtonStateListeners().add(checkboxStateListener);
collapsibleCheckbox.getButtonStateListeners().add(checkboxStateListener);
ButtonStateListener radioButtonStateListener = new ButtonStateListener() {
@Override
public void stateChanged(Button button, Button.State previousState) {
if (button.isSelected()) {
updateTabPane();
}
}
};
horizontalRadioButton.getButtonStateListeners().add(radioButtonStateListener);
verticalRadioButton.getButtonStateListeners().add(radioButtonStateListener);
updateTabPane();
}
private void updateTabPane() {
tabPane.setCloseable(closeableCheckbox.isSelected());
tabPane.setCollapsible(collapsibleCheckbox.isSelected());
if (horizontalRadioButton.isSelected()) {
tabPane.getStyles().put("tabOrientation", Orientation.HORIZONTAL);
if (tabPane.getCorner() == null) {
tabPane.setCorner(cornerBoxPane);
}
} else {
tabPane.getStyles().put("tabOrientation", Orientation.VERTICAL);
if (tabPane.getCorner() == cornerBoxPane) {
tabPane.setCorner(null);
}
}
}
}
]]>
</source>
<p>
Note that this example also demonstrates the use of the tab pane corner component. For
horizontally oriented tabs, this component appears in the upper right corner; for
vertical tabs, it appears in the lower left. The corner component in this example is a
flow pane containing a text input; it is hidden when the orientation is changed to
vertical because the corner component itself is not rotated and would cause the button
area to grow horizontally.
</p>
</body>
</document>