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

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

Powered by Google App Engine
This is Rietveld 408576698