- add sources.
[platform/framework/web/crosswalk.git] / src / chrome / browser / notifications / balloon_collection_impl.h
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 // Handles the visible notification (or balloons).
6
7 #ifndef CHROME_BROWSER_NOTIFICATIONS_BALLOON_COLLECTION_IMPL_H_
8 #define CHROME_BROWSER_NOTIFICATIONS_BALLOON_COLLECTION_IMPL_H_
9
10 #include <deque>
11
12 #include "base/basictypes.h"
13 #include "base/compiler_specific.h"
14 #include "base/memory/weak_ptr.h"
15 #include "base/message_loop/message_loop.h"
16 #include "chrome/browser/notifications/balloon_collection.h"
17 #include "chrome/browser/notifications/balloon_collection_base.h"
18 #include "content/public/browser/notification_observer.h"
19 #include "content/public/browser/notification_registrar.h"
20 #include "ui/gfx/point.h"
21 #include "ui/gfx/rect.h"
22
23 // Mac balloons grow from the top down and have close buttons on top, so
24 // offsetting is not necessary for easy multiple-closing.  Other platforms grow
25 // from the bottom up and have close buttons on top, so it is necessary.
26 #if defined(OS_MACOSX)
27 #define USE_OFFSETS 0
28 #else
29 #define USE_OFFSETS 1
30 #endif
31
32 // A balloon collection represents a set of notification balloons being
33 // shown on the screen.  It positions new notifications according to
34 // a layout, and monitors for balloons being closed, which it reports
35 // up to its parent, the notification UI manager.
36 class BalloonCollectionImpl : public BalloonCollection,
37                               public content::NotificationObserver
38 #if USE_OFFSETS
39                             , public base::MessageLoopForUI::Observer
40 #endif
41 {
42  public:
43   BalloonCollectionImpl();
44   virtual ~BalloonCollectionImpl();
45
46   // BalloonCollection interface.
47   virtual void Add(const Notification& notification,
48                    Profile* profile) OVERRIDE;
49   virtual const Notification* FindById(const std::string& id) const OVERRIDE;
50   virtual bool RemoveById(const std::string& id) OVERRIDE;
51   virtual bool RemoveBySourceOrigin(const GURL& source_origin) OVERRIDE;
52   virtual bool RemoveByProfile(Profile* profile) OVERRIDE;
53   virtual void RemoveAll() OVERRIDE;
54   virtual bool HasSpace() const OVERRIDE;
55   virtual void ResizeBalloon(Balloon* balloon, const gfx::Size& size) OVERRIDE;
56   virtual void SetPositionPreference(PositionPreference position) OVERRIDE;
57   virtual void DisplayChanged() OVERRIDE;
58   virtual void OnBalloonClosed(Balloon* source) OVERRIDE;
59   virtual const Balloons& GetActiveBalloons() OVERRIDE;
60
61   // content::NotificationObserver interface.
62   virtual void Observe(int type,
63                        const content::NotificationSource& source,
64                        const content::NotificationDetails& details) OVERRIDE;
65
66   // MessageLoopForUI::Observer interface.
67 #if defined(OS_WIN) || defined(USE_AURA)
68   virtual base::EventStatus WillProcessEvent(
69       const base::NativeEvent& event) OVERRIDE;
70   virtual void DidProcessEvent(const base::NativeEvent& event) OVERRIDE;
71 #elif defined(TOOLKIT_GTK)
72   virtual void WillProcessEvent(GdkEvent* event) OVERRIDE;
73   virtual void DidProcessEvent(GdkEvent* event) OVERRIDE;
74 #endif
75
76   // base_ is embedded, so this is a simple accessor for the number of
77   // balloons in the collection.
78   int count() const { return base_.count(); }
79
80   static int min_balloon_width() { return Layout::min_balloon_width(); }
81   static int max_balloon_width() { return Layout::max_balloon_width(); }
82   static int min_balloon_height() { return Layout::min_balloon_height(); }
83   static int max_balloon_height() { return Layout::max_balloon_height(); }
84
85  protected:
86   // Calculates layout values for the balloons including
87   // the scaling, the max/min sizes, and the upper left corner of each.
88   class Layout {
89    public:
90     Layout();
91
92     // These enumerations all are based on a screen orientation where
93     // the origin is the top-left.
94     enum Placement {
95       INVALID,
96       VERTICALLY_FROM_TOP_LEFT,
97       VERTICALLY_FROM_TOP_RIGHT,
98       VERTICALLY_FROM_BOTTOM_LEFT,
99       VERTICALLY_FROM_BOTTOM_RIGHT
100     };
101
102     // Refresh the work area and balloon placement.
103     void OnDisplaySettingsChanged();
104
105     // TODO(johnnyg): Scale the size to account for the system font factor.
106     static int min_balloon_width() { return kBalloonMinWidth; }
107     static int max_balloon_width() { return kBalloonMaxWidth; }
108     static int min_balloon_height() { return kBalloonMinHeight; }
109     static int max_balloon_height() { return kBalloonMaxHeight; }
110
111     // Utility function constrains the input rectangle to the min and max sizes.
112     static gfx::Size ConstrainToSizeLimits(const gfx::Size& rect);
113
114     void set_placement(Placement placement) { placement_ = placement; }
115
116     // Returns both the total space available and the maximum
117     // allowed per balloon.
118     //
119     // The size may be a height or length depending on the way that
120     // balloons are laid out.
121     void GetMaxLinearSize(int* max_balloon_size, int* total_size) const;
122
123     // Refresh the cached values for work area and drawing metrics.
124     // The application should call this method to re-acquire metrics after
125     // any resolution or settings change.
126     // Returns true if and only if a metric changed.
127     bool RefreshSystemMetrics();
128
129     // Returns the origin for the sequence of balloons depending on layout.
130     // Should not be used to place a balloon -- only to call NextPosition().
131     gfx::Point GetLayoutOrigin() const;
132
133     // Compute the position for the next balloon.
134     // Start with *position_iterator = GetLayoutOrigin() and call repeatedly
135     // to get a sequence of positions. Return value is the upper-left coordinate
136     // for each next balloon.
137     gfx::Point NextPosition(const gfx::Size& balloon_size,
138                             gfx::Point* position_iterator) const;
139
140     // Return a offscreen location which is offscreen for this layout,
141     // to be used as the initial position for an animation into view.
142     gfx::Point OffScreenLocation() const;
143
144     // Returns true if the layout requires offsetting for keeping the close
145     // buttons under the cursor during rapid-close interaction.
146     bool RequiresOffsets() const;
147
148     // Returns true if there is change to the offset that requires the balloons
149     // to be repositioned.
150     bool ComputeOffsetToMoveAbovePanels();
151
152     void enable_computing_panel_offset() {
153       need_to_compute_panel_offset_ = true;
154     }
155
156    private:
157     // Layout parameters
158     int VerticalEdgeMargin() const;
159     int HorizontalEdgeMargin() const;
160     int InterBalloonMargin() const;
161
162     bool NeedToMoveAboveLeftSidePanels() const;
163     bool NeedToMoveAboveRightSidePanels() const;
164
165     // Minimum and maximum size of balloon content.
166     static const int kBalloonMinWidth = 300;
167     static const int kBalloonMaxWidth = 300;
168     static const int kBalloonMinHeight = 24;
169     static const int kBalloonMaxHeight = 160;
170
171     Placement placement_;
172     gfx::Rect work_area_;
173
174     // The flag that indicates that the panel offset computation should be
175     // performed.
176     bool need_to_compute_panel_offset_;
177
178     // The offset that guarantees that the notificaitions shown in the
179     // lower-right or lower-left corner of the screen will go above currently
180     // shown panels and will not be obscured by them.
181     int offset_to_move_above_panels_;
182
183     DISALLOW_COPY_AND_ASSIGN(Layout);
184   };
185
186   // Creates a new balloon. Overridable by derived classes and unit tests.
187   // The caller is responsible for freeing the pointer returned.
188   virtual Balloon* MakeBalloon(const Notification& notification,
189                                Profile* profile);
190
191   // Protected implementation of Add with additional add_to_front parameter
192   // for use by derived classes.
193   void AddImpl(const Notification& notification,
194                Profile* profile,
195                bool add_to_front);
196
197   // Gets a bounding box for all the current balloons in screen coordinates.
198   gfx::Rect GetBalloonsBoundingBox() const;
199
200   BalloonCollectionBase& base() { return base_; }
201   Layout& layout() { return layout_; }
202
203  private:
204   // Adjusts the positions of the balloons (e.g., when one is closed).
205   // Implemented by each platform for specific UI requirements.
206   void PositionBalloons(bool is_reposition);
207
208   // Cross-platform internal implementation for PositionBalloons.
209   void PositionBalloonsInternal(bool is_reposition);
210
211 #if defined(OS_MACOSX)
212   // Get the work area on Mac OS, without inverting the coordinates.
213   static gfx::Rect GetMacWorkArea();
214 #endif
215
216   // Base implementation for the collection of active balloons.
217   BalloonCollectionBase base_;
218
219   // The layout parameters for balloons in this collection.
220   Layout layout_;
221
222   content::NotificationRegistrar registrar_;
223
224 #if USE_OFFSETS
225   // Start and stop observing all UI events.
226   void AddMessageLoopObserver();
227   void RemoveMessageLoopObserver();
228
229   // Cancel all offset and reposition the balloons normally.
230   void CancelOffsets();
231
232   // Handles a mouse motion while the balloons are temporarily offset.
233   void HandleMouseMoveEvent();
234
235   // Is the current cursor in the balloon area?
236   bool IsCursorInBalloonCollection() const;
237
238   // Factory for generating delayed reposition tasks on mouse motion.
239   base::WeakPtrFactory<BalloonCollectionImpl> reposition_factory_;
240
241   // Is the balloon collection currently listening for UI events?
242   bool added_as_message_loop_observer_;
243 #endif
244
245   DISALLOW_COPY_AND_ASSIGN(BalloonCollectionImpl);
246 };
247
248 #endif  // CHROME_BROWSER_NOTIFICATIONS_BALLOON_COLLECTION_IMPL_H_