You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@pivot.apache.org by tv...@apache.org on 2009/03/16 17:16:58 UTC

svn commit: r754926 [13/38] - in /incubator/pivot/tags/v1.0: ./ charts-test/ charts-test/src/ charts-test/src/pivot/ charts-test/src/pivot/charts/ charts-test/src/pivot/charts/test/ charts/ charts/lib/ charts/src/ charts/src/pivot/ charts/src/pivot/cha...

Added: incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/Button.java
URL: http://svn.apache.org/viewvc/incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/Button.java?rev=754926&view=auto
==============================================================================
--- incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/Button.java (added)
+++ incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/Button.java Mon Mar 16 16:16:40 2009
@@ -0,0 +1,628 @@
+/*
+ * Copyright (c) 2008 VMware, Inc.
+ *
+ * Licensed 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.
+ */
+package pivot.wtk;
+
+import pivot.collections.Dictionary;
+import pivot.collections.HashMap;
+import pivot.util.ListenerList;
+import pivot.util.Vote;
+
+/**
+ * Abstract base class for button components.
+ *
+ * TODO Ensure that button group names are unique across applications?
+ * Applets downloaded from different domains won't clash, but multiple instances
+ * of the same application from the same domain would. Put the groups in the
+ * application context?
+ *
+ * TODO Allow callers to remove a button group (possibly by exposing group
+ * dictionary interface).
+ *
+ * @author gbrown
+ */
+public abstract class Button extends Component {
+    /**
+     * Enumeration representing a button's selection state.
+     *
+     * @author gbrown
+     */
+    public enum State {
+        SELECTED,
+        UNSELECTED,
+        MIXED;
+
+        public static State decode(String value) {
+            return valueOf(value.toUpperCase());
+        }
+    }
+
+    /**
+     * Button data renderer interface.
+     *
+     * @author gbrown
+     */
+    public interface DataRenderer extends Renderer {
+        public void render(Object data, Button button, boolean highlighted);
+    }
+
+    /**
+     * Class representing a toggle button group.
+     *
+     * @author gbrown
+     */
+    public static class Group {
+        private static class GroupListenerList extends ListenerList<GroupListener>
+            implements GroupListener {
+            public void selectionChanged(Group group, Button previousSelection) {
+                for (GroupListener listener : this) {
+                    listener.selectionChanged(group, previousSelection);
+                }
+            }
+        }
+
+        private Button selection = null;
+        private GroupListenerList groupListeners = new GroupListenerList();
+
+        public Group() {
+        }
+
+        public Button getSelection() {
+            return selection;
+        }
+
+        private void setSelection(Button selection) {
+            Button previousSelection = this.selection;
+
+            if (previousSelection != selection) {
+                this.selection = selection;
+                groupListeners.selectionChanged(this, previousSelection);
+            }
+        }
+
+        public ListenerList<GroupListener> getGroupListeners() {
+            return groupListeners;
+        }
+    }
+
+    /**
+     * Listener interface for toggle button groups.
+     *
+     * @author gbrown
+     */
+    public interface GroupListener {
+        public void selectionChanged(Group group, Button previousSelection);
+    }
+
+    /**
+     * Button listener list.
+     *
+     * @author gbrown
+     */
+    private static class ButtonListenerList extends ListenerList<ButtonListener>
+        implements ButtonListener {
+        public void buttonDataChanged(Button button, Object previousButtonData) {
+            for (ButtonListener listener : this) {
+                listener.buttonDataChanged(button, previousButtonData);
+            }
+        }
+
+        public void dataRendererChanged(Button button, DataRenderer previousDataRenderer) {
+            for (ButtonListener listener : this) {
+                listener.dataRendererChanged(button, previousDataRenderer);
+            }
+        }
+
+        public void actionChanged(Button button, Action previousAction) {
+            for (ButtonListener listener : this) {
+                listener.actionChanged(button, previousAction);
+            }
+        }
+
+        public void toggleButtonChanged(Button button) {
+            for (ButtonListener listener : this) {
+                listener.toggleButtonChanged(button);
+            }
+        }
+
+        public void triStateChanged(Button button) {
+            for (ButtonListener listener : this) {
+                listener.triStateChanged(button);
+            }
+        }
+
+        public void groupChanged(Button button, Button.Group previousGroup) {
+            for (ButtonListener listener : this) {
+                listener.groupChanged(button, previousGroup);
+            }
+        }
+
+        public void selectedKeyChanged(Button button, String previousSelectedKey) {
+            for (ButtonListener listener : this) {
+                listener.selectedKeyChanged(button, previousSelectedKey);
+            }
+        }
+
+        public void stateKeyChanged(Button button, String previousStateKey) {
+            for (ButtonListener listener : this) {
+                listener.stateKeyChanged(button, previousStateKey);
+            }
+        }
+    }
+
+    /**
+     * Button state listener list.
+     *
+     * @author gbrown
+     */
+    private static class ButtonStateListenerList extends ListenerList<ButtonStateListener>
+        implements ButtonStateListener {
+        public Vote previewStateChange(Button button, Button.State state) {
+            Vote vote = Vote.APPROVE;
+
+            for (ButtonStateListener listener : this) {
+                vote = vote.tally(listener.previewStateChange(button, state));
+            }
+
+            return vote;
+        }
+
+        public void stateChangeVetoed(Button button, Vote reason) {
+            for (ButtonStateListener listener : this) {
+                listener.stateChangeVetoed(button, reason);
+            }
+        }
+
+        public void stateChanged(Button button, Button.State previousState) {
+            for (ButtonStateListener listener : this) {
+                listener.stateChanged(button, previousState);
+            }
+        }
+    }
+
+    /**
+     * Button press listener list.
+     *
+     * @author gbrown
+     */
+    private static class ButtonPressListenerList extends ListenerList<ButtonPressListener>
+        implements ButtonPressListener {
+        public void buttonPressed(Button button) {
+            for (ButtonPressListener listener : this) {
+                listener.buttonPressed(button);
+            }
+        }
+    }
+
+    private Object buttonData = null;
+    private DataRenderer dataRenderer = null;
+    private Action action = null;
+    private ActionListener actionListener = new ActionListener() {
+        public void enabledChanged(Action action) {
+            setEnabled(action.isEnabled());
+        }
+    };
+
+    private State state = null;
+    private Group group = null;
+
+    private boolean toggleButton = false;
+    private boolean triState = false;
+    private String selectedKey = null;
+    private String stateKey = null;
+
+    private ButtonListenerList buttonListeners = new ButtonListenerList();
+    private ButtonStateListenerList buttonStateListeners = new ButtonStateListenerList();
+    private ButtonPressListenerList buttonPressListeners = new ButtonPressListenerList();
+
+    private static HashMap<String, Group> groups = new HashMap<String, Group>();
+
+    public Button() {
+        this(null);
+    }
+
+    public Button(Object buttonData) {
+        this.buttonData = buttonData;
+    }
+
+    public Object getButtonData() {
+        return buttonData;
+    }
+
+    public void setButtonData(Object buttonData) {
+        Object previousButtonData = this.buttonData;
+        if (previousButtonData != buttonData) {
+            this.buttonData = buttonData;
+
+            buttonListeners.buttonDataChanged(this, previousButtonData);
+        }
+    }
+
+    public DataRenderer getDataRenderer() {
+        return dataRenderer;
+    }
+
+    public void setDataRenderer(DataRenderer dataRenderer) {
+        if (dataRenderer == null) {
+            throw new IllegalArgumentException("dataRenderer is null.");
+        }
+
+        DataRenderer previousDataRenderer = this.dataRenderer;
+
+        if (previousDataRenderer != dataRenderer) {
+            this.dataRenderer = dataRenderer;
+            buttonListeners.dataRendererChanged(this, previousDataRenderer);
+        }
+    }
+
+    /**
+     * Returns the action associated with this button.
+     *
+     * @return
+     * The button's action, or <tt>null</tt> if no action is defined.
+     */
+    public Action getAction() {
+        return action;
+    }
+
+    /**
+     * Sets this button's action.
+     *
+     * @param action
+     * The action to be triggered when this button is pressed, or <tt>null</tt>
+     * for no action.
+     */
+    public void setAction(Action action) {
+        Action previousAction = this.action;
+
+        if (previousAction != action) {
+            if (previousAction != null) {
+                previousAction.getActionListeners().remove(actionListener);
+            }
+
+            this.action = action;
+
+            if (action != null) {
+                action.getActionListeners().add(actionListener);
+                setEnabled(action.isEnabled());
+            }
+
+            buttonListeners.actionChanged(this, previousAction);
+        }
+    }
+
+    /**
+     * Sets this button's action.
+     *
+     * @param actionID
+     * The ID of the action to be triggered when this button is pressed.
+     *
+     * @throws IllegalArgumentException
+     * If an action with the given ID does not exist.
+     */
+    public void setAction(String actionID) {
+        if (actionID == null) {
+            throw new IllegalArgumentException("actionID is null");
+        }
+
+        Action action = Action.getActions().get(actionID);
+        if (action == null) {
+            throw new IllegalArgumentException("An action with ID "
+                + actionID + " does not exist.");
+        }
+
+        setAction(action);
+    }
+
+    @Override
+    public void setEnabled(boolean enabled) {
+        if (action != null
+            && enabled != action.isEnabled()) {
+            throw new IllegalArgumentException("Button and action enabled"
+                + " states are not consistent.");
+        }
+
+        super.setEnabled(enabled);
+    }
+
+    /**
+     * "Presses" the button. Performs any action associated with the button.
+     */
+    public void press() {
+        if (action != null) {
+            action.perform();
+        }
+
+        buttonPressListeners.buttonPressed(this);
+    }
+
+    /**
+     * Returns the button's selected state.
+     */
+    public boolean isSelected() {
+        return (getState() == State.SELECTED);
+    }
+
+    /**
+     * Sets the button's selected state.
+     *
+     * @param selected
+     */
+    public void setSelected(boolean selected) {
+        setState(selected ? State.SELECTED : State.UNSELECTED);
+    }
+
+    /**
+     * Returns the button's selection state.
+     */
+    public State getState() {
+        return state;
+    }
+
+    /**
+     * Sets the button's selection state.
+     *
+     * @param state
+     */
+    public void setState(State state) {
+        if (state == null) {
+            throw new IllegalArgumentException("state is null.");
+        }
+
+        if (!toggleButton) {
+            throw new IllegalStateException("Button is not in toggle mode.");
+        }
+
+        if (state == State.MIXED
+            && !triState) {
+            throw new IllegalArgumentException("Button is not tri-state.");
+        }
+
+        State previousState = this.state;
+
+        if (previousState != state) {
+            Vote vote = buttonStateListeners.previewStateChange(this, state);
+
+            if (vote == Vote.APPROVE) {
+                this.state = state;
+
+                if (group != null) {
+                    // Update the group's selection
+                    Button selection = group.getSelection();
+
+                    if (state == State.SELECTED) {
+                        // Set this as the new selection (do this before
+                        // de-selecting any currently selected button so the
+                        // group's change event isn't fired twice)
+                        group.setSelection(this);
+
+                        // De-select any previously selected button
+                        if (selection != null) {
+                            selection.setSelected(false);
+                        }
+                    }
+                    else {
+                        // If this button is currently selected, clear the
+                        // selection
+                        if (selection == this) {
+                            group.setSelection(null);
+                        }
+                    }
+                }
+
+                buttonStateListeners.stateChanged(this, previousState);
+            } else {
+                buttonStateListeners.stateChangeVetoed(this, vote);
+            }
+        }
+    }
+
+    public void setState(String state) {
+        if (state == null) {
+            throw new IllegalArgumentException("state is null.");
+        }
+
+        setState(State.decode(state));
+    }
+
+    /**
+     * Returns the button's toggle state.
+     */
+    public boolean isToggleButton() {
+        return toggleButton;
+    }
+
+    /**
+     * Sets the button's toggle state.
+     *
+     * @param toggleButton
+     */
+    public void setToggleButton(boolean toggleButton) {
+        if (this.toggleButton != toggleButton) {
+            // Non-toggle push buttons can't be selected, can't be part of a
+            // group, and can't be tri-state
+            if (!toggleButton) {
+                setSelected(false);
+                setGroup((Group)null);
+                setTriState(false);
+            }
+
+            this.toggleButton = toggleButton;
+
+            buttonListeners.toggleButtonChanged(this);
+        }
+    }
+
+    /**
+     * Returns the button's tri-state state.
+     */
+    public boolean isTriState() {
+        return triState;
+    }
+
+    /**
+     * Sets the button's tri-state state.
+     *
+     * @param triState
+     */
+    public void setTriState(boolean triState) {
+        if (!toggleButton) {
+            throw new IllegalStateException("Button is not in toggle mode.");
+        }
+
+        if (triState
+            && group != null) {
+            throw new IllegalStateException("Toggle button is a member of a group.");
+        }
+
+        if (this.triState != triState) {
+            this.triState = triState;
+            buttonListeners.triStateChanged(this);
+        }
+    }
+
+    /**
+     * Returns the button's group.
+     */
+    public Group getGroup() {
+        return group;
+    }
+
+    /**
+     * Sets the button's group.
+     *
+     * @param group
+     */
+    public void setGroup(Group group) {
+        if (!toggleButton) {
+            throw new IllegalStateException("Button is not in toggle mode.");
+        }
+
+        if (group != null
+            && triState) {
+            throw new IllegalStateException("Toggle button is tri-state.");
+        }
+
+        Group previousGroup = this.group;
+
+        if (previousGroup != group) {
+            this.group = group;
+
+            // If this was the selected button in the previous group,
+            // clear the group's selection
+            if (previousGroup != null
+                && previousGroup.getSelection() == this) {
+                previousGroup.setSelection(null);
+            }
+
+            // If this button is selected, set it as the group's selection
+            if (group != null
+                && isSelected()) {
+                group.setSelection(this);
+            }
+
+            buttonListeners.groupChanged(this, previousGroup);
+        }
+    }
+
+    public void setGroup(String group) {
+        if (group == null) {
+            throw new IllegalArgumentException("group is null.");
+        }
+
+        if (!groups.containsKey(group)) {
+            groups.put(group, new Group());
+        }
+
+        setGroup(groups.get(group));
+    }
+
+    public String getSelectedKey() {
+        return selectedKey;
+    }
+
+    public void setSelectedKey(String selectedKey) {
+        String previousSelectedKey = this.selectedKey;
+        this.selectedKey = selectedKey;
+        buttonListeners.selectedKeyChanged(this, previousSelectedKey);
+    }
+
+    public String getStateKey() {
+        return stateKey;
+    }
+
+    public void setStateKey(String stateKey) {
+        String previousStateKey = this.stateKey;
+        this.stateKey = stateKey;
+        buttonListeners.stateKeyChanged(this, previousStateKey);
+    }
+
+    @Override
+    public void load(Dictionary<String, Object> context) {
+        if (selectedKey != null
+            && context.containsKey(selectedKey)) {
+            Object value = context.get(selectedKey);
+
+            if (!(value instanceof Boolean)) {
+                throw new IllegalArgumentException("value must be an instance of "
+                    + Boolean.class.getName());
+            }
+
+            setSelected((Boolean)value);
+        }
+
+        if (stateKey != null
+            && context.containsKey(stateKey)) {
+            Object value = context.get(stateKey);
+            if (value instanceof String) {
+                value = State.decode((String)value);
+            }
+
+            if (!(value instanceof State)) {
+                throw new IllegalArgumentException("value must be an instance of "
+                    + State.class.getName());
+            }
+
+            setState((State)value);
+        }
+    }
+
+    @Override
+    public void store(Dictionary<String, Object> context) {
+        if (selectedKey != null) {
+            context.put(selectedKey, isSelected());
+        }
+
+        if (stateKey != null) {
+            context.put(stateKey, state);
+        }
+    }
+
+    public static Group getGroup(String groupName) {
+        return groups.get(groupName);
+    }
+
+    public ListenerList<ButtonListener> getButtonListeners() {
+        return buttonListeners;
+    }
+
+    public ListenerList<ButtonStateListener> getButtonStateListeners() {
+        return buttonStateListeners;
+    }
+
+    public ListenerList<ButtonPressListener> getButtonPressListeners() {
+        return buttonPressListeners;
+    }
+}

Added: incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/ButtonListener.java
URL: http://svn.apache.org/viewvc/incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/ButtonListener.java?rev=754926&view=auto
==============================================================================
--- incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/ButtonListener.java (added)
+++ incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/ButtonListener.java Mon Mar 16 16:16:40 2009
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2008 VMware, Inc.
+ *
+ * Licensed 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.
+ */
+package pivot.wtk;
+
+/**
+ * Button listener interface.
+ *
+ * @author gbrown
+ */
+public interface ButtonListener {
+    /**
+     * Called when a button's data has changed.
+     *
+     * @param button
+     * @param previousButtonData
+     */
+    public void buttonDataChanged(Button button, Object previousButtonData);
+
+    /**
+     * Called when a button's data renderer has changed.
+     *
+     * @param button
+     * @param previousDataRenderer
+     */
+    public void dataRendererChanged(Button button, Button.DataRenderer previousDataRenderer);
+
+    /**
+     * Called when a button's action has changed.
+     *
+     * @param button
+     * @param previousAction
+     */
+    public void actionChanged(Button button, Action previousAction);
+
+    /**
+     * Called when a button's toggle button flag has changed.
+     *
+     * @param button
+     */
+    public void toggleButtonChanged(Button button);
+
+    /**
+     * Called when a button's tri-state flag has changed.
+     *
+     * @param button
+     */
+    public void triStateChanged(Button button);
+
+    /**
+     * Called when a button's group has changed.
+     *
+     * @param button
+     * @param previousGroup
+     */
+    public void groupChanged(Button button, Button.Group previousGroup);
+
+    /**
+     * Called when a button's selected key has changed.
+     *
+     * @param button
+     * @param previousSelectedKey
+     */
+    public void selectedKeyChanged(Button button, String previousSelectedKey);
+
+    /**
+     * Called when a button's state key has changed.
+     *
+     * @param button
+     * @param previousStateKey
+     */
+    public void stateKeyChanged(Button button, String previousStateKey);
+}

Added: incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/ButtonPressListener.java
URL: http://svn.apache.org/viewvc/incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/ButtonPressListener.java?rev=754926&view=auto
==============================================================================
--- incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/ButtonPressListener.java (added)
+++ incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/ButtonPressListener.java Mon Mar 16 16:16:40 2009
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2008 VMware, Inc.
+ *
+ * Licensed 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.
+ */
+package pivot.wtk;
+
+/**
+ * Button press listener interface.
+ *
+ * @author gbrown
+ */
+public interface ButtonPressListener {
+    /**
+     * Called when a button is pressed.
+     *
+     * @param button
+     */
+    public void buttonPressed(Button button);
+}

Added: incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/ButtonStateListener.java
URL: http://svn.apache.org/viewvc/incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/ButtonStateListener.java?rev=754926&view=auto
==============================================================================
--- incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/ButtonStateListener.java (added)
+++ incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/ButtonStateListener.java Mon Mar 16 16:16:40 2009
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2008 VMware, Inc.
+ *
+ * Licensed 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.
+ */
+package pivot.wtk;
+
+import pivot.util.Vote;
+
+/**
+ * Button state listener interface.
+ *
+ * @author gbrown
+ * @author tvolkert
+ */
+public interface ButtonStateListener {
+    /**
+     * Called to preview a button state change event.
+     *
+     * @param button
+     * @param state
+     */
+    public Vote previewStateChange(Button button, Button.State state);
+
+    /**
+     * Called when a state change event has been vetoed.
+     *
+     * @param button
+     * @param reason
+     */
+    public void stateChangeVetoed(Button button, Vote reason);
+
+    /**
+     * Called when a button's state has changed.
+     *
+     * @param button
+     * @param previousState
+     */
+    public void stateChanged(Button button, Button.State previousState);
+}

Added: incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/Calendar.java
URL: http://svn.apache.org/viewvc/incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/Calendar.java?rev=754926&view=auto
==============================================================================
--- incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/Calendar.java (added)
+++ incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/Calendar.java Mon Mar 16 16:16:40 2009
@@ -0,0 +1,258 @@
+/*
+ * Copyright (c) 2008 VMware, Inc.
+ *
+ * Licensed 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.
+ */
+package pivot.wtk;
+
+import pivot.collections.Dictionary;
+import pivot.util.CalendarDate;
+import pivot.util.ListenerList;
+
+/**
+ * Component that allows the user to select a date.
+ *
+ * @author tvolkert
+ */
+public class Calendar extends Container {
+    /**
+     * calendar listener list.
+     *
+     * @author tvolkert
+     */
+    private static class CalendarListenerList extends ListenerList<CalendarListener>
+        implements CalendarListener {
+
+        public void yearChanged(Calendar calendar, int previousYear) {
+            for (CalendarListener listener : this) {
+                listener.yearChanged(calendar, previousYear);
+            }
+        }
+
+        public void monthChanged(Calendar calendar, int previousMonth) {
+            for (CalendarListener listener : this) {
+                listener.monthChanged(calendar, previousMonth);
+            }
+        }
+
+        public void selectedDateKeyChanged(Calendar calendar,
+            String previousSelectedDateKey) {
+            for (CalendarListener listener : this) {
+                listener.selectedDateKeyChanged(calendar, previousSelectedDateKey);
+            }
+        }
+    }
+
+    /**
+     * calendar selection listener list.
+     *
+     * @author tvolkert
+     */
+    private static class CalendarSelectionListenerList
+        extends ListenerList<CalendarSelectionListener>
+        implements CalendarSelectionListener {
+
+        public void selectedDateChanged(Calendar calendar,
+            CalendarDate previousSelectedDate) {
+            for (CalendarSelectionListener listener : this) {
+                listener.selectedDateChanged(calendar, previousSelectedDate);
+            }
+        }
+    }
+
+    private int year;
+    private int month;
+
+    private CalendarDate selectedDate = null;
+
+    private String selectedDateKey = null;
+
+    private CalendarListenerList calendarListeners = new CalendarListenerList();
+    private CalendarSelectionListenerList calendarSelectionListeners =
+        new CalendarSelectionListenerList();
+
+    /**
+     * Creates a calendar set to the current month and year in the default
+     * timezone in the default locale.
+     */
+    public Calendar() {
+        this(new CalendarDate());
+    }
+
+    /**
+     * Creates a new calendar set to the specified calendar's year and
+     * month.
+     */
+    private Calendar(CalendarDate calendarDate) {
+        this(calendarDate.getYear(), calendarDate.getMonth());
+    }
+
+    /**
+     * Creates a new calendar set to the specified year and month.
+     *
+     * @param year
+     * The year (e.g. 2008)
+     * @param month
+     * The month, 0-based (e.g. 2 for March)
+     */
+    public Calendar(int year, int month) {
+        this.year = year;
+        this.month = month;
+
+        installSkin(Calendar.class);
+    }
+
+    /**
+     * Gets the year to which this calendar is currently set.
+     */
+    public int getYear() {
+        return year;
+    }
+
+    /**
+     * Sets this calendar's year.
+     */
+    public void setYear(int year) {
+        int previousYear = this.year;
+
+        if (previousYear != year) {
+            this.year = year;
+            calendarListeners.yearChanged(this, previousYear);
+        }
+    }
+
+    /**
+     * Gets the month to which this calendar is currently set.
+     */
+    public int getMonth() {
+        return month;
+    }
+
+    /**
+     * Sets this calendar's month.
+     */
+    public void setMonth(int month) {
+        int previousMonth = this.month;
+
+        if (previousMonth != month) {
+            this.month = month;
+            calendarListeners.monthChanged(this, previousMonth);
+        }
+    }
+
+    /**
+     * Gets the currently selected date, or <tt>null</tt> if no date is
+     * selected.
+     */
+    public CalendarDate getSelectedDate() {
+        return selectedDate;
+    }
+
+    /**
+     * Sets the currently selected date.
+     *
+     * @param selectedDate
+     * The selected date, or <tt>null</tt> to specify no selection
+     */
+    public void setSelectedDate(CalendarDate selectedDate) {
+        CalendarDate previousSelectedDate = this.selectedDate;
+
+        if ((selectedDate == null ^ previousSelectedDate == null)
+            || (selectedDate != null && !selectedDate.equals(previousSelectedDate))) {
+            this.selectedDate = selectedDate;
+            calendarSelectionListeners.selectedDateChanged(this, previousSelectedDate);
+        }
+    }
+
+    /**
+     * Sets the selected date to the date represented by the specified date
+     * string. The date string must be in the <tt>ISO 8601</tt> "calendar date"
+     * format, which is <tt>[YYYY]-[MM]-[DD]</tt>.
+     *
+     * @param selectedDate
+     * A string in the form of <tt>[YYYY]-[MM]-[DD]</tt> (e.g. 2008-07-23)
+     */
+    public final void setSelectedDate(String selectedDate) {
+        if (selectedDate == null) {
+            throw new IllegalArgumentException("selectedDate is null.");
+        }
+
+        setSelectedDate(new CalendarDate(selectedDate));
+    }
+
+    /**
+     * Gets the data binding key that is set on this calendar.
+     */
+    public String getSelectedDateKey() {
+        return selectedDateKey;
+    }
+
+    /**
+     * Sets this calendar's data binding key.
+     */
+    public void setSelectedDateKey(String selectedDateKey) {
+        String previousSelectedDateKey = this.selectedDateKey;
+
+        if ((selectedDateKey == null ^ previousSelectedDateKey == null)
+            || (selectedDateKey != null && !selectedDateKey.equals(previousSelectedDateKey))) {
+            this.selectedDateKey = selectedDateKey;
+            calendarListeners.selectedDateKeyChanged(this, previousSelectedDateKey);
+        }
+    }
+
+    /**
+     * Loads the selected date from the specified bind context using this date
+     * picker's bind key, if one is set.
+     */
+    @Override
+    public void load(Dictionary<String, Object> context) {
+        if (selectedDateKey != null
+            && context.containsKey(selectedDateKey)) {
+            Object value = context.get(selectedDateKey);
+
+            if (value instanceof CalendarDate) {
+                setSelectedDate((CalendarDate)value);
+            } else if (value instanceof String) {
+                setSelectedDate((String)value);
+            } else {
+                throw new IllegalArgumentException("Invalid date type: " +
+                    value.getClass().getName());
+            }
+        }
+    }
+
+    /**
+     * Stores the selected date into the specified bind context using this date
+     * picker's bind key, if one is set.
+     */
+    @Override
+    public void store(Dictionary<String, Object> context) {
+        if (selectedDateKey != null) {
+            context.put(selectedDateKey, selectedDate);
+        }
+    }
+
+    /**
+     * Gets this calendar's <tt>CalendarListener</tt> collection.
+     */
+    public ListenerList<CalendarListener> getCalendarListeners() {
+        return calendarListeners;
+    }
+
+    /**
+     * Gets this calendar's <tt>CalendarSelectionListener</tt> collection.
+     */
+    public ListenerList<CalendarSelectionListener> getCalendarSelectionListeners() {
+        return calendarSelectionListeners;
+    }
+}

Added: incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/CalendarButton.java
URL: http://svn.apache.org/viewvc/incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/CalendarButton.java?rev=754926&view=auto
==============================================================================
--- incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/CalendarButton.java (added)
+++ incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/CalendarButton.java Mon Mar 16 16:16:40 2009
@@ -0,0 +1,324 @@
+/*
+ * Copyright (c) 2008 VMware, Inc.
+ *
+ * Licensed 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.
+ */
+package pivot.wtk;
+
+import pivot.collections.Dictionary;
+import pivot.util.CalendarDate;
+import pivot.util.ListenerList;
+import pivot.wtk.content.ButtonDataRenderer;
+
+/**
+ * A component that allows a user to select a calendar date. The calendar
+ * is hidden until the user pushes the button.
+ *
+ * @author tvolkert
+ */
+public class CalendarButton extends Button {
+    /**
+     * calendar button skin interface. calendar button skins are required
+     * to implement this.
+     *
+     * @author tvolkert
+     */
+    public interface Skin {
+        public Calendar getCalendar();
+    }
+
+    /**
+     * calendar button listener list.
+     *
+     * @author tvolkert
+     */
+    private static class CalendarButtonListenerList
+        extends ListenerList<CalendarButtonListener>
+        implements CalendarButtonListener {
+
+        public void yearChanged(CalendarButton calendarButton, int previousYear) {
+            for (CalendarButtonListener listener : this) {
+                listener.yearChanged(calendarButton, previousYear);
+            }
+        }
+
+        public void monthChanged(CalendarButton calendarButton, int previousMonth) {
+            for (CalendarButtonListener listener : this) {
+                listener.monthChanged(calendarButton, previousMonth);
+            }
+        }
+
+        public void selectedDateKeyChanged(CalendarButton calendarButton,
+            String previousSelectedDateKey) {
+            for (CalendarButtonListener listener : this) {
+                listener.selectedDateKeyChanged(calendarButton, previousSelectedDateKey);
+            }
+        }
+    }
+
+    /**
+     * calendar button selection listener list.
+     *
+     * @author tvolkert
+     */
+    private static class CalendarButtonSelectionListenerList
+        extends ListenerList<CalendarButtonSelectionListener>
+        implements CalendarButtonSelectionListener {
+
+        public void selectedDateChanged(CalendarButton calendarButton,
+            CalendarDate previousSelectedDate) {
+            for (CalendarButtonSelectionListener listener : this) {
+                listener.selectedDateChanged(calendarButton, previousSelectedDate);
+            }
+        }
+    }
+
+    private CalendarButtonListenerList calendarButtonListeners =
+        new CalendarButtonListenerList();
+    private CalendarButtonSelectionListenerList calendarButtonSelectionListeners =
+        new CalendarButtonSelectionListenerList();
+
+    private static final Button.DataRenderer DEFAULT_DATA_RENDERER = new ButtonDataRenderer();
+
+    /**
+     * Creates a blank calendar button whose calendar is set to the
+     * current month and year in the default timezone in the default locale.
+     */
+    public CalendarButton() {
+        this(null);
+    }
+
+    /**
+     * Creates a calendar button with the given button data and whose date
+     * picker is set to the current month and year in the default timezone in
+     * the default locale.
+     *
+     * @param buttonData
+     * The button's button data
+     */
+    public CalendarButton(Object buttonData) {
+        super(buttonData);
+
+        setDataRenderer(DEFAULT_DATA_RENDERER);
+
+        installSkin(CalendarButton.class);
+    }
+
+    @Override
+    protected void setSkin(pivot.wtk.Skin skin) {
+        if (!(skin instanceof CalendarButton.Skin)) {
+            throw new IllegalArgumentException("Skin class must implement "
+                + CalendarButton.Skin.class.getName());
+        }
+
+        super.setSkin(skin);
+    }
+
+    /**
+     * @throws UnsupportedOperationException
+     * This method is not supported by CalendarButton.
+     */
+    @Override
+    public void setToggleButton(boolean toggleButton) {
+        throw new UnsupportedOperationException("calendar buttons cannot be toggle buttons.");
+    }
+
+    /**
+     * Returns the year associated with this calendar button.
+     *
+     * @return
+     * The calendar year.
+     */
+    public int getYear() {
+        CalendarButton.Skin calendarButtonSkin = (CalendarButton.Skin)getSkin();
+        Calendar calendar = calendarButtonSkin.getCalendar();
+
+        return calendar.getYear();
+    }
+
+    /**
+     * Sets the year associated with this calendar button.
+     * <p>
+     * Fires {@link CalendarButtonListener#yearChanged(CalendarButton, int)}.
+     *
+     * @param year
+     * The year
+     */
+    public void setYear(int year) {
+        CalendarButton.Skin calendarButtonSkin = (CalendarButton.Skin)getSkin();
+        Calendar calendar = calendarButtonSkin.getCalendar();
+        int previousYear = calendar.getYear();
+
+        if (previousYear != year) {
+            calendar.setYear(year);
+            calendarButtonListeners.yearChanged(this, previousYear);
+        }
+    }
+
+    /**
+     * Returns the month associated with this calendar button.
+     *
+     * @return
+     * The calendar month.
+     */
+    public int getMonth() {
+        CalendarButton.Skin calendarButtonSkin = (CalendarButton.Skin)getSkin();
+        Calendar calendar = calendarButtonSkin.getCalendar();
+
+        return calendar.getMonth();
+    }
+
+    /**
+     * Sets the month associated with this calendar button.
+     * <p>
+     * Fires {@link CalendarButtonListener#monthChanged(CalendarButton, int)}.
+     *
+     * @param month
+     * The month
+     */
+    public void setMonth(int month) {
+        CalendarButton.Skin calendarButtonSkin = (CalendarButton.Skin)getSkin();
+        Calendar calendar = calendarButtonSkin.getCalendar();
+        int previousMonth = calendar.getMonth();
+
+        if (previousMonth != month) {
+            calendar.setMonth(month);
+            calendarButtonListeners.monthChanged(this, previousMonth);
+        }
+    }
+
+    /**
+     * Returns the currently selected date.
+     *
+     * @return
+     * The currently selected date, or <tt>null</tt> if nothing is selected
+     */
+    public CalendarDate getSelectedDate() {
+        CalendarButton.Skin calendarButtonSkin = (CalendarButton.Skin)getSkin();
+        Calendar calendar = calendarButtonSkin.getCalendar();
+
+        return calendar.getSelectedDate();
+    }
+
+    /**
+     * Sets the selected date.
+     *
+     * @param selectedDate
+     * The date to select, or <tt>null</tt> to clear the selection
+     */
+    public void setSelectedDate(CalendarDate selectedDate) {
+        CalendarButton.Skin calendarButtonSkin = (CalendarButton.Skin)getSkin();
+        Calendar calendar = calendarButtonSkin.getCalendar();
+        CalendarDate previousSelectedDate = calendar.getSelectedDate();
+
+        if ((selectedDate == null ^ previousSelectedDate == null)
+            || (selectedDate != null && !selectedDate.equals(previousSelectedDate))) {
+            calendar.setSelectedDate(selectedDate);
+            calendarButtonSelectionListeners.selectedDateChanged(this,
+                previousSelectedDate);
+        }
+    }
+
+    /**
+     * Sets the selected date to the date represented by the specified date
+     * string. The date string must be in the <tt>ISO 8601</tt> "calendar date"
+     * format, which is <tt>[YYYY]-[MM]-[DD]</tt>.
+     *
+     * @param selectedDate
+     * A string in the form of <tt>[YYYY]-[MM]-[DD]</tt> (e.g. 2008-07-23)
+     */
+    public final void setSelectedDate(String selectedDate) {
+        if (selectedDate == null) {
+            throw new IllegalArgumentException("selectedDate is null.");
+        }
+
+        setSelectedDate(new CalendarDate(selectedDate));
+    }
+
+    /**
+     * Gets the data binding key that is set on this calendar button.
+     */
+    public String getSelectedDateKey() {
+        CalendarButton.Skin calendarButtonSkin = (CalendarButton.Skin)getSkin();
+        Calendar calendar = calendarButtonSkin.getCalendar();
+
+        return calendar.getSelectedDateKey();
+    }
+
+    /**
+     * Sets this calendar button's data binding key.
+     */
+    public void setSelectedDateKey(String selectedDateKey) {
+        CalendarButton.Skin calendarButtonSkin = (CalendarButton.Skin)getSkin();
+        Calendar calendar = calendarButtonSkin.getCalendar();
+
+        String previousSelectedDateKey = calendar.getSelectedDateKey();
+
+        if ((selectedDateKey == null ^ previousSelectedDateKey == null)
+            || (selectedDateKey != null && !selectedDateKey.equals(previousSelectedDateKey))) {
+            calendar.setSelectedDateKey(selectedDateKey);
+            calendarButtonListeners.selectedDateKeyChanged(this,
+                previousSelectedDateKey);
+        }
+    }
+
+    /**
+     * Loads the selected date from the specified bind context using this date
+     * picker button's bind key, if one is set.
+     */
+    @Override
+    public void load(Dictionary<String, Object> context) {
+        String selectedDateKey = getSelectedDateKey();
+
+        if (selectedDateKey != null
+            && context.containsKey(selectedDateKey)) {
+            Object value = context.get(selectedDateKey);
+
+            if (value instanceof CalendarDate) {
+                setSelectedDate((CalendarDate)value);
+            } else if (value instanceof String) {
+                setSelectedDate((String)value);
+            } else {
+                throw new IllegalArgumentException("Invalid date type: " +
+                    value.getClass().getName());
+            }
+        }
+    }
+
+    /**
+     * Stores the selected date into the specified bind context using this date
+     * picker button's bind key, if one is set.
+     */
+    @Override
+    public void store(Dictionary<String, Object> context) {
+        String selectedDateKey = getSelectedDateKey();
+
+        if (selectedDateKey != null) {
+            context.put(selectedDateKey, getSelectedDate());
+        }
+    }
+
+    /**
+     * Gets this calendar's <tt>CalendarButtonListener</tt> collection.
+     */
+    public ListenerList<CalendarButtonListener> getCalendarButtonListeners() {
+        return calendarButtonListeners;
+    }
+
+    /**
+     * Gets this calendar's <tt>CalendarButtonSelectionListener</tt> collection.
+     */
+    public ListenerList<CalendarButtonSelectionListener> getCalendarButtonSelectionListeners() {
+        return calendarButtonSelectionListeners;
+    }
+}

Added: incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/CalendarButtonListener.java
URL: http://svn.apache.org/viewvc/incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/CalendarButtonListener.java?rev=754926&view=auto
==============================================================================
--- incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/CalendarButtonListener.java (added)
+++ incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/CalendarButtonListener.java Mon Mar 16 16:16:40 2009
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2008 VMware, Inc.
+ *
+ * Licensed 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.
+ */
+package pivot.wtk;
+
+/**
+ * calendar button listener interface.
+ *
+ * @author tvolkert
+ */
+public interface CalendarButtonListener {
+    /**
+     * Called when a calendar button's year value has changed.
+     *
+     * @param calendarButton
+     * @param previousYear
+     */
+    public void yearChanged(CalendarButton calendarButton, int previousYear);
+
+    /**
+     * Called when a calendar button's month value has changed.
+     *
+     * @param calendarButton
+     * @param previousMonth
+     */
+    public void monthChanged(CalendarButton calendarButton, int previousMonth);
+
+    /**
+     * Called when a calendar button's selected date key has changed.
+     *
+     * @param calendarButton
+     * @param previousSelectedDateKey
+     */
+    public void selectedDateKeyChanged(CalendarButton calendarButton,
+        String previousSelectedDateKey);
+}

Added: incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/CalendarButtonSelectionListener.java
URL: http://svn.apache.org/viewvc/incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/CalendarButtonSelectionListener.java?rev=754926&view=auto
==============================================================================
--- incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/CalendarButtonSelectionListener.java (added)
+++ incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/CalendarButtonSelectionListener.java Mon Mar 16 16:16:40 2009
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2008 VMware, Inc.
+ *
+ * Licensed 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.
+ */
+package pivot.wtk;
+
+import pivot.util.CalendarDate;
+
+/**
+ * calendar button selection listener interface.
+ *
+ * @author tvolkert
+ */
+public interface CalendarButtonSelectionListener {
+    /**
+     * Called when a calendar button's selected date has changed.
+     *
+     * @param calendarButton
+     * @param previousSelectedDate
+     */
+    public void selectedDateChanged(CalendarButton calendarButton,
+        CalendarDate previousSelectedDate);
+}

Added: incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/CalendarListener.java
URL: http://svn.apache.org/viewvc/incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/CalendarListener.java?rev=754926&view=auto
==============================================================================
--- incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/CalendarListener.java (added)
+++ incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/CalendarListener.java Mon Mar 16 16:16:40 2009
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2008 VMware, Inc.
+ *
+ * Licensed 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.
+ */
+package pivot.wtk;
+
+/**
+ * calendar listener interface.
+ *
+ * @author tvolkert
+ */
+public interface CalendarListener {
+    /**
+     * Called when a calendar's year value has changed.
+     *
+     * @param calendar
+     * @param previousYear
+     */
+    public void yearChanged(Calendar calendar, int previousYear);
+
+    /**
+     * Called when a calendar's month value has changed.
+     *
+     * @param calendar
+     * @param previousMonth
+     */
+    public void monthChanged(Calendar calendar, int previousMonth);
+
+    /**
+     * Called when a calendar's selected date key has changed.
+     *
+     * @param calendar
+     * @param previousSelectedDateKey
+     */
+    public void selectedDateKeyChanged(Calendar calendar,
+        String previousSelectedDateKey);
+}

Added: incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/CalendarSelectionListener.java
URL: http://svn.apache.org/viewvc/incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/CalendarSelectionListener.java?rev=754926&view=auto
==============================================================================
--- incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/CalendarSelectionListener.java (added)
+++ incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/CalendarSelectionListener.java Mon Mar 16 16:16:40 2009
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2008 VMware, Inc.
+ *
+ * Licensed 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.
+ */
+package pivot.wtk;
+
+import pivot.util.CalendarDate;
+
+/**
+ * calendar selection listener interface.
+ *
+ * @author tvolkert
+ */
+public interface CalendarSelectionListener {
+    /**
+     * Called when a calendar's selected date has changed.
+     *
+     * @param calendar
+     * @param previousSelectedDate
+     */
+    public void selectedDateChanged(Calendar calendar,
+        CalendarDate previousSelectedDate);
+}

Added: incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/CardPane.java
URL: http://svn.apache.org/viewvc/incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/CardPane.java?rev=754926&view=auto
==============================================================================
--- incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/CardPane.java (added)
+++ incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/CardPane.java Mon Mar 16 16:16:40 2009
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 2008 VMware, Inc.
+ *
+ * Licensed 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.
+ */
+package pivot.wtk;
+
+import pivot.collections.Sequence;
+import pivot.util.ListenerList;
+
+/**
+ * Container that behaves like a deck of cards, only one of which may be
+ * visible at a time.
+ * <p>
+ * TODO Add a "transition" property to support transitions such as CROSS_FADE,
+ * SLIDE, etc.
+ *
+ * @author gbrown
+ */
+public class CardPane extends Container {
+    private static class CardPaneListenerList extends ListenerList<CardPaneListener>
+        implements CardPaneListener {
+        public void selectedIndexChanged(CardPane cardPane, int previousSelectedIndex) {
+            for (CardPaneListener listener : this) {
+                listener.selectedIndexChanged(cardPane, previousSelectedIndex);
+            }
+        }
+    }
+
+    private int selectedIndex = -1;
+    private CardPaneListenerList cardPaneListeners = new CardPaneListenerList();
+
+    public CardPane() {
+        installSkin(CardPane.class);
+    }
+
+    /**
+     * Returns the currently selected card index.
+     *
+     * @return
+     * The selected card index, or <tt>-1</tt> if no card is selected.
+     */
+    public int getSelectedIndex() {
+        return selectedIndex;
+    }
+
+    public void setSelectedIndex(int selectedIndex) {
+        if (selectedIndex < -1
+            || selectedIndex > getLength() - 1) {
+            throw new IndexOutOfBoundsException();
+        }
+
+        int previousSelectedIndex = this.selectedIndex;
+
+        if (previousSelectedIndex != selectedIndex) {
+            this.selectedIndex = selectedIndex;
+            cardPaneListeners.selectedIndexChanged(this, previousSelectedIndex);
+        }
+    }
+
+    @Override
+    public void insert(Component component, int index) {
+        super.insert(component, index);
+
+        // If the selected component's index changed as a result of
+        // this insertion, update it
+        if (selectedIndex >= index) {
+            setSelectedIndex(selectedIndex + 1);
+        }
+    }
+
+    @Override
+    public Sequence<Component> remove(int index, int count) {
+        Sequence<Component> removed = super.remove(index, count);
+
+        // If the selected component was removed, clear the selection
+        if (selectedIndex >= index
+            && selectedIndex < index + count) {
+            setSelectedIndex(-1);
+        }
+
+        return removed;
+    }
+
+    public ListenerList<CardPaneListener> getCardPaneListeners() {
+        return cardPaneListeners;
+    }
+}

Added: incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/CardPaneListener.java
URL: http://svn.apache.org/viewvc/incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/CardPaneListener.java?rev=754926&view=auto
==============================================================================
--- incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/CardPaneListener.java (added)
+++ incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/CardPaneListener.java Mon Mar 16 16:16:40 2009
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2008 VMware, Inc.
+ *
+ * Licensed 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.
+ */
+package pivot.wtk;
+
+/**
+ * Card pane listener interface.
+ *
+ * @author gbrown
+ */
+public interface CardPaneListener {
+    /**
+     * Called when a card pane's selected index has changed.
+     *
+     * @param cardPane
+     * @param previousSelectedIndex
+     */
+    public void selectedIndexChanged(CardPane cardPane, int previousSelectedIndex);
+}

Added: incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/Checkbox.java
URL: http://svn.apache.org/viewvc/incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/Checkbox.java?rev=754926&view=auto
==============================================================================
--- incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/Checkbox.java (added)
+++ incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/Checkbox.java Mon Mar 16 16:16:40 2009
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2008 VMware, Inc.
+ *
+ * Licensed 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.
+ */
+package pivot.wtk;
+
+import pivot.wtk.content.ButtonDataRenderer;
+
+/**
+ * Component representing a checkbox.
+ *
+ * @author gbrown
+ */
+@ComponentInfo(icon="Checkbox.png")
+public class Checkbox extends Button {
+    private static final Button.DataRenderer DEFAULT_DATA_RENDERER = new ButtonDataRenderer();
+
+    static {
+        DEFAULT_DATA_RENDERER.getStyles().put("horizontalAlignment", HorizontalAlignment.LEFT);
+    }
+
+    public Checkbox() {
+        this(null);
+    }
+
+    public Checkbox(Object buttonData) {
+        super(buttonData);
+        super.setToggleButton(true);
+
+        setDataRenderer(DEFAULT_DATA_RENDERER);
+
+        installSkin(Checkbox.class);
+    }
+
+    public void press() {
+        State state = getState();
+
+        if (state == State.SELECTED) {
+            setState(State.UNSELECTED);
+        }
+        else if (state == State.UNSELECTED) {
+            setState(isTriState() ? State.MIXED : State.SELECTED);
+        }
+        else {
+            setState(State.SELECTED);
+        }
+
+        super.press();
+    }
+
+    @Override
+    public void setToggleButton(boolean toggleButton) {
+        throw new UnsupportedOperationException("Checkboxes are always toggle buttons.");
+    }
+
+    @Override
+    public void setGroup(Group group) {
+        throw new UnsupportedOperationException("Checkboxes can't be added to a group.");
+    }
+}

Added: incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/Checkbox.png
URL: http://svn.apache.org/viewvc/incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/Checkbox.png?rev=754926&view=auto
==============================================================================
Binary file - no diff available.

Propchange: incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/Checkbox.png
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Added: incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/Clipboard.java
URL: http://svn.apache.org/viewvc/incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/Clipboard.java?rev=754926&view=auto
==============================================================================
--- incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/Clipboard.java (added)
+++ incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/Clipboard.java Mon Mar 16 16:16:40 2009
@@ -0,0 +1,177 @@
+/*
+ * Copyright (c) 2008 VMware, Inc.
+ *
+ * Licensed 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.
+ */
+package pivot.wtk;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+
+import pivot.collections.Dictionary;
+import pivot.collections.HashMap;
+import pivot.serialization.SerializationException;
+import pivot.serialization.Serializer;
+import pivot.serialization.JSONSerializer;
+
+/**
+ * Singleton class providing a means of sharing data between components and
+ * applications.
+ * <p>
+ * TODO Copy data to system clipboard when allowed (and the data format is
+ * supported).
+ * <p>
+ * TODO Use a list of Class:Serializer mapping, so we can prioritize? Using
+ * this approach, we could walk the list and use the first matching serializer
+ * (e.g. to use BinarySerializer for classes that implement Serializable).
+ * Alternatively, this would let us serialize to all matching types (though
+ * this could be a peformance issue).
+ * <p>
+ * Another alternative is to require the caller to specify the serializer(s)
+ * at put() time.
+ */
+public class Clipboard {
+    /**
+     * Serializer dictionary implementation.
+     *
+     * @author gbrown
+     */
+    public static final class SerializerDictionary
+        implements Dictionary<Class<?>, Class<? extends Serializer>> {
+        public Class<? extends Serializer> get(Class<?> type) {
+            // TODO Walk class hierarchy to find a match
+
+            return serializers.get(type);
+        }
+
+        public Class<? extends Serializer> put(Class<?> type,
+            Class<? extends Serializer> serializerType) {
+            if (serializerType == null) {
+                throw new IllegalArgumentException("serializerType is null.");
+            }
+
+            return serializers.put(type, serializerType);
+        }
+
+        public Class<? extends Serializer> remove(Class<?> type) {
+            return serializers.remove(type);
+        }
+
+        public boolean containsKey(Class<?> type) {
+            return serializers.containsKey(type);
+        }
+
+        public boolean isEmpty() {
+            return serializers.isEmpty();
+        }
+    }
+
+    private Class<?> type = null;
+    private byte[] buffer = null;
+
+    private static Clipboard instance = new Clipboard();
+
+    private static HashMap<Class<?>, Class<? extends Serializer>> serializers = new HashMap<Class<?>, Class<? extends Serializer>>();
+    private static SerializerDictionary serializerDictionary = new SerializerDictionary();
+
+    public void put(Object contents) {
+        if (contents == null) {
+            throw new IllegalArgumentException("contents is null");
+        }
+
+        Class<?> type = contents.getClass();
+
+        if (!serializers.containsKey(type)) {
+            throw new IllegalArgumentException("No serializer found for "
+                + type.getName());
+        }
+
+        Class<? extends Serializer> serializerType = serializers.get(type);
+
+        Serializer serializer = null;
+        try {
+            serializer = serializerType.newInstance();
+        } catch(IllegalAccessException exception) {
+            throw new RuntimeException(exception);
+        } catch(InstantiationException exception) {
+            throw new RuntimeException(exception);
+        }
+
+        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
+
+        try {
+            serializer.writeObject(contents, byteArrayOutputStream);
+        } catch(IOException exception) {
+            throw new RuntimeException(exception);
+        } catch(SerializationException exception) {
+            throw new RuntimeException(exception);
+        }
+
+        this.type = type;
+        buffer = byteArrayOutputStream.toByteArray();
+    }
+
+    public Object get() {
+        Object contents = null;
+
+        if (buffer != null) {
+            if (!serializers.containsKey(type)) {
+                throw new IllegalStateException("No serializer found for "
+                    + type.getName());
+            }
+
+            Class<? extends Serializer> serializerType = serializers.get(type);
+
+            Serializer serializer = null;
+            try {
+                serializer = serializerType.newInstance();
+            } catch(IllegalAccessException exception) {
+                throw new RuntimeException(exception);
+            } catch(InstantiationException exception) {
+                throw new RuntimeException(exception);
+            }
+
+            ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(buffer);
+
+            try {
+                contents = serializer.readObject(byteArrayInputStream);
+            } catch(IOException exception) {
+                throw new RuntimeException(exception);
+            } catch(SerializationException exception) {
+                throw new RuntimeException(exception);
+            }
+        }
+
+        return contents;
+    }
+
+    public void clear() {
+        type = null;
+        buffer = null;
+    }
+
+    public static Clipboard getInstance() {
+        return instance;
+    }
+
+    public static SerializerDictionary getSerializers() {
+        return serializerDictionary;
+    }
+
+    static {
+        serializers.put(String.class, JSONSerializer.class);
+        serializers.put(Number.class, JSONSerializer.class);
+        serializers.put(Boolean.class, JSONSerializer.class);
+    }
+}