summaryrefslogtreecommitdiffstats
path: root/chrome/browser/views/first_run_bubble.cc
diff options
context:
space:
mode:
Diffstat (limited to 'chrome/browser/views/first_run_bubble.cc')
-rw-r--r--chrome/browser/views/first_run_bubble.cc241
1 files changed, 241 insertions, 0 deletions
diff --git a/chrome/browser/views/first_run_bubble.cc b/chrome/browser/views/first_run_bubble.cc
new file mode 100644
index 0000000..86f9fb1
--- /dev/null
+++ b/chrome/browser/views/first_run_bubble.cc
@@ -0,0 +1,241 @@
+// Copyright 2008, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include "chrome/browser/views/first_run_bubble.h"
+
+#include "chrome/app/locales/locale_settings.h"
+#include "chrome/browser/browser.h"
+#include "chrome/browser/browser_list.h"
+#include "chrome/browser/chrome_frame.h"
+#include "chrome/browser/options_window.h"
+#include "chrome/browser/standard_layout.h"
+#include "chrome/browser/template_url_model.h"
+#include "chrome/common/l10n_util.h"
+#include "chrome/common/resource_bundle.h"
+#include "chrome/views/event.h"
+#include "chrome/views/label.h"
+#include "chrome/views/native_button.h"
+
+#include "generated_resources.h"
+
+namespace {
+
+// How much extra padding to put around our content over what
+// infobubble provides.
+static const int kBubblePadding = 4;
+
+// TODO(cpu): bug 1187517. It is possible that there is no default provider.
+// we should make sure there is none at first run.
+std::wstring GetDefaultSearchEngineName() {
+ Browser* browser = BrowserList::GetLastActive();
+ DCHECK(browser);
+ const TemplateURL* const default_provider =
+ browser->profile()->GetTemplateURLModel()->GetDefaultSearchProvider();
+ DCHECK(default_provider);
+ return default_provider->short_name();
+}
+
+} // namespace
+
+// Implements the client view inside the first run bubble. It is kind of a
+// dialog-ish view, but is not a true dialog.
+class FirstRunBubbleView : public ChromeViews::View,
+ public ChromeViews::NativeButton::Listener {
+ public:
+ explicit FirstRunBubbleView(FirstRunBubble* bubble_window)
+ : bubble_window_(bubble_window),
+ label1_(NULL),
+ label2_(NULL),
+ label3_(NULL),
+ keep_button_(NULL),
+ change_button_(NULL) {
+ ChromeFont& font =
+ ResourceBundle::GetSharedInstance().GetFont(ResourceBundle::MediumFont);
+
+ label1_ = new ChromeViews::Label(l10n_util::GetString(IDS_FR_BUBBLE_TITLE));
+ label1_->SetFont(font.DeriveFont(3, ChromeFont::BOLD));
+ label1_->SetHorizontalAlignment(ChromeViews::Label::ALIGN_LEFT);
+ AddChildView(label1_);
+
+ CSize ps;
+ GetPreferredSize(&ps);
+
+ label2_ =
+ new ChromeViews::Label(l10n_util::GetString(IDS_FR_BUBBLE_SUBTEXT));
+ label2_->SetMultiLine(true);
+ label2_->SetFont(font);
+ label2_->SetHorizontalAlignment(ChromeViews::Label::ALIGN_LEFT);
+ label2_->SizeToFit(ps.cx - kBubblePadding * 2);
+ AddChildView(label2_);
+
+ std::wstring question_str
+ = l10n_util::GetStringF(IDS_FR_BUBBLE_QUESTION,
+ GetDefaultSearchEngineName());
+ label3_ = new ChromeViews::Label(question_str);
+ label3_->SetMultiLine(true);
+ label3_->SetFont(font);
+ label3_->SetHorizontalAlignment(ChromeViews::Label::ALIGN_LEFT);
+ label3_->SizeToFit(ps.cx - kBubblePadding * 2);
+ AddChildView(label3_);
+
+ std::wstring keep_str = l10n_util::GetStringF(IDS_FR_BUBBLE_OK,
+ GetDefaultSearchEngineName());
+ keep_button_ = new ChromeViews::NativeButton(keep_str, true);
+ keep_button_->SetListener(this);
+ AddChildView(keep_button_);
+
+ std::wstring change_str = l10n_util::GetString(IDS_FR_BUBBLE_CHANGE);
+ change_button_ = new ChromeViews::NativeButton(change_str);
+ change_button_->SetListener(this);
+ AddChildView(change_button_);
+ }
+
+ // Overridden from ChromeViews::View.
+ virtual void DidChangeBounds(const CRect& previous, const CRect& current) {
+ Layout();
+ }
+
+ // Overridden from NativeButton::Listener.
+ virtual void ButtonPressed(ChromeViews::NativeButton* sender) {
+ bubble_window_->Close();
+ if (change_button_ == sender) {
+ Browser* browser = BrowserList::GetLastActive();
+ if (browser) {
+ ShowOptionsWindow(OPTIONS_PAGE_GENERAL, OPTIONS_GROUP_DEFAULT_SEARCH,
+ browser->profile());
+ }
+ }
+ }
+
+ // Overridden from ChromeViews::View.
+ virtual void Layout() {
+ CSize canvas;
+ GetPreferredSize(&canvas);
+
+ CSize pref_size;
+ label1_->GetPreferredSize(&pref_size);
+ label1_->SetBounds(kBubblePadding, kBubblePadding, pref_size.cx,
+ pref_size.cy);
+
+ int next_v_space = label1_->GetY() + label1_->GetHeight() +
+ kRelatedControlSmallVerticalSpacing;
+
+ label2_->GetPreferredSize(&pref_size);
+ label2_->SetBounds(kBubblePadding, next_v_space,
+ canvas.cx - kBubblePadding * 2,
+ pref_size.cy);
+
+ next_v_space = label2_->GetY() + label2_->GetHeight() +
+ kPanelSubVerticalSpacing;
+
+ label3_->GetPreferredSize(&pref_size);
+ label3_->SetBounds(kBubblePadding, next_v_space,
+ canvas.cx - kBubblePadding * 2,
+ pref_size.cy);
+
+ change_button_->GetPreferredSize(&pref_size);
+ change_button_->SetBounds(canvas.cx - pref_size.cx - kBubblePadding,
+ canvas.cy - pref_size.cy - kButtonVEdgeMargin,
+ pref_size.cx, pref_size.cy);
+
+ keep_button_->GetPreferredSize(&pref_size);
+ keep_button_->SetBounds(change_button_->GetX() - pref_size.cx -
+ kRelatedButtonHSpacing, change_button_->GetY(),
+ pref_size.cx, pref_size.cy);
+ }
+
+ virtual void ViewHierarchyChanged(bool is_add, View* parent, View* child) {
+ if (keep_button_)
+ keep_button_->RequestFocus();
+ }
+
+ // Overridden from ChromeViews::View.
+ virtual void GetPreferredSize(CSize *out) {
+ DCHECK(out);
+ *out = ChromeViews::Window::GetLocalizedContentsSize(
+ IDS_FIRSTRUNBUBBLE_DIALOG_WIDTH_CHARS,
+ IDS_FIRSTRUNBUBBLE_DIALOG_HEIGHT_LINES).ToSIZE();
+ }
+
+ private:
+ FirstRunBubble* bubble_window_;
+ ChromeViews::Label* label1_;
+ ChromeViews::Label* label2_;
+ ChromeViews::Label* label3_;
+ ChromeViews::NativeButton* change_button_;
+ ChromeViews::NativeButton* keep_button_;
+ DISALLOW_EVIL_CONSTRUCTORS(FirstRunBubbleView);
+};
+
+// Keep the bubble around for kLingerTime milliseconds, to prevent accidental
+// closure.
+static const int kLingerTime = 1000;
+
+void FirstRunBubble::OnActivate(UINT action, BOOL minimized, HWND window) {
+ // We might get re-enabled right before we are closed (sequence is: we get
+ // deactivated, we call close, before we are actually closed we get
+ // reactivated). Don't do the disabling of the parent in such cases.
+ if (action == WA_ACTIVE && !has_been_activated_) {
+ has_been_activated_ = true;
+
+ // Disable the browser to prevent accidental rapid clicks from closing the
+ // bubble.
+ ::EnableWindow(GetParent(), false);
+
+ MessageLoop::current()->PostDelayedTask(FROM_HERE,
+ enable_window_method_factory_.NewRunnableMethod(
+ &FirstRunBubble::EnableParent),
+ kLingerTime);
+ }
+ InfoBubble::OnActivate(action, minimized, window);
+}
+
+void FirstRunBubble::InfoBubbleClosing(InfoBubble* info_bubble) {
+ // Make sure our parent window is re-enabled.
+ if (!IsWindowEnabled(GetParent()))
+ ::EnableWindow(GetParent(), true);
+ enable_window_method_factory_.RevokeAll();
+}
+
+FirstRunBubble* FirstRunBubble::Show(HWND parent_hwnd,
+ const gfx::Rect& position_relative_to) {
+ FirstRunBubble* window = new FirstRunBubble();
+ ChromeViews::View* view = new FirstRunBubbleView(window);
+ window->SetDelegate(window);
+ window->Init(parent_hwnd, position_relative_to, view);
+ ChromeFrame* frame = window->GetHostingFrame();
+ DCHECK(frame);
+ frame->InfoBubbleShowing();
+ window->ShowWindow(SW_SHOW);
+ return window;
+}
+
+void FirstRunBubble::EnableParent() {
+ ::EnableWindow(GetParent(), true);
+}