diff options
Diffstat (limited to 'chrome/browser/gtk/options/options_window_gtk.cc')
-rw-r--r-- | chrome/browser/gtk/options/options_window_gtk.cc | 269 |
1 files changed, 269 insertions, 0 deletions
diff --git a/chrome/browser/gtk/options/options_window_gtk.cc b/chrome/browser/gtk/options/options_window_gtk.cc new file mode 100644 index 0000000..3b370eb --- /dev/null +++ b/chrome/browser/gtk/options/options_window_gtk.cc @@ -0,0 +1,269 @@ +// Copyright (c) 2010 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/options_window.h" + +#include <gtk/gtk.h> + +#include "app/l10n_util.h" +#include "base/message_loop.h" +#include "base/scoped_ptr.h" +#include "chrome/browser/accessibility_events.h" +#include "chrome/browser/browser_list.h" +#include "chrome/browser/browser_process.h" +#include "chrome/browser/browser_window.h" +#include "chrome/browser/gtk/accessible_widget_helper_gtk.h" +#include "chrome/browser/gtk/gtk_util.h" +#include "chrome/browser/gtk/options/advanced_page_gtk.h" +#include "chrome/browser/gtk/options/content_page_gtk.h" +#include "chrome/browser/gtk/options/general_page_gtk.h" +#include "chrome/browser/pref_member.h" +#include "chrome/browser/pref_service.h" +#include "chrome/browser/profile.h" +#include "chrome/browser/window_sizer.h" +#include "chrome/common/notification_service.h" +#include "chrome/common/pref_names.h" +#include "grit/chromium_strings.h" +#include "grit/generated_resources.h" + +#if defined(OS_CHROMEOS) +#include "chrome/browser/chromeos/options/internet_page_view.h" +#include "chrome/browser/chromeos/options/system_page_view.h" +#endif + +/////////////////////////////////////////////////////////////////////////////// +// OptionsWindowGtk +// +// The contents of the Options dialog window. + +class OptionsWindowGtk { + public: + explicit OptionsWindowGtk(Profile* profile); + ~OptionsWindowGtk(); + + // Shows the Tab corresponding to the specified OptionsPage. + void ShowOptionsPage(OptionsPage page, OptionsGroup highlight_group); + + private: + static void OnSwitchPage(GtkNotebook* notebook, GtkNotebookPage* page, + guint page_num, OptionsWindowGtk* window); + + static void OnWindowDestroy(GtkWidget* widget, OptionsWindowGtk* window); + + // The options dialog. + GtkWidget* dialog_; + + // The container of the option pages. + GtkWidget* notebook_; + + // The Profile associated with these options. + Profile* profile_; + + // The general page. + GeneralPageGtk general_page_; + + // The content page. + ContentPageGtk content_page_; + + // The advanced (user data) page. + AdvancedPageGtk advanced_page_; + + // The last page the user was on when they opened the Options window. + IntegerPrefMember last_selected_page_; + + scoped_ptr<AccessibleWidgetHelper> accessible_widget_helper_; + + DISALLOW_COPY_AND_ASSIGN(OptionsWindowGtk); +}; + +// The singleton options window object. +static OptionsWindowGtk* options_window = NULL; + +/////////////////////////////////////////////////////////////////////////////// +// OptionsWindowGtk, public: + +OptionsWindowGtk::OptionsWindowGtk(Profile* profile) + // Always show preferences for the original profile. Most state when off + // the record comes from the original profile, but we explicitly use + // the original profile to avoid potential problems. + : profile_(profile->GetOriginalProfile()), + general_page_(profile_), + content_page_(profile_), + advanced_page_(profile_) { + + // We don't need to observe changes in this value. + last_selected_page_.Init(prefs::kOptionsWindowLastTabIndex, + g_browser_process->local_state(), NULL); + + std::string dialog_name = + l10n_util::GetStringFUTF8( + IDS_OPTIONS_DIALOG_TITLE, + WideToUTF16(l10n_util::GetString(IDS_PRODUCT_NAME))); + dialog_ = gtk_dialog_new_with_buttons( + dialog_name.c_str(), + // Prefs window is shared between all browser windows. + NULL, + // Non-modal. + GTK_DIALOG_NO_SEPARATOR, + GTK_STOCK_CLOSE, + GTK_RESPONSE_CLOSE, + NULL); + + accessible_widget_helper_.reset(new AccessibleWidgetHelper( + dialog_, profile)); + accessible_widget_helper_->SendOpenWindowNotification(dialog_name); + + gtk_window_set_default_size(GTK_WINDOW(dialog_), 500, -1); + // Allow browser windows to go in front of the options dialog in metacity. + gtk_window_set_type_hint(GTK_WINDOW(dialog_), GDK_WINDOW_TYPE_HINT_NORMAL); + gtk_box_set_spacing(GTK_BOX(GTK_DIALOG(dialog_)->vbox), + gtk_util::kContentAreaSpacing); + + notebook_ = gtk_notebook_new(); + +#if defined(OS_CHROMEOS) + gtk_notebook_append_page( + GTK_NOTEBOOK(notebook_), + (new chromeos::SystemPageView(profile_))->WrapInGtkWidget(), + gtk_label_new( + l10n_util::GetStringUTF8(IDS_OPTIONS_SYSTEM_TAB_LABEL).c_str())); + + gtk_notebook_append_page( + GTK_NOTEBOOK(notebook_), + (new chromeos::InternetPageView(profile_))->WrapInGtkWidget(), + gtk_label_new( + l10n_util::GetStringUTF8(IDS_OPTIONS_INTERNET_TAB_LABEL).c_str())); +#endif + + gtk_notebook_append_page( + GTK_NOTEBOOK(notebook_), + general_page_.get_page_widget(), + gtk_label_new( + l10n_util::GetStringUTF8(IDS_OPTIONS_GENERAL_TAB_LABEL).c_str())); + + gtk_notebook_append_page( + GTK_NOTEBOOK(notebook_), + content_page_.get_page_widget(), + gtk_label_new( + l10n_util::GetStringUTF8(IDS_OPTIONS_CONTENT_TAB_LABEL).c_str())); + + gtk_notebook_append_page( + GTK_NOTEBOOK(notebook_), + advanced_page_.get_page_widget(), + gtk_label_new( + l10n_util::GetStringUTF8(IDS_OPTIONS_ADVANCED_TAB_LABEL).c_str())); + + gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog_)->vbox), notebook_); + + DCHECK_EQ( + gtk_notebook_get_n_pages(GTK_NOTEBOOK(notebook_)), OPTIONS_PAGE_COUNT); + + // Show the content so that we can compute full dialog size, both + // for centering and because we want to show the notebook before + // connecting switch-page signal, otherwise we'll immediately get a + // signal switching to page 0 and overwrite our last_selected_page_ + // value. + gtk_widget_show_all(gtk_bin_get_child(GTK_BIN(dialog_))); + + if (Browser* b = BrowserList::GetLastActive()) { + gtk_util::CenterOverWindow(GTK_WINDOW(dialog_), + b->window()->GetNativeHandle()); + } + + // Now that we're centered over the browser, we add our dialog to its own + // window group. We don't do anything with the response and we don't want the + // options window's modal dialogs to be associated with the main browser + // window because gtk grabs work on a per window group basis. + gtk_window_group_add_window(gtk_window_group_new(), GTK_WINDOW(dialog_)); + g_object_unref(gtk_window_get_group(GTK_WINDOW(dialog_))); + + g_signal_connect(notebook_, "switch-page", G_CALLBACK(OnSwitchPage), this); + + // We only have one button and don't do any special handling, so just hook it + // directly to gtk_widget_destroy. + g_signal_connect(dialog_, "response", G_CALLBACK(gtk_widget_destroy), NULL); + + g_signal_connect(dialog_, "destroy", G_CALLBACK(OnWindowDestroy), this); + + gtk_widget_show(dialog_); +} + +OptionsWindowGtk::~OptionsWindowGtk() { +} + +void OptionsWindowGtk::ShowOptionsPage(OptionsPage page, + OptionsGroup highlight_group) { + if (Browser* b = BrowserList::GetLastActive()) { + gtk_util::CenterOverWindow(GTK_WINDOW(dialog_), + b->window()->GetNativeHandle()); + } + + // Bring options window to front if it already existed and isn't already + // in front + gtk_window_present_with_time(GTK_WINDOW(dialog_), + gtk_get_current_event_time()); + + if (page == OPTIONS_PAGE_DEFAULT) { + // Remember the last visited page from local state. + page = static_cast<OptionsPage>(last_selected_page_.GetValue()); + if (page == OPTIONS_PAGE_DEFAULT) + page = OPTIONS_PAGE_GENERAL; + } + // If the page number is out of bounds, reset to the first tab. + if (page < 0 || page >= gtk_notebook_get_n_pages(GTK_NOTEBOOK(notebook_))) + page = OPTIONS_PAGE_GENERAL; + + gtk_notebook_set_current_page(GTK_NOTEBOOK(notebook_), page); + + // TODO(mattm): set highlight_group +} + +/////////////////////////////////////////////////////////////////////////////// +// OptionsWindowGtk, private: + +// static +void OptionsWindowGtk::OnSwitchPage(GtkNotebook* notebook, + GtkNotebookPage* page, + guint page_num, + OptionsWindowGtk* window) { + int index = page_num; + DCHECK(index > OPTIONS_PAGE_DEFAULT && index < OPTIONS_PAGE_COUNT); + window->last_selected_page_.SetValue(index); +} + +// static +void OptionsWindowGtk::OnWindowDestroy(GtkWidget* widget, + OptionsWindowGtk* window) { + options_window = NULL; + MessageLoop::current()->DeleteSoon(FROM_HERE, window); +} + +/////////////////////////////////////////////////////////////////////////////// +// Factory/finder method: + +#if !defined(OS_CHROMEOS) +// ShowOptionsWindow for non ChromeOS build. For ChromeOS build, see +// chrome/browser/chromeos/options/options_window_view.h +void ShowOptionsWindow(OptionsPage page, + OptionsGroup highlight_group, + Profile* profile) { + DCHECK(profile); + + // If there's already an existing options window, activate it and switch to + // the specified page. + if (!options_window) { + // Creating and initializing a bunch of controls generates a bunch of + // spurious events as control values change. Temporarily suppress + // accessibility events until the window is created. + profile->PauseAccessibilityEvents(); + + // Create the options window. + options_window = new OptionsWindowGtk(profile); + + // Resume accessibility events. + profile->ResumeAccessibilityEvents(); + } + options_window->ShowOptionsPage(page, highlight_group); +} +#endif // !defined(OS_CHROMEOS) |