Home | History | Annotate | Download | only in combobox
      1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #ifndef UI_VIEWS_CONTROLS_COMBOBOX_COMBOBOX_H_
      6 #define UI_VIEWS_CONTROLS_COMBOBOX_COMBOBOX_H_
      7 
      8 #include <string>
      9 
     10 #include "base/time/time.h"
     11 #include "ui/base/models/combobox_model_observer.h"
     12 #include "ui/gfx/animation/animation_delegate.h"
     13 #include "ui/gfx/native_widget_types.h"
     14 #include "ui/views/controls/button/button.h"
     15 #include "ui/views/controls/menu/menu_delegate.h"
     16 #include "ui/views/controls/prefix_delegate.h"
     17 
     18 namespace gfx {
     19 class Font;
     20 class SlideAnimation;
     21 }
     22 
     23 namespace ui {
     24 class ComboboxModel;
     25 }
     26 
     27 namespace views {
     28 
     29 class ComboboxListener;
     30 class ComboboxMenuRunner;
     31 class CustomButton;
     32 class FocusableBorder;
     33 class MenuRunner;
     34 class MenuRunnerHandler;
     35 class Painter;
     36 class PrefixSelector;
     37 
     38 // A non-editable combobox (aka a drop-down list or selector).
     39 // Combobox has two distinct parts, the drop down arrow and the text. When the
     40 // user clicks on the text the drop down is either shown
     41 // (STYLE_SHOW_DROP_DOWN_ON_CLICK) or the listener is notified
     42 // (STYLE_NOTIFY_ON_CLICK).
     43 class VIEWS_EXPORT Combobox : public MenuDelegate,
     44                               public PrefixDelegate,
     45                               public ui::ComboboxModelObserver,
     46                               public ButtonListener {
     47  public:
     48   // The style of the combobox.
     49   enum Style {
     50     STYLE_SHOW_DROP_DOWN_ON_CLICK,
     51     STYLE_NOTIFY_ON_CLICK,
     52   };
     53 
     54   // The combobox's class name.
     55   static const char kViewClassName[];
     56 
     57   // |model| is not owned by the combobox.
     58   explicit Combobox(ui::ComboboxModel* model);
     59   virtual ~Combobox();
     60 
     61   static const gfx::Font& GetFont();
     62 
     63   // Sets the listener which will be called when a selection has been made.
     64   void set_listener(ComboboxListener* listener) { listener_ = listener; }
     65 
     66   void SetStyle(Style style);
     67 
     68   // Informs the combobox that its model changed.
     69   void ModelChanged();
     70 
     71   // Gets/Sets the selected index.
     72   int selected_index() const { return selected_index_; }
     73   void SetSelectedIndex(int index);
     74 
     75   // Looks for the first occurrence of |value| in |model()|. If found, selects
     76   // the found index and returns true. Otherwise simply noops and returns false.
     77   bool SelectValue(const base::string16& value);
     78 
     79   ui::ComboboxModel* model() const { return model_; }
     80 
     81   // Set the accessible name of the combobox.
     82   void SetAccessibleName(const string16& name);
     83 
     84   // Visually marks the combobox as having an invalid value selected.
     85   // When invalid, it paints with white text on a red background.
     86   // Callers are responsible for restoring validity with selection changes.
     87   void SetInvalid(bool invalid);
     88   bool invalid() const { return invalid_; }
     89 
     90   // Overridden from View:
     91   virtual gfx::Size GetPreferredSize() OVERRIDE;
     92   virtual const char* GetClassName() const OVERRIDE;
     93   virtual bool SkipDefaultKeyEventProcessing(const ui::KeyEvent& e) OVERRIDE;
     94   virtual bool OnKeyPressed(const ui::KeyEvent& e) OVERRIDE;
     95   virtual bool OnKeyReleased(const ui::KeyEvent& e) OVERRIDE;
     96   virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE;
     97   virtual void OnFocus() OVERRIDE;
     98   virtual void OnBlur() OVERRIDE;
     99   virtual void GetAccessibleState(ui::AccessibleViewState* state) OVERRIDE;
    100   virtual ui::TextInputClient* GetTextInputClient() OVERRIDE;
    101   virtual void Layout() OVERRIDE;
    102 
    103   // Overridden from MenuDelegate:
    104   virtual bool IsItemChecked(int id) const OVERRIDE;
    105   virtual bool IsCommandEnabled(int id) const OVERRIDE;
    106   virtual void ExecuteCommand(int id) OVERRIDE;
    107   virtual bool GetAccelerator(int id, ui::Accelerator* accelerator) OVERRIDE;
    108 
    109   // Overridden from PrefixDelegate:
    110   virtual int GetRowCount() OVERRIDE;
    111   virtual int GetSelectedRow() OVERRIDE;
    112   virtual void SetSelectedRow(int row) OVERRIDE;
    113   virtual string16 GetTextForRow(int row) OVERRIDE;
    114 
    115   // Overriden from ComboboxModelObserver:
    116   virtual void OnModelChanged() OVERRIDE;
    117 
    118   // Overriden from ButtonListener:
    119   virtual void ButtonPressed(Button* sender, const ui::Event& event) OVERRIDE;
    120 
    121  private:
    122   FRIEND_TEST_ALL_PREFIXES(ComboboxTest, Click);
    123   FRIEND_TEST_ALL_PREFIXES(ComboboxTest, NotifyOnClickWithMouse);
    124 
    125   // Updates the combobox's content from its model.
    126   void UpdateFromModel();
    127 
    128   // Updates the border according to the current state.
    129   void UpdateBorder();
    130 
    131   // Given bounds within our View, this helper mirrors the bounds if necessary.
    132   void AdjustBoundsForRTLUI(gfx::Rect* rect) const;
    133 
    134   // Draws the selected value of the drop down list
    135   void PaintText(gfx::Canvas* canvas);
    136 
    137   // Draws the button images.
    138   void PaintButtons(gfx::Canvas* canvas);
    139 
    140   // Show the drop down list
    141   void ShowDropDownMenu(ui::MenuSourceType source_type);
    142 
    143   // Called when the selection is changed by the user.
    144   void OnSelectionChanged();
    145 
    146   // Converts a menu command ID to a menu item index.
    147   int MenuCommandToIndex(int menu_command_id) const;
    148 
    149   int GetDisclosureArrowLeftPadding() const;
    150   int GetDisclosureArrowRightPadding() const;
    151 
    152   // Handles the clicking event.
    153   void HandleClickEvent();
    154 
    155   // Our model. Not owned.
    156   ui::ComboboxModel* model_;
    157 
    158   // The visual style of this combobox.
    159   Style style_;
    160 
    161   // Our listener. Not owned. Notified when the selected index change.
    162   ComboboxListener* listener_;
    163 
    164   // The current selected index; -1 and means no selection.
    165   int selected_index_;
    166 
    167   // True when the selection is visually denoted as invalid.
    168   bool invalid_;
    169 
    170   // The accessible name of this combobox.
    171   string16 accessible_name_;
    172 
    173   // A helper used to select entries by keyboard input.
    174   scoped_ptr<PrefixSelector> selector_;
    175 
    176   // The disclosure arrow next to the currently selected item from the list.
    177   const gfx::ImageSkia* disclosure_arrow_;
    178 
    179   // Responsible for showing the context menu.
    180   scoped_ptr<MenuRunner> dropdown_list_menu_runner_;
    181 
    182   // Is the drop down list showing
    183   bool dropdown_open_;
    184 
    185   // Like MenuButton, we use a time object in order to keep track of when the
    186   // combobox was closed. The time is used for simulating menu behavior; that
    187   // is, if the menu is shown and the button is pressed, we need to close the
    188   // menu. There is no clean way to get the second click event because the
    189   // menu is displayed using a modal loop and, unlike regular menus in Windows,
    190   // the button is not part of the displayed menu.
    191   base::Time closed_time_;
    192 
    193   // The maximum dimensions of the content in the dropdown
    194   gfx::Size content_size_;
    195 
    196   // The painters or images that are used when |style_| is STYLE_BUTTONS. The
    197   // first index means the state of unfocused or focused.
    198   // The images are owned by ResourceBundle.
    199   scoped_ptr<Painter> body_button_painters_[2][Button::STATE_COUNT];
    200   std::vector<const gfx::ImageSkia*>
    201       menu_button_images_[2][Button::STATE_COUNT];
    202 
    203   // The transparent buttons to handle events and render buttons. These are
    204   // placed on top of this combobox as child views, accept event and manage the
    205   // button states. These are not rendered but when |style_| is
    206   // STYLE_NOTIFY_ON_CLICK, a Combobox renders the button images according to
    207   // these button states.
    208   // The base View takes the ownerships of these as child views.
    209   CustomButton* text_button_;
    210   CustomButton* arrow_button_;
    211 
    212   DISALLOW_COPY_AND_ASSIGN(Combobox);
    213 };
    214 
    215 }  // namespace views
    216 
    217 #endif  // UI_VIEWS_CONTROLS_COMBOBOX_COMBOBOX_H_
    218