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

Side by Side Diff: chrome/browser/ui/views/first_run_bubble.cc

Issue 8265005: first run bubble using the views/bubble api. (Closed) Base URL: http://git.chromium.org/git/chromium.git@trunk
Patch Set: update. Created 9 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
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/ui/views/first_run_bubble.h" 5 #include "chrome/browser/ui/views/first_run_bubble.h"
6 6
7 #include "base/bind.h" 7 #include "base/bind.h"
8 #include "base/utf_string_conversions.h" 8 #include "base/utf_string_conversions.h"
9 #include "chrome/browser/first_run/first_run.h" 9 #include "chrome/browser/first_run/first_run.h"
10 #include "chrome/browser/search_engines/util.h" 10 #include "chrome/browser/search_engines/util.h"
11 #include "chrome/browser/ui/browser.h" 11 #include "chrome/browser/ui/browser.h"
12 #include "chrome/browser/ui/browser_list.h" 12 #include "chrome/browser/ui/browser_list.h"
13 #include "chrome/browser/ui/browser_window.h" 13 #include "chrome/browser/ui/browser_window.h"
14 #include "content/browser/user_metrics.h" 14 #include "content/browser/user_metrics.h"
15 #include "grit/chromium_strings.h" 15 #include "grit/chromium_strings.h"
16 #include "grit/generated_resources.h" 16 #include "grit/generated_resources.h"
17 #include "grit/locale_settings.h" 17 #include "grit/locale_settings.h"
18 #include "grit/theme_resources_standard.h" 18 #include "grit/theme_resources_standard.h"
19 #include "ui/base/l10n/l10n_font_util.h" 19 #include "ui/base/l10n/l10n_font_util.h"
20 #include "ui/base/l10n/l10n_util.h" 20 #include "ui/base/l10n/l10n_util.h"
21 #include "ui/base/resource/resource_bundle.h" 21 #include "ui/base/resource/resource_bundle.h"
22 #include "views/controls/button/image_button.h" 22 #include "views/controls/button/image_button.h"
23 #include "views/controls/button/text_button.h"
24 #include "views/controls/label.h" 23 #include "views/controls/label.h"
25 #include "views/events/event.h" 24 #include "views/events/event.h"
26 #include "views/focus/focus_manager.h" 25 #include "views/focus/focus_manager.h"
26 #include "views/layout/fill_layout.h"
27 #include "views/layout/grid_layout.h"
27 #include "views/layout/layout_constants.h" 28 #include "views/layout/layout_constants.h"
29 #if defined(OS_WIN) && !defined(USE_AURA)
28 #include "views/widget/native_widget_win.h" 30 #include "views/widget/native_widget_win.h"
31 #endif
29 #include "views/widget/widget.h" 32 #include "views/widget/widget.h"
30 33
31 namespace { 34 // FirstRunBubbleView --------------------------------------------------
32 35
33 // How much extra padding to put around our content over what the Bubble 36 class FirstRunBubbleView : public views::View,
34 // provides. 37 public views::ButtonListener,
35 const int kBubblePadding = 4; 38 public views::FocusChangeListener {
36
37 // How much extra padding to put around our content over what the Bubble
38 // provides in alternative OEM bubble.
39 const int kOEMBubblePadding = 4;
40
41 // Padding between parts of strings on the same line (for instance,
42 // "New!" and "Search from the address bar!"
43 const int kStringSeparationPadding = 2;
44
45 // Margin around close button.
46 const int kMarginRightOfCloseButton = 7;
47
48 // The bubble's HWND is actually owned by the border widget, and it's the border
49 // widget that's owned by the frame window the bubble is anchored to. This
50 // function makes the two leaps necessary to go from the bubble contents HWND
51 // to the frame HWND.
52 HWND GetLogicalBubbleOwner(HWND bubble_hwnd) {
53 HWND border_widget_hwnd = GetWindow(bubble_hwnd, GW_OWNER);
54 return GetWindow(border_widget_hwnd, GW_OWNER);
55 }
56
57 } // namespace
58
59 // Base class for implementations of the client view which appears inside the
60 // first run bubble. It is a dialog-ish view, but is not a true dialog.
61 class FirstRunBubbleViewBase : public views::View,
62 public views::ButtonListener,
63 public views::FocusChangeListener {
64 public:
65 // Called by FirstRunBubble::Show to request focus for the proper button
66 // in the FirstRunBubbleView when it is shown.
67 virtual void BubbleShown() = 0;
68 };
69
70 // FirstRunBubbleView ---------------------------------------------------------
71
72 class FirstRunBubbleView : public FirstRunBubbleViewBase {
73 public: 39 public:
74 FirstRunBubbleView(FirstRunBubble* bubble_window, Profile* profile); 40 FirstRunBubbleView(FirstRunBubble* bubble_window, Profile* profile);
75 41
42 // Initialize labels used in the first run bubble.
43 void InitContents();
44
76 private: 45 private:
77 virtual ~FirstRunBubbleView() {} 46 virtual ~FirstRunBubbleView();
78 47
79 // FirstRunBubbleViewBase: 48 // Overrides from ButtonListener:
80 virtual void BubbleShown(); 49 virtual void ButtonPressed(views::Button* sender,
50 const views::Event& event) OVERRIDE;
81 51
82 // Overridden from View: 52 // Overrides from views::FocusChangeListener
83 virtual void ButtonPressed(views::Button* sender, const views::Event& event); 53 void FocusWillChange(View* focused_before, View* focused_now);
Miranda Callahan 2011/11/02 15:36:14 should also have OVERRIDE.
alicet1 2011/11/03 18:21:51 oops. sorry, it's an implementation of this interf
84 virtual void Layout();
85 virtual gfx::Size GetPreferredSize();
86
87 // FocusChangeListener:
88 virtual void FocusWillChange(View* focused_before, View* focused_now);
89 54
90 FirstRunBubble* bubble_window_; 55 FirstRunBubble* bubble_window_;
56 Profile* profile_;
91 views::Label* label1_; 57 views::Label* label1_;
92 views::Label* label2_; 58 views::Label* label2_;
93 views::Label* label3_; 59 views::Label* label3_;
94 views::NativeTextButton* change_button_; 60 views::ImageButton* close_button_;
95 views::NativeTextButton* keep_button_;
96 Profile* profile_;
97 61
98 DISALLOW_COPY_AND_ASSIGN(FirstRunBubbleView); 62 DISALLOW_COPY_AND_ASSIGN(FirstRunBubbleView);
99 }; 63 };
100 64
101 FirstRunBubbleView::FirstRunBubbleView(FirstRunBubble* bubble_window, 65 FirstRunBubbleView::FirstRunBubbleView(FirstRunBubble* bubble_window,
102 Profile* profile) 66 Profile* profile)
103 : bubble_window_(bubble_window), 67 : bubble_window_(bubble_window),
68 profile_(profile),
104 label1_(NULL), 69 label1_(NULL),
105 label2_(NULL), 70 label2_(NULL),
106 label3_(NULL), 71 label3_(NULL),
107 keep_button_(NULL), 72 close_button_(NULL) {}
108 change_button_(NULL),
109 profile_(profile) {
110 const gfx::Font& font =
111 ResourceBundle::GetSharedInstance().GetFont(ResourceBundle::MediumFont);
112 73
113 label1_ = new views::Label(l10n_util::GetStringUTF16(IDS_FR_BUBBLE_TITLE)); 74 void FirstRunBubbleView::InitContents() {
114 label1_->SetFont(font.DeriveFont(3, gfx::Font::BOLD)); 75 ResourceBundle& rb = ResourceBundle::GetSharedInstance();
115 label1_->SetBackgroundColor(Bubble::kBackgroundColor); 76 const gfx::Font& original_font = rb.GetFont(ResourceBundle::MediumFont);
77 const gfx::Font& derived_font = original_font.DeriveFont(2, gfx::Font::BOLD);
78
79 label1_ = new views::Label(l10n_util::GetStringFUTF16(
80 IDS_FR_SE_BUBBLE_TITLE,
81 GetDefaultSearchEngineName(profile_)));
82 label1_->SetFont(derived_font);
116 label1_->SetHorizontalAlignment(views::Label::ALIGN_LEFT); 83 label1_->SetHorizontalAlignment(views::Label::ALIGN_LEFT);
117 AddChildView(label1_);
118
119 gfx::Size ps = GetPreferredSize();
120
121 label2_ = new views::Label(l10n_util::GetStringUTF16(IDS_FR_BUBBLE_SUBTEXT));
122 label2_->SetMultiLine(true);
123 label2_->SetFont(font);
124 label2_->SetBackgroundColor(Bubble::kBackgroundColor);
125 label2_->SetHorizontalAlignment(views::Label::ALIGN_LEFT);
126 label2_->SizeToFit(ps.width() - kBubblePadding * 2);
127 AddChildView(label2_);
128
129 string16 question_str = l10n_util::GetStringFUTF16(
130 IDS_FR_BUBBLE_QUESTION,
131 GetDefaultSearchEngineName(profile));
132 label3_ = new views::Label(question_str);
133 label3_->SetMultiLine(true);
134 label3_->SetFont(font);
135 label3_->SetBackgroundColor(Bubble::kBackgroundColor);
136 label3_->SetHorizontalAlignment(views::Label::ALIGN_LEFT);
137 label3_->SizeToFit(ps.width() - kBubblePadding * 2);
138 AddChildView(label3_);
139
140 std::wstring keep_str = UTF16ToWide(l10n_util::GetStringFUTF16(
141 IDS_FR_BUBBLE_OK,
142 GetDefaultSearchEngineName(profile)));
143 keep_button_ = new views::NativeTextButton(this, keep_str);
144 keep_button_->SetIsDefault(true);
145 AddChildView(keep_button_);
146
147 std::wstring change_str =
148 UTF16ToWide(l10n_util::GetStringUTF16(IDS_FR_BUBBLE_CHANGE));
149 change_button_ = new views::NativeTextButton(this, change_str);
150 AddChildView(change_button_);
151 }
152
153 void FirstRunBubbleView::BubbleShown() {
154 keep_button_->RequestFocus();
155 }
156
157 void FirstRunBubbleView::ButtonPressed(views::Button* sender,
158 const views::Event& event) {
159 UserMetrics::RecordAction(UserMetricsAction("FirstRunBubbleView_Clicked"));
160 bubble_window_->set_fade_away_on_close(true);
161 bubble_window_->Close();
162 if (change_button_ == sender) {
163 UserMetrics::RecordAction(
164 UserMetricsAction("FirstRunBubbleView_ChangeButton"));
165
166 Browser* browser = BrowserList::GetLastActiveWithProfile(profile_);
167 if (browser) {
168 browser->OpenSearchEngineOptionsDialog();
169 }
170 }
171 }
172
173 void FirstRunBubbleView::Layout() {
174 gfx::Size canvas = GetPreferredSize();
175
176 // The multiline business that follows is dirty hacks to get around
177 // bug 1325257.
178 label1_->SetMultiLine(false);
179 gfx::Size pref_size = label1_->GetPreferredSize();
180 label1_->SetMultiLine(true);
181 label1_->SizeToFit(canvas.width() - kBubblePadding * 2);
182 label1_->SetBounds(kBubblePadding, kBubblePadding,
183 canvas.width() - kBubblePadding * 2,
184 pref_size.height());
185
186 int next_v_space = label1_->y() + pref_size.height() +
187 views::kRelatedControlSmallVerticalSpacing;
188
189 pref_size = label2_->GetPreferredSize();
190 label2_->SetBounds(kBubblePadding, next_v_space,
191 canvas.width() - kBubblePadding * 2,
192 pref_size.height());
193
194 next_v_space = label2_->y() + label2_->height() +
195 views::kPanelSubVerticalSpacing;
196
197 pref_size = label3_->GetPreferredSize();
198 label3_->SetBounds(kBubblePadding, next_v_space,
199 canvas.width() - kBubblePadding * 2,
200 pref_size.height());
201
202 pref_size = change_button_->GetPreferredSize();
203 change_button_->SetBounds(
204 canvas.width() - pref_size.width() - kBubblePadding,
205 canvas.height() - pref_size.height() - views::kButtonVEdgeMargin,
206 pref_size.width(), pref_size.height());
207
208 pref_size = keep_button_->GetPreferredSize();
209 keep_button_->SetBounds(change_button_->x() - pref_size.width() -
210 views::kRelatedButtonHSpacing, change_button_->y(),
211 pref_size.width(), pref_size.height());
212 }
213
214 gfx::Size FirstRunBubbleView::GetPreferredSize() {
215 return gfx::Size(views::Widget::GetLocalizedContentsSize(
216 IDS_FIRSTRUNBUBBLE_DIALOG_WIDTH_CHARS,
217 IDS_FIRSTRUNBUBBLE_DIALOG_HEIGHT_LINES));
218 }
219
220 void FirstRunBubbleView::FocusWillChange(View* focused_before,
221 View* focused_now) {
222 if (focused_before &&
223 (focused_before->GetClassName() ==
224 views::NativeTextButton::kViewClassName)) {
225 views::NativeTextButton* before =
226 static_cast<views::NativeTextButton*>(focused_before);
227 before->SetIsDefault(false);
228 }
229 if (focused_now &&
230 (focused_now->GetClassName() ==
231 views::NativeTextButton::kViewClassName)) {
232 views::NativeTextButton* after =
233 static_cast<views::NativeTextButton*>(focused_now);
234 after->SetIsDefault(true);
235 }
236 }
237
238 // FirstRunOEMBubbleView ------------------------------------------------------
239
240 class FirstRunOEMBubbleView : public FirstRunBubbleViewBase {
241 public:
242 FirstRunOEMBubbleView(FirstRunBubble* bubble_window, Profile* profile);
243
244 private:
245 virtual ~FirstRunOEMBubbleView() { }
246
247 // FirstRunBubbleViewBase:
248 virtual void BubbleShown();
249
250 // Overridden from View:
251 virtual void ButtonPressed(views::Button* sender, const views::Event& event);
252 virtual void Layout();
253 virtual gfx::Size GetPreferredSize();
254
255 // FocusChangeListener:
256 virtual void FocusWillChange(View* focused_before, View* focused_now);
257
258 FirstRunBubble* bubble_window_;
259 views::Label* label1_;
260 views::Label* label2_;
261 views::Label* label3_;
262 views::ImageButton* close_button_;
263 Profile* profile_;
264
265 DISALLOW_COPY_AND_ASSIGN(FirstRunOEMBubbleView);
266 };
267
268 FirstRunOEMBubbleView::FirstRunOEMBubbleView(FirstRunBubble* bubble_window,
269 Profile* profile)
270 : bubble_window_(bubble_window),
271 label1_(NULL),
272 label2_(NULL),
273 label3_(NULL),
274 close_button_(NULL),
275 profile_(profile) {
276 ResourceBundle& rb = ResourceBundle::GetSharedInstance();
277 const gfx::Font& font = rb.GetFont(ResourceBundle::MediumFont);
278
279 label1_ = new views::Label(
280 l10n_util::GetStringUTF16(IDS_FR_OEM_BUBBLE_TITLE_1));
281 label1_->SetFont(font.DeriveFont(3, gfx::Font::BOLD));
282 label1_->SetBackgroundColor(Bubble::kBackgroundColor);
283 label1_->SetEnabledColor(SK_ColorRED);
284 label1_->SetHorizontalAlignment(views::Label::ALIGN_LEFT);
285 AddChildView(label1_);
286 84
287 label2_ = new views::Label( 85 label2_ = new views::Label(
288 l10n_util::GetStringUTF16(IDS_FR_OEM_BUBBLE_TITLE_2)); 86 l10n_util::GetStringUTF16(IDS_FR_BUBBLE_SUBTEXT));
289 label2_->SetFont(font.DeriveFont(3, gfx::Font::BOLD)); 87 label2_->SetMultiLine(true);
290 label2_->SetBackgroundColor(Bubble::kBackgroundColor); 88 label2_->SetFont(original_font);
291 label2_->SetHorizontalAlignment(views::Label::ALIGN_LEFT); 89 label2_->SetHorizontalAlignment(views::Label::ALIGN_LEFT);
292 AddChildView(label2_);
293
294 gfx::Size ps = GetPreferredSize();
295
296 label3_ = new views::Label(
297 l10n_util::GetStringUTF16(IDS_FR_OEM_BUBBLE_SUBTEXT));
298 label3_->SetMultiLine(true);
299 label3_->SetFont(font);
300 label3_->SetBackgroundColor(Bubble::kBackgroundColor);
301 label3_->SetHorizontalAlignment(views::Label::ALIGN_LEFT);
302 label3_->SizeToFit(ps.width() - kOEMBubblePadding * 2);
303 AddChildView(label3_);
304 90
305 close_button_ = new views::ImageButton(this); 91 close_button_ = new views::ImageButton(this);
306 close_button_->SetImage(views::CustomButton::BS_NORMAL, 92 close_button_->SetImage(views::CustomButton::BS_NORMAL,
307 rb.GetBitmapNamed(IDR_CLOSE_BAR)); 93 rb.GetBitmapNamed(IDR_CLOSE_BAR));
308 close_button_->SetImage(views::CustomButton::BS_HOT, 94 close_button_->SetImage(views::CustomButton::BS_HOT,
309 rb.GetBitmapNamed(IDR_CLOSE_BAR_H)); 95 rb.GetBitmapNamed(IDR_CLOSE_BAR_H));
310 close_button_->SetImage(views::CustomButton::BS_PUSHED, 96 close_button_->SetImage(views::CustomButton::BS_PUSHED,
311 rb.GetBitmapNamed(IDR_CLOSE_BAR_P)); 97 rb.GetBitmapNamed(IDR_CLOSE_BAR_P));
98 gfx::Size sz = close_button_->GetPreferredSize();
312 99
313 AddChildView(close_button_); 100 views::GridLayout* layout = views::GridLayout::CreatePanel(this);
101 SetLayoutManager(layout);
102 // TODO(alicet): fix this after padding change goes in.
103 layout->SetInsets(9, 10, 3, 7);
104
105 views::ColumnSet* column_set = layout->AddColumnSet(0);
106 column_set->AddColumn(views::GridLayout::LEADING,
107 views::GridLayout::LEADING, 1,
108 views::GridLayout::USE_PREF, 0, 0);
109 column_set->AddColumn(views::GridLayout::TRAILING, views::GridLayout::FILL, 0,
110 views::GridLayout::USE_PREF, 0, 0);
111
112 layout->StartRow(0, 0);
113 layout->AddView(label1_);
114 layout->AddView(close_button_, 1, 1, views::GridLayout::TRAILING,
115 views::GridLayout::LEADING);
116 layout->AddPaddingRow(0, views::kRelatedControlSmallVerticalSpacing);
117
118 layout->StartRow(0, 0);
119 layout->AddView(label2_);
120 layout->AddPaddingRow(0, views::kRelatedControlSmallVerticalSpacing);
314 } 121 }
315 122
316 void FirstRunOEMBubbleView::BubbleShown() { 123 void FirstRunBubbleView::ButtonPressed(views::Button* sender,
317 RequestFocus(); 124 const views::Event& event) {
318 // No button in oem_bubble to request focus. 125 UserMetrics::RecordAction(
126 UserMetricsAction("FirstRunOEMBubbleView_Clicked"));
127 bubble_window_->GetWidget()->Close();
319 } 128 }
320 129
321 void FirstRunOEMBubbleView::ButtonPressed(views::Button* sender, 130 FirstRunBubbleView::~FirstRunBubbleView() {}
322 const views::Event& event) { 131
323 UserMetrics::RecordAction( 132 void FirstRunBubbleView::FocusWillChange(View* focused_before,
324 UserMetricsAction("FirstRunOEMBubbleView_Clicked")); 133 View* focused_now) {
325 bubble_window_->set_fade_away_on_close(true); 134 // TODO(alicet): this should be in the DidChangeFocus() call
326 bubble_window_->Close(); 135 // when that is checked in.
136 if (!Contains(focused_now)) {
137 bubble_window_->GetWidget()->Close();
138 }
327 } 139 }
328 140
329 void FirstRunOEMBubbleView::Layout() {
330 gfx::Size canvas = GetPreferredSize();
331
332 // First, draw the close button on the far right.
333 gfx::Size sz = close_button_->GetPreferredSize();
334 close_button_->SetBounds(
335 canvas.width() - sz.width() - kMarginRightOfCloseButton,
336 kOEMBubblePadding, sz.width(), sz.height());
337
338 gfx::Size pref_size = label1_->GetPreferredSize();
339 label1_->SetBounds(kOEMBubblePadding, kOEMBubblePadding,
340 pref_size.width() + kOEMBubblePadding * 2,
341 pref_size.height());
342
343 pref_size = label2_->GetPreferredSize();
344 label2_->SetBounds(
345 kOEMBubblePadding * 2 + label1_->GetPreferredSize().width(),
346 kOEMBubblePadding, canvas.width() - kOEMBubblePadding * 2,
347 pref_size.height());
348
349 int next_v_space =
350 label1_->y() + pref_size.height() +
351 views::kRelatedControlSmallVerticalSpacing;
352
353 pref_size = label3_->GetPreferredSize();
354 label3_->SetBounds(kOEMBubblePadding, next_v_space,
355 canvas.width() - kOEMBubblePadding * 2,
356 pref_size.height());
357 }
358
359 gfx::Size FirstRunOEMBubbleView::GetPreferredSize() {
360 // Calculate width based on font and text.
361 ResourceBundle& rb = ResourceBundle::GetSharedInstance();
362 const gfx::Font& font = rb.GetFont(
363 ResourceBundle::MediumFont).DeriveFont(3, gfx::Font::BOLD);
364 gfx::Size size = gfx::Size(
365 ui::GetLocalizedContentsWidthForFont(
366 IDS_FIRSTRUNOEMBUBBLE_DIALOG_WIDTH_CHARS, font),
367 ui::GetLocalizedContentsHeightForFont(
368 IDS_FIRSTRUNOEMBUBBLE_DIALOG_HEIGHT_LINES, font));
369
370 // WARNING: HACK. Vista and XP calculate font size differently; this means
371 // that a dialog box correctly proportioned for XP will appear too large in
372 // Vista. The correct thing to do is to change font size calculations in
373 // XP or Vista so that the length of a string is calculated properly. For
374 // now, we force Vista to show a correctly-sized box by taking account of
375 // the difference in font size calculation. The coefficient should not be
376 // stored in a variable because it's a hack and should go away.
377 if (views::NativeWidgetWin::IsAeroGlassEnabled()) {
378 size.set_width(static_cast<int>(size.width() * 0.85));
379 size.set_height(static_cast<int>(size.height() * 0.85));
380 }
381 return size;
382 }
383
384 void FirstRunOEMBubbleView::FocusWillChange(View* focused_before,
385 View* focused_now) {
386 // No buttons in oem_bubble to register focus changes.
387 }
388
389 // FirstRunMinimalBubbleView --------------------------------------------------
390 // TODO(mirandac): combine FRBubbles more elegantly. http://crbug.com/41353
391
392 class FirstRunMinimalBubbleView : public FirstRunBubbleViewBase {
393 public:
394 FirstRunMinimalBubbleView(FirstRunBubble* bubble_window, Profile* profile);
395
396 private:
397 virtual ~FirstRunMinimalBubbleView() { }
398
399 // FirstRunBubbleViewBase:
400 virtual void BubbleShown();
401
402 // Overridden from View:
403 virtual void ButtonPressed(views::Button* sender,
404 const views::Event& event) { }
405 virtual void Layout();
406 virtual gfx::Size GetPreferredSize();
407
408 // FocusChangeListener:
409 virtual void FocusWillChange(View* focused_before, View* focused_now);
410
411 FirstRunBubble* bubble_window_;
412 Profile* profile_;
413 views::Label* label1_;
414 views::Label* label2_;
415
416 DISALLOW_COPY_AND_ASSIGN(FirstRunMinimalBubbleView);
417 };
418
419 FirstRunMinimalBubbleView::FirstRunMinimalBubbleView(
420 FirstRunBubble* bubble_window,
421 Profile* profile)
422 : bubble_window_(bubble_window),
423 profile_(profile),
424 label1_(NULL),
425 label2_(NULL) {
426 const gfx::Font& font =
427 ResourceBundle::GetSharedInstance().GetFont(ResourceBundle::MediumFont);
428
429 label1_ = new views::Label(l10n_util::GetStringFUTF16(
430 IDS_FR_SE_BUBBLE_TITLE,
431 GetDefaultSearchEngineName(profile_)));
432 label1_->SetFont(font.DeriveFont(3, gfx::Font::BOLD));
433 label1_->SetBackgroundColor(Bubble::kBackgroundColor);
434 label1_->SetHorizontalAlignment(views::Label::ALIGN_LEFT);
435 AddChildView(label1_);
436
437 gfx::Size ps = GetPreferredSize();
438
439 label2_ = new views::Label(
440 l10n_util::GetStringUTF16(IDS_FR_BUBBLE_SUBTEXT));
441 label2_->SetMultiLine(true);
442 label2_->SetFont(font);
443 label2_->SetBackgroundColor(Bubble::kBackgroundColor);
444 label2_->SetHorizontalAlignment(views::Label::ALIGN_LEFT);
445 label2_->SizeToFit(ps.width() - kBubblePadding * 2);
446 AddChildView(label2_);
447 }
448
449 void FirstRunMinimalBubbleView::BubbleShown() {
450 RequestFocus();
451 }
452
453 void FirstRunMinimalBubbleView::Layout() {
454 gfx::Size canvas = GetPreferredSize();
455
456 // See comments in FirstRunOEMBubbleView::Layout explaining this hack.
457 label1_->SetMultiLine(false);
458 gfx::Size pref_size = label1_->GetPreferredSize();
459 label1_->SetMultiLine(true);
460 label1_->SizeToFit(canvas.width() - kBubblePadding * 2);
461 label1_->SetBounds(kBubblePadding, kBubblePadding,
462 canvas.width() - kBubblePadding * 2,
463 pref_size.height());
464
465 int next_v_space = label1_->y() + pref_size.height() +
466 views::kRelatedControlSmallVerticalSpacing;
467
468 pref_size = label2_->GetPreferredSize();
469 label2_->SetBounds(kBubblePadding, next_v_space,
470 canvas.width() - kBubblePadding * 2,
471 pref_size.height());
472 }
473
474 gfx::Size FirstRunMinimalBubbleView::GetPreferredSize() {
475 return gfx::Size(views::Widget::GetLocalizedContentsSize(
476 IDS_FIRSTRUN_MINIMAL_BUBBLE_DIALOG_WIDTH_CHARS,
477 IDS_FIRSTRUN_MINIMAL_BUBBLE_DIALOG_HEIGHT_LINES));
478 }
479
480 void FirstRunMinimalBubbleView::FocusWillChange(View* focused_before,
481 View* focused_now) {
482 // No buttons in minimal bubble to register focus changes.
483 }
484
485
486 // FirstRunBubble ------------------------------------------------------------- 141 // FirstRunBubble -------------------------------------------------------------
487 142
488 // static 143 // static
489 FirstRunBubble* FirstRunBubble::Show( 144 FirstRunBubble* FirstRunBubble::Show(
490 Profile* profile, 145 Profile* profile,
491 views::Widget* parent, 146 views::Widget* parent,
492 const gfx::Rect& position_relative_to, 147 const gfx::Rect& position_relative_to,
493 views::BubbleBorder::ArrowLocation arrow_location, 148 views::BubbleBorder::ArrowLocation arrow_location) {
494 FirstRun::BubbleType bubble_type) { 149 FirstRunBubble* delegate =
495 FirstRunBubble* bubble = new FirstRunBubble(); 150 new FirstRunBubble(profile,
496 FirstRunBubbleViewBase* view = NULL; 151 parent,
497 152 position_relative_to,
498 switch (bubble_type) { 153 arrow_location);
499 case FirstRun::OEM_BUBBLE: 154 views::BubbleDelegateView::CreateBubble(delegate, parent);
500 view = new FirstRunOEMBubbleView(bubble, profile); 155 delegate->StartFade(true);
501 break; 156 return delegate;
502 case FirstRun::LARGE_BUBBLE:
503 view = new FirstRunBubbleView(bubble, profile);
504 break;
505 case FirstRun::MINIMAL_BUBBLE:
506 view = new FirstRunMinimalBubbleView(bubble, profile);
507 break;
508 default:
509 NOTREACHED();
510 }
511 bubble->set_view(view);
512 bubble->InitBubble(
513 parent, position_relative_to, arrow_location, view, bubble);
514 bubble->GetWidget()->GetFocusManager()->AddFocusChangeListener(view);
515 view->BubbleShown();
516 return bubble;
517 } 157 }
518 158
519 FirstRunBubble::FirstRunBubble() 159 void FirstRunBubble::Init() {
520 : has_been_activated_(false), 160 SetLayoutManager(new views::FillLayout());
521 ALLOW_THIS_IN_INITIALIZER_LIST(enable_window_method_factory_(this)), 161 view_ = new FirstRunBubbleView(this, profile_);
522 view_(NULL) { 162 view_->InitContents();
163 AddChildView(view_);
164 }
165
166 FirstRunBubble::FirstRunBubble(
167 Profile* profile,
168 views::Widget* parent,
169 const gfx::Rect& position_relative_to,
170 views::BubbleBorder::ArrowLocation arrow_location)
171 : views::BubbleDelegateView(position_relative_to.origin(),
172 arrow_location,
173 SK_ColorWHITE),
174 profile_(profile),
175 parent_(parent),
176 has_been_activated_(false),
177 ALLOW_THIS_IN_INITIALIZER_LIST(enable_window_method_factory_(this)) {
523 } 178 }
524 179
525 FirstRunBubble::~FirstRunBubble() { 180 FirstRunBubble::~FirstRunBubble() {
526 enable_window_method_factory_.InvalidateWeakPtrs(); 181 enable_window_method_factory_.InvalidateWeakPtrs();
527 GetWidget()->GetFocusManager()->RemoveFocusChangeListener(view_);
528 } 182 }
529 183
184 #if defined(OS_WIN) && !defined(USE_AURA)
185 // TODO(alicet): do I still need this block?
530 void FirstRunBubble::EnableParent() { 186 void FirstRunBubble::EnableParent() {
531 ::EnableWindow(GetParent(), true); 187 ::EnableWindow(GetParent(), true);
532 // The EnableWindow() call above causes the parent to become active, which 188 // The EnableWindow() call above causes the parent to become active, which
533 // resets the flag set by Bubble's call to DisableInactiveRendering(), so we 189 // resets the flag set by Bubble's call to DisableInactiveRendering(), so we
534 // have to call it again before activating the bubble to prevent the parent 190 // have to call it again before activating the bubble to prevent the parent
535 // window from rendering inactive. 191 // window from rendering inactive.
536 // TODO(beng): this only works in custom-frame mode, not glass-frame mode. 192 // TODO(beng): this only works in custom-frame mode, not glass-frame mode.
Miranda Callahan 2011/11/02 15:36:14 Is this TODO still valid, or did it refer to the G
alicet1 2011/11/03 18:21:51 ah right, this is left there so that I remember to
537 HWND bubble_owner = GetLogicalBubbleOwner(GetNativeView()); 193 if (parent_)
538 views::Widget* parent = views::Widget::GetWidgetForNativeView(bubble_owner); 194 parent_->DisableInactiveRendering();
539 if (parent)
540 parent->DisableInactiveRendering();
541 // Reactivate the FirstRunBubble so it responds to OnActivate messages. 195 // Reactivate the FirstRunBubble so it responds to OnActivate messages.
542 SetWindowPos(GetParent(), 0, 0, 0, 0, 196 SetWindowPos(GetParent(), 0, 0, 0, 0,
543 SWP_NOSIZE | SWP_NOMOVE | SWP_NOREDRAW | SWP_SHOWWINDOW); 197 SWP_NOSIZE | SWP_NOMOVE | SWP_NOREDRAW | SWP_SHOWWINDOW);
544 } 198 }
545 199
546 #if defined(OS_WIN) && !defined(USE_AURA)
547 void FirstRunBubble::OnActivate(UINT action, BOOL minimized, HWND window) { 200 void FirstRunBubble::OnActivate(UINT action, BOOL minimized, HWND window) {
548 // Keep the bubble around for kLingerTime milliseconds, to prevent accidental 201 // Keep the bubble around for kLingerTime milliseconds, to prevent accidental
549 // closure. 202 // closure.
550 const int kLingerTime = 3000; 203 const int kLingerTime = 3000;
551 204
552 // We might get re-enabled right before we are closed (sequence is: we get 205 // We might get re-enabled right before we are closed (sequence is: we get
553 // deactivated, we call close, before we are actually closed we get 206 // deactivated, we call close, before we are actually closed we get
554 // reactivated). Don't do the disabling of the parent in such cases. 207 // reactivated). Don't do the disabling of the parent in such cases.
555 if (action == WA_ACTIVE && !has_been_activated_) { 208 if (action == WA_ACTIVE && !has_been_activated_) {
556 has_been_activated_ = true; 209 has_been_activated_ = true;
557 210
558 ::EnableWindow(GetParent(), false); 211 ::EnableWindow(GetParent(), false);
559 212
560 MessageLoop::current()->PostDelayedTask( 213 MessageLoop::current()->PostDelayedTask(
561 FROM_HERE, 214 FROM_HERE,
562 base::Bind(&FirstRunBubble::EnableParent, 215 base::Bind(&FirstRunBubble::EnableParent,
563 enable_window_method_factory_.GetWeakPtr()), 216 enable_window_method_factory_.GetWeakPtr()),
564 kLingerTime); 217 kLingerTime);
565 return; 218 return;
566 } 219 }
567 220
568 // Keep window from automatically closing until kLingerTime has passed. 221 // Keep window from automatically closing until kLingerTime has passed.
569 if (::IsWindowEnabled(GetParent())) 222 if (::IsWindowEnabled(GetParent()))
570 Bubble::OnActivate(action, minimized, window); 223 Bubble::OnActivate(action, minimized, window);
571 } 224 }
572 #endif 225 #endif
573 226
574 void FirstRunBubble::BubbleClosing(Bubble* bubble, bool closed_by_escape) { 227 void FirstRunBubble::WindowClosing() {
575 // Make sure our parent window is re-enabled. 228 // Make sure our parent window is re-enabled.
576 if (!IsWindowEnabled(GetParent())) 229 if (parent_ && parent_->GetNativeView())
577 ::EnableWindow(GetParent(), true); 230 GetFocusManager()->FocusNativeView(parent_->GetNativeView());
578 } 231 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698