1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
|
// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Handles the visible notification (or balloons).
#ifndef CHROME_BROWSER_NOTIFICATIONS_BALLOON_COLLECTION_IMPL_H_
#define CHROME_BROWSER_NOTIFICATIONS_BALLOON_COLLECTION_IMPL_H_
#include <deque>
#include "base/basictypes.h"
#include "base/message_loop.h"
#include "chrome/browser/notifications/balloon_collection.h"
#include "gfx/point.h"
#include "gfx/rect.h"
// Mac balloons grow from the top down and have close buttons on top, so
// offsetting is not necessary for easy multiple-closing. Other platforms grow
// from the bottom up and have close buttons on top, so it is necessary.
#if defined(OS_MACOSX)
#define USE_OFFSETS 0
#else
#define USE_OFFSETS 1
#endif
// A balloon collection represents a set of notification balloons being
// shown on the screen. It positions new notifications according to
// a layout, and monitors for balloons being closed, which it reports
// up to its parent, the notification UI manager.
class BalloonCollectionImpl : public BalloonCollection
#if USE_OFFSETS
, public MessageLoopForUI::Observer
#endif
{
public:
BalloonCollectionImpl();
virtual ~BalloonCollectionImpl();
// BalloonCollection interface.
virtual void Add(const Notification& notification,
Profile* profile);
virtual bool Remove(const Notification& notification);
virtual bool HasSpace() const;
virtual void ResizeBalloon(Balloon* balloon, const gfx::Size& size);
virtual void DisplayChanged();
virtual void OnBalloonClosed(Balloon* source);
virtual const Balloons& GetActiveBalloons() {
return balloons_;
}
// MessageLoopForUI::Observer interface.
#if defined(OS_WIN)
virtual void WillProcessMessage(const MSG& event) {}
virtual void DidProcessMessage(const MSG& event);
#endif
#if defined(OS_LINUX)
virtual void WillProcessEvent(GdkEvent* event) {}
virtual void DidProcessEvent(GdkEvent* event);
#endif
protected:
// Calculates layout values for the balloons including
// the scaling, the max/min sizes, and the upper left corner of each.
class Layout {
public:
Layout();
// Refresh the work area and balloon placement.
void OnDisplaySettingsChanged();
// TODO(johnnyg): Scale the size to account for the system font factor.
static int min_balloon_width() { return kBalloonMinWidth; }
static int max_balloon_width() { return kBalloonMaxWidth; }
static int min_balloon_height() { return kBalloonMinHeight; }
static int max_balloon_height() { return kBalloonMaxHeight; }
// Utility function constrains the input rectangle to the min and max sizes.
static gfx::Size ConstrainToSizeLimits(const gfx::Size& rect);
// Returns both the total space available and the maximum
// allowed per balloon.
//
// The size may be a height or length depending on the way that
// balloons are laid out.
void GetMaxLinearSize(int* max_balloon_size, int* total_size) const;
// Refresh the cached values for work area and drawing metrics.
// The application should call this method to re-acquire metrics after
// any resolution or settings change.
// Returns true if and only if a metric changed.
bool RefreshSystemMetrics();
// Returns the origin for the sequence of balloons depending on layout.
// Should not be used to place a balloon -- only to call NextPosition().
gfx::Point GetLayoutOrigin() const;
// Compute the position for the next balloon.
// Start with *position_iterator = GetLayoutOrigin() and call repeatedly
// to get a sequence of positions. Return value is the upper-left coordinate
// for each next balloon.
gfx::Point NextPosition(const gfx::Size& balloon_size,
gfx::Point* position_iterator) const;
// Return a offscreen location which is offscreen for this layout,
// to be used as the initial position for an animation into view.
gfx::Point OffScreenLocation() const;
private:
enum Placement {
VERTICALLY_FROM_TOP_RIGHT,
VERTICALLY_FROM_BOTTOM_RIGHT
};
// Layout parameters
int VerticalEdgeMargin() const;
int HorizontalEdgeMargin() const;
int InterBalloonMargin() const;
// Minimum and maximum size of balloon content.
static const int kBalloonMinWidth = 300;
static const int kBalloonMaxWidth = 300;
static const int kBalloonMinHeight = 24;
static const int kBalloonMaxHeight = 120;
static Placement placement_;
gfx::Rect work_area_;
DISALLOW_COPY_AND_ASSIGN(Layout);
};
// Creates a new balloon. Overridable by unit tests. The caller is
// responsible for freeing the pointer returned.
virtual Balloon* MakeBalloon(const Notification& notification,
Profile* profile);
private:
// The number of balloons being displayed.
int count() const { return balloons_.size(); }
// Adjusts the positions of the balloons (e.g., when one is closed).
void PositionBalloons(bool is_reposition);
#if defined(OS_MACOSX)
// Get the work area on Mac OS, without inverting the coordinates.
static gfx::Rect GetMacWorkArea();
#endif
#if USE_OFFSETS
// Start and stop observing all UI events.
void AddMessageLoopObserver();
void RemoveMessageLoopObserver();
// Cancel all offset and reposition the balloons normally.
void CancelOffsets();
// Handles a mouse motion while the balloons are temporarily offset.
void HandleMouseMoveEvent();
// Is the current cursor in the balloon area?
bool IsCursorInBalloonCollection() const;
#endif
// Queue of active balloons.
typedef std::deque<Balloon*> Balloons;
Balloons balloons_;
// The layout parameters for balloons in this collection.
Layout layout_;
#if USE_OFFSETS
// Factory for generating delayed reposition tasks on mouse motion.
ScopedRunnableMethodFactory<BalloonCollectionImpl> reposition_factory_;
// Is the balloon collection currently listening for UI events?
bool added_as_message_loop_observer_;
#endif
DISALLOW_COPY_AND_ASSIGN(BalloonCollectionImpl);
};
#endif // CHROME_BROWSER_NOTIFICATIONS_BALLOON_COLLECTION_IMPL_H_
|