diff options
author | kuchhal@chromium.org <kuchhal@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-07-14 16:43:15 +0000 |
---|---|---|
committer | kuchhal@chromium.org <kuchhal@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-07-14 16:43:15 +0000 |
commit | 4f26826dc91e9aa41f3adbda05f94c44581eddd8 (patch) | |
tree | f5de5a1b868c8b8d1cfc22c9e44dc77da23ccbae | |
parent | 88efb7ec99239eeecaa17d21f8635be1bce29cca (diff) | |
download | chromium_src-4f26826dc91e9aa41f3adbda05f94c44581eddd8.zip chromium_src-4f26826dc91e9aa41f3adbda05f94c44581eddd8.tar.gz chromium_src-4f26826dc91e9aa41f3adbda05f94c44581eddd8.tar.bz2 |
Linux: Add first run search bubble.
Review URL: http://codereview.chromium.org/149501
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@20625 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | chrome/browser/first_run.cc | 25 | ||||
-rw-r--r-- | chrome/browser/first_run_win.cc | 22 | ||||
-rw-r--r-- | chrome/browser/gtk/bookmark_manager_gtk.cc | 26 | ||||
-rw-r--r-- | chrome/browser/gtk/first_run_bubble.cc | 124 | ||||
-rw-r--r-- | chrome/browser/gtk/first_run_bubble.h | 68 | ||||
-rw-r--r-- | chrome/browser/gtk/first_run_dialog.cc | 13 | ||||
-rw-r--r-- | chrome/browser/gtk/location_bar_view_gtk.cc | 30 | ||||
-rw-r--r-- | chrome/browser/gtk/location_bar_view_gtk.h | 5 | ||||
-rw-r--r-- | chrome/chrome.gyp | 2 | ||||
-rw-r--r-- | chrome/common/gtk_util.cc | 21 | ||||
-rw-r--r-- | chrome/common/gtk_util.h | 6 |
11 files changed, 295 insertions, 47 deletions
diff --git a/chrome/browser/first_run.cc b/chrome/browser/first_run.cc index f0b0f74..712d3b1 100644 --- a/chrome/browser/first_run.cc +++ b/chrome/browser/first_run.cc @@ -15,6 +15,8 @@ #include "base/file_util.h" #include "base/path_service.h" #include "chrome/common/chrome_paths.h" +#include "chrome/common/pref_names.h" +#include "chrome/common/pref_service.h" namespace { @@ -87,3 +89,26 @@ bool FirstRun::CreateSentinel() { return false; return file_util::WriteFile(first_run_sentinel, "", 0) != -1; } + +bool FirstRun::SetShowFirstRunBubblePref() { + PrefService* local_state = g_browser_process->local_state(); + if (!local_state) + return false; + if (!local_state->IsPrefRegistered(prefs::kShouldShowFirstRunBubble)) { + local_state->RegisterBooleanPref(prefs::kShouldShowFirstRunBubble, false); + local_state->SetBoolean(prefs::kShouldShowFirstRunBubble, true); + } + return true; +} + +bool FirstRun::SetShowWelcomePagePref() { + PrefService* local_state = g_browser_process->local_state(); + if (!local_state) + return false; + if (!local_state->IsPrefRegistered(prefs::kShouldShowWelcomePage)) { + local_state->RegisterBooleanPref(prefs::kShouldShowWelcomePage, false); + local_state->SetBoolean(prefs::kShouldShowWelcomePage, true); + } + return true; +} + diff --git a/chrome/browser/first_run_win.cc b/chrome/browser/first_run_win.cc index 4e58792..18b0a44 100644 --- a/chrome/browser/first_run_win.cc +++ b/chrome/browser/first_run_win.cc @@ -592,17 +592,6 @@ int FirstRun::ImportNow(Profile* profile, const CommandLine& cmdline) { return observer.import_result(); } -bool FirstRun::SetShowFirstRunBubblePref() { - PrefService* local_state = g_browser_process->local_state(); - if (!local_state) - return false; - if (!local_state->IsPrefRegistered(prefs::kShouldShowFirstRunBubble)) { - local_state->RegisterBooleanPref(prefs::kShouldShowFirstRunBubble, false); - local_state->SetBoolean(prefs::kShouldShowFirstRunBubble, true); - } - return true; -} - bool FirstRun::SetOEMFirstRunBubblePref() { PrefService* local_state = g_browser_process->local_state(); if (!local_state) @@ -615,17 +604,6 @@ bool FirstRun::SetOEMFirstRunBubblePref() { return true; } -bool FirstRun::SetShowWelcomePagePref() { - PrefService* local_state = g_browser_process->local_state(); - if (!local_state) - return false; - if (!local_state->IsPrefRegistered(prefs::kShouldShowWelcomePage)) { - local_state->RegisterBooleanPref(prefs::kShouldShowWelcomePage, false); - local_state->SetBoolean(prefs::kShouldShowWelcomePage, true); - } - return true; -} - ////////////////////////////////////////////////////////////////////////// namespace { diff --git a/chrome/browser/gtk/bookmark_manager_gtk.cc b/chrome/browser/gtk/bookmark_manager_gtk.cc index 77a7c6a..dab3508 100644 --- a/chrome/browser/gtk/bookmark_manager_gtk.cc +++ b/chrome/browser/gtk/bookmark_manager_gtk.cc @@ -329,28 +329,12 @@ void BookmarkManagerGtk::InitWidgets() { l10n_util::GetStringUTF8(IDS_BOOKMARK_MANAGER_TITLE).c_str()); // Set the default size of the bookmark manager. - // Windows has code to do this that uses ChromeFont; we could share it but - // since we don't plan to use it elsewhere it's probably not worth the effort. - PangoContext* context = gtk_widget_create_pango_context(window_); - PangoFontMetrics* metrics = - pango_context_get_metrics(context, window_->style->font_desc, - pango_context_get_language(context)); - double chars = 0; - StringToDouble(WideToUTF8(l10n_util::GetString( - IDS_BOOKMARK_MANAGER_DIALOG_WIDTH_CHARS)), &chars); - int width = - pango_font_metrics_get_approximate_char_width(metrics) * - static_cast<int>(chars) / PANGO_SCALE; - double lines = 0; - StringToDouble(WideToUTF8(l10n_util::GetString( - IDS_BOOKMARK_MANAGER_DIALOG_HEIGHT_LINES)), &lines); - int height = - (pango_font_metrics_get_ascent(metrics) + - pango_font_metrics_get_descent(metrics)) * - static_cast<int>(lines) / PANGO_SCALE; + int width, height; + gtk_util::GetWidgetSizeFromResources(window_, + IDS_BOOKMARK_MANAGER_DIALOG_WIDTH_CHARS, + IDS_BOOKMARK_MANAGER_DIALOG_HEIGHT_LINES, + &width, &height); gtk_window_set_default_size(GTK_WINDOW(window_), width, height); - pango_font_metrics_unref(metrics); - g_object_unref(context); // Build the organize and tools menus. organize_ = gtk_menu_item_new_with_label( diff --git a/chrome/browser/gtk/first_run_bubble.cc b/chrome/browser/gtk/first_run_bubble.cc new file mode 100644 index 0000000..05287a8 --- /dev/null +++ b/chrome/browser/gtk/first_run_bubble.cc @@ -0,0 +1,124 @@ +// Copyright (c) 2009 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. + +#include "chrome/browser/gtk/first_run_bubble.h" + +#include <gtk/gtk.h> + +#include "app/l10n_util.h" +#include "chrome/browser/options_window.h" +#include "chrome/browser/search_engines/template_url_model.h" +#include "chrome/common/gtk_util.h" +#include "grit/generated_resources.h" +#include "grit/google_chrome_strings.h" + +namespace { +// Markup for the text of the Omnibox search label +const char kSearchLabelMarkup[] = "<big><b>%s</b></big>"; + +// Padding for the buttons on first run bubble. +const int kButtonPadding = 4; + +string16 GetDefaultSearchEngineName(Profile* profile) { + if (!profile) { + NOTREACHED(); + return string16(); + } + const TemplateURL* const default_provider = + profile->GetTemplateURLModel()->GetDefaultSearchProvider(); + if (!default_provider) { + return string16(); + } + return WideToUTF16(default_provider->short_name()); +} +} // namespace + +// static +void FirstRunBubble::Show(Profile* profile, + GtkWindow* parent, + const gfx::Rect& rect, + bool use_OEM_bubble) { + new FirstRunBubble(profile, parent, rect); +} + +void FirstRunBubble::InfoBubbleClosing(InfoBubbleGtk* info_bubble, + bool closed_by_escape) { + // TODO(port): Enable parent window +} + +FirstRunBubble::FirstRunBubble(Profile* profile, + GtkWindow* parent, + const gfx::Rect& rect) + : profile_(profile), + parent_(parent), + content_(NULL), + bubble_(NULL) { + GtkWidget* label1 = gtk_label_new(NULL); + char* markup = g_markup_printf_escaped(kSearchLabelMarkup, + l10n_util::GetStringUTF8(IDS_FR_BUBBLE_TITLE).c_str()); + gtk_label_set_markup(GTK_LABEL(label1), markup); + g_free(markup); + gtk_misc_set_alignment(GTK_MISC(label1), 0, .5); + + GtkWidget* label2 = gtk_label_new( + l10n_util::GetStringUTF8(IDS_FR_BUBBLE_SUBTEXT).c_str()); + gtk_misc_set_alignment(GTK_MISC(label2), 0, .5); + gtk_label_set_line_wrap(GTK_LABEL(label2), TRUE); + + string16 search_engine = GetDefaultSearchEngineName(profile_); + GtkWidget* label3 = gtk_label_new( + l10n_util::GetStringFUTF8(IDS_FR_BUBBLE_QUESTION, search_engine).c_str()); + gtk_misc_set_alignment(GTK_MISC(label3), 0, .5); + gtk_label_set_line_wrap(GTK_LABEL(label3), TRUE); + + GtkWidget* keep_button = gtk_button_new_with_label( + l10n_util::GetStringFUTF8(IDS_FR_BUBBLE_OK, search_engine).c_str()); + GtkWidget* change_button = gtk_button_new_with_label( + l10n_util::GetStringUTF8(IDS_FR_BUBBLE_CHANGE).c_str()); + + content_ = gtk_vbox_new(FALSE, 5); + gtk_box_pack_start(GTK_BOX(content_), label1, TRUE, TRUE, 0); + gtk_box_pack_start(GTK_BOX(content_), label2, TRUE, TRUE, 0); + gtk_box_pack_start(GTK_BOX(content_), label3, TRUE, TRUE, 0); + + GtkWidget* bottom = gtk_hbox_new(FALSE, 0); + // We want the buttons on the right, so just use an expanding label to fill + // all of the extra space on the right. + gtk_box_pack_start(GTK_BOX(bottom), gtk_label_new(""), TRUE, TRUE, 0); + gtk_box_pack_start(GTK_BOX(bottom), keep_button, FALSE, FALSE, + kButtonPadding); + gtk_box_pack_start(GTK_BOX(bottom), change_button, FALSE, FALSE, 0); + + gtk_box_pack_start(GTK_BOX(content_), bottom, TRUE, TRUE, 0); + // We want the focus to start on the keep entry, not on the change button. + gtk_container_set_focus_child(GTK_CONTAINER(content_), keep_button); + + bubble_ = InfoBubbleGtk::Show(parent_, rect, content_, this); + if (!bubble_) { + NOTREACHED(); + return; + } + + g_signal_connect(content_, "destroy", + G_CALLBACK(&HandleDestroyThunk), this); + g_signal_connect(keep_button, "clicked", + G_CALLBACK(&HandleKeepButtonThunk), this); + g_signal_connect(change_button, "clicked", + G_CALLBACK(&HandleChangeButtonThunk), this); +} + +void FirstRunBubble::HandleChangeButton() { + bubble_->Close(); + ShowOptionsWindow(OPTIONS_PAGE_GENERAL, OPTIONS_GROUP_DEFAULT_SEARCH, + profile_); +} + +void FirstRunBubble::HandleDestroy() { + content_ = NULL; + delete this; +} + +void FirstRunBubble::HandleKeepButton() { + bubble_->Close(); +} diff --git a/chrome/browser/gtk/first_run_bubble.h b/chrome/browser/gtk/first_run_bubble.h new file mode 100644 index 0000000..6e7c817 --- /dev/null +++ b/chrome/browser/gtk/first_run_bubble.h @@ -0,0 +1,68 @@ +// Copyright (c) 2009 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. + +// This is the GTK implementation of the First Run bubble, the dialog box +// presented on first run of Chromium. There can only ever be a single +// bubble open, so the class presents only static methods. + +#ifndef CHROME_BROWSER_GTK_FIRST_RUN_BUBBLE_GTK_H_ +#define CHROME_BROWSER_GTK_FIRST_RUN_BUBBLE_GTK_H_ + +#include <gtk/gtk.h> + +#include "base/basictypes.h" +#include "chrome/browser/gtk/info_bubble_gtk.h" +#include "chrome/browser/profile.h" + +class FirstRunBubble : public InfoBubbleGtkDelegate { + public: + // Shows the first run bubble, pointing at |rect|. + static void Show(Profile* profile, + GtkWindow* parent, + const gfx::Rect& rect, + bool use_OEM_bubble); + + // Implements the InfoBubbleGtkDelegate. We are notified when the bubble + // is about to be closed. + virtual void InfoBubbleClosing(InfoBubbleGtk* info_bubble, + bool closed_by_escape); + virtual bool CloseOnEscape() { return true; } + + private: + FirstRunBubble(Profile* profile, + GtkWindow* parent, + const gfx::Rect& rect); + ~FirstRunBubble() { } + + static void HandleChangeButtonThunk(GtkWidget* widget, gpointer user_data) { + reinterpret_cast<FirstRunBubble*>(user_data)->HandleChangeButton(); + } + void HandleChangeButton(); + + static void HandleDestroyThunk(GtkWidget* widget, gpointer userdata) { + reinterpret_cast<FirstRunBubble*>(userdata)->HandleDestroy(); + } + void HandleDestroy(); + + static void HandleKeepButtonThunk(GtkWidget* widget, gpointer user_data) { + reinterpret_cast<FirstRunBubble*>(user_data)->HandleKeepButton(); + } + void HandleKeepButton(); + + // Our current profile. + Profile* profile_; + + // The toplevel window our dialogs should be transient for. + GtkWindow* parent_; + + // We let the InfoBubble own our content, and then we delete ourself + // when the widget is destroyed (when the InfoBubble is destroyed). + GtkWidget* content_; + + InfoBubbleGtk* bubble_; + + DISALLOW_COPY_AND_ASSIGN(FirstRunBubble); +}; + +#endif // CHROME_BROWSER_GTK_FIRST_RUN_BUBBLE_GTK_H_ diff --git a/chrome/browser/gtk/first_run_dialog.cc b/chrome/browser/gtk/first_run_dialog.cc index 2646b6f..f7a104f 100644 --- a/chrome/browser/gtk/first_run_dialog.cc +++ b/chrome/browser/gtk/first_run_dialog.cc @@ -13,6 +13,7 @@ #include "chrome/installer/util/google_update_settings.h" #include "grit/generated_resources.h" #include "grit/google_chrome_strings.h" +#include "grit/locale_settings.h" // static bool FirstRunDialog::Show(Profile* profile) { @@ -35,6 +36,12 @@ FirstRunDialog::FirstRunDialog(Profile* profile, int& response) GTK_RESPONSE_REJECT, NULL); gtk_window_set_resizable(GTK_WINDOW(dialog_), FALSE); + int width, height; + gtk_util::GetWidgetSizeFromResources(dialog_, + IDS_FIRSTRUN_DIALOG_WIDTH_CHARS, + IDS_FIRSTRUN_DIALOG_HEIGHT_LINES, + &width, &height); + gtk_window_set_default_size(GTK_WINDOW(dialog_), width, height); g_signal_connect(G_OBJECT(dialog_), "delete-event", G_CALLBACK(gtk_widget_hide_on_delete), NULL); @@ -42,8 +49,6 @@ FirstRunDialog::FirstRunDialog(Profile* profile, int& response) gtk_box_set_spacing(GTK_BOX(content_area), 18); GtkWidget* vbox = gtk_vbox_new(FALSE, 12); - // Force a size on the vbox so the labels wrap. - gtk_widget_set_size_request(vbox, 350, -1); #if defined(GOOGLE_CHROME_BUILD) // TODO(port): remove this warning before beta release when we have all the @@ -149,6 +154,10 @@ void FirstRunDialog::OnDialogResponse(GtkWidget* widget, int response) { } } + // Set preference to show first run bubble and welcome page. + FirstRun::SetShowFirstRunBubblePref(); + FirstRun::SetShowWelcomePagePref(); + gtk_widget_destroy(dialog_); MessageLoop::current()->Quit(); } diff --git a/chrome/browser/gtk/location_bar_view_gtk.cc b/chrome/browser/gtk/location_bar_view_gtk.cc index 08eb6fc..38c2901 100644 --- a/chrome/browser/gtk/location_bar_view_gtk.cc +++ b/chrome/browser/gtk/location_bar_view_gtk.cc @@ -16,6 +16,7 @@ #include "chrome/browser/alternate_nav_url_fetcher.h" #include "chrome/browser/autocomplete/autocomplete_edit_view_gtk.h" #include "chrome/browser/command_updater.h" +#include "chrome/browser/gtk/first_run_bubble.h" #include "chrome/browser/gtk/gtk_theme_provider.h" #include "chrome/browser/profile.h" #include "chrome/browser/search_engines/template_url.h" @@ -36,6 +37,11 @@ const int kBottomMargin = 1; // We draw a border on the top and bottom (but not on left or right). const int kBorderThickness = 1; +// Left margin of first run bubble. +const int kFirstRunBubbleLeftMargin = 20; +// Task delay (in milliseconds) to show first run bubble. +const int kFirstRunBubbleTaskDelay = 30; + // Left and right padding/margin. // no icon/text : 4px url_text 4px // [4px|url text|4px] <hide ssl icon> <hide ev text> @@ -103,7 +109,8 @@ LocationBarViewGtk::LocationBarViewGtk(CommandUpdater* command_updater, toolbar_model_(toolbar_model), popup_positioner_(popup_positioner), disposition_(CURRENT_TAB), - transition_(PageTransition::TYPED) { + transition_(PageTransition::TYPED), + first_run_bubble_(this) { } LocationBarViewGtk::~LocationBarViewGtk() { @@ -308,7 +315,10 @@ std::wstring LocationBarViewGtk::GetTitle() const { } void LocationBarViewGtk::ShowFirstRunBubble(bool use_OEM_bubble) { - NOTIMPLEMENTED(); + Task* task = first_run_bubble_.NewRunnableMethod( + &LocationBarViewGtk::ShowFirstRunBubbleInternal, use_OEM_bubble); + MessageLoop::current()->PostDelayedTask(FROM_HERE, task, + kFirstRunBubbleTaskDelay); } std::wstring LocationBarViewGtk::GetInputString() const { @@ -491,3 +501,19 @@ void LocationBarViewGtk::SetKeywordHintLabel(const std::wstring& keyword) { gtk_label_set_text(GTK_LABEL(tab_to_search_hint_trailing_label_), trailing.c_str()); } + +void LocationBarViewGtk::ShowFirstRunBubbleInternal(bool use_OEM_bubble) { + if (!location_entry_.get() || !widget()->window) + return; + + gint x, y; + gdk_window_get_origin(widget()->window, &x, &y); + // The bubble needs to be just below the Omnibox and slightly to the right + // of star button, so shift x and y co-ordinates. + x += widget()->allocation.x + kFirstRunBubbleLeftMargin; + y += widget()->allocation.y + widget()->allocation.height; + + FirstRunBubble::Show(profile_, + GTK_WINDOW(gtk_widget_get_toplevel(widget())), + gfx::Rect(x, y, 0, 0), use_OEM_bubble); +} diff --git a/chrome/browser/gtk/location_bar_view_gtk.h b/chrome/browser/gtk/location_bar_view_gtk.h index 3ccbbb2..f3cafd2 100644 --- a/chrome/browser/gtk/location_bar_view_gtk.h +++ b/chrome/browser/gtk/location_bar_view_gtk.h @@ -102,6 +102,8 @@ class LocationBarViewGtk : public AutocompleteEditController, // Set the keyword text for the "Press tab to search BLAH" hint box. void SetKeywordHintLabel(const std::wstring& keyword); + void ShowFirstRunBubbleInternal(bool use_OEM_bubble); + // The outermost widget we want to be hosted. OwnedWidgetGtk hbox_; @@ -141,6 +143,9 @@ class LocationBarViewGtk : public AutocompleteEditController, // The transition type to use for the navigation. PageTransition::Type transition_; + // Used schedule a task for the first run info bubble. + ScopedRunnableMethodFactory<LocationBarViewGtk> first_run_bubble_; + DISALLOW_COPY_AND_ASSIGN(LocationBarViewGtk); }; diff --git a/chrome/chrome.gyp b/chrome/chrome.gyp index 5a62435..4a55ddd 100644 --- a/chrome/chrome.gyp +++ b/chrome/chrome.gyp @@ -1026,6 +1026,8 @@ 'browser/gtk/download_started_animation_gtk.cc', 'browser/gtk/edit_search_engine_dialog.cc', 'browser/gtk/edit_search_engine_dialog.h', + 'browser/gtk/first_run_bubble.cc', + 'browser/gtk/first_run_bubble.h', 'browser/gtk/first_run_dialog.cc', 'browser/gtk/first_run_dialog.h', 'browser/gtk/go_button_gtk.cc', diff --git a/chrome/common/gtk_util.cc b/chrome/common/gtk_util.cc index e985bf6..8b7dfd8 100644 --- a/chrome/common/gtk_util.cc +++ b/chrome/common/gtk_util.cc @@ -178,6 +178,27 @@ GtkWidget* CreateGtkBorderBin(GtkWidget* child, const GdkColor* color, return ebox; } +bool GetWidgetSizeFromResources(GtkWidget* widget, int width_chars, + int height_lines, int* width, int* height) { + PangoContext* context = gtk_widget_create_pango_context(widget); + PangoFontMetrics* metrics = pango_context_get_metrics(context, + widget->style->font_desc, pango_context_get_language(context)); + double chars = 0; + StringToDouble(l10n_util::GetStringUTF8(width_chars), &chars); + *width = + pango_font_metrics_get_approximate_char_width(metrics) * + static_cast<int>(chars) / PANGO_SCALE; + double lines = 0; + StringToDouble(l10n_util::GetStringUTF8(height_lines), &lines); + *height = + (pango_font_metrics_get_ascent(metrics) + + pango_font_metrics_get_descent(metrics)) * + static_cast<int>(lines) / PANGO_SCALE; + pango_font_metrics_unref(metrics); + g_object_unref(context); + return true; +} + void RemoveAllChildren(GtkWidget* container) { gtk_container_foreach(GTK_CONTAINER(container), RemoveWidget, container); } diff --git a/chrome/common/gtk_util.h b/chrome/common/gtk_util.h index 983cf4a..85bcc4b 100644 --- a/chrome/common/gtk_util.h +++ b/chrome/common/gtk_util.h @@ -62,6 +62,12 @@ GtkWidget* CreateLabeledControlsGroup(const char* text, ...); GtkWidget* CreateGtkBorderBin(GtkWidget* child, const GdkColor* color, int top, int bottom, int left, int right); +// Calculates the size of given widget based on the size specified in +// number of characters/lines (in locale specific resource file) and +// font metrics. +bool GetWidgetSizeFromResources(GtkWidget* widget, int width_chars, + int height_lines, int* width, int* height); + // Remove all children from this container. void RemoveAllChildren(GtkWidget* container); |