Home | History | Annotate | Download | only in chromium
      1 /*
      2  * Copyright (c) 2008, 2009, Google Inc. All rights reserved.
      3  *
      4  * Redistribution and use in source and binary forms, with or without
      5  * modification, are permitted provided that the following conditions are
      6  * met:
      7  *
      8  *     * Redistributions of source code must retain the above copyright
      9  * notice, this list of conditions and the following disclaimer.
     10  *     * Redistributions in binary form must reproduce the above
     11  * copyright notice, this list of conditions and the following disclaimer
     12  * in the documentation and/or other materials provided with the
     13  * distribution.
     14  *     * Neither the name of Google Inc. nor the names of its
     15  * contributors may be used to endorse or promote products derived from
     16  * this software without specific prior written permission.
     17  *
     18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     19  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     20  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     21  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     22  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     23  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     24  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     25  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     26  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     28  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     29  */
     30 
     31 #ifndef PopupMenuChromium_h
     32 #define PopupMenuChromium_h
     33 
     34 #include "config.h"
     35 
     36 #include "FramelessScrollView.h"
     37 #include "IntRect.h"
     38 #include "PlatformString.h"
     39 #include "PopupMenu.h"
     40 #include "PopupMenuPrivate.h"
     41 #include "PopupMenuStyle.h"
     42 
     43 namespace WebCore {
     44 
     45 class ChromeClientChromium;
     46 class FrameView;
     47 class PopupListBox;
     48 class PopupMenuClient;
     49 
     50 // A container for the data for each menu item (e.g. represented by <option>
     51 // or <optgroup> in a <select> widget) and is used by PopupListBox.
     52 struct PopupItem {
     53     enum Type {
     54         TypeOption,
     55         TypeGroup,
     56         TypeSeparator
     57     };
     58 
     59     PopupItem(const String& label, Type type)
     60         : label(label)
     61         , type(type)
     62         , yOffset(0)
     63     {
     64     }
     65     String label;
     66     Type type;
     67     int yOffset; // y offset of this item, relative to the top of the popup.
     68     TextDirection textDirection;
     69     bool hasTextDirectionOverride;
     70     bool enabled;
     71 };
     72 
     73 // FIXME: Our FramelessScrollView classes should probably implement HostWindow!
     74 
     75 // The PopupContainer class holds a PopupListBox (see cpp file).  Its sole purpose is to be
     76 // able to draw a border around its child.  All its paint/event handling is
     77 // just forwarded to the child listBox (with the appropriate transforms).
     78 // NOTE: this class is exposed so it can be instantiated direcly for the
     79 // autofill popup.  We cannot use the Popup class directly in that case as the
     80 // autofill popup should not be focused when shown and we want to forward the
     81 // key events to it (through handleKeyEvent).
     82 
     83 struct PopupContainerSettings {
     84     // Whether the PopupMenuClient should be told to change its text when a
     85     // new item is selected by using the arrow keys.
     86     bool setTextOnIndexChange;
     87 
     88     // Whether the selection should be accepted when the popup menu is
     89     // closed (through ESC being pressed or the focus going away).
     90     // Note that when TAB is pressed, the selection is always accepted
     91     // regardless of this setting.
     92     bool acceptOnAbandon;
     93 
     94     // Whether we should move the selection to the first/last item when
     95     // the user presses down/up arrow keys and the last/first item is
     96     // selected.
     97     bool loopSelectionNavigation;
     98 
     99     // Whether we should restrict the width of the PopupListBox or not.
    100     // Autocomplete popups are restricted, combo-boxes (select tags) aren't.
    101     bool restrictWidthOfListBox;
    102 };
    103 
    104 class PopupContainer : public FramelessScrollView {
    105 public:
    106     enum PopupType {
    107         Select, // HTML select popup.
    108         Suggestion, // Autocomplete/autofill popup.
    109     };
    110 
    111     static PassRefPtr<PopupContainer> create(PopupMenuClient*, PopupType,
    112                                              const PopupContainerSettings&);
    113 
    114     // Whether a key event should be sent to this popup.
    115     virtual bool isInterestedInEventForKey(int keyCode);
    116 
    117     // FramelessScrollView
    118     virtual void paint(GraphicsContext*, const IntRect&);
    119     virtual void hide();
    120     virtual bool handleMouseDownEvent(const PlatformMouseEvent&);
    121     virtual bool handleMouseMoveEvent(const PlatformMouseEvent&);
    122     virtual bool handleMouseReleaseEvent(const PlatformMouseEvent&);
    123     virtual bool handleWheelEvent(const PlatformWheelEvent&);
    124     virtual bool handleKeyEvent(const PlatformKeyboardEvent&);
    125 
    126     // PopupContainer methods
    127 
    128     // Show the popup
    129     void showPopup(FrameView*);
    130 
    131     // Show the popup in the specified rect for the specified frame.
    132     // Note: this code was somehow arbitrarily factored-out of the Popup class
    133     // so WebViewImpl can create a PopupContainer. This method is used for
    134     // displaying auto complete popup menus on Mac Chromium, and for all
    135     // popups on other platforms.
    136     void showInRect(const IntRect&, FrameView*, int index);
    137 
    138     // Hides the popup.
    139     void hidePopup();
    140 
    141     // The popup was hidden.
    142     void notifyPopupHidden();
    143 
    144     // Compute size of widget and children. Return right offset for RTL.
    145     int layoutAndGetRightOffset();
    146 
    147     PopupListBox* listBox() const { return m_listBox.get(); }
    148 
    149     // Gets the index of the item that the user is currently moused-over or
    150     // has selected with the keyboard up/down arrows.
    151     int selectedIndex() const;
    152 
    153     // Refresh the popup values from the PopupMenuClient.
    154     void refresh(const IntRect& targetControlRect);
    155 
    156     // The menu per-item data.
    157     const WTF::Vector<PopupItem*>& popupData() const;
    158 
    159     // The height of a row in the menu.
    160     int menuItemHeight() const;
    161 
    162     // The size of the font being used.
    163     int menuItemFontSize() const;
    164 
    165     // The style of the menu being used.
    166     PopupMenuStyle menuStyle() const;
    167 
    168     PopupType popupType() const { return m_popupType; }
    169 
    170 private:
    171     friend class WTF::RefCounted<PopupContainer>;
    172 
    173     PopupContainer(PopupMenuClient*, PopupType popupType, const PopupContainerSettings&);
    174     ~PopupContainer();
    175 
    176     // Paint the border.
    177     void paintBorder(GraphicsContext*, const IntRect&);
    178 
    179     // Layout and calculate popup widget size and location and returns it as IntRect.
    180     IntRect layoutAndCalculateWidgetRect(int targetControlHeight, const IntPoint& popupInitialCoordinate);
    181 
    182     // Returns the ChromeClient of the page this popup is associated with.
    183     ChromeClientChromium* chromeClientChromium();
    184 
    185     RefPtr<PopupListBox> m_listBox;
    186     RefPtr<FrameView> m_frameView;
    187 
    188     PopupContainerSettings m_settings;
    189     PopupType m_popupType;
    190     // Whether the popup is currently open.
    191     bool m_popupOpen;
    192 };
    193 
    194 class PopupMenuChromium : public PopupMenu {
    195 public:
    196     PopupMenuChromium(PopupMenuClient*);
    197     ~PopupMenuChromium();
    198 
    199     virtual void show(const IntRect&, FrameView*, int index);
    200     virtual void hide();
    201     virtual void updateFromElement();
    202     virtual void disconnectClient();
    203 
    204 private:
    205     PopupMenuClient* client() const { return m_popupClient; }
    206 
    207     PopupMenuClient* m_popupClient;
    208     PopupMenuPrivate p;
    209 };
    210 
    211 } // namespace WebCore
    212 
    213 #endif
    214