Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(337)

Side by Side Diff: chrome_frame/infobars/internal/infobar_window.cc

Issue 4766003: Preview CL for adding an Infobar facility to Google Chrome Frame.... (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: '' Created 10 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
Property Changes:
Added: svn:eol-style
+ LF
OLDNEW
(Empty)
1 // Copyright (c) 2010 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 // Implementation of the manager for infobar windows.
6
7 #include "chrome_frame/infobars/internal/infobar_window.h"
8
grt (UTC plus 2) 2010/11/25 18:00:13 Include <algorithm> to explicitly pull in std::min
erikwright (departed) 2010/12/01 20:05:52 Awesome catch!
9 #include "base/compiler_specific.h"
10 #include "base/logging.h"
11
12 #include "chrome_frame/infobars/content.h"
13
14 namespace {
15 const UINT_PTR kInfobarSlidingTimerId = 1U;
16 const UINT kInfobarSlidingTimerIntervalMs = 50U;
17 // The step when the infobar is sliding, in pixels.
18 const int kInfobarSlideOpenStep = 2;
19 const int kInfobarSlideCloseStep = 6;
20 } // namespace
21
22 InfobarWindow::InfobarWindow(InfobarType type, InfobarHost* host)
23 : type_(type),
24 host_(host),
25 target_height_(0),
26 initial_height_(0),
27 content_(NULL),
28 frame_impl_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) {
29 DCHECK(type_ >= FIRST_INFOBAR_TYPE);
30 DCHECK(type_ < END_OF_INFOBAR_TYPE);
31 DCHECK(host_);
32 }
33
34 InfobarWindow::~InfobarWindow() {
35 ResetContent();
36 }
37
38 bool InfobarWindow::InitializeWindow() {
39 RECT dimensions = {0, 0, 0, 0};
40 if (!Create(host_->GetContainerWindow())) {
41 DPLOG(ERROR) << "Failure to create InfobarWindow.";
42 return false;
43 }
44
45 if (!::GetClientRect(host_->GetContainerWindow(), &dimensions)) {
46 DPLOG(ERROR) << "Failure in GetClientRect.";
47 DestroyWindow();
48 return false;
49 }
50
51 if (type_ == TOP_INFOBAR) {
52 dimensions.bottom = dimensions.top;
53 } else {
54 DCHECK(type_ == BOTTOM_INFOBAR);
55 dimensions.top = dimensions.bottom;
56 }
57
58 if (!MoveWindow(&dimensions, FALSE)) {
59 DPLOG(ERROR) << "Failure in MoveWindow.";
60 DestroyWindow();
61 return false;
62 }
63
64 return true;
65 }
66
67 bool InfobarWindow::Show(InfobarContent *content) {
68 ResetContent();
69
70 // Create the window if not created.
71 if (!IsWindow() && !InitializeWindow()) {
72 content->Reset();
73 return false;
74 }
75
76 if (!InstallContent(content))
77 return false;
78
79 return true;
80 }
81
82 void InfobarWindow::Hide() {
83 if (!IsWindow()) {
84 ResetContent();
85 } else if (!StartSlidingTowards(0)) {
86 // Failed to trigger a layout - seems our environment is going away or gone.
87 // Just hide immediately.
88 RECT empty = {0, 0, 0, 0};
89 MoveWindow(&empty, TRUE);
90 KillTimer(kInfobarSlidingTimerId);
91 ResetContent();
92 }
93 }
94
95 void InfobarWindow::ReserveSpace(RECT* rect) {
96 DCHECK(rect);
97 if (rect == NULL || !IsWindow())
98 return;
99
100 int current_height = CalculateHeight();
101
102 RECT infobar_rect = *rect;
103
104 switch (type_) {
105 case TOP_INFOBAR:
106 rect->top = std::min(rect->bottom,
107 infobar_rect.bottom = rect->top + current_height);
108 break;
109 case BOTTOM_INFOBAR:
110 rect->bottom = std::max(rect->top,
111 infobar_rect.top = rect->bottom - current_height);
112 break;
113 default:
114 NOTREACHED() << "Unknown InfobarType value.";
115 break;
116 }
117
118 if (!MoveWindow(&infobar_rect, TRUE))
119 DPLOG(ERROR) << "Failure in MoveWindow.";
120
121 if (!SetWindowPos(HWND_TOP,
122 &infobar_rect,
123 current_height != 0 ? SWP_SHOWWINDOW : SWP_HIDEWINDOW)) {
124 DPLOG(ERROR) << "Failure in SetWindowPos.";
125 }
126
127 if (content_ != NULL)
128 content_->SetDimensions(infobar_rect);
129
130 // Done sliding?
131 if (current_height == target_height_) {
132 KillTimer(kInfobarSlidingTimerId);
133 if (current_height == 0)
134 ResetContent();
135 }
136 }
137
138 bool InfobarWindow::StartSlidingTowards(int target_height) {
139 if (!IsWindow())
140 return false;
141
142 RECT dimensions = {0, 0, 0, 0};
143 if (!GetClientRect(&dimensions)) {
144 DPLOG(ERROR) << "Failure in GetClientRect.";
145 return false;
146 }
147
148 if (!SetTimer(kInfobarSlidingTimerId, kInfobarSlidingTimerIntervalMs, NULL)) {
149 DPLOG(ERROR) << "Failure in SetTimer.";
150 return false;
151 }
152
153 slide_start_ = base::Time::Now();
154 initial_height_ = dimensions.bottom - dimensions.top;
155 target_height_ = target_height;
156
157 // Trigger an immediate re-laying out. The timer will handle remaining steps.
158 host_->UpdateLayout();
159 return true;
160 }
161
162 int InfobarWindow::CalculateHeight() {
163 if (slide_start_.is_null())
164 return target_height_;
165
166 base::TimeDelta elapsed = base::Time::Now() - slide_start_;
167 int elapsed_steps = static_cast<int>(elapsed.InMilliseconds()) /
168 kInfobarSlidingTimerIntervalMs;
169
170 if (initial_height_ < target_height_) {
171 return std::min(initial_height_ + elapsed_steps * kInfobarSlideOpenStep,
172 target_height_);
173 } else if (initial_height_ > target_height_) {
174 return std::max(initial_height_ - elapsed_steps * kInfobarSlideCloseStep,
175 target_height_);
176 } else {
177 return target_height_;
178 }
179 }
180
181 bool InfobarWindow::InstallContent(InfobarContent* content) {
182 // Clear existing content, if any
183 ResetContent();
184
185 content_ = content;
186
187 if (!content_->InstallInFrame(&frame_impl_)) {
188 ResetContent();
grt (UTC plus 2) 2010/11/25 18:00:13 Multiple exits that require the same DoStuffBefore
erikwright (departed) 2010/12/01 20:05:52 Yeah, I didn't like it either. Moved to Show(), B
189 return false;
190 }
191
192 RECT dimensions = {0, 0, 0, 0};
193 if (!GetClientRect(&dimensions)) {
194 DPLOG(INFO) << "Failure in GetClientRect.";
195 ResetContent();
196 return false;
197 }
198
199 int infobar_width = dimensions.right - dimensions.left;
200 int content_height = content_->GetDesiredSize(infobar_width, 0);
201
202 if (!StartSlidingTowards(content_height)) {
203 ResetContent();
204 return false;
205 }
206
207 return true;
208 }
209
210 void InfobarWindow::ResetContent() {
211 if (content_ != NULL) {
212 content_->Reset();
213 content_ = NULL;
214 }
215 }
216
217 LRESULT InfobarWindow::OnTimer(UINT_PTR nIDEvent) {
218 DCHECK(nIDEvent == kInfobarSlidingTimerId);
219
220 // Might fail if the host is not able to update right now. Expect it to
221 // eventually succeed (on a future OnTimer invocation).
222 host_->UpdateLayout();
223 return S_OK;
224 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698