You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@pivot.apache.org by sm...@apache.org on 2011/12/24 17:07:40 UTC
svn commit: r1222994 [10/11] - in /pivot/trunk:
core/test/org/apache/pivot/beans/test/
demos/src/org/apache/pivot/demos/memorygame/
demos/src/org/apache/pivot/demos/memorygame/img/
demos/src/org/apache/pivot/demos/roweditor/ demos/www/ etc/ examples/sr...
Modified: pivot/trunk/wtk/src/org/apache/pivot/wtk/FillPaneListener.java
URL: http://svn.apache.org/viewvc/pivot/trunk/wtk/src/org/apache/pivot/wtk/FillPaneListener.java?rev=1222994&r1=1222993&r2=1222994&view=diff
==============================================================================
--- pivot/trunk/wtk/src/org/apache/pivot/wtk/FillPaneListener.java (original)
+++ pivot/trunk/wtk/src/org/apache/pivot/wtk/FillPaneListener.java Sat Dec 24 16:07:37 2011
@@ -1,29 +1,29 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to you under the Apache License,
- * Version 2.0 (the "License"); you may not use this file except in
- * compliance with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.pivot.wtk;
-
-/**
- * Fill pane listener interface.
- */
-public interface FillPaneListener {
- /**
- * Called when a fill pane's orientation has changed.
- *
- * @param fillPane
- */
- public void orientationChanged(FillPane fillPane);
-}
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to you under the Apache License,
+ * Version 2.0 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.pivot.wtk;
+
+/**
+ * Fill pane listener interface.
+ */
+public interface FillPaneListener {
+ /**
+ * Called when a fill pane's orientation has changed.
+ *
+ * @param fillPane
+ */
+ public void orientationChanged(FillPane fillPane);
+}
Propchange: pivot/trunk/wtk/src/org/apache/pivot/wtk/FillPaneListener.java
------------------------------------------------------------------------------
svn:eol-style = native
Modified: pivot/trunk/wtk/src/org/apache/pivot/wtk/RadioButtonGroup.java
URL: http://svn.apache.org/viewvc/pivot/trunk/wtk/src/org/apache/pivot/wtk/RadioButtonGroup.java?rev=1222994&r1=1222993&r2=1222994&view=diff
==============================================================================
--- pivot/trunk/wtk/src/org/apache/pivot/wtk/RadioButtonGroup.java (original)
+++ pivot/trunk/wtk/src/org/apache/pivot/wtk/RadioButtonGroup.java Sat Dec 24 16:07:37 2011
@@ -1,614 +1,614 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to you under the Apache License,
- * Version 2.0 (the "License"); you may not use this file except in
- * compliance with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.pivot.wtk;
-
-import java.util.Iterator;
-
-import org.apache.pivot.collections.ArrayList;
-import org.apache.pivot.collections.Group;
-import org.apache.pivot.collections.List;
-import org.apache.pivot.collections.Sequence;
-import org.apache.pivot.util.Filter;
-import org.apache.pivot.util.ImmutableIterator;
-import org.apache.pivot.wtk.Keyboard.KeyCode;
-import org.apache.pivot.wtk.Keyboard.KeyLocation;
-import org.apache.pivot.wtk.Keyboard.Modifier;
-
-/**
- * Extension of {@link ButtonGroup} providing keyboard navigation within the
- * group and modified focus navigation that treats the group as a single
- * focusable entity.<br/><br/>
- *
- * {@link KeyCode#UP UP} & {@link KeyCode#LEFT LEFT} Select the previous
- * button<br/>
- * {@link KeyCode#DOWN DOWN} & {@link KeyCode#RIGHT RIGHT} Select the next
- * button<br/>
- * {@link KeyCode#HOME HOME} Select the first button<br/>
- * {@link KeyCode#END END} Select the last button<br/><br/>
- *
- * (Note that only {@link Component#isFocusable() focusable} buttons are
- * considered when searching for a Button to select)<br/><br/>
- *
- * When a button within the group is focused and key is typed, an attempt is
- * made to find the next button (default) or previous button (when the SHIFT
- * modifier is pressed) whose renderer text starts with the typed character.
- * This search will always behave as if the <code>circular</code> property were
- * set.<br/><br/>
- *
- * By default, {@link KeyCode#TAB TAB} and {@link KeyCode#TAB SHIFT+TAB}
- * key presses will transfer focus out of the group (forwards or backwards
- * respectively).
- * This is managed by the {@link #setIntraGroupFocusTransferEnabled(boolean)
- * intraGroupFocusTransferEnabled} property.<br/><br/>
- *
- * The {@link #setCircular(boolean) circular} property can be enabled to allow
- * the selection to transfer seamlessly from one end of the group to the other.
- * (i.e. holding down an arrow key will cycle through all focusable buttons)
- * <br/><br/>
- *
- * Note that due to the conflicting return types of the <code>add(T)</code> and
- * <code>remove(T)</code> methods in the {@link Group#add(Object) Group} and
- * {@link Sequence#add(Object) Sequence} interfaces, this class cannot actually
- * implement <code>Sequence<Button></code>, although most of the same
- * methods are implemented.<br/>
- */
-public class RadioButtonGroup extends ButtonGroup {
-
- /**
- * Filter used to determine selectable buttons whose rendered data starts
- * with the target character.
- */
- private class FirstCharacterFilter implements Filter<Integer> {
- private char target = '\0';
-
- public void setTarget(char target) {
- this.target = Character.toUpperCase(target);
- }
-
- @Override
- public boolean include(Integer index) {
- boolean include = defaultFilter.include(index);
- if (include) {
- Button button = buttonOrder.get(index);
- String rendered = button.getDataRenderer().toString(button.getButtonData());
- if (rendered != null && rendered.length() > 0) {
- char first = Character.toUpperCase(rendered.charAt(0));
- if (first != target) {
- include = false;
- }
- }
- }
- return include;
- }
- }
-
- /**
- * ComponentKeyListener to be applied to all buttons as they are added to
- * the group.<br/><br/>
- *
- * At least one button in the group must be focused for this listener to be
- * executed, but that won't necessarily be a selected button.<br/>
- * This also means that the group will not be empty, although some of the
- * buttons contained within may not be focusable, or even visible.
- */
- private final ComponentKeyListener componentKeyListener = new ComponentKeyListener.Adapter() {
- /**
- * Handle TAB & SHIFT+TAB focus traversal, HOME, END & arrow keys
- */
- @Override
- public boolean keyPressed(Component component, int keyCode, KeyLocation keyLocation) {
- int modifiers = Keyboard.getModifiers();
- boolean handled = false;
-
- /*
- * Potentially transfer focus away from the buttons in this group.
- *
- * At this point we know that at least one button is focused, so we
- * just need to find the first or last (and possibly only) focusable
- * button depending on the focus transfer direction and then
- * transfer away from it.
- */
- if (!intraGroupFocusTransferEnabled) {
- if (keyCode == KeyCode.TAB) {
- if (modifiers == 0) {
- Button lastFocusableButton = get(findPrevious(buttonOrder.getLength()));
- lastFocusableButton.transferFocus(FocusTraversalDirection.FORWARD);
- handled = true;
- } else if (modifiers == Modifier.SHIFT.getMask()) {
- Button firstFocusableButton = get(findNext(NO_SELECTION_INDEX));
- firstFocusableButton.transferFocus(FocusTraversalDirection.BACKWARD);
- handled = true;
- }
- }
- }
-
- // Navigation/selection within the group
- if (!handled && modifiers == 0) {
- RadioButtonGroup radioButtonGroup = RadioButtonGroup.this;
- Button selectedButton = radioButtonGroup.getSelection();
- handled = true;
- if (keyCode == Keyboard.KeyCode.HOME) {
- radioButtonGroup.selectFirstButton();
- } else if (keyCode == Keyboard.KeyCode.END) {
- radioButtonGroup.selectLastButton();
- } else if (keyCode == Keyboard.KeyCode.LEFT || keyCode == Keyboard.KeyCode.UP) {
- radioButtonGroup.selectPreviousButton(selectedButton);
- } else if (keyCode == Keyboard.KeyCode.RIGHT || keyCode == Keyboard.KeyCode.DOWN) {
- radioButtonGroup.selectNextButton(selectedButton);
- } else {
- handled = false;
- }
- }
-
- return handled;
- }
-
- /**
- * Attempt to jump to the button whose rendered text begins with the
- * typed character.<br/>
- */
- @Override
- public boolean keyTyped(Component component, char character) {
- int modifiers = Keyboard.getModifiers();
- boolean handled = false;
-
- // We are only interested when a key is typed with no modifier, or
- // just SHIFT (which is used to reverse the search direction)
- boolean noModifiersPressed = (modifiers == 0);
- boolean shiftPressed = (modifiers == Modifier.SHIFT.getMask());
- if (noModifiersPressed || shiftPressed) {
- RadioButtonGroup radioButtonGroup = RadioButtonGroup.this;
- Button selectedButton = radioButtonGroup.getSelection();
-
- firstCharacterFilter.setTarget(character);
-
- // Determine the starting point for the search
- int searchStartIndex;
- if (selectedButton != null) {
- searchStartIndex = radioButtonGroup.indexOf(selectedButton);
- } else {
- if (noModifiersPressed) {
- searchStartIndex = NO_SELECTION_INDEX;
- } else {
- searchStartIndex = buttonOrder.getLength();
- }
- }
-
- int result = NOT_FOUND_INDEX;
- if (noModifiersPressed) {
- result = radioButtonGroup.findNext(searchStartIndex, firstCharacterFilter, true);
- } else if (shiftPressed) {
- result = radioButtonGroup.findPrevious(searchStartIndex, firstCharacterFilter,
- true);
- }
-
- // Consider the event to have been handled if a different
- // button end up being selected
- if (result != NOT_FOUND_INDEX && result != searchStartIndex) {
- radioButtonGroup.setSelection(result);
- handled = true;
- }
- }
- return handled;
- }
- };
-
- /**
- * Ensure that all buttons in this group have the custom
- * ComponentKeyListener.<br/>
- * This relies on the logic within ButtonGroup to prevent duplicates.
- */
- private final ButtonGroupListener buttonGroupListener = new ButtonGroupListener.Adapter() {
- @Override
- public void buttonAdded(ButtonGroup buttonGroup, Button button) {
- button.getComponentKeyListeners().add(componentKeyListener);
- }
-
- @Override
- public void buttonRemoved(ButtonGroup buttonGroup, Button button) {
- button.getComponentKeyListeners().remove(componentKeyListener);
- }
- };
-
- /**
- * Filter used to determine selectable buttons within the group
- */
- private final Filter<Integer> defaultFilter = new Filter<Integer>() {
- @Override
- public boolean include(Integer index) {
- Button button = buttonOrder.get(index);
- boolean focusable = button.isFocusable();
- return focusable;
- }
- };
-
- private final FirstCharacterFilter firstCharacterFilter = new FirstCharacterFilter();
- private final List<Button> buttonOrder = new ArrayList<Button>();
- private boolean circular = false;
- private boolean intraGroupFocusTransferEnabled = false;
-
- private static final int NOT_FOUND_INDEX = -1;
- private static final int NO_SELECTION_INDEX = -1;
-
- public RadioButtonGroup() {
- getButtonGroupListeners().add(buttonGroupListener);
- }
-
- /**
- * When enabled, a search for the
- * {@link RadioButtonGroup#selectPreviousButton(Button) previous} or
- * {@link RadioButtonGroup#selectNextButton(Button) next} focusable button
- * will not stop when the group's lower or upper bounds (respectively) are
- * reached.<br/>
- *
- * Instead, the search will 'wrap' and continue from the opposite bound
- * until each button in the entire group has been tested for inclusion.
- * <br/><br/>
- *
- * Defaults to <code>false</code>
- */
- public boolean isCircular() {
- return circular;
- }
-
- /**
- * When enabled, a search for the
- * {@link RadioButtonGroup#selectPreviousButton(Button) previous} or
- * {@link RadioButtonGroup#selectNextButton(Button) next} focusable button
- * will not stop when the group's lower or upper bounds (respectively) are
- * reached.<br/>
- *
- * Instead, the search will 'wrap' and continue from the opposite bound
- * until each button in the entire group has been tested for inclusion.
- */
- public void setCircular(boolean circular) {
- this.circular = circular;
- }
-
- /**
- * When true, TAB and SHIFT+TAB transfer focus out of the RadioButtonGroup.
- * <br/>
- * Defaults to <code>false</code>
- */
- public boolean isIntraGroupFocusTransferEnabled() {
- return intraGroupFocusTransferEnabled;
- }
-
- /**
- * Controls whether TAB and SHIFT+TAB will transfer focus out of the
- * RadioButtonGroup, or simply maintain their default behaviour.
- */
- public void setIntraGroupFocusTransferEnabled(boolean intraGroupFocusTransferEnabled) {
- this.intraGroupFocusTransferEnabled = intraGroupFocusTransferEnabled;
- }
-
- /**
- * Add a button to the group.
- *
- * @see Group#add(Object)
- * @see Sequence#add(Object)
- */
- @Override
- public boolean add(Button button) {
- if (button == null) {
- throw new IllegalArgumentException("Button cannot be null");
- }
- boolean result = super.add(button);
- if (result) {
- buttonOrder.add(button);
- }
- return result;
- }
-
- /**
- * Return the button at the specified index.
- *
- * @see Sequence#get(int)
- */
- public Button get(int index) {
- return buttonOrder.get(index);
- }
-
- /**
- * Return the number of buttons in the group.
- *
- * @see Sequence#getLength()
- */
- public int getLength() {
- return buttonOrder.getLength();
- }
-
- /**
- * Return the index (order) of the button within the group.
- *
- * @return The index or -1 if the button does not belong to this
- * RadioButtonGroup
- *
- * @see Sequence#indexOf(Object)
- */
- public int indexOf(Button button) {
- return buttonOrder.indexOf(button);
- }
-
- /**
- * Insert a button at the specified index.
- *
- * @see Sequence#insert(Object, int)
- */
- public void insert(Button button, int index) {
- if (button == null) {
- throw new IllegalArgumentException("Button cannot be null");
- }
- boolean result = super.add(button);
- if (result) {
- buttonOrder.insert(button, index);
- }
- }
-
- /**
- * Remove the button from the group.
- *
- * @see Group#remove(Object)
- * @see Sequence#remove(Object)
- */
- @Override
- public boolean remove(Button button) {
- boolean result = false;
- if (button != null) {
- result = super.remove(button);
- if (result) {
- buttonOrder.remove(button);
- }
- }
- return result;
- }
-
- /**
- * Remove <code>count</code> buttons from the group starting at
- * <code>index</code>.
- *
- * @see Sequence#remove(int, int)
- */
- public Sequence<Button> remove(int index, int count) {
- Sequence<Button> removed = new ArrayList<Button>();
- while (count-- > 0) {
- Button button = get(index);
- boolean result = this.remove(button);
- if (result) {
- removed.add(button);
- }
- }
- return removed;
- }
-
-
- /**
- * Return an iterator for the <strong>ordered</strong> list of buttons
- */
- @Override
- public Iterator<Button> iterator() {
- return new ImmutableIterator<Button>(buttonOrder.iterator());
- }
-
- /**
- * Select and <strong>focus</strong> the specified button.
- *
- * @see ButtonGroup#setSelection(Button)
- */
- @Override
- public void setSelection(Button button) {
- super.setSelection(button);
- if (button != null) {
- button.requestFocus();
- }
- }
-
- /**
- * Select and <strong>focus</strong> the button at the specified index,
- * unless the index is NOT_FOUND_INDEX.
- */
- public void setSelection(int index) {
- if (index != NOT_FOUND_INDEX) {
- this.setSelection(buttonOrder.get(index));
- }
- }
-
- /**
- * Select the first focusable button in the group.
- */
- public void selectFirstButton() {
- setSelection(findNext(NO_SELECTION_INDEX));
- }
-
- /**
- * Select the last focusable button in the group.
- */
- public void selectLastButton() {
- setSelection(findPrevious(buttonOrder.getLength()));
- }
-
- /**
- * Working forwards from the specified button, select the first focusable
- * button.
- *
- * @param button If null, the first available button will be selected,
- * unless the group contains a selected or focused button, in which case
- * that button will be used as the starting point for the search.
- */
- public void selectNextButton(Button button) {
- // No explicit starting point was supplied
- if (button == null) {
- // If there is a selected button in this group, we will try to use
- // it as the starting point.
- button = getSelection();
-
- if (button == null) {
- // No selection, but perhaps one of the buttons has focus?
- Component focusedComponent = Component.getFocusedComponent();
- if (focusedComponent instanceof Button) {
- int index = this.indexOf((Button)focusedComponent);
- if (index != NOT_FOUND_INDEX) {
- button = this.get(index);
- }
- }
- }
- // Try again, using new starting point if one was determined
- if (button != null) {
- selectNextButton(button);
- } else {
- selectFirstButton();
- }
- } else {
- int index = indexOf(button);
- if (index == NOT_FOUND_INDEX) {
- throw new IllegalArgumentException(
- "Button does not belong to this RadioButtonGroup.");
- }
- index = findNext(index);
- if (index != NOT_FOUND_INDEX) {
- setSelection(index);
- }
- }
- }
-
- /**
- * Working backwards from the specified button, select the first focusable
- * button.
- *
- * @param button If null, the last available button will be selected, unless
- * the group contains a selected or focused button, in which case that
- * button will be used as the starting point for the search.
- */
- public void selectPreviousButton(Button button) {
- // No explicit starting point was supplied
- if (button == null) {
- // If there is a selected button in this group, we will try to use
- // it as the starting point.
- button = getSelection();
-
- if (button == null) {
- // No selection, but perhaps one of the buttons has focus?
- Component focusedComponent = Component.getFocusedComponent();
- if (focusedComponent instanceof Button) {
- int index = this.indexOf((Button)focusedComponent);
- if (index != NOT_FOUND_INDEX) {
- button = this.get(index);
- }
- }
- }
-
- // Try again, using new starting point if one was determined
- if (button != null) {
- selectPreviousButton(button);
- } else {
- selectLastButton();
- }
- } else {
- int index = indexOf(button);
- if (index == NOT_FOUND_INDEX) {
- throw new IllegalArgumentException(
- "Button does not belong to this RadioButtonGroup.");
- }
- index = findPrevious(index);
- if (index != NOT_FOUND_INDEX) {
- setSelection(index);
- }
- }
- }
-
- /**
- * Iterate forwards over the buttons in the group, looping back to the start
- * if the upper bound is reached and the <code>circular</code> parameter is
- * true.
- *
- * @param index Index to which the 'next' is relative
- * @param filter Alternative filter to use during the search.
- * @param circular Loop when upper bound is reached
- * @return The first button found to satisfy the filter
- *
- * @see #setCircular(boolean)
- */
- private int findNext(int index, Filter<Integer> filter, boolean circular) {
- filter = (filter == null ? defaultFilter : filter);
- int result = NOT_FOUND_INDEX;
- int length = buttonOrder.getLength();
- if (length > 0) {
- // (index + 1) --> last index
- for (int i = (index + 1); i < length; i++) {
- if (filter.include(i)) {
- result = i;
- break;
- }
- }
- if (circular && result == NOT_FOUND_INDEX) {
- // first index --> index
- for (int i = 0; i <= index; i++) {
- if (filter.include(i)) {
- result = i;
- break;
- }
- }
- }
- }
- return result;
- }
-
- private int findNext(int index) {
- return findNext(index, defaultFilter, circular);
- }
-
- /**
- * Iterate backwards over the buttons in the group, looping back to the end
- * if the lower bound is reached and the <code>circular</code> parameter is
- * true.
- *
- * @param index Index to which the 'previous' is relative
- * @param filter Alternative filter to use during the search.
- * @param circular Loop when lower bound is reached
- * @return The first focusable button found
- *
- * @see #setCircular(boolean)
- */
- private int findPrevious(int index, Filter<Integer> filter, boolean circular) {
- filter = (filter == null ? defaultFilter : filter);
- int result = NOT_FOUND_INDEX;
- int length = buttonOrder.getLength();
- if (length > 0) {
- // (index - 1) --> first index
- for (int i = (index - 1); i >= 0; i--) {
- if (filter.include(i)) {
- result = i;
- break;
- }
- }
- if (circular && result == NOT_FOUND_INDEX) {
- // last index --> index
- for (int i = (length - 1); i >= index; i--) {
- if (filter.include(i)) {
- result = i;
- break;
- }
- }
- }
- }
- return result;
- }
-
- private int findPrevious(int index) {
- return findPrevious(index, defaultFilter, circular);
- }
-}
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to you under the Apache License,
+ * Version 2.0 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.pivot.wtk;
+
+import java.util.Iterator;
+
+import org.apache.pivot.collections.ArrayList;
+import org.apache.pivot.collections.Group;
+import org.apache.pivot.collections.List;
+import org.apache.pivot.collections.Sequence;
+import org.apache.pivot.util.Filter;
+import org.apache.pivot.util.ImmutableIterator;
+import org.apache.pivot.wtk.Keyboard.KeyCode;
+import org.apache.pivot.wtk.Keyboard.KeyLocation;
+import org.apache.pivot.wtk.Keyboard.Modifier;
+
+/**
+ * Extension of {@link ButtonGroup} providing keyboard navigation within the
+ * group and modified focus navigation that treats the group as a single
+ * focusable entity.<br/><br/>
+ *
+ * {@link KeyCode#UP UP} & {@link KeyCode#LEFT LEFT} Select the previous
+ * button<br/>
+ * {@link KeyCode#DOWN DOWN} & {@link KeyCode#RIGHT RIGHT} Select the next
+ * button<br/>
+ * {@link KeyCode#HOME HOME} Select the first button<br/>
+ * {@link KeyCode#END END} Select the last button<br/><br/>
+ *
+ * (Note that only {@link Component#isFocusable() focusable} buttons are
+ * considered when searching for a Button to select)<br/><br/>
+ *
+ * When a button within the group is focused and key is typed, an attempt is
+ * made to find the next button (default) or previous button (when the SHIFT
+ * modifier is pressed) whose renderer text starts with the typed character.
+ * This search will always behave as if the <code>circular</code> property were
+ * set.<br/><br/>
+ *
+ * By default, {@link KeyCode#TAB TAB} and {@link KeyCode#TAB SHIFT+TAB}
+ * key presses will transfer focus out of the group (forwards or backwards
+ * respectively).
+ * This is managed by the {@link #setIntraGroupFocusTransferEnabled(boolean)
+ * intraGroupFocusTransferEnabled} property.<br/><br/>
+ *
+ * The {@link #setCircular(boolean) circular} property can be enabled to allow
+ * the selection to transfer seamlessly from one end of the group to the other.
+ * (i.e. holding down an arrow key will cycle through all focusable buttons)
+ * <br/><br/>
+ *
+ * Note that due to the conflicting return types of the <code>add(T)</code> and
+ * <code>remove(T)</code> methods in the {@link Group#add(Object) Group} and
+ * {@link Sequence#add(Object) Sequence} interfaces, this class cannot actually
+ * implement <code>Sequence<Button></code>, although most of the same
+ * methods are implemented.<br/>
+ */
+public class RadioButtonGroup extends ButtonGroup {
+
+ /**
+ * Filter used to determine selectable buttons whose rendered data starts
+ * with the target character.
+ */
+ private class FirstCharacterFilter implements Filter<Integer> {
+ private char target = '\0';
+
+ public void setTarget(char target) {
+ this.target = Character.toUpperCase(target);
+ }
+
+ @Override
+ public boolean include(Integer index) {
+ boolean include = defaultFilter.include(index);
+ if (include) {
+ Button button = buttonOrder.get(index);
+ String rendered = button.getDataRenderer().toString(button.getButtonData());
+ if (rendered != null && rendered.length() > 0) {
+ char first = Character.toUpperCase(rendered.charAt(0));
+ if (first != target) {
+ include = false;
+ }
+ }
+ }
+ return include;
+ }
+ }
+
+ /**
+ * ComponentKeyListener to be applied to all buttons as they are added to
+ * the group.<br/><br/>
+ *
+ * At least one button in the group must be focused for this listener to be
+ * executed, but that won't necessarily be a selected button.<br/>
+ * This also means that the group will not be empty, although some of the
+ * buttons contained within may not be focusable, or even visible.
+ */
+ private final ComponentKeyListener componentKeyListener = new ComponentKeyListener.Adapter() {
+ /**
+ * Handle TAB & SHIFT+TAB focus traversal, HOME, END & arrow keys
+ */
+ @Override
+ public boolean keyPressed(Component component, int keyCode, KeyLocation keyLocation) {
+ int modifiers = Keyboard.getModifiers();
+ boolean handled = false;
+
+ /*
+ * Potentially transfer focus away from the buttons in this group.
+ *
+ * At this point we know that at least one button is focused, so we
+ * just need to find the first or last (and possibly only) focusable
+ * button depending on the focus transfer direction and then
+ * transfer away from it.
+ */
+ if (!intraGroupFocusTransferEnabled) {
+ if (keyCode == KeyCode.TAB) {
+ if (modifiers == 0) {
+ Button lastFocusableButton = get(findPrevious(buttonOrder.getLength()));
+ lastFocusableButton.transferFocus(FocusTraversalDirection.FORWARD);
+ handled = true;
+ } else if (modifiers == Modifier.SHIFT.getMask()) {
+ Button firstFocusableButton = get(findNext(NO_SELECTION_INDEX));
+ firstFocusableButton.transferFocus(FocusTraversalDirection.BACKWARD);
+ handled = true;
+ }
+ }
+ }
+
+ // Navigation/selection within the group
+ if (!handled && modifiers == 0) {
+ RadioButtonGroup radioButtonGroup = RadioButtonGroup.this;
+ Button selectedButton = radioButtonGroup.getSelection();
+ handled = true;
+ if (keyCode == Keyboard.KeyCode.HOME) {
+ radioButtonGroup.selectFirstButton();
+ } else if (keyCode == Keyboard.KeyCode.END) {
+ radioButtonGroup.selectLastButton();
+ } else if (keyCode == Keyboard.KeyCode.LEFT || keyCode == Keyboard.KeyCode.UP) {
+ radioButtonGroup.selectPreviousButton(selectedButton);
+ } else if (keyCode == Keyboard.KeyCode.RIGHT || keyCode == Keyboard.KeyCode.DOWN) {
+ radioButtonGroup.selectNextButton(selectedButton);
+ } else {
+ handled = false;
+ }
+ }
+
+ return handled;
+ }
+
+ /**
+ * Attempt to jump to the button whose rendered text begins with the
+ * typed character.<br/>
+ */
+ @Override
+ public boolean keyTyped(Component component, char character) {
+ int modifiers = Keyboard.getModifiers();
+ boolean handled = false;
+
+ // We are only interested when a key is typed with no modifier, or
+ // just SHIFT (which is used to reverse the search direction)
+ boolean noModifiersPressed = (modifiers == 0);
+ boolean shiftPressed = (modifiers == Modifier.SHIFT.getMask());
+ if (noModifiersPressed || shiftPressed) {
+ RadioButtonGroup radioButtonGroup = RadioButtonGroup.this;
+ Button selectedButton = radioButtonGroup.getSelection();
+
+ firstCharacterFilter.setTarget(character);
+
+ // Determine the starting point for the search
+ int searchStartIndex;
+ if (selectedButton != null) {
+ searchStartIndex = radioButtonGroup.indexOf(selectedButton);
+ } else {
+ if (noModifiersPressed) {
+ searchStartIndex = NO_SELECTION_INDEX;
+ } else {
+ searchStartIndex = buttonOrder.getLength();
+ }
+ }
+
+ int result = NOT_FOUND_INDEX;
+ if (noModifiersPressed) {
+ result = radioButtonGroup.findNext(searchStartIndex, firstCharacterFilter, true);
+ } else if (shiftPressed) {
+ result = radioButtonGroup.findPrevious(searchStartIndex, firstCharacterFilter,
+ true);
+ }
+
+ // Consider the event to have been handled if a different
+ // button end up being selected
+ if (result != NOT_FOUND_INDEX && result != searchStartIndex) {
+ radioButtonGroup.setSelection(result);
+ handled = true;
+ }
+ }
+ return handled;
+ }
+ };
+
+ /**
+ * Ensure that all buttons in this group have the custom
+ * ComponentKeyListener.<br/>
+ * This relies on the logic within ButtonGroup to prevent duplicates.
+ */
+ private final ButtonGroupListener buttonGroupListener = new ButtonGroupListener.Adapter() {
+ @Override
+ public void buttonAdded(ButtonGroup buttonGroup, Button button) {
+ button.getComponentKeyListeners().add(componentKeyListener);
+ }
+
+ @Override
+ public void buttonRemoved(ButtonGroup buttonGroup, Button button) {
+ button.getComponentKeyListeners().remove(componentKeyListener);
+ }
+ };
+
+ /**
+ * Filter used to determine selectable buttons within the group
+ */
+ private final Filter<Integer> defaultFilter = new Filter<Integer>() {
+ @Override
+ public boolean include(Integer index) {
+ Button button = buttonOrder.get(index);
+ boolean focusable = button.isFocusable();
+ return focusable;
+ }
+ };
+
+ private final FirstCharacterFilter firstCharacterFilter = new FirstCharacterFilter();
+ private final List<Button> buttonOrder = new ArrayList<Button>();
+ private boolean circular = false;
+ private boolean intraGroupFocusTransferEnabled = false;
+
+ private static final int NOT_FOUND_INDEX = -1;
+ private static final int NO_SELECTION_INDEX = -1;
+
+ public RadioButtonGroup() {
+ getButtonGroupListeners().add(buttonGroupListener);
+ }
+
+ /**
+ * When enabled, a search for the
+ * {@link RadioButtonGroup#selectPreviousButton(Button) previous} or
+ * {@link RadioButtonGroup#selectNextButton(Button) next} focusable button
+ * will not stop when the group's lower or upper bounds (respectively) are
+ * reached.<br/>
+ *
+ * Instead, the search will 'wrap' and continue from the opposite bound
+ * until each button in the entire group has been tested for inclusion.
+ * <br/><br/>
+ *
+ * Defaults to <code>false</code>
+ */
+ public boolean isCircular() {
+ return circular;
+ }
+
+ /**
+ * When enabled, a search for the
+ * {@link RadioButtonGroup#selectPreviousButton(Button) previous} or
+ * {@link RadioButtonGroup#selectNextButton(Button) next} focusable button
+ * will not stop when the group's lower or upper bounds (respectively) are
+ * reached.<br/>
+ *
+ * Instead, the search will 'wrap' and continue from the opposite bound
+ * until each button in the entire group has been tested for inclusion.
+ */
+ public void setCircular(boolean circular) {
+ this.circular = circular;
+ }
+
+ /**
+ * When true, TAB and SHIFT+TAB transfer focus out of the RadioButtonGroup.
+ * <br/>
+ * Defaults to <code>false</code>
+ */
+ public boolean isIntraGroupFocusTransferEnabled() {
+ return intraGroupFocusTransferEnabled;
+ }
+
+ /**
+ * Controls whether TAB and SHIFT+TAB will transfer focus out of the
+ * RadioButtonGroup, or simply maintain their default behaviour.
+ */
+ public void setIntraGroupFocusTransferEnabled(boolean intraGroupFocusTransferEnabled) {
+ this.intraGroupFocusTransferEnabled = intraGroupFocusTransferEnabled;
+ }
+
+ /**
+ * Add a button to the group.
+ *
+ * @see Group#add(Object)
+ * @see Sequence#add(Object)
+ */
+ @Override
+ public boolean add(Button button) {
+ if (button == null) {
+ throw new IllegalArgumentException("Button cannot be null");
+ }
+ boolean result = super.add(button);
+ if (result) {
+ buttonOrder.add(button);
+ }
+ return result;
+ }
+
+ /**
+ * Return the button at the specified index.
+ *
+ * @see Sequence#get(int)
+ */
+ public Button get(int index) {
+ return buttonOrder.get(index);
+ }
+
+ /**
+ * Return the number of buttons in the group.
+ *
+ * @see Sequence#getLength()
+ */
+ public int getLength() {
+ return buttonOrder.getLength();
+ }
+
+ /**
+ * Return the index (order) of the button within the group.
+ *
+ * @return The index or -1 if the button does not belong to this
+ * RadioButtonGroup
+ *
+ * @see Sequence#indexOf(Object)
+ */
+ public int indexOf(Button button) {
+ return buttonOrder.indexOf(button);
+ }
+
+ /**
+ * Insert a button at the specified index.
+ *
+ * @see Sequence#insert(Object, int)
+ */
+ public void insert(Button button, int index) {
+ if (button == null) {
+ throw new IllegalArgumentException("Button cannot be null");
+ }
+ boolean result = super.add(button);
+ if (result) {
+ buttonOrder.insert(button, index);
+ }
+ }
+
+ /**
+ * Remove the button from the group.
+ *
+ * @see Group#remove(Object)
+ * @see Sequence#remove(Object)
+ */
+ @Override
+ public boolean remove(Button button) {
+ boolean result = false;
+ if (button != null) {
+ result = super.remove(button);
+ if (result) {
+ buttonOrder.remove(button);
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Remove <code>count</code> buttons from the group starting at
+ * <code>index</code>.
+ *
+ * @see Sequence#remove(int, int)
+ */
+ public Sequence<Button> remove(int index, int count) {
+ Sequence<Button> removed = new ArrayList<Button>();
+ while (count-- > 0) {
+ Button button = get(index);
+ boolean result = this.remove(button);
+ if (result) {
+ removed.add(button);
+ }
+ }
+ return removed;
+ }
+
+
+ /**
+ * Return an iterator for the <strong>ordered</strong> list of buttons
+ */
+ @Override
+ public Iterator<Button> iterator() {
+ return new ImmutableIterator<Button>(buttonOrder.iterator());
+ }
+
+ /**
+ * Select and <strong>focus</strong> the specified button.
+ *
+ * @see ButtonGroup#setSelection(Button)
+ */
+ @Override
+ public void setSelection(Button button) {
+ super.setSelection(button);
+ if (button != null) {
+ button.requestFocus();
+ }
+ }
+
+ /**
+ * Select and <strong>focus</strong> the button at the specified index,
+ * unless the index is NOT_FOUND_INDEX.
+ */
+ public void setSelection(int index) {
+ if (index != NOT_FOUND_INDEX) {
+ this.setSelection(buttonOrder.get(index));
+ }
+ }
+
+ /**
+ * Select the first focusable button in the group.
+ */
+ public void selectFirstButton() {
+ setSelection(findNext(NO_SELECTION_INDEX));
+ }
+
+ /**
+ * Select the last focusable button in the group.
+ */
+ public void selectLastButton() {
+ setSelection(findPrevious(buttonOrder.getLength()));
+ }
+
+ /**
+ * Working forwards from the specified button, select the first focusable
+ * button.
+ *
+ * @param button If null, the first available button will be selected,
+ * unless the group contains a selected or focused button, in which case
+ * that button will be used as the starting point for the search.
+ */
+ public void selectNextButton(Button button) {
+ // No explicit starting point was supplied
+ if (button == null) {
+ // If there is a selected button in this group, we will try to use
+ // it as the starting point.
+ button = getSelection();
+
+ if (button == null) {
+ // No selection, but perhaps one of the buttons has focus?
+ Component focusedComponent = Component.getFocusedComponent();
+ if (focusedComponent instanceof Button) {
+ int index = this.indexOf((Button)focusedComponent);
+ if (index != NOT_FOUND_INDEX) {
+ button = this.get(index);
+ }
+ }
+ }
+ // Try again, using new starting point if one was determined
+ if (button != null) {
+ selectNextButton(button);
+ } else {
+ selectFirstButton();
+ }
+ } else {
+ int index = indexOf(button);
+ if (index == NOT_FOUND_INDEX) {
+ throw new IllegalArgumentException(
+ "Button does not belong to this RadioButtonGroup.");
+ }
+ index = findNext(index);
+ if (index != NOT_FOUND_INDEX) {
+ setSelection(index);
+ }
+ }
+ }
+
+ /**
+ * Working backwards from the specified button, select the first focusable
+ * button.
+ *
+ * @param button If null, the last available button will be selected, unless
+ * the group contains a selected or focused button, in which case that
+ * button will be used as the starting point for the search.
+ */
+ public void selectPreviousButton(Button button) {
+ // No explicit starting point was supplied
+ if (button == null) {
+ // If there is a selected button in this group, we will try to use
+ // it as the starting point.
+ button = getSelection();
+
+ if (button == null) {
+ // No selection, but perhaps one of the buttons has focus?
+ Component focusedComponent = Component.getFocusedComponent();
+ if (focusedComponent instanceof Button) {
+ int index = this.indexOf((Button)focusedComponent);
+ if (index != NOT_FOUND_INDEX) {
+ button = this.get(index);
+ }
+ }
+ }
+
+ // Try again, using new starting point if one was determined
+ if (button != null) {
+ selectPreviousButton(button);
+ } else {
+ selectLastButton();
+ }
+ } else {
+ int index = indexOf(button);
+ if (index == NOT_FOUND_INDEX) {
+ throw new IllegalArgumentException(
+ "Button does not belong to this RadioButtonGroup.");
+ }
+ index = findPrevious(index);
+ if (index != NOT_FOUND_INDEX) {
+ setSelection(index);
+ }
+ }
+ }
+
+ /**
+ * Iterate forwards over the buttons in the group, looping back to the start
+ * if the upper bound is reached and the <code>circular</code> parameter is
+ * true.
+ *
+ * @param index Index to which the 'next' is relative
+ * @param filter Alternative filter to use during the search.
+ * @param circular Loop when upper bound is reached
+ * @return The first button found to satisfy the filter
+ *
+ * @see #setCircular(boolean)
+ */
+ private int findNext(int index, Filter<Integer> filter, boolean circular) {
+ filter = (filter == null ? defaultFilter : filter);
+ int result = NOT_FOUND_INDEX;
+ int length = buttonOrder.getLength();
+ if (length > 0) {
+ // (index + 1) --> last index
+ for (int i = (index + 1); i < length; i++) {
+ if (filter.include(i)) {
+ result = i;
+ break;
+ }
+ }
+ if (circular && result == NOT_FOUND_INDEX) {
+ // first index --> index
+ for (int i = 0; i <= index; i++) {
+ if (filter.include(i)) {
+ result = i;
+ break;
+ }
+ }
+ }
+ }
+ return result;
+ }
+
+ private int findNext(int index) {
+ return findNext(index, defaultFilter, circular);
+ }
+
+ /**
+ * Iterate backwards over the buttons in the group, looping back to the end
+ * if the lower bound is reached and the <code>circular</code> parameter is
+ * true.
+ *
+ * @param index Index to which the 'previous' is relative
+ * @param filter Alternative filter to use during the search.
+ * @param circular Loop when lower bound is reached
+ * @return The first focusable button found
+ *
+ * @see #setCircular(boolean)
+ */
+ private int findPrevious(int index, Filter<Integer> filter, boolean circular) {
+ filter = (filter == null ? defaultFilter : filter);
+ int result = NOT_FOUND_INDEX;
+ int length = buttonOrder.getLength();
+ if (length > 0) {
+ // (index - 1) --> first index
+ for (int i = (index - 1); i >= 0; i--) {
+ if (filter.include(i)) {
+ result = i;
+ break;
+ }
+ }
+ if (circular && result == NOT_FOUND_INDEX) {
+ // last index --> index
+ for (int i = (length - 1); i >= index; i--) {
+ if (filter.include(i)) {
+ result = i;
+ break;
+ }
+ }
+ }
+ }
+ return result;
+ }
+
+ private int findPrevious(int index) {
+ return findPrevious(index, defaultFilter, circular);
+ }
+}
Propchange: pivot/trunk/wtk/src/org/apache/pivot/wtk/RadioButtonGroup.java
------------------------------------------------------------------------------
svn:eol-style = native
Modified: pivot/trunk/wtk/src/org/apache/pivot/wtk/WTKListenerList.java
URL: http://svn.apache.org/viewvc/pivot/trunk/wtk/src/org/apache/pivot/wtk/WTKListenerList.java?rev=1222994&r1=1222993&r2=1222994&view=diff
==============================================================================
--- pivot/trunk/wtk/src/org/apache/pivot/wtk/WTKListenerList.java (original)
+++ pivot/trunk/wtk/src/org/apache/pivot/wtk/WTKListenerList.java Sat Dec 24 16:07:37 2011
@@ -1,26 +1,26 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to you under the Apache License,
- * Version 2.0 (the "License"); you may not use this file except in
- * compliance with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.pivot.wtk;
-
-import org.apache.pivot.util.ListenerList;
-
-/**
- * This is a customised subclass of ListenerList that adds thread-safety checks
- * for the WTK components.
- */
-public class WTKListenerList<T> extends ListenerList<T> {
-}
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to you under the Apache License,
+ * Version 2.0 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.pivot.wtk;
+
+import org.apache.pivot.util.ListenerList;
+
+/**
+ * This is a customised subclass of ListenerList that adds thread-safety checks
+ * for the WTK components.
+ */
+public class WTKListenerList<T> extends ListenerList<T> {
+}
Propchange: pivot/trunk/wtk/src/org/apache/pivot/wtk/WTKListenerList.java
------------------------------------------------------------------------------
svn:eol-style = native
Modified: pivot/trunk/wtk/src/org/apache/pivot/wtk/content/TableViewCheckboxCellRenderer.java
URL: http://svn.apache.org/viewvc/pivot/trunk/wtk/src/org/apache/pivot/wtk/content/TableViewCheckboxCellRenderer.java?rev=1222994&r1=1222993&r2=1222994&view=diff
==============================================================================
--- pivot/trunk/wtk/src/org/apache/pivot/wtk/content/TableViewCheckboxCellRenderer.java (original)
+++ pivot/trunk/wtk/src/org/apache/pivot/wtk/content/TableViewCheckboxCellRenderer.java Sat Dec 24 16:07:37 2011
@@ -1,83 +1,83 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to you under the Apache License,
- * Version 2.0 (the "License"); you may not use this file except in
- * compliance with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.pivot.wtk.content;
-
-import org.apache.pivot.wtk.Button;
-import org.apache.pivot.wtk.Checkbox;
-import org.apache.pivot.wtk.BoxPane;
-import org.apache.pivot.wtk.HorizontalAlignment;
-import org.apache.pivot.wtk.TableView;
-import org.apache.pivot.wtk.VerticalAlignment;
-
-/**
- * Default renderer for table view cells that contain boolean data. Renders
- * cell contents as a checkbox.
- */
-public class TableViewCheckboxCellRenderer extends BoxPane
- implements TableView.CellRenderer {
- protected Checkbox checkbox = new Checkbox();
- private boolean checkboxDisabled = false;
-
- public TableViewCheckboxCellRenderer() {
- add(checkbox);
-
- getStyles().put("padding", 3);
- getStyles().put("verticalAlignment", VerticalAlignment.CENTER);
- getStyles().put("horizontalAlignment", HorizontalAlignment.CENTER);
- }
-
- @Override
- public void setSize(int width, int height) {
- super.setSize(width, height);
-
- // Since this component doesn't have a parent, it won't be validated
- // via layout; ensure that it is valid here
- validate();
- }
-
- @Override
- public void render(Object row, int rowIndex, int columnIndex,
- TableView tableView, String columnName,
- boolean selected, boolean highlighted, boolean disabled) {
- if (row != null) {
- // Get the row and cell data
- if (columnName != null) {
- if (checkbox.isTriState()) {
- checkbox.setStateKey(columnName);
- } else {
- checkbox.setSelectedKey(columnName);
- }
- checkbox.load(row);
- } else {
- checkbox.setState(Button.State.UNSELECTED);
- }
- checkbox.setEnabled(!checkboxDisabled && tableView.isEnabled() && !disabled);
- }
- }
-
- public String toString(Object row, String columnName) {
- return null;
- }
-
- public boolean isCheckboxDisabled() {
- return checkboxDisabled;
- }
-
- public void setCheckboxDisabled(boolean checkboxDisabled) {
- this.checkboxDisabled = checkboxDisabled;
- }
-}
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to you under the Apache License,
+ * Version 2.0 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.pivot.wtk.content;
+
+import org.apache.pivot.wtk.Button;
+import org.apache.pivot.wtk.Checkbox;
+import org.apache.pivot.wtk.BoxPane;
+import org.apache.pivot.wtk.HorizontalAlignment;
+import org.apache.pivot.wtk.TableView;
+import org.apache.pivot.wtk.VerticalAlignment;
+
+/**
+ * Default renderer for table view cells that contain boolean data. Renders
+ * cell contents as a checkbox.
+ */
+public class TableViewCheckboxCellRenderer extends BoxPane
+ implements TableView.CellRenderer {
+ protected Checkbox checkbox = new Checkbox();
+ private boolean checkboxDisabled = false;
+
+ public TableViewCheckboxCellRenderer() {
+ add(checkbox);
+
+ getStyles().put("padding", 3);
+ getStyles().put("verticalAlignment", VerticalAlignment.CENTER);
+ getStyles().put("horizontalAlignment", HorizontalAlignment.CENTER);
+ }
+
+ @Override
+ public void setSize(int width, int height) {
+ super.setSize(width, height);
+
+ // Since this component doesn't have a parent, it won't be validated
+ // via layout; ensure that it is valid here
+ validate();
+ }
+
+ @Override
+ public void render(Object row, int rowIndex, int columnIndex,
+ TableView tableView, String columnName,
+ boolean selected, boolean highlighted, boolean disabled) {
+ if (row != null) {
+ // Get the row and cell data
+ if (columnName != null) {
+ if (checkbox.isTriState()) {
+ checkbox.setStateKey(columnName);
+ } else {
+ checkbox.setSelectedKey(columnName);
+ }
+ checkbox.load(row);
+ } else {
+ checkbox.setState(Button.State.UNSELECTED);
+ }
+ checkbox.setEnabled(!checkboxDisabled && tableView.isEnabled() && !disabled);
+ }
+ }
+
+ public String toString(Object row, String columnName) {
+ return null;
+ }
+
+ public boolean isCheckboxDisabled() {
+ return checkboxDisabled;
+ }
+
+ public void setCheckboxDisabled(boolean checkboxDisabled) {
+ this.checkboxDisabled = checkboxDisabled;
+ }
+}
Propchange: pivot/trunk/wtk/src/org/apache/pivot/wtk/content/TableViewCheckboxCellRenderer.java
------------------------------------------------------------------------------
svn:eol-style = native
Modified: pivot/trunk/wtk/src/org/apache/pivot/wtk/content/TableViewTriStateCellRenderer.java
URL: http://svn.apache.org/viewvc/pivot/trunk/wtk/src/org/apache/pivot/wtk/content/TableViewTriStateCellRenderer.java?rev=1222994&r1=1222993&r2=1222994&view=diff
==============================================================================
--- pivot/trunk/wtk/src/org/apache/pivot/wtk/content/TableViewTriStateCellRenderer.java (original)
+++ pivot/trunk/wtk/src/org/apache/pivot/wtk/content/TableViewTriStateCellRenderer.java Sat Dec 24 16:07:37 2011
@@ -1,29 +1,29 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to you under the Apache License,
- * Version 2.0 (the "License"); you may not use this file except in
- * compliance with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.pivot.wtk.content;
-
-/**
- * Default renderer for table view cells that contain tri-state data. Renders
- * cell contents as a tri-state checkbox.
- */
-public class TableViewTriStateCellRenderer extends TableViewCheckboxCellRenderer
-{
- public TableViewTriStateCellRenderer() {
- super();
- checkbox.setTriState(true);
- }
-}
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to you under the Apache License,
+ * Version 2.0 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.pivot.wtk.content;
+
+/**
+ * Default renderer for table view cells that contain tri-state data. Renders
+ * cell contents as a tri-state checkbox.
+ */
+public class TableViewTriStateCellRenderer extends TableViewCheckboxCellRenderer
+{
+ public TableViewTriStateCellRenderer() {
+ super();
+ checkbox.setTriState(true);
+ }
+}
Propchange: pivot/trunk/wtk/src/org/apache/pivot/wtk/content/TableViewTriStateCellRenderer.java
------------------------------------------------------------------------------
svn:eol-style = native