Index: third_party/WebKit/WebCore/platform/chromium/PopupMenuChromium.cpp |
=================================================================== |
--- third_party/WebKit/WebCore/platform/chromium/PopupMenuChromium.cpp (revision 8275) |
+++ third_party/WebKit/WebCore/platform/chromium/PopupMenuChromium.cpp (working copy) |
@@ -89,27 +89,27 @@ |
// PopupListBox methods |
- // Show the popup |
+ // Shows the popup |
void showPopup(); |
- // Hide the popup. Do not call this directly: use client->hidePopup(). |
+ // Hides the popup. Do not call this directly: use client->hidePopup(). |
void hidePopup(); |
- // Update our internal list to match the client. |
+ // Updates our internal list to match the client. |
void updateFromElement(); |
- // Free any allocated resources used in a particular popup session. |
+ // Frees any allocated resources used in a particular popup session. |
void clear(); |
- // Set the index of the option that is displayed in the <select> widget in the page |
+ // Sets the index of the option that is displayed in the <select> widget in the page |
void setOriginalIndex(int index); |
- // Get the index of the item that the user is currently moused over or has selected with |
+ // Gets the index of the item that the user is currently moused over or has selected with |
// the keyboard. This is not the same as the original index, since the user has not yet |
// accepted this input. |
int selectedIndex() const { return m_selectedIndex; } |
- // Move selection down/up the given number of items, scrolling if necessary. |
+ // Moves selection down/up the given number of items, scrolling if necessary. |
// Positive is down. The resulting index will be clamped to the range |
// [0, numItems), and non-option items will be skipped. |
void adjustSelectedIndex(int delta); |
@@ -119,7 +119,7 @@ |
void setBaseWidth(int width) { m_baseWidth = width; } |
- // Compute size of widget and children. |
+ // Computes the size of widget and children. |
void layout(); |
// Returns whether the popup wants to process events for the passed key. |
@@ -133,6 +133,12 @@ |
// abandonned. |
void setAcceptOnAbandon(bool value) { m_shouldAcceptOnAbandon = value; } |
+ // Sets whether pressing the down/up arrow when the last/first row is |
+ // selected clears the selection on the first key press and then selects the |
+ // first/last row on the next key press. If false, the selected row stays |
+ // the last/first row. |
+ void setLoopSelectionNavigation(bool value) { m_loopSelectionNavigation = value; } |
+ |
private: |
friend class PopupContainer; |
friend class RefCounted<PopupListBox>; |
@@ -163,6 +169,7 @@ |
, m_repeatingChar(0) |
, m_lastCharTime(0) |
, m_setTextOnIndexChange(true) |
+ , m_loopSelectionNavigation(false) |
{ |
setScrollbarModes(ScrollbarAlwaysOff, ScrollbarAlwaysOff); |
} |
@@ -186,6 +193,9 @@ |
// Disabled items, or labels cannot be selected. |
bool isSelectableItem(int index); |
+ // Clears the selection (so no row appears selected). |
+ void clearSelection(); |
+ |
// Scrolls to reveal the given index. |
void scrollToRevealRow(int index); |
void scrollToRevealSelection() { scrollToRevealRow(m_selectedIndex); } |
@@ -213,6 +223,12 @@ |
// Returns the font to use for the given row |
Font getRowFont(int index); |
+ // Moves the selection down/up one item, taking care of looping back to the |
+ // first/last element if m_loopSelectionNavigation is true. |
+ void selectPreviousRow(); |
+ void selectNextRow(); |
+ |
+ |
// This is the index of the item marked as "selected" - i.e. displayed in the widget on the |
// page. |
int m_originalIndex; |
@@ -264,6 +280,8 @@ |
TimeStamp m_lastCharTime; |
bool m_setTextOnIndexChange; |
+ |
+ bool m_loopSelectionNavigation; |
}; |
static PlatformMouseEvent constructRelativeMouseEvent(const PlatformMouseEvent& e, |
@@ -488,6 +506,10 @@ |
listBox()->setAcceptOnAbandon(value); |
} |
+void PopupContainer::setLoopSelectionNavigation(bool value) { |
+ listBox()->setLoopSelectionNavigation(value); |
+} |
+ |
void PopupContainer::refresh() |
{ |
listBox()->updateFromElement(); |
@@ -599,13 +621,18 @@ |
abandon(); // may delete this |
return true; |
case VKEY_RETURN: |
+ if (m_selectedIndex == -1) { |
+ m_popupClient->hidePopup(); |
+ // Don't eat the enter if nothing is selected. |
Matt Perry
2009/01/21 22:38:09
Seems strange to me that the enter would propagate
|
+ return false; |
+ } |
acceptIndex(m_selectedIndex); // may delete this |
return true; |
case VKEY_UP: |
- adjustSelectedIndex(-1); |
+ selectPreviousRow(); |
break; |
case VKEY_DOWN: |
- adjustSelectedIndex(1); |
+ selectNextRow(); |
break; |
case VKEY_PRIOR: |
adjustSelectedIndex(-m_visibleRows); |
@@ -938,6 +965,40 @@ |
return m_items[index]->type == TypeOption && m_popupClient->itemIsEnabled(index); |
} |
+void PopupListBox::clearSelection() { |
+ if (m_selectedIndex != -1) { |
+ invalidateRow(m_selectedIndex); |
+ m_selectedIndex = -1; |
+ } |
+} |
+ |
+void PopupListBox::selectNextRow() { |
+ if (!m_loopSelectionNavigation || m_selectedIndex != numItems() - 1) { |
+ adjustSelectedIndex(1); |
+ return; |
+ } |
+ |
+ // We are moving past the last item, no row should be selected. |
+ clearSelection(); |
+} |
+ |
+void PopupListBox::selectPreviousRow() { |
+ if (!m_loopSelectionNavigation || m_selectedIndex > 0) { |
+ adjustSelectedIndex(-1); |
+ return; |
+ } |
+ |
+ if (m_selectedIndex == 0) { |
+ // We are moving past the first item, clear the selection. |
+ clearSelection(); |
+ return; |
+ } |
+ |
+ // No row are selected, jump to the last item. |
+ selectIndex(numItems() - 1); |
+ scrollToRevealSelection(); |
+} |
+ |
void PopupListBox::adjustSelectedIndex(int delta) |
{ |
int targetIndex = m_selectedIndex + delta; |