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 |