| 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 |