OLD | NEW |
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 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
75 true, // focusOnShow | 75 true, // focusOnShow |
76 true, // setTextOnIndexChange | 76 true, // setTextOnIndexChange |
77 true, // acceptOnAbandon | 77 true, // acceptOnAbandon |
78 false // loopSelectionNavigation | 78 false // loopSelectionNavigation |
79 }; | 79 }; |
80 | 80 |
81 // This class uses WebCore code to paint and handle events for a drop-down list | 81 // This class uses WebCore code to paint and handle events for a drop-down list |
82 // box ("combobox" on Windows). | 82 // box ("combobox" on Windows). |
83 class PopupListBox : public FramelessScrollView, public RefCounted<PopupListBox>
{ | 83 class PopupListBox : public FramelessScrollView, public RefCounted<PopupListBox>
{ |
84 public: | 84 public: |
| 85 static PassRefPtr<PopupListBox> create(PopupMenuClient* client, const PopupC
ontainerSettings& settings) |
| 86 { |
| 87 return adoptRef(new PopupListBox(client, settings)); |
| 88 } |
| 89 |
85 // FramelessScrollView | 90 // FramelessScrollView |
86 virtual void paint(GraphicsContext*, const IntRect&); | 91 virtual void paint(GraphicsContext*, const IntRect&); |
87 virtual bool handleMouseDownEvent(const PlatformMouseEvent&); | 92 virtual bool handleMouseDownEvent(const PlatformMouseEvent&); |
88 virtual bool handleMouseMoveEvent(const PlatformMouseEvent&); | 93 virtual bool handleMouseMoveEvent(const PlatformMouseEvent&); |
89 virtual bool handleMouseReleaseEvent(const PlatformMouseEvent&); | 94 virtual bool handleMouseReleaseEvent(const PlatformMouseEvent&); |
90 virtual bool handleWheelEvent(const PlatformWheelEvent&); | 95 virtual bool handleWheelEvent(const PlatformWheelEvent&); |
91 virtual bool handleKeyEvent(const PlatformKeyboardEvent&); | 96 virtual bool handleKeyEvent(const PlatformKeyboardEvent&); |
92 | 97 |
93 // ScrollView | 98 // ScrollView |
94 virtual HostWindow* hostWindow() const; | 99 virtual HostWindow* hostWindow() const; |
(...skipping 207 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
302 // PopupContainer implementation | 307 // PopupContainer implementation |
303 | 308 |
304 // static | 309 // static |
305 PassRefPtr<PopupContainer> PopupContainer::create(PopupMenuClient* client, | 310 PassRefPtr<PopupContainer> PopupContainer::create(PopupMenuClient* client, |
306 const PopupContainerSettings&
settings) | 311 const PopupContainerSettings&
settings) |
307 { | 312 { |
308 return adoptRef(new PopupContainer(client, settings)); | 313 return adoptRef(new PopupContainer(client, settings)); |
309 } | 314 } |
310 | 315 |
311 PopupContainer::PopupContainer(PopupMenuClient* client, const PopupContainerSett
ings& settings) | 316 PopupContainer::PopupContainer(PopupMenuClient* client, const PopupContainerSett
ings& settings) |
312 : m_listBox(new PopupListBox(client, settings)) | 317 : m_listBox(PopupListBox::create(client, settings)) |
313 , m_settings(settings) | 318 , m_settings(settings) |
314 { | 319 { |
315 // FrameViews are created with a refcount of 1 so it needs releasing after w
e | |
316 // assign it to a RefPtr. | |
317 m_listBox->deref(); | |
318 | |
319 setScrollbarModes(ScrollbarAlwaysOff, ScrollbarAlwaysOff); | 320 setScrollbarModes(ScrollbarAlwaysOff, ScrollbarAlwaysOff); |
320 } | 321 } |
321 | 322 |
322 PopupContainer::~PopupContainer() | 323 PopupContainer::~PopupContainer() |
323 { | 324 { |
324 if (m_listBox) | 325 if (m_listBox) |
325 removeChild(m_listBox.get()); | 326 removeChild(m_listBox.get()); |
326 } | 327 } |
327 | 328 |
328 void PopupContainer::showPopup(FrameView* view) | 329 void PopupContainer::showPopup(FrameView* view) |
(...skipping 11 matching lines...) Expand all Loading... |
340 // If the popup would extend past the bottom of the screen, open upwards | 341 // If the popup would extend past the bottom of the screen, open upwards |
341 // instead. | 342 // instead. |
342 FloatRect screen = screenRect(view); | 343 FloatRect screen = screenRect(view); |
343 IntRect widgetRect = chromeClient->windowToScreen(frameRect()); | 344 IntRect widgetRect = chromeClient->windowToScreen(frameRect()); |
344 if (widgetRect.bottom() > static_cast<int>(screen.bottom())) | 345 if (widgetRect.bottom() > static_cast<int>(screen.bottom())) |
345 widgetRect.move(0, -(widgetRect.height() + selectHeight)); | 346 widgetRect.move(0, -(widgetRect.height() + selectHeight)); |
346 | 347 |
347 chromeClient->popupOpened(this, widgetRect, m_settings.focusOnShow); | 348 chromeClient->popupOpened(this, widgetRect, m_settings.focusOnShow); |
348 } | 349 } |
349 | 350 |
350 // Must get called after we have a client and containingWindow. | 351 if (!m_listBox->parent()) |
351 addChild(m_listBox.get()); | 352 addChild(m_listBox.get()); |
352 | 353 |
353 // Enable scrollbars after the listbox is inserted into the hierarchy, so | 354 // Enable scrollbars after the listbox is inserted into the hierarchy, |
354 // it has a proper WidgetClient. | 355 // so it has a proper WidgetClient. |
355 m_listBox->setVerticalScrollbarMode(ScrollbarAuto); | 356 m_listBox->setVerticalScrollbarMode(ScrollbarAuto); |
356 | 357 |
357 m_listBox->scrollToRevealSelection(); | 358 m_listBox->scrollToRevealSelection(); |
358 | 359 |
359 invalidate(); | 360 invalidate(); |
360 } | 361 } |
361 | 362 |
362 void PopupContainer::hidePopup() | 363 void PopupContainer::hidePopup() |
363 { | 364 { |
364 invalidate(); | |
365 | |
366 m_listBox->disconnectClient(); | |
367 removeChild(m_listBox.get()); | |
368 m_listBox = 0; | |
369 | |
370 if (client()) | 365 if (client()) |
371 client()->popupClosed(this); | 366 client()->popupClosed(this); |
372 } | 367 } |
373 | 368 |
374 void PopupContainer::layout() | 369 void PopupContainer::layout() |
375 { | 370 { |
376 m_listBox->layout(); | 371 m_listBox->layout(); |
377 | 372 |
378 // Place the listbox within our border. | 373 // Place the listbox within our border. |
379 m_listBox->move(kBorderSize, kBorderSize); | 374 m_listBox->move(kBorderSize, kBorderSize); |
(...skipping 441 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
821 | 816 |
822 return itemFont; | 817 return itemFont; |
823 } | 818 } |
824 | 819 |
825 void PopupListBox::abandon() | 820 void PopupListBox::abandon() |
826 { | 821 { |
827 RefPtr<PopupListBox> keepAlive(this); | 822 RefPtr<PopupListBox> keepAlive(this); |
828 | 823 |
829 m_selectedIndex = m_originalIndex; | 824 m_selectedIndex = m_originalIndex; |
830 | 825 |
| 826 m_popupClient->hidePopup(); |
| 827 |
831 if (m_willAcceptOnAbandon) | 828 if (m_willAcceptOnAbandon) |
832 m_popupClient->valueChanged(m_selectedIndex); | 829 m_popupClient->valueChanged(m_selectedIndex); |
833 | |
834 // valueChanged may have torn down the popup! | |
835 if (m_popupClient) | |
836 m_popupClient->hidePopup(); | |
837 } | 830 } |
838 | 831 |
839 int PopupListBox::pointToRowIndex(const IntPoint& point) | 832 int PopupListBox::pointToRowIndex(const IntPoint& point) |
840 { | 833 { |
841 int y = scrollY() + point.y(); | 834 int y = scrollY() + point.y(); |
842 | 835 |
843 // FIXME: binary search if perf matters. | 836 // FIXME: binary search if perf matters. |
844 for (int i = 0; i < numItems(); ++i) { | 837 for (int i = 0; i < numItems(); ++i) { |
845 if (y < m_items[i]->y) | 838 if (y < m_items[i]->y) |
846 return i-1; | 839 return i-1; |
(...skipping 11 matching lines...) Expand all Loading... |
858 ASSERT(index >= -1 && index < numItems()); | 851 ASSERT(index >= -1 && index < numItems()); |
859 if (index == -1 && m_popupClient) { | 852 if (index == -1 && m_popupClient) { |
860 // Enter pressed with no selection, just close the popup. | 853 // Enter pressed with no selection, just close the popup. |
861 m_popupClient->hidePopup(); | 854 m_popupClient->hidePopup(); |
862 return; | 855 return; |
863 } | 856 } |
864 | 857 |
865 if (isSelectableItem(index)) { | 858 if (isSelectableItem(index)) { |
866 RefPtr<PopupListBox> keepAlive(this); | 859 RefPtr<PopupListBox> keepAlive(this); |
867 | 860 |
868 // Tell the <select> PopupMenuClient what index was selected, and hide o
urself. | 861 // Hide ourselves first since valueChanged may have numerous side-effect
s. |
| 862 m_popupClient->hidePopup(); |
| 863 |
| 864 // Tell the <select> PopupMenuClient what index was selected. |
869 m_popupClient->valueChanged(index); | 865 m_popupClient->valueChanged(index); |
870 | |
871 // valueChanged may have torn down the popup! | |
872 if (m_popupClient) | |
873 m_popupClient->hidePopup(); | |
874 } | 866 } |
875 } | 867 } |
876 | 868 |
877 void PopupListBox::selectIndex(int index) | 869 void PopupListBox::selectIndex(int index) |
878 { | 870 { |
879 ASSERT(index >= 0 && index < numItems()); | 871 ASSERT(index >= 0 && index < numItems()); |
880 | 872 |
881 if (index != m_selectedIndex && isSelectableItem(index)) { | 873 if (index != m_selectedIndex && isSelectableItem(index)) { |
882 invalidateRow(m_selectedIndex); | 874 invalidateRow(m_selectedIndex); |
883 m_selectedIndex = index; | 875 m_selectedIndex = index; |
(...skipping 239 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1123 { | 1115 { |
1124 } | 1116 } |
1125 | 1117 |
1126 PopupMenu::~PopupMenu() | 1118 PopupMenu::~PopupMenu() |
1127 { | 1119 { |
1128 hide(); | 1120 hide(); |
1129 } | 1121 } |
1130 | 1122 |
1131 void PopupMenu::show(const IntRect& r, FrameView* v, int index) | 1123 void PopupMenu::show(const IntRect& r, FrameView* v, int index) |
1132 { | 1124 { |
1133 p.popup = PopupContainer::create(client(), dropDownSettings); | 1125 if (!p.popup) |
| 1126 p.popup = PopupContainer::create(client(), dropDownSettings); |
1134 p.popup->show(r, v, index); | 1127 p.popup->show(r, v, index); |
1135 } | 1128 } |
1136 | 1129 |
1137 void PopupMenu::hide() | 1130 void PopupMenu::hide() |
1138 { | 1131 { |
1139 if (p.popup) { | 1132 if (p.popup) |
1140 p.popup->hidePopup(); | 1133 p.popup->hidePopup(); |
1141 p.popup = 0; | |
1142 } | |
1143 } | 1134 } |
1144 | 1135 |
1145 void PopupMenu::updateFromElement() | 1136 void PopupMenu::updateFromElement() |
1146 { | 1137 { |
1147 p.popup->listBox()->updateFromElement(); | 1138 p.popup->listBox()->updateFromElement(); |
1148 } | 1139 } |
1149 | 1140 |
1150 bool PopupMenu::itemWritingDirectionIsNatural() | 1141 bool PopupMenu::itemWritingDirectionIsNatural() |
1151 { | 1142 { |
1152 return false; | 1143 return false; |
1153 } | 1144 } |
1154 | 1145 |
1155 } // namespace WebCore | 1146 } // namespace WebCore |
OLD | NEW |