Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(107)

Side by Side Diff: third_party/WebKit/WebCore/platform/chromium/PopupMenuChromium.cpp

Issue 18466: Make the selection loop with arrow keys in the autocomplete popup (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 11 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « third_party/WebKit/WebCore/platform/chromium/PopupMenuChromium.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright (c) 2008, 2009, Google Inc. All rights reserved. 2 * Copyright (c) 2008, 2009, Google Inc. All rights reserved.
3 * 3 *
4 * Redistribution and use in source and binary forms, with or without 4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are 5 * modification, are permitted provided that the following conditions are
6 * met: 6 * met:
7 * 7 *
8 * * Redistributions of source code must retain the above copyright 8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer. 9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above 10 * * Redistributions in binary form must reproduce the above
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
82 virtual bool handleKeyEvent(const PlatformKeyboardEvent&); 82 virtual bool handleKeyEvent(const PlatformKeyboardEvent&);
83 83
84 // ScrollView 84 // ScrollView
85 virtual HostWindow* hostWindow() const; 85 virtual HostWindow* hostWindow() const;
86 86
87 // Widget 87 // Widget
88 virtual void invalidateRect(const IntRect&); 88 virtual void invalidateRect(const IntRect&);
89 89
90 // PopupListBox methods 90 // PopupListBox methods
91 91
92 // Show the popup 92 // Shows the popup
93 void showPopup(); 93 void showPopup();
94 94
95 // Hide the popup. Do not call this directly: use client->hidePopup(). 95 // Hides the popup. Do not call this directly: use client->hidePopup().
96 void hidePopup(); 96 void hidePopup();
97 97
98 // Update our internal list to match the client. 98 // Updates our internal list to match the client.
99 void updateFromElement(); 99 void updateFromElement();
100 100
101 // Free any allocated resources used in a particular popup session. 101 // Frees any allocated resources used in a particular popup session.
102 void clear(); 102 void clear();
103 103
104 // Set the index of the option that is displayed in the <select> widget in t he page 104 // Sets the index of the option that is displayed in the <select> widget in the page
105 void setOriginalIndex(int index); 105 void setOriginalIndex(int index);
106 106
107 // Get the index of the item that the user is currently moused over or has s elected with 107 // Gets the index of the item that the user is currently moused over or has selected with
108 // the keyboard. This is not the same as the original index, since the user has not yet 108 // the keyboard. This is not the same as the original index, since the user has not yet
109 // accepted this input. 109 // accepted this input.
110 int selectedIndex() const { return m_selectedIndex; } 110 int selectedIndex() const { return m_selectedIndex; }
111 111
112 // Move selection down/up the given number of items, scrolling if necessary. 112 // Moves selection down/up the given number of items, scrolling if necessary .
113 // Positive is down. The resulting index will be clamped to the range 113 // Positive is down. The resulting index will be clamped to the range
114 // [0, numItems), and non-option items will be skipped. 114 // [0, numItems), and non-option items will be skipped.
115 void adjustSelectedIndex(int delta); 115 void adjustSelectedIndex(int delta);
116 116
117 // Returns the number of items in the list. 117 // Returns the number of items in the list.
118 int numItems() const { return static_cast<int>(m_items.size()); } 118 int numItems() const { return static_cast<int>(m_items.size()); }
119 119
120 void setBaseWidth(int width) { m_baseWidth = width; } 120 void setBaseWidth(int width) { m_baseWidth = width; }
121 121
122 // Compute size of widget and children. 122 // Computes the size of widget and children.
123 void layout(); 123 void layout();
124 124
125 // Returns whether the popup wants to process events for the passed key. 125 // Returns whether the popup wants to process events for the passed key.
126 bool isInterestedInEventForKey(int keyCode); 126 bool isInterestedInEventForKey(int keyCode);
127 127
128 // Sets whether the PopupMenuClient should be told to change its text when a 128 // Sets whether the PopupMenuClient should be told to change its text when a
129 // new item is selected (by using the arrow keys). Default is true. 129 // new item is selected (by using the arrow keys). Default is true.
130 void setTextOnIndexChange(bool value) { m_setTextOnIndexChange = value; } 130 void setTextOnIndexChange(bool value) { m_setTextOnIndexChange = value; }
131 131
132 // Sets whether we should accept the selected index when the popup is 132 // Sets whether we should accept the selected index when the popup is
133 // abandonned. 133 // abandonned.
134 void setAcceptOnAbandon(bool value) { m_shouldAcceptOnAbandon = value; } 134 void setAcceptOnAbandon(bool value) { m_shouldAcceptOnAbandon = value; }
135 135
136 // Sets whether pressing the down/up arrow when the last/first row is
137 // selected clears the selection on the first key press and then selects the
138 // first/last row on the next key press. If false, the selected row stays
139 // the last/first row.
140 void setLoopSelectionNavigation(bool value) { m_loopSelectionNavigation = va lue; }
141
136 private: 142 private:
137 friend class PopupContainer; 143 friend class PopupContainer;
138 friend class RefCounted<PopupListBox>; 144 friend class RefCounted<PopupListBox>;
139 145
140 // A type of List Item 146 // A type of List Item
141 enum ListItemType { 147 enum ListItemType {
142 TypeOption, 148 TypeOption,
143 TypeGroup, 149 TypeGroup,
144 TypeSeparator 150 TypeSeparator
145 }; 151 };
(...skipping 10 matching lines...) Expand all
156 PopupListBox(PopupMenuClient* client) 162 PopupListBox(PopupMenuClient* client)
157 : m_originalIndex(0) 163 : m_originalIndex(0)
158 , m_selectedIndex(0) 164 , m_selectedIndex(0)
159 , m_shouldAcceptOnAbandon(true) 165 , m_shouldAcceptOnAbandon(true)
160 , m_willAcceptOnAbandon(false) 166 , m_willAcceptOnAbandon(false)
161 , m_visibleRows(0) 167 , m_visibleRows(0)
162 , m_popupClient(client) 168 , m_popupClient(client)
163 , m_repeatingChar(0) 169 , m_repeatingChar(0)
164 , m_lastCharTime(0) 170 , m_lastCharTime(0)
165 , m_setTextOnIndexChange(true) 171 , m_setTextOnIndexChange(true)
172 , m_loopSelectionNavigation(false)
166 { 173 {
167 setScrollbarModes(ScrollbarAlwaysOff, ScrollbarAlwaysOff); 174 setScrollbarModes(ScrollbarAlwaysOff, ScrollbarAlwaysOff);
168 } 175 }
169 176
170 ~PopupListBox() 177 ~PopupListBox()
171 { 178 {
172 clear(); 179 clear();
173 } 180 }
174 181
175 void disconnectClient() { m_popupClient = 0; } 182 void disconnectClient() { m_popupClient = 0; }
176 183
177 // Closes the popup 184 // Closes the popup
178 void abandon(); 185 void abandon();
179 // Select an index in the list, scrolling if necessary. 186 // Select an index in the list, scrolling if necessary.
180 void selectIndex(int index); 187 void selectIndex(int index);
181 // Accepts the selected index as the value to be displayed in the <select> w idget on 188 // Accepts the selected index as the value to be displayed in the <select> w idget on
182 // the web page, and closes the popup. 189 // the web page, and closes the popup.
183 void acceptIndex(int index); 190 void acceptIndex(int index);
184 191
185 // Returns true if the selection can be changed to index. 192 // Returns true if the selection can be changed to index.
186 // Disabled items, or labels cannot be selected. 193 // Disabled items, or labels cannot be selected.
187 bool isSelectableItem(int index); 194 bool isSelectableItem(int index);
188 195
196 // Clears the selection (so no row appears selected).
197 void clearSelection();
198
189 // Scrolls to reveal the given index. 199 // Scrolls to reveal the given index.
190 void scrollToRevealRow(int index); 200 void scrollToRevealRow(int index);
191 void scrollToRevealSelection() { scrollToRevealRow(m_selectedIndex); } 201 void scrollToRevealSelection() { scrollToRevealRow(m_selectedIndex); }
192 202
193 // Invalidates the row at the given index. 203 // Invalidates the row at the given index.
194 void invalidateRow(int index); 204 void invalidateRow(int index);
195 205
196 // Gets the height of a row. 206 // Gets the height of a row.
197 int getRowHeight(int index); 207 int getRowHeight(int index);
198 // Get the bounds of a row. 208 // Get the bounds of a row.
199 IntRect getRowBounds(int index); 209 IntRect getRowBounds(int index);
200 210
201 // Converts a point to an index of the row the point is over 211 // Converts a point to an index of the row the point is over
202 int pointToRowIndex(const IntPoint&); 212 int pointToRowIndex(const IntPoint&);
203 213
204 // Paint an individual row 214 // Paint an individual row
205 void paintRow(GraphicsContext*, const IntRect&, int rowIndex); 215 void paintRow(GraphicsContext*, const IntRect&, int rowIndex);
206 216
207 // Test if the given point is within the bounds of the popup window. 217 // Test if the given point is within the bounds of the popup window.
208 bool isPointInBounds(const IntPoint&); 218 bool isPointInBounds(const IntPoint&);
209 219
210 // Called when the user presses a text key. Does a prefix-search of the ite ms. 220 // Called when the user presses a text key. Does a prefix-search of the ite ms.
211 void typeAheadFind(const PlatformKeyboardEvent&); 221 void typeAheadFind(const PlatformKeyboardEvent&);
212 222
213 // Returns the font to use for the given row 223 // Returns the font to use for the given row
214 Font getRowFont(int index); 224 Font getRowFont(int index);
215 225
226 // Moves the selection down/up one item, taking care of looping back to the
227 // first/last element if m_loopSelectionNavigation is true.
228 void selectPreviousRow();
229 void selectNextRow();
230
231
216 // This is the index of the item marked as "selected" - i.e. displayed in th e widget on the 232 // This is the index of the item marked as "selected" - i.e. displayed in th e widget on the
217 // page. 233 // page.
218 int m_originalIndex; 234 int m_originalIndex;
219 235
220 // This is the index of the item that the user is hovered over or has select ed using the 236 // This is the index of the item that the user is hovered over or has select ed using the
221 // keyboard in the list. They have not confirmed this selection by clicking or pressing 237 // keyboard in the list. They have not confirmed this selection by clicking or pressing
222 // enter yet however. 238 // enter yet however.
223 int m_selectedIndex; 239 int m_selectedIndex;
224 240
225 // Whether we should accept the selectedIndex as chosen when the popup is 241 // Whether we should accept the selectedIndex as chosen when the popup is
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
257 // The string the user has typed so far into the popup. Used for typeAheadFi nd. 273 // The string the user has typed so far into the popup. Used for typeAheadFi nd.
258 String m_typedString; 274 String m_typedString;
259 275
260 // The char the user has hit repeatedly. Used for typeAheadFind. 276 // The char the user has hit repeatedly. Used for typeAheadFind.
261 UChar m_repeatingChar; 277 UChar m_repeatingChar;
262 278
263 // The last time the user hit a key. Used for typeAheadFind. 279 // The last time the user hit a key. Used for typeAheadFind.
264 TimeStamp m_lastCharTime; 280 TimeStamp m_lastCharTime;
265 281
266 bool m_setTextOnIndexChange; 282 bool m_setTextOnIndexChange;
283
284 bool m_loopSelectionNavigation;
267 }; 285 };
268 286
269 static PlatformMouseEvent constructRelativeMouseEvent(const PlatformMouseEvent& e, 287 static PlatformMouseEvent constructRelativeMouseEvent(const PlatformMouseEvent& e,
270 FramelessScrollView* paren t, 288 FramelessScrollView* paren t,
271 FramelessScrollView* child ) 289 FramelessScrollView* child )
272 { 290 {
273 IntPoint pos = parent->convertSelfToChild(child, e.pos()); 291 IntPoint pos = parent->convertSelfToChild(child, e.pos());
274 292
275 // FIXME: This is a horrible hack since PlatformMouseEvent has no setters fo r x/y. 293 // FIXME: This is a horrible hack since PlatformMouseEvent has no setters fo r x/y.
276 PlatformMouseEvent relativeEvent = e; 294 PlatformMouseEvent relativeEvent = e;
(...skipping 204 matching lines...) Expand 10 before | Expand all | Expand 10 after
481 void PopupContainer::setTextOnIndexChange(bool value) 499 void PopupContainer::setTextOnIndexChange(bool value)
482 { 500 {
483 listBox()->setTextOnIndexChange(value); 501 listBox()->setTextOnIndexChange(value);
484 } 502 }
485 503
486 void PopupContainer::setAcceptOnAbandon(bool value) 504 void PopupContainer::setAcceptOnAbandon(bool value)
487 { 505 {
488 listBox()->setAcceptOnAbandon(value); 506 listBox()->setAcceptOnAbandon(value);
489 } 507 }
490 508
509 void PopupContainer::setLoopSelectionNavigation(bool value) {
510 listBox()->setLoopSelectionNavigation(value);
511 }
512
491 void PopupContainer::refresh() 513 void PopupContainer::refresh()
492 { 514 {
493 listBox()->updateFromElement(); 515 listBox()->updateFromElement();
494 layout(); 516 layout();
495 } 517 }
496 518
497 /////////////////////////////////////////////////////////////////////////////// 519 ///////////////////////////////////////////////////////////////////////////////
498 // PopupListBox implementation 520 // PopupListBox implementation
499 521
500 bool PopupListBox::handleMouseDownEvent(const PlatformMouseEvent& event) 522 bool PopupListBox::handleMouseDownEvent(const PlatformMouseEvent& event)
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after
592 return true; 614 return true;
593 615
594 if (numItems() == 0 && event.windowsVirtualKeyCode() != VKEY_ESCAPE) 616 if (numItems() == 0 && event.windowsVirtualKeyCode() != VKEY_ESCAPE)
595 return true; 617 return true;
596 618
597 switch (event.windowsVirtualKeyCode()) { 619 switch (event.windowsVirtualKeyCode()) {
598 case VKEY_ESCAPE: 620 case VKEY_ESCAPE:
599 abandon(); // may delete this 621 abandon(); // may delete this
600 return true; 622 return true;
601 case VKEY_RETURN: 623 case VKEY_RETURN:
624 if (m_selectedIndex == -1) {
625 m_popupClient->hidePopup();
626 // 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
627 return false;
628 }
602 acceptIndex(m_selectedIndex); // may delete this 629 acceptIndex(m_selectedIndex); // may delete this
603 return true; 630 return true;
604 case VKEY_UP: 631 case VKEY_UP:
605 adjustSelectedIndex(-1); 632 selectPreviousRow();
606 break; 633 break;
607 case VKEY_DOWN: 634 case VKEY_DOWN:
608 adjustSelectedIndex(1); 635 selectNextRow();
609 break; 636 break;
610 case VKEY_PRIOR: 637 case VKEY_PRIOR:
611 adjustSelectedIndex(-m_visibleRows); 638 adjustSelectedIndex(-m_visibleRows);
612 break; 639 break;
613 case VKEY_NEXT: 640 case VKEY_NEXT:
614 adjustSelectedIndex(m_visibleRows); 641 adjustSelectedIndex(m_visibleRows);
615 break; 642 break;
616 case VKEY_HOME: 643 case VKEY_HOME:
617 adjustSelectedIndex(-m_selectedIndex); 644 adjustSelectedIndex(-m_selectedIndex);
618 break; 645 break;
(...skipping 312 matching lines...) Expand 10 before | Expand all | Expand 10 after
931 } else if (rowRect.bottom() > scrollY() + visibleHeight()) { 958 } else if (rowRect.bottom() > scrollY() + visibleHeight()) {
932 // Row is below current scroll position, scroll down. 959 // Row is below current scroll position, scroll down.
933 ScrollView::setScrollPosition(IntPoint(0, rowRect.bottom() - visibleHeig ht())); 960 ScrollView::setScrollPosition(IntPoint(0, rowRect.bottom() - visibleHeig ht()));
934 } 961 }
935 } 962 }
936 963
937 bool PopupListBox::isSelectableItem(int index) { 964 bool PopupListBox::isSelectableItem(int index) {
938 return m_items[index]->type == TypeOption && m_popupClient->itemIsEnabled(in dex); 965 return m_items[index]->type == TypeOption && m_popupClient->itemIsEnabled(in dex);
939 } 966 }
940 967
968 void PopupListBox::clearSelection() {
969 if (m_selectedIndex != -1) {
970 invalidateRow(m_selectedIndex);
971 m_selectedIndex = -1;
972 }
973 }
974
975 void PopupListBox::selectNextRow() {
976 if (!m_loopSelectionNavigation || m_selectedIndex != numItems() - 1) {
977 adjustSelectedIndex(1);
978 return;
979 }
980
981 // We are moving past the last item, no row should be selected.
982 clearSelection();
983 }
984
985 void PopupListBox::selectPreviousRow() {
986 if (!m_loopSelectionNavigation || m_selectedIndex > 0) {
987 adjustSelectedIndex(-1);
988 return;
989 }
990
991 if (m_selectedIndex == 0) {
992 // We are moving past the first item, clear the selection.
993 clearSelection();
994 return;
995 }
996
997 // No row are selected, jump to the last item.
998 selectIndex(numItems() - 1);
999 scrollToRevealSelection();
1000 }
1001
941 void PopupListBox::adjustSelectedIndex(int delta) 1002 void PopupListBox::adjustSelectedIndex(int delta)
942 { 1003 {
943 int targetIndex = m_selectedIndex + delta; 1004 int targetIndex = m_selectedIndex + delta;
944 targetIndex = min(max(targetIndex, 0), numItems() - 1); 1005 targetIndex = min(max(targetIndex, 0), numItems() - 1);
945 if (!isSelectableItem(targetIndex)) { 1006 if (!isSelectableItem(targetIndex)) {
946 // We didn't land on an option. Try to find one. 1007 // We didn't land on an option. Try to find one.
947 // We try to select the closest index to target, prioritizing any in 1008 // We try to select the closest index to target, prioritizing any in
948 // the range [current, target]. 1009 // the range [current, target].
949 1010
950 int dir = delta > 0 ? 1 : -1; 1011 int dir = delta > 0 ? 1 : -1;
(...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after
1110 { 1171 {
1111 p.popup->listBox()->updateFromElement(); 1172 p.popup->listBox()->updateFromElement();
1112 } 1173 }
1113 1174
1114 bool PopupMenu::itemWritingDirectionIsNatural() 1175 bool PopupMenu::itemWritingDirectionIsNatural()
1115 { 1176 {
1116 return false; 1177 return false;
1117 } 1178 }
1118 1179
1119 } // namespace WebCore 1180 } // namespace WebCore
OLDNEW
« no previous file with comments | « third_party/WebKit/WebCore/platform/chromium/PopupMenuChromium.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698