| OLD | NEW |
| (Empty) |
| 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 | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #include "base/scoped_ptr.h" | |
| 6 #include "chrome/browser/browser_process.h" | |
| 7 #include "chrome/browser/chromeos/options/internet_page_view.h" | |
| 8 #include "chrome/browser/chromeos/options/system_page_view.h" | |
| 9 #include "chrome/browser/profiles/profile.h" | |
| 10 #include "chrome/browser/ui/browser_list.h" | |
| 11 #include "chrome/browser/ui/browser_window.h" | |
| 12 #include "chrome/browser/ui/gtk/options/advanced_page_gtk.h" | |
| 13 #include "chrome/browser/ui/gtk/options/content_page_gtk.h" | |
| 14 #include "chrome/browser/ui/gtk/options/general_page_gtk.h" | |
| 15 #include "chrome/browser/ui/options/options_window.h" | |
| 16 #include "chrome/browser/ui/views/accessible_view_helper.h" | |
| 17 #include "chrome/browser/ui/views/window.h" | |
| 18 #include "chrome/browser/ui/window_sizer.h" | |
| 19 #include "chrome/common/chrome_constants.h" | |
| 20 #include "chrome/common/pref_names.h" | |
| 21 #include "grit/chromium_strings.h" | |
| 22 #include "grit/generated_resources.h" | |
| 23 #include "grit/locale_settings.h" | |
| 24 #include "ui/base/l10n/l10n_util.h" | |
| 25 #include "views/controls/native/native_view_host.h" | |
| 26 #include "views/controls/tabbed_pane/native_tabbed_pane_gtk.h" | |
| 27 #include "views/controls/tabbed_pane/tabbed_pane.h" | |
| 28 #include "views/widget/root_view.h" | |
| 29 #include "views/window/dialog_delegate.h" | |
| 30 #include "views/window/window.h" | |
| 31 #include "views/window/window_gtk.h" | |
| 32 | |
| 33 | |
| 34 namespace chromeos { | |
| 35 | |
| 36 /////////////////////////////////////////////////////////////////////////////// | |
| 37 // GtkPreferencePageHost | |
| 38 // | |
| 39 // Hosts a GTK preference page and takes care of sizing it appropriately. | |
| 40 // | |
| 41 class GtkPreferencePageHost : public views::NativeViewHost { | |
| 42 public: | |
| 43 explicit GtkPreferencePageHost(GtkWidget* widget); | |
| 44 | |
| 45 private: | |
| 46 // views::View overrides: | |
| 47 virtual void ViewHierarchyChanged(bool is_add, View* parent, View* child); | |
| 48 virtual gfx::Size GetPreferredSize(); | |
| 49 | |
| 50 GtkWidget* widget_; | |
| 51 | |
| 52 DISALLOW_COPY_AND_ASSIGN(GtkPreferencePageHost); | |
| 53 }; | |
| 54 | |
| 55 GtkPreferencePageHost::GtkPreferencePageHost(GtkWidget* widget) | |
| 56 : widget_(widget) { | |
| 57 set_background(views::Background::CreateSolidBackground(SK_ColorWHITE)); | |
| 58 } | |
| 59 | |
| 60 void GtkPreferencePageHost::ViewHierarchyChanged(bool is_add, | |
| 61 View* parent, | |
| 62 View* child) { | |
| 63 NativeViewHost::ViewHierarchyChanged(is_add, parent, child); | |
| 64 if (is_add && child == this) | |
| 65 Attach(widget_); | |
| 66 } | |
| 67 | |
| 68 gfx::Size GtkPreferencePageHost::GetPreferredSize() { | |
| 69 // We need to show the widget and its children since otherwise containers like | |
| 70 // gtk_box don't compute the correct size. | |
| 71 gtk_widget_show_all(widget_); | |
| 72 GtkRequisition requisition = { 0, 0 }; | |
| 73 gtk_widget_size_request(GTK_WIDGET(widget_), &requisition); | |
| 74 GtkRequisition& size(widget_->requisition); | |
| 75 return gfx::Size(size.width, size.height); | |
| 76 } | |
| 77 | |
| 78 /////////////////////////////////////////////////////////////////////////////// | |
| 79 // OptionsWindowView | |
| 80 // | |
| 81 // The contents of the Options dialog window. | |
| 82 // | |
| 83 class OptionsWindowView : public views::View, | |
| 84 public views::DialogDelegate, | |
| 85 public views::TabbedPane::Listener { | |
| 86 public: | |
| 87 static const int kDialogPadding; | |
| 88 static const SkColor kDialogBackground; | |
| 89 static OptionsWindowView* instance_; | |
| 90 | |
| 91 explicit OptionsWindowView(Profile* profile); | |
| 92 virtual ~OptionsWindowView(); | |
| 93 | |
| 94 // Shows the Tab corresponding to the specified OptionsPage. | |
| 95 void ShowOptionsPage(OptionsPage page, OptionsGroup highlight_group); | |
| 96 | |
| 97 // views::DialogDelegate implementation: | |
| 98 virtual int GetDialogButtons() const { | |
| 99 return 0; | |
| 100 } | |
| 101 virtual std::wstring GetWindowTitle() const; | |
| 102 virtual void WindowClosing(); | |
| 103 virtual bool Cancel(); | |
| 104 virtual views::View* GetContentsView(); | |
| 105 virtual bool ShouldShowClientEdge() const { | |
| 106 return false; | |
| 107 } | |
| 108 | |
| 109 // views::TabbedPane::Listener implementation: | |
| 110 virtual void TabSelectedAt(int index); | |
| 111 | |
| 112 // views::View overrides: | |
| 113 virtual void Layout(); | |
| 114 virtual gfx::Size GetPreferredSize(); | |
| 115 | |
| 116 protected: | |
| 117 // views::View overrides: | |
| 118 virtual void ViewHierarchyChanged(bool is_add, | |
| 119 views::View* parent, | |
| 120 views::View* child); | |
| 121 private: | |
| 122 // Init the assorted Tabbed pages | |
| 123 void Init(); | |
| 124 | |
| 125 // Returns the currently selected OptionsPageView. | |
| 126 OptionsPageView* GetCurrentOptionsPageView() const; | |
| 127 | |
| 128 // Flag of whether we are fully initialized. | |
| 129 bool initialized_; | |
| 130 | |
| 131 // The Tab view that contains all of the options pages. | |
| 132 views::TabbedPane* tabs_; | |
| 133 | |
| 134 // The Profile associated with these options. | |
| 135 Profile* profile_; | |
| 136 | |
| 137 // Native Gtk options pages. | |
| 138 GeneralPageGtk general_page_; | |
| 139 ContentPageGtk content_page_; | |
| 140 AdvancedPageGtk advanced_page_; | |
| 141 | |
| 142 // The last page the user was on when they opened the Options window. | |
| 143 IntegerPrefMember last_selected_page_; | |
| 144 | |
| 145 scoped_ptr<AccessibleViewHelper> accessible_view_helper_; | |
| 146 | |
| 147 DISALLOW_IMPLICIT_CONSTRUCTORS(OptionsWindowView); | |
| 148 }; | |
| 149 | |
| 150 /////////////////////////////////////////////////////////////////////////////// | |
| 151 // OptionsWindowView, public: | |
| 152 | |
| 153 // No dialog padding. | |
| 154 const int OptionsWindowView::kDialogPadding = 0; | |
| 155 | |
| 156 // Shaded frame color that matches the rendered frame. It's the result | |
| 157 // of SRC_OVER frame top center image on top of frame color. | |
| 158 const SkColor OptionsWindowView::kDialogBackground = | |
| 159 SkColorSetRGB(0x4E, 0x7D, 0xD0); | |
| 160 | |
| 161 // Live instance of the options view. | |
| 162 OptionsWindowView* OptionsWindowView::instance_ = NULL; | |
| 163 | |
| 164 OptionsWindowView::OptionsWindowView(Profile* profile) | |
| 165 // Always show preferences for the original profile. Most state when off | |
| 166 // the record comes from the original profile, but we explicitly use | |
| 167 // the original profile to avoid potential problems. | |
| 168 : initialized_(false), | |
| 169 tabs_(NULL), | |
| 170 profile_(profile->GetOriginalProfile()), | |
| 171 general_page_(profile_), | |
| 172 content_page_(profile_), | |
| 173 advanced_page_(profile_) { | |
| 174 // We don't need to observe changes in this value. | |
| 175 last_selected_page_.Init(prefs::kOptionsWindowLastTabIndex, | |
| 176 g_browser_process->local_state(), NULL); | |
| 177 | |
| 178 set_background(views::Background::CreateSolidBackground(kDialogBackground)); | |
| 179 } | |
| 180 | |
| 181 OptionsWindowView::~OptionsWindowView() { | |
| 182 } | |
| 183 | |
| 184 void OptionsWindowView::ShowOptionsPage(OptionsPage page, | |
| 185 OptionsGroup highlight_group) { | |
| 186 // This will show invisible windows and bring visible windows to the front. | |
| 187 window()->Show(); | |
| 188 | |
| 189 // Show all controls in tab after tab's size is allocated. We have | |
| 190 // to do this after size allocation otherwise WrapLabelAtAllocationHack | |
| 191 // in ContentPageGtk would break. | |
| 192 GtkWidget* notebook = static_cast<views::NativeTabbedPaneGtk*>( | |
| 193 tabs_->native_wrapper())->native_view(); | |
| 194 gtk_widget_show_all(notebook); | |
| 195 | |
| 196 if (page == OPTIONS_PAGE_DEFAULT) { | |
| 197 // Remember the last visited page from local state. | |
| 198 page = static_cast<OptionsPage>(last_selected_page_.GetValue()); | |
| 199 if (page == OPTIONS_PAGE_DEFAULT) | |
| 200 page = OPTIONS_PAGE_GENERAL; | |
| 201 } | |
| 202 // If the page number is out of bounds, reset to the first tab. | |
| 203 if (page < 0 || page >= tabs_->GetTabCount()) | |
| 204 page = OPTIONS_PAGE_GENERAL; | |
| 205 | |
| 206 tabs_->SelectTabAt(static_cast<int>(page)); | |
| 207 | |
| 208 // TODO(xiyuan): set highlight_group | |
| 209 } | |
| 210 | |
| 211 /////////////////////////////////////////////////////////////////////////////// | |
| 212 // OptionsWindowView, views::DialogDelegate implementation: | |
| 213 | |
| 214 std::wstring OptionsWindowView::GetWindowTitle() const { | |
| 215 return UTF16ToWide( | |
| 216 l10n_util::GetStringFUTF16(IDS_OPTIONS_DIALOG_TITLE, | |
| 217 l10n_util::GetStringUTF16(IDS_PRODUCT_NAME))); | |
| 218 } | |
| 219 | |
| 220 void OptionsWindowView::WindowClosing() { | |
| 221 // Clear the static instance so that the next time ShowOptionsWindow() is | |
| 222 // called a new window is opened. | |
| 223 instance_ = NULL; | |
| 224 } | |
| 225 | |
| 226 bool OptionsWindowView::Cancel() { | |
| 227 OptionsPageView* selected_option_page = GetCurrentOptionsPageView(); | |
| 228 if (selected_option_page) { | |
| 229 return selected_option_page->CanClose(); | |
| 230 } else { | |
| 231 // Gtk option pages does not support CanClose. | |
| 232 return true; | |
| 233 } | |
| 234 } | |
| 235 | |
| 236 views::View* OptionsWindowView::GetContentsView() { | |
| 237 return this; | |
| 238 } | |
| 239 | |
| 240 /////////////////////////////////////////////////////////////////////////////// | |
| 241 // OptionsWindowView, views::TabbedPane::Listener implementation: | |
| 242 | |
| 243 void OptionsWindowView::TabSelectedAt(int index) { | |
| 244 if (!initialized_) | |
| 245 return; | |
| 246 | |
| 247 DCHECK(index > OPTIONS_PAGE_DEFAULT && index < OPTIONS_PAGE_COUNT); | |
| 248 last_selected_page_.SetValue(index); | |
| 249 } | |
| 250 | |
| 251 /////////////////////////////////////////////////////////////////////////////// | |
| 252 // OptionsWindowView, views::View overrides: | |
| 253 | |
| 254 void OptionsWindowView::Layout() { | |
| 255 tabs_->SetBounds(kDialogPadding, kDialogPadding, | |
| 256 width() - (2 * kDialogPadding), | |
| 257 height() - (2 * kDialogPadding)); | |
| 258 if (!accessible_view_helper_.get()) { | |
| 259 accessible_view_helper_.reset(new AccessibleViewHelper(this, profile_)); | |
| 260 } | |
| 261 } | |
| 262 | |
| 263 gfx::Size OptionsWindowView::GetPreferredSize() { | |
| 264 gfx::Size size(tabs_->GetPreferredSize()); | |
| 265 size.Enlarge(2 * kDialogPadding, 2 * kDialogPadding); | |
| 266 return size; | |
| 267 } | |
| 268 | |
| 269 void OptionsWindowView::ViewHierarchyChanged(bool is_add, | |
| 270 views::View* parent, | |
| 271 views::View* child) { | |
| 272 // Can't init before we're inserted into a Container, because we require a | |
| 273 // HWND to parent native child controls to. | |
| 274 if (is_add && child == this) | |
| 275 Init(); | |
| 276 } | |
| 277 | |
| 278 /////////////////////////////////////////////////////////////////////////////// | |
| 279 // OptionsWindowView, private: | |
| 280 | |
| 281 void OptionsWindowView::Init() { | |
| 282 tabs_ = new views::TabbedPane; | |
| 283 tabs_->SetListener(this); | |
| 284 AddChildView(tabs_); | |
| 285 | |
| 286 GtkWidget* notebook = static_cast<views::NativeTabbedPaneGtk*>( | |
| 287 tabs_->native_wrapper())->native_view(); | |
| 288 | |
| 289 // Set vertical padding of tab header. | |
| 290 gtk_notebook_set_tab_vborder(GTK_NOTEBOOK(notebook), 5); | |
| 291 | |
| 292 // Set a name for notebook. Note that the name is also used in theme engine | |
| 293 // to apply specific drawings for this widget. | |
| 294 gtk_widget_set_name(GTK_WIDGET(notebook), "chromeos-options-tab"); | |
| 295 | |
| 296 // Setup tab pages. | |
| 297 int tab_index = 0; | |
| 298 | |
| 299 SystemPageView* system_page = new SystemPageView(profile_); | |
| 300 system_page->set_background(views::Background::CreateSolidBackground( | |
| 301 SK_ColorWHITE)); | |
| 302 tabs_->AddTabAtIndex(tab_index++, | |
| 303 UTF16ToWide(l10n_util::GetStringUTF16( | |
| 304 IDS_OPTIONS_SYSTEM_TAB_LABEL)), | |
| 305 system_page, false); | |
| 306 | |
| 307 InternetPageView* internet_page = new InternetPageView(profile_); | |
| 308 internet_page->set_background(views::Background::CreateSolidBackground( | |
| 309 SK_ColorWHITE)); | |
| 310 tabs_->AddTabAtIndex(tab_index++, | |
| 311 UTF16ToWide(l10n_util::GetStringUTF16( | |
| 312 IDS_OPTIONS_INTERNET_TAB_LABEL)), | |
| 313 internet_page, false); | |
| 314 | |
| 315 tabs_->AddTabAtIndex(tab_index++, | |
| 316 UTF16ToWide(l10n_util::GetStringUTF16( | |
| 317 IDS_OPTIONS_GENERAL_TAB_LABEL)), | |
| 318 new GtkPreferencePageHost( | |
| 319 general_page_.get_page_widget()), | |
| 320 false); | |
| 321 | |
| 322 tabs_->AddTabAtIndex(tab_index++, | |
| 323 UTF16ToWide(l10n_util::GetStringUTF16( | |
| 324 IDS_OPTIONS_CONTENT_TAB_LABEL)), | |
| 325 new GtkPreferencePageHost( | |
| 326 content_page_.get_page_widget()), | |
| 327 false); | |
| 328 | |
| 329 tabs_->AddTabAtIndex(tab_index++, | |
| 330 UTF16ToWide(l10n_util::GetStringUTF16( | |
| 331 IDS_OPTIONS_ADVANCED_TAB_LABEL)), | |
| 332 new GtkPreferencePageHost( | |
| 333 advanced_page_.get_page_widget()), | |
| 334 false); | |
| 335 | |
| 336 DCHECK(tabs_->GetTabCount() == OPTIONS_PAGE_COUNT); | |
| 337 | |
| 338 initialized_ = true; | |
| 339 } | |
| 340 | |
| 341 OptionsPageView* OptionsWindowView::GetCurrentOptionsPageView() const { | |
| 342 int selected_option_page = tabs_->GetSelectedTabIndex(); | |
| 343 if (selected_option_page < OPTIONS_PAGE_GENERAL) { | |
| 344 return static_cast<OptionsPageView*>(tabs_->GetSelectedTab()); | |
| 345 } else { | |
| 346 return NULL; | |
| 347 } | |
| 348 } | |
| 349 | |
| 350 void CloseOptionsWindow() { | |
| 351 if (OptionsWindowView::instance_) | |
| 352 OptionsWindowView::instance_->window()->Close(); | |
| 353 } | |
| 354 | |
| 355 gfx::NativeWindow GetOptionsViewParent() { | |
| 356 if (Browser* b = BrowserList::GetLastActive()) { | |
| 357 if (b->type() != Browser::TYPE_NORMAL) { | |
| 358 b = BrowserList::FindBrowserWithType(b->profile(), | |
| 359 Browser::TYPE_NORMAL, | |
| 360 true); | |
| 361 } | |
| 362 | |
| 363 if (b) | |
| 364 return b->window()->GetNativeHandle(); | |
| 365 } | |
| 366 | |
| 367 return NULL; | |
| 368 } | |
| 369 | |
| 370 }; // namespace chromeos | |
| 371 | |
| 372 /////////////////////////////////////////////////////////////////////////////// | |
| 373 // Factory/finder method: | |
| 374 | |
| 375 void ShowOptionsWindow(OptionsPage page, | |
| 376 OptionsGroup highlight_group, | |
| 377 Profile* profile) { | |
| 378 DCHECK(profile); | |
| 379 | |
| 380 using chromeos::OptionsWindowView; | |
| 381 | |
| 382 // If there's already an existing options window, close it and create | |
| 383 // a new one for the current active browser. | |
| 384 chromeos::CloseOptionsWindow(); | |
| 385 | |
| 386 OptionsWindowView::instance_ = new OptionsWindowView(profile); | |
| 387 browser::CreateViewsWindow(chromeos::GetOptionsViewParent(), | |
| 388 gfx::Rect(), | |
| 389 OptionsWindowView::instance_); | |
| 390 | |
| 391 OptionsWindowView::instance_->ShowOptionsPage(page, highlight_group); | |
| 392 } | |
| OLD | NEW |