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/26 00:12:17 UTC

svn commit: r758461 [17/47] - in /incubator/pivot/branches: ./ 1.1/ 1.1/charts-test/ 1.1/charts-test/src/ 1.1/charts-test/src/pivot/ 1.1/charts-test/src/pivot/charts/ 1.1/charts-test/src/pivot/charts/test/ 1.1/charts/ 1.1/charts/lib/ 1.1/charts/src/ 1....

Added: incubator/pivot/branches/1.1/wtk/src/pivot/wtk/Button.java
URL: http://svn.apache.org/viewvc/incubator/pivot/branches/1.1/wtk/src/pivot/wtk/Button.java?rev=758461&view=auto
==============================================================================
--- incubator/pivot/branches/1.1/wtk/src/pivot/wtk/Button.java (added)
+++ incubator/pivot/branches/1.1/wtk/src/pivot/wtk/Button.java Wed Mar 25 23:08:38 2009
@@ -0,0 +1,612 @@
+/*
+ * 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;
+
+/**
+ * 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 {
+        /**
+         * Called when a button group's selection has changed.
+         *
+         * @param group
+         * @param previousSelection
+         */
+        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 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) {
+            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);
+        }
+    }
+
+    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, ?> 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
+    @SuppressWarnings("unchecked")
+    public void store(Dictionary<String, ?> context) {
+        if (selectedKey != null) {
+            ((Dictionary<String, Boolean>)context).put(selectedKey, isSelected());
+        }
+
+        if (stateKey != null) {
+            ((Dictionary<String, State>)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/branches/1.1/wtk/src/pivot/wtk/ButtonListener.java
URL: http://svn.apache.org/viewvc/incubator/pivot/branches/1.1/wtk/src/pivot/wtk/ButtonListener.java?rev=758461&view=auto
==============================================================================
--- incubator/pivot/branches/1.1/wtk/src/pivot/wtk/ButtonListener.java (added)
+++ incubator/pivot/branches/1.1/wtk/src/pivot/wtk/ButtonListener.java Wed Mar 25 23:08:38 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/branches/1.1/wtk/src/pivot/wtk/ButtonPressListener.java
URL: http://svn.apache.org/viewvc/incubator/pivot/branches/1.1/wtk/src/pivot/wtk/ButtonPressListener.java?rev=758461&view=auto
==============================================================================
--- incubator/pivot/branches/1.1/wtk/src/pivot/wtk/ButtonPressListener.java (added)
+++ incubator/pivot/branches/1.1/wtk/src/pivot/wtk/ButtonPressListener.java Wed Mar 25 23:08:38 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/branches/1.1/wtk/src/pivot/wtk/ButtonStateListener.java
URL: http://svn.apache.org/viewvc/incubator/pivot/branches/1.1/wtk/src/pivot/wtk/ButtonStateListener.java?rev=758461&view=auto
==============================================================================
--- incubator/pivot/branches/1.1/wtk/src/pivot/wtk/ButtonStateListener.java (added)
+++ incubator/pivot/branches/1.1/wtk/src/pivot/wtk/ButtonStateListener.java Wed Mar 25 23:08:38 2009
@@ -0,0 +1,32 @@
+/*
+ * 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 state listener interface.
+ *
+ * @author gbrown
+ * @author tvolkert
+ */
+public interface ButtonStateListener {
+    /**
+     * Called when a button's state has changed.
+     *
+     * @param button
+     * @param previousState
+     */
+    public void stateChanged(Button button, Button.State previousState);
+}

Added: incubator/pivot/branches/1.1/wtk/src/pivot/wtk/Calendar.java
URL: http://svn.apache.org/viewvc/incubator/pivot/branches/1.1/wtk/src/pivot/wtk/Calendar.java?rev=758461&view=auto
==============================================================================
--- incubator/pivot/branches/1.1/wtk/src/pivot/wtk/Calendar.java (added)
+++ incubator/pivot/branches/1.1/wtk/src/pivot/wtk/Calendar.java Wed Mar 25 23:08:38 2009
@@ -0,0 +1,330 @@
+/*
+ * 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.util.Locale;
+
+import pivot.collections.Dictionary;
+import pivot.serialization.JSONSerializer;
+import pivot.util.CalendarDate;
+import pivot.util.ListenerList;
+
+/**
+ * Component that allows the user to select a date.
+ *
+ * @author tvolkert
+ * @author gbrown
+ */
+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);
+            }
+        }
+
+        public void localeChanged(Calendar calendar, Locale previousLocale) {
+            for (CalendarListener listener : this) {
+                listener.localeChanged(calendar, previousLocale);
+            }
+        }
+    }
+
+    /**
+     * 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 Locale locale = Locale.getDefault();
+
+    private CalendarListenerList calendarListeners = new CalendarListenerList();
+    private CalendarSelectionListenerList calendarSelectionListeners =
+        new CalendarSelectionListenerList();
+
+    public static final String LANGUAGE_KEY = "language";
+    public static final String COUNTRY_KEY = "country";
+    public static final String VARIANT_KEY = "variant";
+
+    public Calendar() {
+        this(new CalendarDate());
+    }
+
+    private Calendar(CalendarDate calendarDate) {
+        this(calendarDate.getYear(), calendarDate.getMonth());
+    }
+
+    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 (((previousSelectedDate == null) ^ (selectedDate == null))
+            || (previousSelectedDate != null
+                && !previousSelectedDate.equals(selectedDate))) {
+            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);
+        }
+    }
+
+    /**
+     * Returns the locale used to present calendar data.
+     */
+    public Locale getLocale() {
+        return locale;
+    }
+
+    /**
+     * Sets the locale used to present calendar data.
+     *
+     * @param locale
+     */
+    public void setLocale(Locale locale) {
+        if (locale == null) {
+            throw new IllegalArgumentException("locale is null.");
+        }
+
+        Locale previousLocale = this.locale;
+        if (previousLocale != locale) {
+            this.locale = locale;
+            calendarListeners.localeChanged(this, previousLocale);
+        }
+    }
+
+    /**
+     * Sets the locale used to present calendar data.
+     *
+     * @param locale
+     * An dictionary containing values for language, country, and variant.
+     * Country and variant are optional but the must adhere to the following
+     * rules:
+     *
+     * <ul>
+     * <li>If variant is specified, language and country are required;</li>
+     * <li>Otherwise, if country is specified, language is required;</li>
+     * <li>Otherwise, language is required.</li>
+     * </ul>
+     */
+    public void setLocale(Dictionary<String, ?> locale) {
+        if (locale == null) {
+            throw new IllegalArgumentException("locale is null.");
+        }
+
+        String language = (String)locale.get(LANGUAGE_KEY);
+        String country = (String)locale.get(COUNTRY_KEY);
+        String variant = (String)locale.get(VARIANT_KEY);
+
+        if (variant != null) {
+            setLocale(new Locale(language, country, variant));
+        } else if (country != null) {
+            setLocale(new Locale(language, country));
+        } else {
+            setLocale(new Locale(language));
+        }
+    }
+
+    /**
+     * Sets the locale used to present calendar data.
+     *
+     * @param locale
+     * A JSON map containing values for language, country, and variant.
+     *
+     * @see #setLocale(Dictionary)
+     */
+    public void setLocale(String locale) {
+        if (locale == null) {
+            throw new IllegalArgumentException("locale is null.");
+        }
+
+        setLocale(JSONSerializer.parseMap(locale));
+    }
+
+    /**
+     * 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, ?> 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
+    @SuppressWarnings("unchecked")
+    public void store(Dictionary<String, ?> context) {
+        if (selectedDateKey != null) {
+            ((Dictionary<String, CalendarDate>)context).put(selectedDateKey, selectedDate);
+        }
+    }
+
+    /**
+     * Returns the calendar listener list.
+     */
+    public ListenerList<CalendarListener> getCalendarListeners() {
+        return calendarListeners;
+    }
+
+    /**
+     * Returns the calendar selection listener list.
+     */
+    public ListenerList<CalendarSelectionListener> getCalendarSelectionListeners() {
+        return calendarSelectionListeners;
+    }
+}

Added: incubator/pivot/branches/1.1/wtk/src/pivot/wtk/CalendarButton.java
URL: http://svn.apache.org/viewvc/incubator/pivot/branches/1.1/wtk/src/pivot/wtk/CalendarButton.java?rev=758461&view=auto
==============================================================================
--- incubator/pivot/branches/1.1/wtk/src/pivot/wtk/CalendarButton.java (added)
+++ incubator/pivot/branches/1.1/wtk/src/pivot/wtk/CalendarButton.java Wed Mar 25 23:08:38 2009
@@ -0,0 +1,296 @@
+/*
+ * 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.util.Locale;
+
+import pivot.collections.Dictionary;
+import pivot.serialization.JSONSerializer;
+import pivot.util.CalendarDate;
+import pivot.util.ListenerList;
+import pivot.wtk.content.CalendarButtonDataRenderer;
+
+/**
+ * A component that allows a user to select a calendar date. The calendar
+ * is hidden until the user pushes the button.
+ *
+ * @author tvolkert
+ * @author gbrown
+ */
+public class CalendarButton extends Button {
+    /**
+     * Calendar button listener list.
+     *
+     * @author tvolkert
+     */
+    private static class CalendarButtonListenerList
+        extends ListenerList<CalendarButtonListener>
+        implements CalendarButtonListener {
+        public void selectedDateKeyChanged(CalendarButton calendarButton,
+            String previousSelectedDateKey) {
+            for (CalendarButtonListener listener : this) {
+                listener.selectedDateKeyChanged(calendarButton, previousSelectedDateKey);
+            }
+        }
+
+        public void localeChanged(CalendarButton calendarButton, Locale previousLocale) {
+            for (CalendarButtonListener listener : this) {
+                listener.localeChanged(calendarButton, previousLocale);
+            }
+        }
+    }
+
+    /**
+     * 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 CalendarDate selectedDate = null;
+    private String selectedDateKey = null;
+    private Locale locale = Locale.getDefault();
+
+    private CalendarButtonListenerList calendarButtonListeners =
+        new CalendarButtonListenerList();
+    private CalendarButtonSelectionListenerList calendarButtonSelectionListeners =
+        new CalendarButtonSelectionListenerList();
+
+    public static final String LANGUAGE_KEY = "language";
+    public static final String COUNTRY_KEY = "country";
+    public static final String VARIANT_KEY = "variant";
+
+    private static final Button.DataRenderer DEFAULT_DATA_RENDERER = new CalendarButtonDataRenderer();
+
+    public CalendarButton() {
+        this(null);
+    }
+
+    public CalendarButton(Object buttonData) {
+        super(buttonData);
+
+        setDataRenderer(DEFAULT_DATA_RENDERER);
+        installSkin(CalendarButton.class);
+
+        setSelectedDate(new CalendarDate());
+    }
+
+    /**
+     * @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 currently selected date.
+     *
+     * @return
+     * The currently selected date, or <tt>null</tt> if nothing is selected.
+     */
+    public CalendarDate getSelectedDate() {
+        return selectedDate;
+    }
+
+    /**
+     * Sets the selected date.
+     *
+     * @param selectedDate
+     * The date to select, or <tt>null</tt> to clear the selection.
+     */
+    public void setSelectedDate(CalendarDate selectedDate) {
+        CalendarDate previousSelectedDate = this.selectedDate;
+
+        if (((previousSelectedDate == null) ^ (selectedDate == null))
+            || (previousSelectedDate != null
+                && !previousSelectedDate.equals(selectedDate))) {
+            this.selectedDate = 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() {
+        return selectedDateKey;
+    }
+
+    /**
+     * Sets this calendar button's data binding key.
+     */
+    public void setSelectedDateKey(String selectedDateKey) {
+        String previousSelectedDateKey = this.selectedDateKey;
+
+        if (previousSelectedDateKey != selectedDateKey) {
+            this.selectedDateKey = selectedDateKey;
+            calendarButtonListeners.selectedDateKeyChanged(this,
+                previousSelectedDateKey);
+        }
+    }
+
+    /**
+     * Returns the locale used to present calendar data.
+     */
+    public Locale getLocale() {
+        return locale;
+    }
+
+    /**
+     * Sets the locale used to present calendar data.
+     *
+     * @param locale
+     */
+    public void setLocale(Locale locale) {
+        if (locale == null) {
+            throw new IllegalArgumentException("locale is null.");
+        }
+
+        Locale previousLocale = this.locale;
+        if (previousLocale != locale) {
+            this.locale = locale;
+            calendarButtonListeners.localeChanged(this, previousLocale);
+        }
+    }
+
+    /**
+     * Sets the locale used to present calendar data.
+     *
+     * @param locale
+     * An dictionary containing values for language, country, and variant.
+     * Country and variant are optional but the must adhere to the following
+     * rules:
+     *
+     * <ul>
+     * <li>If variant is specified, language and country are required;</li>
+     * <li>Otherwise, if country is specified, language is required;</li>
+     * <li>Otherwise, language is required.</li>
+     * </ul>
+     */
+    public void setLocale(Dictionary<String, ?> locale) {
+        if (locale == null) {
+            throw new IllegalArgumentException("locale is null.");
+        }
+
+        String language = (String)locale.get(LANGUAGE_KEY);
+        String country = (String)locale.get(COUNTRY_KEY);
+        String variant = (String)locale.get(VARIANT_KEY);
+
+        if (variant != null) {
+            setLocale(new Locale(language, country, variant));
+        } else if (country != null) {
+            setLocale(new Locale(language, country));
+        } else {
+            setLocale(new Locale(language));
+        }
+    }
+
+    /**
+     * Sets the locale used to present calendar data.
+     *
+     * @param locale
+     * A JSON map containing values for language, country, and variant.
+     *
+     * @see #setLocale(Dictionary)
+     */
+    public void setLocale(String locale) {
+        if (locale == null) {
+            throw new IllegalArgumentException("locale is null.");
+        }
+
+        setLocale(JSONSerializer.parseMap(locale));
+    }
+
+    /**
+     * 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, ?> 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
+    @SuppressWarnings("unchecked")
+    public void store(Dictionary<String, ?> context) {
+        String selectedDateKey = getSelectedDateKey();
+
+        if (selectedDateKey != null) {
+            ((Dictionary<String, CalendarDate>)context).put(selectedDateKey, getSelectedDate());
+        }
+    }
+
+    /**
+     * Returns the calendar button listener list.
+     */
+    public ListenerList<CalendarButtonListener> getCalendarButtonListeners() {
+        return calendarButtonListeners;
+    }
+
+    /**
+     * Returns the calendar button selection listener list.
+     */
+    public ListenerList<CalendarButtonSelectionListener> getCalendarButtonSelectionListeners() {
+        return calendarButtonSelectionListeners;
+    }
+}

Added: incubator/pivot/branches/1.1/wtk/src/pivot/wtk/CalendarButtonListener.java
URL: http://svn.apache.org/viewvc/incubator/pivot/branches/1.1/wtk/src/pivot/wtk/CalendarButtonListener.java?rev=758461&view=auto
==============================================================================
--- incubator/pivot/branches/1.1/wtk/src/pivot/wtk/CalendarButtonListener.java (added)
+++ incubator/pivot/branches/1.1/wtk/src/pivot/wtk/CalendarButtonListener.java Wed Mar 25 23:08:38 2009
@@ -0,0 +1,43 @@
+/*
+ * 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.util.Locale;
+
+/**
+ * Calendar button listener interface.
+ *
+ * @author tvolkert
+ * @author gbrown
+ */
+public interface CalendarButtonListener {
+    /**
+     * Called when a calendar button's selected date key has changed.
+     *
+     * @param calendarButton
+     * @param previousSelectedDateKey
+     */
+    public void selectedDateKeyChanged(CalendarButton calendarButton,
+        String previousSelectedDateKey);
+
+    /**
+     * Called when a calendar button's locale has changed.
+     *
+     * @param calendarButton
+     * @param previousLocale
+     */
+    public void localeChanged(CalendarButton calendarButton, Locale previousLocale);
+}

Added: incubator/pivot/branches/1.1/wtk/src/pivot/wtk/CalendarButtonSelectionListener.java
URL: http://svn.apache.org/viewvc/incubator/pivot/branches/1.1/wtk/src/pivot/wtk/CalendarButtonSelectionListener.java?rev=758461&view=auto
==============================================================================
--- incubator/pivot/branches/1.1/wtk/src/pivot/wtk/CalendarButtonSelectionListener.java (added)
+++ incubator/pivot/branches/1.1/wtk/src/pivot/wtk/CalendarButtonSelectionListener.java Wed Mar 25 23:08:38 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/branches/1.1/wtk/src/pivot/wtk/CalendarListener.java
URL: http://svn.apache.org/viewvc/incubator/pivot/branches/1.1/wtk/src/pivot/wtk/CalendarListener.java?rev=758461&view=auto
==============================================================================
--- incubator/pivot/branches/1.1/wtk/src/pivot/wtk/CalendarListener.java (added)
+++ incubator/pivot/branches/1.1/wtk/src/pivot/wtk/CalendarListener.java Wed Mar 25 23:08:38 2009
@@ -0,0 +1,58 @@
+/*
+ * 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.util.Locale;
+
+/**
+ * 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);
+
+    /**
+     * Called when a calendar's locale has changed.
+     *
+     * @param calendar
+     * @param previousLocale
+     */
+    public void localeChanged(Calendar calendar, Locale previousLocale);
+}

Added: incubator/pivot/branches/1.1/wtk/src/pivot/wtk/CalendarSelectionListener.java
URL: http://svn.apache.org/viewvc/incubator/pivot/branches/1.1/wtk/src/pivot/wtk/CalendarSelectionListener.java?rev=758461&view=auto
==============================================================================
--- incubator/pivot/branches/1.1/wtk/src/pivot/wtk/CalendarSelectionListener.java (added)
+++ incubator/pivot/branches/1.1/wtk/src/pivot/wtk/CalendarSelectionListener.java Wed Mar 25 23:08:38 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/branches/1.1/wtk/src/pivot/wtk/CardPane.java
URL: http://svn.apache.org/viewvc/incubator/pivot/branches/1.1/wtk/src/pivot/wtk/CardPane.java?rev=758461&view=auto
==============================================================================
--- incubator/pivot/branches/1.1/wtk/src/pivot/wtk/CardPane.java (added)
+++ incubator/pivot/branches/1.1/wtk/src/pivot/wtk/CardPane.java Wed Mar 25 23:08:38 2009
@@ -0,0 +1,156 @@
+/*
+ * 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;
+import pivot.util.Vote;
+
+/**
+ * Container that behaves like a deck of cards, only one of which may be
+ * visible at a time.
+ *
+ * @author gbrown
+ */
+public class CardPane extends Container {
+    private static class CardPaneListenerList extends ListenerList<CardPaneListener>
+        implements CardPaneListener {
+        public void orientationChanged(CardPane cardPane, Orientation previousOrientation) {
+            for (CardPaneListener listener : this) {
+                listener.orientationChanged(cardPane, previousOrientation);
+            }
+        }
+
+    	public Vote previewSelectedIndexChange(CardPane cardPane, int selectedIndex) {
+            Vote vote = Vote.APPROVE;
+
+            for (CardPaneListener listener : this) {
+                vote = vote.tally(listener.previewSelectedIndexChange(cardPane, selectedIndex));
+            }
+
+            return vote;
+    	}
+
+    	public void selectedIndexChangeVetoed(CardPane cardPane, Vote reason) {
+            for (CardPaneListener listener : this) {
+                listener.selectedIndexChangeVetoed(cardPane, reason);
+            }
+    	}
+
+        public void selectedIndexChanged(CardPane cardPane, int previousSelectedIndex) {
+            for (CardPaneListener listener : this) {
+                listener.selectedIndexChanged(cardPane, previousSelectedIndex);
+            }
+        }
+    }
+
+    private Orientation orientation = null;
+    private int selectedIndex = -1;
+    private CardPaneListenerList cardPaneListeners = new CardPaneListenerList();
+
+    public CardPane() {
+        installSkin(CardPane.class);
+    }
+
+    public Orientation getOrientation() {
+        return orientation;
+    }
+
+    public void setOrientation(Orientation orientation) {
+        Orientation previousOrientation = this.orientation;
+
+        if (previousOrientation != orientation) {
+            this.orientation = orientation;
+            cardPaneListeners.orientationChanged(this, previousOrientation);
+        }
+    }
+
+    public final void setOrientation(String orientation) {
+        if (orientation == null) {
+            throw new IllegalArgumentException("orientation is null.");
+        }
+
+        setOrientation(Orientation.decode(orientation));
+    }
+
+    /**
+     * 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;
+    }
+
+    /**
+     * Sets the selected card index.
+     *
+     * @param selectedIndex
+     * The selected card index, or <tt>-1</tt> for no selection.
+     */
+    public void setSelectedIndex(int selectedIndex) {
+        if (selectedIndex < -1
+            || selectedIndex > getLength() - 1) {
+            throw new IndexOutOfBoundsException();
+        }
+
+        int previousSelectedIndex = this.selectedIndex;
+
+        if (previousSelectedIndex != selectedIndex) {
+        	Vote vote = cardPaneListeners.previewSelectedIndexChange(this, selectedIndex);
+
+        	if (vote == Vote.APPROVE) {
+                this.selectedIndex = selectedIndex;
+                cardPaneListeners.selectedIndexChanged(this, previousSelectedIndex);
+        	} else {
+        		cardPaneListeners.selectedIndexChangeVetoed(this, vote);
+        	}
+        }
+    }
+
+    public Component getSelectedCard() {
+    	return (selectedIndex == -1) ? null : get(selectedIndex);
+    }
+
+    @Override
+    public void insert(Component component, int index) {
+        // Update the selection
+        if (selectedIndex >= index) {
+            selectedIndex++;
+        }
+
+        super.insert(component, index);
+    }
+
+    @Override
+    public Sequence<Component> remove(int index, int count) {
+        // Update the selection
+        if (selectedIndex >= index) {
+            if (selectedIndex < index + count) {
+                selectedIndex = -1;
+            } else {
+                selectedIndex -= count;
+            }
+        }
+
+        return super.remove(index, count);
+    }
+
+    public ListenerList<CardPaneListener> getCardPaneListeners() {
+        return cardPaneListeners;
+    }
+}

Added: incubator/pivot/branches/1.1/wtk/src/pivot/wtk/CardPaneListener.java
URL: http://svn.apache.org/viewvc/incubator/pivot/branches/1.1/wtk/src/pivot/wtk/CardPaneListener.java?rev=758461&view=auto
==============================================================================
--- incubator/pivot/branches/1.1/wtk/src/pivot/wtk/CardPaneListener.java (added)
+++ incubator/pivot/branches/1.1/wtk/src/pivot/wtk/CardPaneListener.java Wed Mar 25 23:08:38 2009
@@ -0,0 +1,57 @@
+/*
+ * 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;
+
+/**
+ * Card pane listener interface.
+ *
+ * @author gbrown
+ */
+public interface CardPaneListener {
+    /**
+     * Called when a card pane's orientation has changed.
+     *
+     * @param cardPane
+     * @param previousOrientation
+     */
+    public void orientationChanged(CardPane cardPane, Orientation previousOrientation);
+
+	/**
+	 * Called to preview a selected index change.
+	 *
+	 * @param cardPane
+	 * @param selectedIndex
+	 */
+	public Vote previewSelectedIndexChange(CardPane cardPane, int selectedIndex);
+
+	/**
+	 * Called when a selected index change has been vetoed.
+	 *
+	 * @param cardPane
+	 * @param reason
+	 */
+	public void selectedIndexChangeVetoed(CardPane cardPane, Vote reason);
+
+    /**
+     * Called when a card pane's selected index has changed.
+     *
+     * @param cardPane
+     * @param previousSelectedIndex
+     */
+    public void selectedIndexChanged(CardPane cardPane, int previousSelectedIndex);
+}

Added: incubator/pivot/branches/1.1/wtk/src/pivot/wtk/Checkbox.java
URL: http://svn.apache.org/viewvc/incubator/pivot/branches/1.1/wtk/src/pivot/wtk/Checkbox.java?rev=758461&view=auto
==============================================================================
--- incubator/pivot/branches/1.1/wtk/src/pivot/wtk/Checkbox.java (added)
+++ incubator/pivot/branches/1.1/wtk/src/pivot/wtk/Checkbox.java Wed Mar 25 23:08:38 2009
@@ -0,0 +1,70 @@
+/*
+ * 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
+ */
+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/branches/1.1/wtk/src/pivot/wtk/Clipboard.java
URL: http://svn.apache.org/viewvc/incubator/pivot/branches/1.1/wtk/src/pivot/wtk/Clipboard.java?rev=758461&view=auto
==============================================================================
--- incubator/pivot/branches/1.1/wtk/src/pivot/wtk/Clipboard.java (added)
+++ incubator/pivot/branches/1.1/wtk/src/pivot/wtk/Clipboard.java Wed Mar 25 23:08:38 2009
@@ -0,0 +1,94 @@
+/*
+ * 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.awt.Toolkit;
+import java.awt.datatransfer.ClipboardOwner;
+import java.awt.datatransfer.Transferable;
+
+/**
+ * Singleton class providing a means of sharing data between components and
+ * applications.
+ *
+ * @author gbrown
+ */
+public final class Clipboard {
+    private static LocalManifest content = null;
+    private static ClipboardContentListener clipboardContentListener = null;
+
+    /**
+     * Retrieves the contents of the clipboard.
+     */
+    public static Manifest getContent() {
+        Manifest content = Clipboard.content;
+
+        if (content == null) {
+            try {
+                java.awt.datatransfer.Clipboard awtClipboard =
+                    Toolkit.getDefaultToolkit().getSystemClipboard();
+                content = new RemoteManifest(awtClipboard.getContents(null));
+            } catch(SecurityException exception) {
+                // No-op
+            }
+        }
+
+        return content;
+    }
+
+    /**
+     * Places content on the clipboard.
+     *
+     * @param content
+     */
+    public static void setContent(LocalManifest content) {
+        setContent(content, null);
+    }
+
+    /**
+     * Places content on the clipboard.
+     *
+     * @param content
+     */
+    public static void setContent(LocalManifest content,
+        ClipboardContentListener clipboardContentListener) {
+        if (content == null) {
+            throw new IllegalArgumentException("content is null");
+        }
+
+        try {
+            java.awt.datatransfer.Clipboard awtClipboard =
+                Toolkit.getDefaultToolkit().getSystemClipboard();
+
+            LocalManifestAdapter localManifestAdapter = new LocalManifestAdapter(content);
+            awtClipboard.setContents(localManifestAdapter, new ClipboardOwner() {
+                public void lostOwnership(java.awt.datatransfer.Clipboard clipboard,
+                    Transferable contents) {
+                    LocalManifest previousContent = Clipboard.content;
+                    Clipboard.content = null;
+
+                    if (Clipboard.clipboardContentListener != null) {
+                        Clipboard.clipboardContentListener.contentChanged(previousContent);
+                    }
+                }
+            });
+        } catch(SecurityException exception) {
+            // No-op
+        }
+
+        Clipboard.content = content;
+        Clipboard.clipboardContentListener = clipboardContentListener;
+    }
+}

Added: incubator/pivot/branches/1.1/wtk/src/pivot/wtk/ClipboardContentListener.java
URL: http://svn.apache.org/viewvc/incubator/pivot/branches/1.1/wtk/src/pivot/wtk/ClipboardContentListener.java?rev=758461&view=auto
==============================================================================
--- incubator/pivot/branches/1.1/wtk/src/pivot/wtk/ClipboardContentListener.java (added)
+++ incubator/pivot/branches/1.1/wtk/src/pivot/wtk/ClipboardContentListener.java Wed Mar 25 23:08:38 2009
@@ -0,0 +1,25 @@
+/*
+ * 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;
+
+/**
+ * Clipboard content listener interface.
+ *
+ * @author gbrown
+ */
+public interface ClipboardContentListener {
+    public void contentChanged(LocalManifest previousContent);
+}