| <?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="card-panes"> |
| <properties> |
| <title>Card Panes</title> |
| </properties> |
| |
| <body> |
| <p> |
| Card panes are the most basic of the navigation components. They present a simple |
| "card stack" of components, only one of which is visible at a time. |
| </p> |
| |
| <p> |
| Unlike other navigation components, card panes don't include any "chrome" or intrinsic |
| means of navigation - all selection management must be performed programmatically by |
| the caller. While this imposes more responsibility on the developer, it is also the most |
| flexible, giving the developer complete control over the navigation experience. |
| </p> |
| |
| <p> |
| By default, the preferred size of a card pane is the maximum of the preferred widths |
| and heights of the cards, and each card is sized to fill the entire space. However, |
| card panes can also dynamically resize to match the preferred size of the currently |
| selected card. Additionally, a transition effect can be applied to the selection change |
| event, providing a more visually engaging experience when navigating between cards. |
| <tt>CardPane</tt> currently supports the following transition effects: |
| </p> |
| |
| <ul> |
| <li>Crossfade</li> |
| <li>Horizontal slide ("wipe" left/right)</li> |
| <li>Vertical slide ("wipe" up/down)</li> |
| <li>Horizonal Flip</li> |
| <li>Vertical Flip</li> |
| <li>Zoom</li> |
| </ul> |
| |
| <p> |
| Note that, by default, "directional" transitions (such as slide and zoom) will appear |
| to move forward when transitioning from a lower card index to a higher card index, and |
| vice versa. This means that, when moving from the last card to the first card, for |
| example, the transition will appear to move forward rather than backward. Since this |
| may not always be the desired user experience, card panes can also be specified as |
| circular, preserving the apparent direction when the selection wraps. |
| </p> |
| |
| <p> |
| The following application demonstrates the behavior of <tt>CardPane</tt>: |
| </p> |
| |
| <application class="org.apache.pivot.wtk.ScriptApplication" |
| width="640" 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/card_panes.bxml</src> |
| </startup-properties> |
| </application> |
| |
| <p> |
| The BXML source for the application is shown below. A set of buttons is provided to |
| allow the user to control the styles that affect the card pane's presentation; |
| specifically, "sizeToSelection" and "selectionChangeEffect". The card pane itself is |
| contained within a <tt>FlowPane</tt> so that its response to changes in these styles is |
| visible: |
| </p> |
| |
| <source type="xml" location="org/apache/pivot/tutorials/navigation/card_panes.bxml"> |
| <![CDATA[ |
| <navigation:CardPanes title="Card Panes" maximized="true" |
| xmlns:bxml="http://pivot.apache.org/bxml" |
| xmlns:navigation="org.apache.pivot.tutorials.navigation" |
| xmlns="org.apache.pivot.wtk"> |
| <TablePane styles="{padding:8, horizontalSpacing:6}"> |
| <columns> |
| <TablePane.Column width="1*"/> |
| <TablePane.Column/> |
| </columns> |
| |
| <TablePane.Row height="1*"> |
| <Border styles="{padding:12}"> |
| <TablePane styles="{verticalSpacing:6}"> |
| <columns> |
| <TablePane.Column width="1*"/> |
| </columns> |
| |
| <TablePane.Row height="1*"> |
| <BoxPane styles="{horizontalAlignment:'center', verticalAlignment:'center', |
| backgroundColor:'#cccccc'}"> |
| <Border styles="{padding:6}"> |
| <CardPane bxml:id="cardPane"> |
| <ImageView image="/org/apache/pivot/tutorials/IMG_0725_2.jpg"/> |
| <ImageView image="/org/apache/pivot/tutorials/IMG_0735_2.jpg"/> |
| <ImageView image="/org/apache/pivot/tutorials/IMG_0767_2.jpg"/> |
| </CardPane> |
| </Border> |
| </BoxPane> |
| </TablePane.Row> |
| |
| <TablePane.Row> |
| <Separator/> |
| </TablePane.Row> |
| |
| <TablePane.Row> |
| <BoxPane styles="{horizontalAlignment:'center'}"> |
| <LinkButton bxml:id="previousButton" buttonData="Previous"/> |
| <LinkButton bxml:id="nextButton" buttonData="Next"/> |
| </BoxPane> |
| </TablePane.Row> |
| </TablePane> |
| </Border> |
| |
| <Border styles="{padding:2}"> |
| <BoxPane orientation="vertical" styles="{padding:4, spacing:6}"> |
| <Checkbox bxml:id="sizeToSelectionCheckbox" buttonData="Size to selection"/> |
| <Label text="Selection change effect:"/> |
| |
| <bxml:define> |
| <ButtonGroup bxml:id="selectionChangeEffect"/> |
| </bxml:define> |
| |
| <RadioButton bxml:id="crossfadeRadioButton" buttonData="Crossfade" selected="true" |
| buttonGroup="$selectionChangeEffect"/> |
| <RadioButton bxml:id="horizontalSlideRadioButton" buttonData="Horizontal Slide" |
| buttonGroup="$selectionChangeEffect"/> |
| <RadioButton bxml:id="verticalSlideRadioButton" buttonData="Vertical Slide" |
| buttonGroup="$selectionChangeEffect"/> |
| <RadioButton bxml:id="horizontalFlipRadioButton" buttonData="Horizontal Flip" |
| buttonGroup="$selectionChangeEffect"/> |
| <RadioButton bxml:id="verticalFlipRadioButton" buttonData="Vertical Flip" |
| buttonGroup="$selectionChangeEffect"/> |
| <RadioButton bxml:id="zoomRadioButton" buttonData="Zoom" |
| buttonGroup="$selectionChangeEffect"/> |
| <RadioButton bxml:id="noneRadioButton" buttonData="None" |
| buttonGroup="$selectionChangeEffect"/> |
| </BoxPane> |
| </Border> |
| </TablePane.Row> |
| </TablePane> |
| </navigation:CardPanes> |
| ]]> |
| </source> |
| |
| <p> |
| The Java source is as follows. The <tt>updateCardPane()</tt> method applies the |
| appropriate styles to the card pane based on the button state: |
| </p> |
| |
| <source type="java" location="org/apache/pivot/tutorials/navigation/CardPanes.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.wtk.Button; |
| import org.apache.pivot.wtk.ButtonPressListener; |
| import org.apache.pivot.wtk.ButtonStateListener; |
| import org.apache.pivot.wtk.CardPane; |
| import org.apache.pivot.wtk.CardPaneListener; |
| import org.apache.pivot.wtk.Checkbox; |
| import org.apache.pivot.wtk.LinkButton; |
| import org.apache.pivot.wtk.RadioButton; |
| import org.apache.pivot.wtk.Window; |
| import org.apache.pivot.wtk.skin.CardPaneSkin; |
| |
| public class CardPanes extends Window implements Bindable { |
| private CardPane cardPane = null; |
| private LinkButton previousButton = null; |
| private LinkButton nextButton = null; |
| private Checkbox sizeToSelectionCheckbox = null; |
| private RadioButton crossfadeRadioButton = null; |
| private RadioButton horizontalSlideRadioButton = null; |
| private RadioButton verticalSlideRadioButton = null; |
| private RadioButton horizontalFlipRadioButton = null; |
| private RadioButton verticalFlipRadioButton = null; |
| private RadioButton zoomRadioButton = null; |
| private RadioButton noneRadioButton = null; |
| |
| @Override |
| public void initialize(Map<String, Object> namespace, URL location, Resources resources) { |
| cardPane = (CardPane)namespace.get("cardPane"); |
| previousButton = (LinkButton)namespace.get("previousButton"); |
| nextButton = (LinkButton)namespace.get("nextButton"); |
| sizeToSelectionCheckbox = (Checkbox)namespace.get("sizeToSelectionCheckbox"); |
| |
| crossfadeRadioButton = (RadioButton)namespace.get("crossfadeRadioButton"); |
| horizontalSlideRadioButton = (RadioButton)namespace.get("horizontalSlideRadioButton"); |
| verticalSlideRadioButton = (RadioButton)namespace.get("verticalSlideRadioButton"); |
| horizontalFlipRadioButton = (RadioButton)namespace.get("horizontalFlipRadioButton"); |
| verticalFlipRadioButton = (RadioButton)namespace.get("verticalFlipRadioButton"); |
| zoomRadioButton = (RadioButton)namespace.get("zoomRadioButton"); |
| noneRadioButton = (RadioButton)namespace.get("noneRadioButton"); |
| |
| cardPane.getCardPaneListeners().add(new CardPaneListener.Adapter() { |
| @Override |
| public void selectedIndexChanged(CardPane cardPane, int previousSelectedIndex) { |
| updateLinkButtonState(); |
| } |
| }); |
| |
| previousButton.getButtonPressListeners().add(new ButtonPressListener() { |
| @Override |
| public void buttonPressed(Button button) { |
| cardPane.setSelectedIndex(cardPane.getSelectedIndex() - 1); |
| } |
| }); |
| |
| nextButton.getButtonPressListeners().add(new ButtonPressListener() { |
| @Override |
| public void buttonPressed(Button button) { |
| cardPane.setSelectedIndex(cardPane.getSelectedIndex() + 1); |
| } |
| }); |
| |
| ButtonStateListener checkboxStateListener = new ButtonStateListener() { |
| @Override |
| public void stateChanged(Button button, Button.State previousState) { |
| updateCardPane(); |
| } |
| }; |
| |
| sizeToSelectionCheckbox.getButtonStateListeners().add(checkboxStateListener); |
| |
| ButtonStateListener radioButtonStateListener = new ButtonStateListener() { |
| @Override |
| public void stateChanged(Button button, Button.State previousState) { |
| if (button.isSelected()) { |
| updateCardPane(); |
| } |
| } |
| }; |
| |
| crossfadeRadioButton.getButtonStateListeners().add(radioButtonStateListener); |
| horizontalSlideRadioButton.getButtonStateListeners().add(radioButtonStateListener); |
| verticalSlideRadioButton.getButtonStateListeners().add(radioButtonStateListener); |
| horizontalFlipRadioButton.getButtonStateListeners().add(radioButtonStateListener); |
| verticalFlipRadioButton.getButtonStateListeners().add(radioButtonStateListener); |
| zoomRadioButton.getButtonStateListeners().add(radioButtonStateListener); |
| noneRadioButton.getButtonStateListeners().add(radioButtonStateListener); |
| |
| updateCardPane(); |
| updateLinkButtonState(); |
| } |
| |
| private void updateCardPane() { |
| cardPane.getStyles().put("sizeToSelection", sizeToSelectionCheckbox.isSelected()); |
| |
| if (crossfadeRadioButton.isSelected()) { |
| cardPane.getStyles().put("selectionChangeEffect", |
| CardPaneSkin.SelectionChangeEffect.CROSSFADE); |
| } else if (horizontalSlideRadioButton.isSelected()) { |
| cardPane.getStyles().put("selectionChangeEffect", |
| CardPaneSkin.SelectionChangeEffect.HORIZONTAL_SLIDE); |
| } else if (verticalSlideRadioButton.isSelected()) { |
| cardPane.getStyles().put("selectionChangeEffect", |
| CardPaneSkin.SelectionChangeEffect.VERTICAL_SLIDE); |
| } else if (horizontalFlipRadioButton.isSelected()) { |
| cardPane.getStyles().put("selectionChangeEffect", |
| CardPaneSkin.SelectionChangeEffect.HORIZONTAL_FLIP); |
| } else if (verticalFlipRadioButton.isSelected()) { |
| cardPane.getStyles().put("selectionChangeEffect", |
| CardPaneSkin.SelectionChangeEffect.VERTICAL_FLIP); |
| } else if (zoomRadioButton.isSelected()) { |
| cardPane.getStyles().put("selectionChangeEffect", |
| CardPaneSkin.SelectionChangeEffect.ZOOM); |
| } else { |
| cardPane.getStyles().put("selectionChangeEffect", null); |
| } |
| } |
| |
| private void updateLinkButtonState() { |
| int selectedIndex = cardPane.getSelectedIndex(); |
| previousButton.setEnabled(selectedIndex > 0); |
| nextButton.setEnabled(selectedIndex < cardPane.getLength() - 1); |
| } |
| } |
| ]]> |
| </source> |
| </body> |
| </document> |