OLD | NEW |
(Empty) | |
| 1 // Copyright (c) 2009 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 "chrome/browser/chromeos/settings_contents_view.h" |
| 6 |
| 7 #include <map> |
| 8 #include <vector> |
| 9 |
| 10 #include "app/combobox_model.h" |
| 11 #include "app/l10n_util.h" |
| 12 #include "app/resource_bundle.h" |
| 13 #include "base/basictypes.h" |
| 14 #include "base/string_util.h" |
| 15 #include "chrome/common/pref_member.h" |
| 16 #include "chrome/common/pref_names.h" |
| 17 #include "grit/chromium_strings.h" |
| 18 #include "grit/generated_resources.h" |
| 19 #include "grit/locale_settings.h" |
| 20 #include "views/background.h" |
| 21 #include "views/controls/button/checkbox.h" |
| 22 #include "views/controls/combobox/combobox.h" |
| 23 #include "views/controls/textfield/textfield.h" |
| 24 #include "views/grid_layout.h" |
| 25 #include "views/standard_layout.h" |
| 26 #include "views/window/dialog_delegate.h" |
| 27 #include "views/window/window.h" |
| 28 |
| 29 using views::GridLayout; |
| 30 using views::ColumnSet; |
| 31 |
| 32 namespace { |
| 33 |
| 34 //////////////////////////////////////////////////////////////////////////////// |
| 35 // WifiSSIDComboModel |
| 36 |
| 37 // The Combobox model for the list of wifi networks |
| 38 class WifiSSIDComboModel : public ComboboxModel { |
| 39 public: |
| 40 struct NetworkData { |
| 41 NetworkData() { } |
| 42 NetworkData(const string16& encryption, const int& strength) |
| 43 : encryption(encryption), |
| 44 strength(strength) { } |
| 45 |
| 46 string16 encryption; |
| 47 int strength; |
| 48 }; |
| 49 typedef std::map<string16, NetworkData> NetworkDataMap; |
| 50 |
| 51 WifiSSIDComboModel(); |
| 52 |
| 53 virtual int GetItemCount(); |
| 54 virtual std::wstring GetItemAt(int index); |
| 55 |
| 56 const string16& GetSSIDAt(int index); |
| 57 bool RequiresPassword(const string16& ssid); |
| 58 |
| 59 private: |
| 60 std::vector<string16> ssids_; |
| 61 |
| 62 // A map of some extra data (NetworkData) keyed off the ssids. |
| 63 NetworkDataMap ssids_map_; |
| 64 |
| 65 void AddWifiNetwork(const string16& ssid, |
| 66 const string16& encryption, |
| 67 int strength); |
| 68 |
| 69 DISALLOW_COPY_AND_ASSIGN(WifiSSIDComboModel); |
| 70 }; |
| 71 |
| 72 WifiSSIDComboModel::WifiSSIDComboModel() { |
| 73 // TODO(chocobo): Load wifi info from conman. |
| 74 // This is just temporary data until we hook this up to real data. |
| 75 AddWifiNetwork(ASCIIToUTF16("Wifi Combobox Mock"), string16(), 80); |
| 76 AddWifiNetwork(ASCIIToUTF16("Wifi WPA-PSK Password is chronos"), |
| 77 ASCIIToUTF16("WPA-PSK"), 60); |
| 78 AddWifiNetwork(ASCIIToUTF16("Wifi No Encryption"), string16(), 90); |
| 79 } |
| 80 |
| 81 int WifiSSIDComboModel::GetItemCount() { |
| 82 return static_cast<int>(ssids_.size()); |
| 83 } |
| 84 |
| 85 std::wstring WifiSSIDComboModel::GetItemAt(int index) { |
| 86 DCHECK(static_cast<int>(ssids_.size()) > index); |
| 87 |
| 88 NetworkDataMap::const_iterator it = ssids_map_.find(ssids_[index]); |
| 89 DCHECK(it != ssids_map_.end()); |
| 90 |
| 91 // TODO(chocobo): Finalize UI, then put strings in resource file. |
| 92 std::vector<string16> subst; |
| 93 subst.push_back(it->first); // $1 |
| 94 // The "None" string is just temporary for now. Have not finalized the UI yet. |
| 95 if (it->second.encryption.empty()) |
| 96 subst.push_back(ASCIIToUTF16("None")); // $2 |
| 97 else |
| 98 subst.push_back(it->second.encryption); // $2 |
| 99 subst.push_back(IntToString16(it->second.strength)); // $3 |
| 100 |
| 101 return UTF16ToWide( |
| 102 ReplaceStringPlaceholders(ASCIIToUTF16("$1 ($2, $3)"), subst, NULL)); |
| 103 } |
| 104 |
| 105 const string16& WifiSSIDComboModel::GetSSIDAt(int index) { |
| 106 DCHECK(static_cast<int>(ssids_.size()) > index); |
| 107 return ssids_[index]; |
| 108 } |
| 109 |
| 110 bool WifiSSIDComboModel::RequiresPassword(const string16& ssid) { |
| 111 NetworkDataMap::const_iterator it = ssids_map_.find(ssid); |
| 112 DCHECK(it != ssids_map_.end()); |
| 113 return !it->second.encryption.empty(); |
| 114 } |
| 115 |
| 116 void WifiSSIDComboModel::AddWifiNetwork(const string16& ssid, |
| 117 const string16& encryption, |
| 118 int strength) { |
| 119 ssids_.push_back(ssid); |
| 120 ssids_map_[ssid] = NetworkData(encryption, strength); |
| 121 } |
| 122 |
| 123 //////////////////////////////////////////////////////////////////////////////// |
| 124 // NetworkSection |
| 125 |
| 126 // Network section for wifi settings |
| 127 class NetworkSection : public OptionsPageView, |
| 128 public views::Combobox::Listener { |
| 129 public: |
| 130 explicit NetworkSection(Profile* profile); |
| 131 virtual ~NetworkSection() {} |
| 132 |
| 133 // Overridden from views::Combobox::Listener: |
| 134 virtual void ItemChanged(views::Combobox* sender, |
| 135 int prev_index, |
| 136 int new_index); |
| 137 |
| 138 bool OnPasswordWindowCancel(); |
| 139 bool OnPasswordWindowAccept(const string16& password); |
| 140 bool ConnectToWifi(const string16& ssid, const string16& password); |
| 141 |
| 142 protected: |
| 143 // OptionsPageView overrides: |
| 144 virtual void InitControlLayout(); |
| 145 virtual void InitContents(); |
| 146 |
| 147 private: |
| 148 // The View that contains the contents of the section. |
| 149 views::View* contents_; |
| 150 |
| 151 // Controls for this section: |
| 152 views::Combobox* wifi_ssid_combobox_; |
| 153 |
| 154 // Used to store the index (in combobox) of the currently connected wifi. |
| 155 int last_selected_wifi_ssid_index_; |
| 156 |
| 157 // Dummy for now. Used to populate wifi ssid models. |
| 158 WifiSSIDComboModel wifi_ssid_model_; |
| 159 |
| 160 DISALLOW_COPY_AND_ASSIGN(NetworkSection); |
| 161 }; |
| 162 |
| 163 //////////////////////////////////////////////////////////////////////////////// |
| 164 // PasswordWindowView |
| 165 |
| 166 static const int kDialogPadding = 7; |
| 167 |
| 168 // A view for showing a password textfield |
| 169 class PasswordWindowView : public views::View, |
| 170 public views::DialogDelegate { |
| 171 public: |
| 172 PasswordWindowView(NetworkSection* network_delegate, Profile* profile); |
| 173 views::Window* container() const { return container_; } |
| 174 void set_container(views::Window* container) { |
| 175 container_ = container; |
| 176 } |
| 177 |
| 178 // views::DialogDelegate methods. |
| 179 virtual bool Cancel(); |
| 180 virtual bool Accept(); |
| 181 virtual std::wstring GetWindowTitle() const; |
| 182 |
| 183 // views::WindowDelegate method. |
| 184 virtual bool IsModal() const { return true; } |
| 185 virtual views::View* GetContentsView() { return this; } |
| 186 |
| 187 // views::View overrides. |
| 188 virtual void Layout(); |
| 189 virtual gfx::Size GetPreferredSize(); |
| 190 |
| 191 protected: |
| 192 virtual void ViewHierarchyChanged(bool is_add, views::View* parent, |
| 193 views::View* child); |
| 194 |
| 195 private: |
| 196 void Init(); |
| 197 |
| 198 // The Options dialog window. |
| 199 views::Window* container_; |
| 200 |
| 201 // Used for Call back to NetworkSection that password has been entered. |
| 202 NetworkSection* network_delegate_; |
| 203 |
| 204 // Combobox and its corresponding model. |
| 205 views::Textfield* password_textfield_; |
| 206 |
| 207 DISALLOW_COPY_AND_ASSIGN(PasswordWindowView); |
| 208 }; |
| 209 |
| 210 PasswordWindowView::PasswordWindowView( |
| 211 NetworkSection* network_delegate, |
| 212 Profile* profile) |
| 213 : network_delegate_(network_delegate), |
| 214 password_textfield_(NULL) { |
| 215 Init(); |
| 216 } |
| 217 |
| 218 std::wstring PasswordWindowView::GetWindowTitle() const { |
| 219 return l10n_util::GetString(IDS_OPTIONS_SETTINGS_SECTION_TITLE_PASSWORD); |
| 220 } |
| 221 |
| 222 bool PasswordWindowView::Cancel() { |
| 223 return network_delegate_->OnPasswordWindowCancel(); |
| 224 } |
| 225 |
| 226 bool PasswordWindowView::Accept() { |
| 227 // TODO(chocobo): we should not need to call SyncText ourself here. |
| 228 password_textfield_->SyncText(); |
| 229 return network_delegate_->OnPasswordWindowAccept(password_textfield_->text()); |
| 230 } |
| 231 |
| 232 void PasswordWindowView::Layout() { |
| 233 gfx::Size sz = password_textfield_->GetPreferredSize(); |
| 234 password_textfield_->SetBounds(kDialogPadding, kDialogPadding, |
| 235 width() - 2*kDialogPadding, |
| 236 sz.height()); |
| 237 } |
| 238 |
| 239 gfx::Size PasswordWindowView::GetPreferredSize() { |
| 240 // TODO(chocobo): Create our own localized content size once the UI is done. |
| 241 return gfx::Size(views::Window::GetLocalizedContentsSize( |
| 242 IDS_ABOUT_DIALOG_WIDTH_CHARS, |
| 243 IDS_ABOUT_DIALOG_MINIMUM_HEIGHT_LINES)); |
| 244 } |
| 245 |
| 246 void PasswordWindowView::ViewHierarchyChanged(bool is_add, |
| 247 views::View* parent, |
| 248 views::View* child) { |
| 249 if (is_add && child == this) |
| 250 Init(); |
| 251 } |
| 252 |
| 253 void PasswordWindowView::Init() { |
| 254 password_textfield_ = new views::Textfield(views::Textfield::STYLE_PASSWORD); |
| 255 AddChildView(password_textfield_); |
| 256 } |
| 257 |
| 258 //////////////////////////////////////////////////////////////////////////////// |
| 259 // NetworkSection |
| 260 |
| 261 NetworkSection::NetworkSection(Profile* profile) |
| 262 : OptionsPageView(profile), |
| 263 contents_(NULL), |
| 264 wifi_ssid_combobox_(NULL), |
| 265 last_selected_wifi_ssid_index_(0) { |
| 266 } |
| 267 |
| 268 void NetworkSection::ItemChanged(views::Combobox* sender, |
| 269 int prev_index, |
| 270 int new_index) { |
| 271 if (new_index == prev_index) |
| 272 return; |
| 273 if (sender == wifi_ssid_combobox_) { |
| 274 last_selected_wifi_ssid_index_ = prev_index; |
| 275 string16 ssid = wifi_ssid_model_.GetSSIDAt(new_index); |
| 276 // Connect to wifi here. Open password page if appropriate |
| 277 if (wifi_ssid_model_.RequiresPassword(ssid)) { |
| 278 views::Window* window = views::Window::CreateChromeWindow( |
| 279 NULL, |
| 280 gfx::Rect(), |
| 281 new PasswordWindowView(this, profile())); |
| 282 window->Show(); |
| 283 } else { |
| 284 ConnectToWifi(ssid, string16()); |
| 285 } |
| 286 } |
| 287 } |
| 288 |
| 289 bool NetworkSection::OnPasswordWindowCancel() { |
| 290 // Change combobox to previous setting |
| 291 wifi_ssid_combobox_->SetSelectedItem(last_selected_wifi_ssid_index_); |
| 292 return true; |
| 293 } |
| 294 |
| 295 bool NetworkSection::OnPasswordWindowAccept(const string16& password) { |
| 296 // Try connecting to wifi |
| 297 return ConnectToWifi(wifi_ssid_model_.GetSSIDAt( |
| 298 wifi_ssid_combobox_->selected_item()), password); |
| 299 } |
| 300 |
| 301 bool NetworkSection::ConnectToWifi(const string16& ssid, |
| 302 const string16& password) { |
| 303 // TODO(chocobo): Connect to wifi |
| 304 return password == ASCIIToUTF16("chronos"); |
| 305 } |
| 306 |
| 307 void NetworkSection::InitControlLayout() { |
| 308 GridLayout* layout = new GridLayout(this); |
| 309 SetLayoutManager(layout); |
| 310 |
| 311 int single_column_layout_id = 0; |
| 312 ColumnSet* column_set = layout->AddColumnSet(single_column_layout_id); |
| 313 column_set->AddColumn(GridLayout::LEADING, GridLayout::LEADING, 0, |
| 314 GridLayout::USE_PREF, 0, 0); |
| 315 int inset_column_layout_id = 1; |
| 316 column_set = layout->AddColumnSet(inset_column_layout_id); |
| 317 column_set->AddPaddingColumn(0, kUnrelatedControlHorizontalSpacing); |
| 318 column_set->AddColumn(GridLayout::FILL, GridLayout::LEADING, 1, |
| 319 GridLayout::USE_PREF, 0, 0); |
| 320 |
| 321 layout->StartRow(0, single_column_layout_id); |
| 322 views::Label* title_label = new views::Label( |
| 323 l10n_util::GetString(IDS_OPTIONS_SETTINGS_SECTION_TITLE_NETWORK)); |
| 324 ResourceBundle& rb = ResourceBundle::GetSharedInstance(); |
| 325 gfx::Font title_font = |
| 326 rb.GetFont(ResourceBundle::BaseFont).DeriveFont(0, gfx::Font::BOLD); |
| 327 title_label->SetFont(title_font); |
| 328 layout->AddView(title_label); |
| 329 layout->AddPaddingRow(0, kRelatedControlVerticalSpacing); |
| 330 layout->StartRow(0, inset_column_layout_id); |
| 331 InitContents(); |
| 332 layout->AddView(contents_); |
| 333 } |
| 334 |
| 335 void NetworkSection::InitContents() { |
| 336 contents_ = new views::View; |
| 337 GridLayout* layout = new GridLayout(contents_); |
| 338 contents_->SetLayoutManager(layout); |
| 339 |
| 340 wifi_ssid_combobox_ = new views::Combobox(&wifi_ssid_model_); |
| 341 wifi_ssid_combobox_->set_listener(this); |
| 342 |
| 343 int single_column_view_set_id = 0; |
| 344 ColumnSet* column_set = layout->AddColumnSet(single_column_view_set_id); |
| 345 column_set->AddColumn(GridLayout::FILL, GridLayout::CENTER, 1, |
| 346 GridLayout::USE_PREF, 0, 0); |
| 347 |
| 348 layout->StartRow(0, single_column_view_set_id); |
| 349 layout->AddView(wifi_ssid_combobox_); |
| 350 layout->AddPaddingRow(0, kRelatedControlVerticalSpacing); |
| 351 } |
| 352 |
| 353 //////////////////////////////////////////////////////////////////////////////// |
| 354 // TouchpadSection |
| 355 |
| 356 class TouchpadSection : public OptionsPageView, |
| 357 public views::ButtonListener { |
| 358 public: |
| 359 explicit TouchpadSection(Profile* profile); |
| 360 virtual ~TouchpadSection() {} |
| 361 |
| 362 // Overridden from views::ButtonListener: |
| 363 virtual void ButtonPressed(views::Button* sender, const views::Event& event); |
| 364 |
| 365 protected: |
| 366 // OptionsPageView overrides: |
| 367 virtual void InitControlLayout(); |
| 368 virtual void InitContents(); |
| 369 virtual void NotifyPrefChanged(const std::wstring* pref_name); |
| 370 |
| 371 private: |
| 372 // The View that contains the contents of the section. |
| 373 views::View* contents_; |
| 374 |
| 375 // Controls for this section: |
| 376 views::Checkbox* enable_tap_to_click_checkbox_; |
| 377 views::Checkbox* enable_vert_edge_scroll_checkbox_; |
| 378 |
| 379 // Preferences for this section: |
| 380 BooleanPrefMember tap_to_click_enabled_; |
| 381 BooleanPrefMember vert_edge_scroll_enabled_; |
| 382 |
| 383 DISALLOW_COPY_AND_ASSIGN(TouchpadSection); |
| 384 }; |
| 385 |
| 386 TouchpadSection::TouchpadSection(Profile* profile) |
| 387 : OptionsPageView(profile), |
| 388 contents_(NULL), |
| 389 enable_tap_to_click_checkbox_(NULL), |
| 390 enable_vert_edge_scroll_checkbox_(NULL) { |
| 391 } |
| 392 |
| 393 void TouchpadSection::ButtonPressed( |
| 394 views::Button* sender, const views::Event& event) { |
| 395 if (sender == enable_tap_to_click_checkbox_) { |
| 396 bool enabled = enable_tap_to_click_checkbox_->checked(); |
| 397 UserMetricsRecordAction(enabled ? |
| 398 L"Options_TapToClickCheckbox_Enable" : |
| 399 L"Options_TapToClickCheckbox_Disable", |
| 400 profile()->GetPrefs()); |
| 401 tap_to_click_enabled_.SetValue(enabled); |
| 402 } else if (sender == enable_vert_edge_scroll_checkbox_) { |
| 403 bool enabled = enable_vert_edge_scroll_checkbox_->checked(); |
| 404 UserMetricsRecordAction(enabled ? |
| 405 L"Options_VertEdgeScrollCheckbox_Enable" : |
| 406 L"Options_VertEdgeScrollCheckbox_Disable", |
| 407 profile()->GetPrefs()); |
| 408 vert_edge_scroll_enabled_.SetValue(enabled); |
| 409 } |
| 410 } |
| 411 |
| 412 void TouchpadSection::InitControlLayout() { |
| 413 GridLayout* layout = new GridLayout(this); |
| 414 SetLayoutManager(layout); |
| 415 |
| 416 int single_column_layout_id = 0; |
| 417 ColumnSet* column_set = layout->AddColumnSet(single_column_layout_id); |
| 418 column_set->AddColumn(GridLayout::LEADING, GridLayout::LEADING, 0, |
| 419 GridLayout::USE_PREF, 0, 0); |
| 420 int inset_column_layout_id = 1; |
| 421 column_set = layout->AddColumnSet(inset_column_layout_id); |
| 422 column_set->AddPaddingColumn(0, kUnrelatedControlHorizontalSpacing); |
| 423 column_set->AddColumn(GridLayout::FILL, GridLayout::LEADING, 1, |
| 424 GridLayout::USE_PREF, 0, 0); |
| 425 |
| 426 layout->StartRow(0, single_column_layout_id); |
| 427 views::Label* title_label = new views::Label( |
| 428 l10n_util::GetString(IDS_OPTIONS_SETTINGS_SECTION_TITLE_TOUCHPAD)); |
| 429 ResourceBundle& rb = ResourceBundle::GetSharedInstance(); |
| 430 gfx::Font title_font = |
| 431 rb.GetFont(ResourceBundle::BaseFont).DeriveFont(0, gfx::Font::BOLD); |
| 432 title_label->SetFont(title_font); |
| 433 layout->AddView(title_label); |
| 434 layout->AddPaddingRow(0, kRelatedControlVerticalSpacing); |
| 435 layout->StartRow(0, inset_column_layout_id); |
| 436 InitContents(); |
| 437 layout->AddView(contents_); |
| 438 } |
| 439 |
| 440 void TouchpadSection::InitContents() { |
| 441 contents_ = new views::View; |
| 442 GridLayout* layout = new GridLayout(contents_); |
| 443 contents_->SetLayoutManager(layout); |
| 444 |
| 445 enable_tap_to_click_checkbox_ = new views::Checkbox(l10n_util::GetString( |
| 446 IDS_OPTIONS_SETTINGS_TAP_TO_CLICK_ENABLED_DESCRIPTION)); |
| 447 enable_tap_to_click_checkbox_->set_listener(this); |
| 448 enable_tap_to_click_checkbox_->SetMultiLine(true); |
| 449 enable_vert_edge_scroll_checkbox_ = new views::Checkbox(l10n_util::GetString( |
| 450 IDS_OPTIONS_SETTINGS_VERT_EDGE_SCROLL_ENABLED_DESCRIPTION)); |
| 451 enable_vert_edge_scroll_checkbox_->set_listener(this); |
| 452 enable_vert_edge_scroll_checkbox_->SetMultiLine(true); |
| 453 |
| 454 int single_column_view_set_id = 0; |
| 455 ColumnSet* column_set = layout->AddColumnSet(single_column_view_set_id); |
| 456 column_set->AddColumn(GridLayout::FILL, GridLayout::CENTER, 1, |
| 457 GridLayout::USE_PREF, 0, 0); |
| 458 |
| 459 layout->StartRow(0, single_column_view_set_id); |
| 460 layout->AddView(enable_tap_to_click_checkbox_); |
| 461 layout->AddPaddingRow(0, kRelatedControlVerticalSpacing); |
| 462 layout->StartRow(0, single_column_view_set_id); |
| 463 layout->AddView(enable_vert_edge_scroll_checkbox_); |
| 464 layout->AddPaddingRow(0, kUnrelatedControlVerticalSpacing); |
| 465 |
| 466 // Init member prefs so we can update the controls if prefs change. |
| 467 tap_to_click_enabled_.Init(prefs::kTapToClickEnabled, |
| 468 profile()->GetPrefs(), this); |
| 469 vert_edge_scroll_enabled_.Init(prefs::kVertEdgeScrollEnabled, |
| 470 profile()->GetPrefs(), this); |
| 471 } |
| 472 |
| 473 void TouchpadSection::NotifyPrefChanged(const std::wstring* pref_name) { |
| 474 if (!pref_name || *pref_name == prefs::kTapToClickEnabled) { |
| 475 bool enabled = tap_to_click_enabled_.GetValue(); |
| 476 enable_tap_to_click_checkbox_->SetChecked(enabled); |
| 477 } |
| 478 if (!pref_name || *pref_name == prefs::kVertEdgeScrollEnabled) { |
| 479 bool enabled = vert_edge_scroll_enabled_.GetValue(); |
| 480 enable_vert_edge_scroll_checkbox_->SetChecked(enabled); |
| 481 } |
| 482 } |
| 483 |
| 484 } // namespace |
| 485 |
| 486 //////////////////////////////////////////////////////////////////////////////// |
| 487 // SettingsContentsView |
| 488 |
| 489 //////////////////////////////////////////////////////////////////////////////// |
| 490 // SettingsContentsView, OptionsPageView implementation: |
| 491 |
| 492 void SettingsContentsView::InitControlLayout() { |
| 493 GridLayout* layout = CreatePanelGridLayout(this); |
| 494 SetLayoutManager(layout); |
| 495 |
| 496 int single_column_view_set_id = 0; |
| 497 ColumnSet* column_set = layout->AddColumnSet(single_column_view_set_id); |
| 498 column_set->AddColumn(GridLayout::FILL, GridLayout::FILL, 1, |
| 499 GridLayout::USE_PREF, 0, 0); |
| 500 |
| 501 layout->StartRow(0, single_column_view_set_id); |
| 502 layout->AddView(new NetworkSection(profile())); |
| 503 layout->AddPaddingRow(0, kRelatedControlVerticalSpacing); |
| 504 layout->StartRow(0, single_column_view_set_id); |
| 505 layout->AddView(new TouchpadSection(profile())); |
| 506 layout->AddPaddingRow(0, kRelatedControlVerticalSpacing); |
| 507 } |
OLD | NEW |