15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef UI_VIEWS_CONTROLS_SCROLLBAR_BASE_SCROLL_BAR_H_
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define UI_VIEWS_CONTROLS_SCROLLBAR_BASE_SCROLL_BAR_H_
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/gtest_prod_util.h"
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/views/animation/scroll_animator.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/views/context_menu_controller.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/views/controls/button/image_button.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/views/controls/menu/menu_delegate.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/views/controls/scrollbar/scroll_bar.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/views/repeat_controller.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace views {
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class BaseScrollBarThumb;
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class MenuRunner;
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)///////////////////////////////////////////////////////////////////////////////
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// BaseScrollBar
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)///////////////////////////////////////////////////////////////////////////////
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class VIEWS_EXPORT BaseScrollBar : public ScrollBar,
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   public ScrollDelegate,
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   public ContextMenuController,
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   public MenuDelegate {
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BaseScrollBar(bool horizontal, BaseScrollBarThumb* thumb);
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~BaseScrollBar();
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Get the bounds of the "track" area that the thumb is free to slide within.
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual gfx::Rect GetTrackBounds() const = 0;
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // An enumeration of different amounts of incremental scroll, representing
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // events sent from different parts of the UI/keyboard.
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  enum ScrollAmount {
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SCROLL_NONE = 0,
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SCROLL_START,
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SCROLL_END,
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SCROLL_PREV_LINE,
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SCROLL_NEXT_LINE,
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SCROLL_PREV_PAGE,
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SCROLL_NEXT_PAGE,
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Scroll the contents by the specified type (see ScrollAmount above).
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void ScrollByAmount(ScrollAmount amount);
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Scroll the contents to the appropriate position given the supplied
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // position of the thumb (thumb track coordinates). If |scroll_to_middle| is
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // true, then the conversion assumes |thumb_position| is in the middle of the
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // thumb rather than the top.
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void ScrollToThumbPosition(int thumb_position, bool scroll_to_middle);
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Scroll the contents by the specified offset (contents coordinates).
592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool ScrollByContentsOffset(int contents_offset);
602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Called when the thumb state has been changed from |old_state| to
622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // |new_state|.
632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void OnThumbStateChanged(CustomButton::ButtonState old_state,
642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                           CustomButton::ButtonState new_state);
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // View overrides:
67cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  virtual gfx::Size GetPreferredSize() const OVERRIDE = 0;
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void Layout() OVERRIDE = 0;
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual bool OnMousePressed(const ui::MouseEvent& event) OVERRIDE;
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void OnMouseReleased(const ui::MouseEvent& event) OVERRIDE;
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void OnMouseCaptureLost() OVERRIDE;
722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void OnMouseEntered(const ui::MouseEvent& event) OVERRIDE;
732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void OnMouseExited(const ui::MouseEvent& event) OVERRIDE;
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual bool OnKeyPressed(const ui::KeyEvent& event) OVERRIDE;
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual bool OnMouseWheel(const ui::MouseWheelEvent& event) OVERRIDE;
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // ui::EventHandler overrides:
782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void OnGestureEvent(ui::GestureEvent* event) OVERRIDE;
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // ScrollBar overrides:
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void Update(int viewport_size,
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      int content_size,
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      int contents_scroll_offset) OVERRIDE;
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual int GetLayoutSize() const OVERRIDE = 0;
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual int GetPosition() const OVERRIDE;
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // ScrollDelegate overrides:
882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual bool OnScroll(float dx, float dy) OVERRIDE;
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // ContextMenuController overrides:
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void ShowContextMenuForView(View* source,
927d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                                      const gfx::Point& point,
937d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                                      ui::MenuSourceType source_type) OVERRIDE;
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Menu::Delegate overrides:
965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  virtual base::string16 GetLabel(int id) const OVERRIDE;
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual bool IsCommandEnabled(int id) const OVERRIDE;
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void ExecuteCommand(int id) OVERRIDE;
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) protected:
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // View overrides:
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE = 0;
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BaseScrollBarThumb* GetThumb() const;
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CustomButton::ButtonState GetThumbTrackState() const;
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Wrapper functions that calls the controller. We need this since native
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // scrollbars wrap around a different scrollbar. When calling the controller
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // we need to pass in the appropriate scrollbar. For normal scrollbars it's
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the |this| scrollbar, for native scrollbars it's the native scrollbar used
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // to create this.
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void ScrollToPosition(int position);
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual int GetScrollIncrement(bool is_page, bool is_positive);
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
116868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  FRIEND_TEST_ALL_PREFIXES(NativeScrollBarTest, ScrollBarFitsToBottom);
117868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  int GetThumbSizeForTest();
118868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Changes to 'pushed' state and starts a timer to scroll repeatedly.
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void ProcessPressEvent(const ui::LocatedEvent& event);
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Sets state to |state| and stops the repeater.
1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void SetState(CustomButton::ButtonState state);
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Called when the mouse is pressed down in the track area.
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void TrackClicked();
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Responsible for scrolling the contents and also updating the UI to the
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // current value of the Scroll Offset.
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void ScrollContentsToOffset();
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Returns the size (width or height) of the track area of the ScrollBar.
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int GetTrackSize() const;
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Calculate the position of the thumb within the track based on the
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // specified scroll offset of the contents.
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int CalculateThumbPosition(int contents_scroll_offset) const;
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Calculates the current value of the contents offset (contents coordinates)
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // based on the current thumb position (thumb track coordinates). See
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // |ScrollToThumbPosition| for an explanation of |scroll_to_middle|.
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int CalculateContentsOffset(int thumb_position,
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              bool scroll_to_middle) const;
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Called when the state of the thumb track changes (e.g. by the user
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // pressing the mouse button down in it).
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void SetThumbTrackState(CustomButton::ButtonState state);
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BaseScrollBarThumb* thumb_;
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The size of the scrolled contents, in pixels.
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int contents_size_;
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The current amount the contents is offset by in the viewport.
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int contents_scroll_offset_;
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
157868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // The current size of the view port, in pixels.
158868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  int viewport_size_;
159868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The state of the scrollbar track. Typically, the track will highlight when
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the user presses the mouse on them (during page scrolling).
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CustomButton::ButtonState thumb_track_state_;
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The last amount of incremental scroll that this scrollbar performed. This
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // is accessed by the callbacks for the auto-repeat up/down buttons to know
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // what direction to repeatedly scroll in.
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ScrollAmount last_scroll_amount_;
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // An instance of a RepeatController which scrolls the scrollbar continuously
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // as the user presses the mouse button down on the up/down buttons or the
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // track.
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RepeatController repeater_;
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The position of the mouse within the scroll bar when the context menu
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // was invoked.
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int context_menu_mouse_position_;
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<MenuRunner> menu_runner_;
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<ScrollAnimator> scroll_animator_;
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Difference between current position and cumulative deltas obtained from
1825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // scroll update events.
1835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // TODO(tdresser): This should be removed when raw pixel scrolling for views
1845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // is enabled. See crbug.com/329354.
1855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  gfx::Vector2dF roundoff_error_;
1865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(BaseScrollBar);
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace views
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif  // UI_VIEWS_CONTROLS_SCROLLBAR_BASE_SCROLL_BAR_H_
193