You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@pivot.apache.org by gb...@apache.org on 2009/07/31 19:44:45 UTC
svn commit: r799669 - in /incubator/pivot/trunk:
demos/src/org/apache/pivot/demos/lists/ wtk/src/org/apache/pivot/wtk/
wtk/src/org/apache/pivot/wtk/content/
Author: gbrown
Date: Fri Jul 31 17:44:44 2009
New Revision: 799669
URL: http://svn.apache.org/viewvc?rev=799669&view=rev
Log:
Fix some issues with focus management:
- Component#isFocusable() now checks for showing and enabled, not showing and !blocked
- Container#requestFocus() now only checks for showing, not showing and !blocked
- Window#restoreFocus() now only asserts showing, not showing and !blocked
- ApplicationContext.DisplayHost#processKeyEvent() doesn't propagate events to the focused component if it is blocked
Partially implement multiple selection support in ListSelection class; add demo app to test selection state.
Added:
incubator/pivot/trunk/demos/src/org/apache/pivot/demos/lists/
incubator/pivot/trunk/demos/src/org/apache/pivot/demos/lists/MultiSelect.java
incubator/pivot/trunk/demos/src/org/apache/pivot/demos/lists/multi_select.wtkx
Modified:
incubator/pivot/trunk/wtk/src/org/apache/pivot/wtk/ApplicationContext.java
incubator/pivot/trunk/wtk/src/org/apache/pivot/wtk/Component.java
incubator/pivot/trunk/wtk/src/org/apache/pivot/wtk/Container.java
incubator/pivot/trunk/wtk/src/org/apache/pivot/wtk/ListSelection.java
incubator/pivot/trunk/wtk/src/org/apache/pivot/wtk/ListView.java
incubator/pivot/trunk/wtk/src/org/apache/pivot/wtk/Sheet.java
incubator/pivot/trunk/wtk/src/org/apache/pivot/wtk/TableView.java
incubator/pivot/trunk/wtk/src/org/apache/pivot/wtk/Window.java
incubator/pivot/trunk/wtk/src/org/apache/pivot/wtk/content/NumericSpinnerData.java
Added: incubator/pivot/trunk/demos/src/org/apache/pivot/demos/lists/MultiSelect.java
URL: http://svn.apache.org/viewvc/incubator/pivot/trunk/demos/src/org/apache/pivot/demos/lists/MultiSelect.java?rev=799669&view=auto
==============================================================================
--- incubator/pivot/trunk/demos/src/org/apache/pivot/demos/lists/MultiSelect.java (added)
+++ incubator/pivot/trunk/demos/src/org/apache/pivot/demos/lists/MultiSelect.java Fri Jul 31 17:44:44 2009
@@ -0,0 +1,87 @@
+/*
+ * 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.demos.lists;
+
+import org.apache.pivot.collections.ArrayList;
+import org.apache.pivot.collections.Map;
+import org.apache.pivot.collections.Sequence;
+import org.apache.pivot.wtk.Application;
+import org.apache.pivot.wtk.DesktopApplicationContext;
+import org.apache.pivot.wtk.Display;
+import org.apache.pivot.wtk.ListView;
+import org.apache.pivot.wtk.ListViewSelectionListener;
+import org.apache.pivot.wtk.Span;
+import org.apache.pivot.wtk.Window;
+import org.apache.pivot.wtkx.WTKXSerializer;
+
+public class MultiSelect implements Application {
+ private Window window = null;
+ private ListView dataListView = null;
+ private ListView selectionListView = null;
+
+ @Override
+ public void startup(Display display, Map<String, String> properties)
+ throws Exception {
+ WTKXSerializer wtkxSerializer = new WTKXSerializer();
+ window = (Window)wtkxSerializer.readObject(this, "multi_select.wtkx");
+
+ dataListView = (ListView)wtkxSerializer.get("dataListView");
+ selectionListView = (ListView)wtkxSerializer.get("selectionListView");
+
+ dataListView.getListViewSelectionListeners().add(new ListViewSelectionListener() {
+ public void selectedRangeAdded(ListView listView, int rangeStart, int rangeEnd) {
+ refreshSelectionListData();
+ }
+
+ public void selectedRangeRemoved(ListView listView, int rangeStart, int rangeEnd) {
+ refreshSelectionListData();
+ }
+
+ public void selectedRangesChanged(ListView listView, Sequence<Span> previousSelectedRanges) {
+ refreshSelectionListData();
+ }
+
+ private void refreshSelectionListData() {
+ selectionListView.setListData(new ArrayList<Span>(dataListView.getSelectedRanges()));
+ }
+ });
+
+ window.open(display);
+ dataListView.requestFocus();
+ }
+
+ @Override
+ public boolean shutdown(boolean optional) {
+ if (window != null) {
+ window.close();
+ }
+
+ return false;
+ }
+
+ @Override
+ public void suspend() {
+ }
+
+ @Override
+ public void resume() {
+ }
+
+ public static void main(String[] args) {
+ DesktopApplicationContext.main(MultiSelect.class, args);
+ }
+}
Added: incubator/pivot/trunk/demos/src/org/apache/pivot/demos/lists/multi_select.wtkx
URL: http://svn.apache.org/viewvc/incubator/pivot/trunk/demos/src/org/apache/pivot/demos/lists/multi_select.wtkx?rev=799669&view=auto
==============================================================================
--- incubator/pivot/trunk/demos/src/org/apache/pivot/demos/lists/multi_select.wtkx (added)
+++ incubator/pivot/trunk/demos/src/org/apache/pivot/demos/lists/multi_select.wtkx Fri Jul 31 17:44:44 2009
@@ -0,0 +1,60 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements. See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to you under the Apache License,
+Version 2.0 (the "License"); you may not use this file except in
+compliance with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+-->
+
+<Window title="Multiple Selection Demo" maximized="true"
+ xmlns:wtkx="http://pivot.apache.org/wtkx"
+ xmlns:collections="org.apache.pivot.collections"
+ xmlns:content="org.apache.pivot.wtk.content"
+ xmlns="org.apache.pivot.wtk">
+ <content>
+ <TablePane styles="{padding:8, horizontalSpacing:8}">
+ <columns>
+ <TablePane.Column width="1*"/>
+ <TablePane.Column width="1*"/>
+ </columns>
+ <rows>
+ <TablePane.Row height="1*">
+ <Border styles="{padding:0, color:10}">
+ <content>
+ <ScrollPane horizontalScrollBarPolicy="fill">
+ <view>
+ <ListView wtkx:id="dataListView" selectMode="multi"
+ selectedRanges="[{start:0, end:1}, {start:3, end:7}, {start:10, end:15}]">
+ <listData>
+ <content:NumericSpinnerData lowerBound="0" upperBound="31"
+ increment="1"/>
+ </listData>
+ </ListView>
+ </view>
+ </ScrollPane>
+ </content>
+ </Border>
+ <Border styles="{padding:0, color:10}">
+ <content>
+ <ScrollPane horizontalScrollBarPolicy="fill">
+ <view>
+ <ListView wtkx:id="selectionListView" selectMode="none"/>
+ </view>
+ </ScrollPane>
+ </content>
+ </Border>
+ </TablePane.Row>
+ </rows>
+ </TablePane>
+ </content>
+</Window>
Modified: incubator/pivot/trunk/wtk/src/org/apache/pivot/wtk/ApplicationContext.java
URL: http://svn.apache.org/viewvc/incubator/pivot/trunk/wtk/src/org/apache/pivot/wtk/ApplicationContext.java?rev=799669&r1=799668&r2=799669&view=diff
==============================================================================
--- incubator/pivot/trunk/wtk/src/org/apache/pivot/wtk/ApplicationContext.java (original)
+++ incubator/pivot/trunk/wtk/src/org/apache/pivot/wtk/ApplicationContext.java Fri Jul 31 17:44:44 2009
@@ -1179,7 +1179,9 @@
unprocessedKeyHandler.keyPressed(keyCode, keyLocation);
}
} else {
- consumed = focusedComponent.keyPressed(keyCode, keyLocation);
+ if (!focusedComponent.isBlocked()) {
+ consumed = focusedComponent.keyPressed(keyCode, keyLocation);
+ }
}
} catch (Exception exception) {
if (application instanceof Application.UncaughtExceptionHandler) {
@@ -1211,7 +1213,9 @@
unprocessedKeyHandler.keyReleased(keyCode, keyLocation);
}
} else {
- consumed = focusedComponent.keyReleased(keyCode, keyLocation);
+ if (!focusedComponent.isBlocked()) {
+ consumed = focusedComponent.keyReleased(keyCode, keyLocation);
+ }
}
} catch (Exception exception) {
if (application instanceof Application.UncaughtExceptionHandler) {
@@ -1243,7 +1247,9 @@
unprocessedKeyHandler.keyTyped(keyChar);
}
} else {
- consumed = focusedComponent.keyTyped(keyChar);
+ if (!focusedComponent.isBlocked()) {
+ consumed = focusedComponent.keyTyped(keyChar);
+ }
}
} catch (Exception exception) {
if (application instanceof Application.UncaughtExceptionHandler) {
Modified: incubator/pivot/trunk/wtk/src/org/apache/pivot/wtk/Component.java
URL: http://svn.apache.org/viewvc/incubator/pivot/trunk/wtk/src/org/apache/pivot/wtk/Component.java?rev=799669&r1=799668&r2=799669&view=diff
==============================================================================
--- incubator/pivot/trunk/wtk/src/org/apache/pivot/wtk/Component.java (original)
+++ incubator/pivot/trunk/wtk/src/org/apache/pivot/wtk/Component.java Fri Jul 31 17:44:44 2009
@@ -1964,7 +1964,7 @@
public boolean isFocusable() {
return skin.isFocusable()
&& isShowing()
- && !isBlocked();
+ && isEnabled();
}
/**
Modified: incubator/pivot/trunk/wtk/src/org/apache/pivot/wtk/Container.java
URL: http://svn.apache.org/viewvc/incubator/pivot/trunk/wtk/src/org/apache/pivot/wtk/Container.java?rev=799669&r1=799668&r2=799669&view=diff
==============================================================================
--- incubator/pivot/trunk/wtk/src/org/apache/pivot/wtk/Container.java (original)
+++ incubator/pivot/trunk/wtk/src/org/apache/pivot/wtk/Container.java Fri Jul 31 17:44:44 2009
@@ -254,7 +254,7 @@
// and contains the focused component, clear the focus
if (parent == null
&& containsFocus()) {
- clearFocus(true);
+ clearFocus(false);
}
super.setParent(parent);
@@ -303,7 +303,7 @@
public void setVisible(boolean visible) {
if (!visible
&& containsFocus()) {
- clearFocus(true);
+ clearFocus(false);
}
super.setVisible(visible);
@@ -459,8 +459,7 @@
*/
@Override
protected boolean requestFocus(boolean temporary) {
- if (isShowing()
- && !isBlocked()) {
+ if (isShowing()) {
FocusTraversalPolicy focusTraversalPolicy = getFocusTraversalPolicy();
Component component = focusTraversalPolicy.getNextComponent(this, null, Direction.FORWARD);
if (component != null) {
Modified: incubator/pivot/trunk/wtk/src/org/apache/pivot/wtk/ListSelection.java
URL: http://svn.apache.org/viewvc/incubator/pivot/trunk/wtk/src/org/apache/pivot/wtk/ListSelection.java?rev=799669&r1=799668&r2=799669&view=diff
==============================================================================
--- incubator/pivot/trunk/wtk/src/org/apache/pivot/wtk/ListSelection.java (original)
+++ incubator/pivot/trunk/wtk/src/org/apache/pivot/wtk/ListSelection.java Fri Jul 31 17:44:44 2009
@@ -27,31 +27,36 @@
* @author gbrown
*/
class ListSelection {
+ private ArrayList<Span> selectedRanges = new ArrayList<Span>();
+
/**
- * Determines the relative order of two ranges.
- *
- * @author gbrown
+ * Comparator that determines the relative order of two ranges' start
+ * values.
*/
- public static class IntersectionComparator implements Comparator<Span> {
- /**
- * Compares two range values. A range is considered less than or greater
- * than another range if and only if it is absolutely less than or
- * greater than the other range; if the ranges overlap in any way,
- * they are considered equal.
- *
- * @return
- * A positive value if <tt>range1</tt> is greater than <tt>range2</tt>;
- * a negative value if <tt>range1</tt> is less than <tt>range2</tt>; a
- * value of zero if <tt>range1</tt> intersects with <tt>range2</tt>.
- */
+ public static final Comparator<Span> START_COMPARATOR = new Comparator<Span>() {
public int compare(Span range1, Span range2) {
- return (range1.start > range2.end) ? 1 : (range2.start > range1.end) ? -1 : 0;
+ return (range1.start - range2.start);
}
- }
+ };
- private ArrayList<Span> selectedRanges = new ArrayList<Span>();
+ /**
+ * Comparator that determines the relative order of two ranges' end
+ * values.
+ */
+ public static final Comparator<Span> END_COMPARATOR = new Comparator<Span>() {
+ public int compare(Span range1, Span range2) {
+ return (range1.end - range2.end);
+ }
+ };
- public static final IntersectionComparator INTERSECTION_COMPARATOR = new IntersectionComparator();
+ /**
+ * Comparator that determines if two ranges intersect.
+ */
+ public static final Comparator<Span> INTERSECTION_COMPARATOR = new Comparator<Span>() {
+ public int compare(Span range1, Span range2) {
+ return (range1.start > range2.end) ? 1 : (range2.start > range1.end) ? -1 : 0;
+ }
+ };
/**
* Adds a range to the selection, merging and removing intersecting ranges
@@ -72,12 +77,59 @@
int n = selectedRanges.getLength();
if (n == 0) {
- // Nothing is currently selected
+ // The selection is currently empty; append the new range
selectedRanges.add(range);
added.add(range);
} else {
- // TODO Perform two binary searches to determine the endpoints
+ // Perform two binary searches to determine the endpoints
// of the intersection
+ int i = ArrayList.binarySearch(selectedRanges, range, START_COMPARATOR);
+ if (i <= 0) {
+ i = -(i + 1);
+ }
+
+ int j = ArrayList.binarySearch(selectedRanges, range, END_COMPARATOR);
+ if (j <= 0) {
+ j = -(j + 1);
+ }
+
+ // Merge the selection with the previous and next ranges, if necessary
+ if (i > 0) {
+ Span previousRange = selectedRanges.get(i - 1);
+ if (range.start == previousRange.end + 1) {
+ i--;
+ }
+ }
+
+ if (j < n) {
+ Span nextRange = selectedRanges.get(j);
+ if (range.end == nextRange.start - 1) {
+ j++;
+ }
+ }
+
+ if (i == n) {
+ // The new range starts after the last existing selection
+ // ends; append
+ selectedRanges.add(range);
+ added.add(range);
+ } else {
+ // TODO Add any gaps to the added list
+
+ // Remove any redundant ranges
+ if (i < j) {
+ selectedRanges.remove(i + 1, j - i - 1);
+ }
+
+ // Create a new range representing the union of the intersecting ranges
+ Span lowerRange = selectedRanges.get(i);
+ Span upperRange = selectedRanges.get(j);
+
+ range = new Span(Math.min(range.start, lowerRange.start),
+ Math.max(range.end, upperRange.end));
+
+ selectedRanges.update(i, range);
+ }
}
}
@@ -101,7 +153,21 @@
if (range.getLength() > 0
&& selectedRanges.getLength() > 0) {
- // TODO
+ // Perform two binary searches to determine the endpoints
+ // of the intersection
+ int i = ArrayList.binarySearch(selectedRanges, range, START_COMPARATOR);
+ if (i <= 0) {
+ i = -(i + 1);
+ }
+
+ int j = ArrayList.binarySearch(selectedRanges, range, END_COMPARATOR);
+ if (j <= 0) {
+ j = -(j + 1);
+ }
+
+ if (i == j) {
+
+ }
}
return removed;
@@ -133,8 +199,8 @@
* @param range
*
* @return
- * The index of the range, if it exists in the selection in its entirety;
- * <tt>-1</tt>, otherwise.
+ * The index of the range, if it exists in the selection; <tt>-1</tt>,
+ * otherwise.
*/
public int indexOf(Span range) {
assert (range != null);
@@ -158,7 +224,10 @@
* <tt>true</tt> if the index is selected; <tt>false</tt>, otherwise.
*/
public boolean containsIndex(int index) {
- return (indexOf(new Span(index, index)) != -1);
+ Span range = new Span(index, index);
+ int i = ArrayList.binarySearch(selectedRanges, range, INTERSECTION_COMPARATOR);
+
+ return (i >= 0);
}
/**
Modified: incubator/pivot/trunk/wtk/src/org/apache/pivot/wtk/ListView.java
URL: http://svn.apache.org/viewvc/incubator/pivot/trunk/wtk/src/org/apache/pivot/wtk/ListView.java?rev=799669&r1=799668&r2=799669&view=diff
==============================================================================
--- incubator/pivot/trunk/wtk/src/org/apache/pivot/wtk/ListView.java (original)
+++ incubator/pivot/trunk/wtk/src/org/apache/pivot/wtk/ListView.java Fri Jul 31 17:44:44 2009
@@ -538,7 +538,7 @@
*
* @param selectedRanges
*/
- public void setSelectedRanges(Sequence<Span> selectedRanges) {
+ public final void setSelectedRanges(Sequence<Span> selectedRanges) {
if (selectedRanges == null) {
throw new IllegalArgumentException("selectedRanges is null.");
}
Modified: incubator/pivot/trunk/wtk/src/org/apache/pivot/wtk/Sheet.java
URL: http://svn.apache.org/viewvc/incubator/pivot/trunk/wtk/src/org/apache/pivot/wtk/Sheet.java?rev=799669&r1=799668&r2=799669&view=diff
==============================================================================
--- incubator/pivot/trunk/wtk/src/org/apache/pivot/wtk/Sheet.java (original)
+++ incubator/pivot/trunk/wtk/src/org/apache/pivot/wtk/Sheet.java Fri Jul 31 17:44:44 2009
@@ -117,8 +117,8 @@
if (isOpen()) {
Component content = owner.getContent();
- if (content.isBlocked()) {
- throw new IllegalStateException("Owner content is already blocked.");
+ if (!content.isEnabled()) {
+ throw new IllegalStateException("Owner content is already disabled.");
}
content.setEnabled(false);
Modified: incubator/pivot/trunk/wtk/src/org/apache/pivot/wtk/TableView.java
URL: http://svn.apache.org/viewvc/incubator/pivot/trunk/wtk/src/org/apache/pivot/wtk/TableView.java?rev=799669&r1=799668&r2=799669&view=diff
==============================================================================
--- incubator/pivot/trunk/wtk/src/org/apache/pivot/wtk/TableView.java (original)
+++ incubator/pivot/trunk/wtk/src/org/apache/pivot/wtk/TableView.java Fri Jul 31 17:44:44 2009
@@ -1055,7 +1055,7 @@
*
* @see #setSelectedRanges(Sequence)
*/
- public void setSelectedRanges(String selectedRanges) {
+ public final void setSelectedRanges(String selectedRanges) {
if (selectedRanges == null) {
throw new IllegalArgumentException("selectedRanges is null.");
}
Modified: incubator/pivot/trunk/wtk/src/org/apache/pivot/wtk/Window.java
URL: http://svn.apache.org/viewvc/incubator/pivot/trunk/wtk/src/org/apache/pivot/wtk/Window.java?rev=799669&r1=799668&r2=799669&view=diff
==============================================================================
--- incubator/pivot/trunk/wtk/src/org/apache/pivot/wtk/Window.java (original)
+++ incubator/pivot/trunk/wtk/src/org/apache/pivot/wtk/Window.java Fri Jul 31 17:44:44 2009
@@ -899,8 +899,7 @@
* have a focus descendant, the focus is cleared.
*/
protected void restoreFocus() {
- assert(isShowing()
- && !isBlocked());
+ assert(isShowing());
if (focusDescendant != null) {
if (isAncestor(focusDescendant)) {
@@ -911,7 +910,7 @@
}
if (focusDescendant == null) {
- Component.clearFocus(true);
+ Component.clearFocus(false);
}
}
@@ -976,7 +975,7 @@
} else {
// Activate the window
if (window.isShowing()
- && !window.isBlocked()
+ && window.isEnabled()
&& !window.isAuxilliary()) {
setActiveWindow(window);
window.restoreFocus();
Modified: incubator/pivot/trunk/wtk/src/org/apache/pivot/wtk/content/NumericSpinnerData.java
URL: http://svn.apache.org/viewvc/incubator/pivot/trunk/wtk/src/org/apache/pivot/wtk/content/NumericSpinnerData.java?rev=799669&r1=799668&r2=799669&view=diff
==============================================================================
--- incubator/pivot/trunk/wtk/src/org/apache/pivot/wtk/content/NumericSpinnerData.java (original)
+++ incubator/pivot/trunk/wtk/src/org/apache/pivot/wtk/content/NumericSpinnerData.java Fri Jul 31 17:44:44 2009
@@ -33,21 +33,8 @@
* the list).
* <p>
* The iterator returned by this class's <tt>iterator</tt> method is
- * <i>fail-fast</i>: if the data is structurally modified at any time after
- * the iterator is created, in any way except through the iterator's own
- * remove or add methods, the iterator will throw a
- * <tt>ConcurrentModificationException</tt>. Thus, in the face of concurrent
- * modification, the iterator fails quickly and cleanly, rather than risking
- * arbitrary, non-deterministic behavior at an undetermined time in the
- * future.
- * <p>
- * Note that the fail-fast behavior of an iterator cannot be guaranteed
- * as it is, generally speaking, impossible to make any hard guarantees in the
- * presence of unsynchronized concurrent modification. Fail-fast iterators
- * throw <tt>ConcurrentModificationException</tt> on a best-effort basis.
- * Therefore, it would be wrong to write a program that depended on this
- * exception for its correctness: <i>the fail-fast behavior of iterators
- * should be used only to detect bugs.</i>
+ * <i>fail-fast</i>: if the bounds of the enclosing spinner data change during
+ * iteration, a <tt>ConcurrentModificationException</tt> will be thrown.
*
* @author tvolkert
*/