Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(74)

Side by Side Diff: chrome/browser/views/options/cookies_view.cc

Issue 365005: Converting the Cookies options page from a TableView to a TreeView... (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 11 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « chrome/browser/views/options/cookies_view.h ('k') | chrome/chrome.gyp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/views/options/cookies_view.h" 5 #include "chrome/browser/views/options/cookies_view.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 8
9 #include "app/gfx/canvas.h" 9 #include "app/gfx/canvas.h"
10 #include "app/gfx/color_utils.h" 10 #include "app/gfx/color_utils.h"
11 #include "app/l10n_util.h" 11 #include "app/l10n_util.h"
12 #include "base/i18n/time_formatting.h" 12 #include "base/i18n/time_formatting.h"
13 #include "base/message_loop.h" 13 #include "base/message_loop.h"
14 #include "base/string_util.h" 14 #include "base/string_util.h"
15 #include "chrome/browser/cookies_table_model.h" 15 #include "chrome/browser/cookies_tree_model.h"
16 #include "chrome/browser/profile.h" 16 #include "chrome/browser/profile.h"
17 #include "grit/generated_resources.h" 17 #include "grit/generated_resources.h"
18 #include "grit/locale_settings.h" 18 #include "grit/locale_settings.h"
19 #include "net/base/cookie_monster.h" 19 #include "net/base/cookie_monster.h"
20 #include "views/border.h" 20 #include "views/border.h"
21 #include "views/grid_layout.h" 21 #include "views/grid_layout.h"
22 #include "views/controls/label.h" 22 #include "views/controls/label.h"
23 #include "views/controls/button/native_button.h" 23 #include "views/controls/button/native_button.h"
24 #include "views/controls/table/table_view.h" 24 #include "views/controls/tree/tree_view.h"
25 #include "views/controls/textfield/textfield.h" 25 #include "views/controls/textfield/textfield.h"
26 #include "views/standard_layout.h" 26 #include "views/standard_layout.h"
27 27
28 // static 28 // static
29 views::Window* CookiesView::instance_ = NULL; 29 views::Window* CookiesView::instance_ = NULL;
30 static const int kCookieInfoViewBorderSize = 1; 30 static const int kCookieInfoViewBorderSize = 1;
31 static const int kCookieInfoViewInsetSize = 3; 31 static const int kCookieInfoViewInsetSize = 3;
32 static const int kSearchFilterDelayMs = 500; 32
33 33
34 /////////////////////////////////////////////////////////////////////////////// 34 ///////////////////////////////////////////////////////////////////////////////
35 // CookiesTableView 35 // CookiesTreeView
36 // Overridden to handle Delete key presses 36 // Overridden to handle Delete key presses
37 37
38 class CookiesTableView : public views::TableView { 38 class CookiesTreeView : public views::TreeView {
39 public: 39 public:
40 CookiesTableView(CookiesTableModel* cookies_model, 40 explicit CookiesTreeView(CookiesTreeModel* cookies_model);
41 std::vector<TableColumn> columns); 41 virtual ~CookiesTreeView() {}
42 virtual ~CookiesTableView() {}
43 42
44 // Removes the cookies associated with the selected rows in the TableView. 43 // Removes the items associated with the selected node in the TreeView
45 void RemoveSelectedCookies(); 44 void RemoveSelectedItems();
46 45
47 private: 46 private:
48 // Our model, as a CookiesTableModel. 47 // Our model, as a CookiesTreeModel.
49 CookiesTableModel* cookies_model_; 48 CookiesTreeModel* cookies_model_;
50 49
51 DISALLOW_COPY_AND_ASSIGN(CookiesTableView); 50 DISALLOW_COPY_AND_ASSIGN(CookiesTreeView);
52 }; 51 };
53 52
54 CookiesTableView::CookiesTableView( 53 CookiesTreeView::CookiesTreeView(CookiesTreeModel* cookies_model)
55 CookiesTableModel* cookies_model, 54 : cookies_model_(cookies_model) {
56 std::vector<TableColumn> columns) 55 SetModel(cookies_model_);
57 : views::TableView(cookies_model, columns, views::ICON_AND_TEXT, false, 56 SetRootShown(false);
58 true, true), 57 SetEditable(false);
59 cookies_model_(cookies_model) {
60 } 58 }
61 59
62 void CookiesTableView::RemoveSelectedCookies() { 60 void CookiesTreeView::RemoveSelectedItems() {
63 // It's possible that we don't have anything selected. 61 TreeModelNode* selected_node = GetSelectedNode();
64 if (SelectedRowCount() <= 0) 62 if (selected_node) {
65 return; 63 cookies_model_->DeleteCookieNode(static_cast<CookieTreeCookieNode*>(
66 64 GetSelectedNode()));
67 if (SelectedRowCount() == cookies_model_->RowCount()) {
68 cookies_model_->RemoveAllShownCookies();
69 return;
70 } 65 }
71
72 // Remove the selected cookies. This iterates over the rows backwards, which
73 // is required when calling RemoveCookies, see bug 2994.
74 int last_selected_view_row = -1;
75 int remove_count = 0;
76 for (views::TableView::iterator i = SelectionBegin();
77 i != SelectionEnd(); ++i) {
78 int selected_model_row = *i;
79 ++remove_count;
80 if (last_selected_view_row == -1) {
81 // Store the view row since the view to model mapping changes when
82 // we delete.
83 last_selected_view_row = model_to_view(selected_model_row);
84 }
85 cookies_model_->RemoveCookies(selected_model_row, 1);
86 }
87
88 // Select the next row after the last row deleted (unless removing last row).
89 DCHECK(RowCount() > 0 && last_selected_view_row != -1);
90 Select(view_to_model(std::min(RowCount() - 1,
91 last_selected_view_row - remove_count + 1)));
92 } 66 }
93 67
94 ///////////////////////////////////////////////////////////////////////////////
95 // CookieInfoView
96 //
97 // Responsible for displaying a tabular grid of Cookie information.
98 class CookieInfoView : public views::View {
99 public:
100 CookieInfoView();
101 virtual ~CookieInfoView();
102
103 // Update the display from the specified CookieNode.
104 void SetCookie(const std::string& domain,
105 const net::CookieMonster::CanonicalCookie& cookie_node);
106
107 // Clears the cookie display to indicate that no or multiple cookies are
108 // selected.
109 void ClearCookieDisplay();
110
111 // Enables or disables the cookie proerty text fields.
112 void EnableCookieDisplay(bool enabled);
113
114 protected:
115 // views::View overrides:
116 virtual void ViewHierarchyChanged(bool is_add,
117 views::View* parent,
118 views::View* child);
119
120 private:
121 // Set up the view layout
122 void Init();
123
124 // Individual property labels
125 views::Label* name_label_;
126 views::Textfield* name_value_field_;
127 views::Label* content_label_;
128 views::Textfield* content_value_field_;
129 views::Label* domain_label_;
130 views::Textfield* domain_value_field_;
131 views::Label* path_label_;
132 views::Textfield* path_value_field_;
133 views::Label* send_for_label_;
134 views::Textfield* send_for_value_field_;
135 views::Label* created_label_;
136 views::Textfield* created_value_field_;
137 views::Label* expires_label_;
138 views::Textfield* expires_value_field_;
139
140 DISALLOW_COPY_AND_ASSIGN(CookieInfoView);
141 };
142 68
143 /////////////////////////////////////////////////////////////////////////////// 69 ///////////////////////////////////////////////////////////////////////////////
144 // CookieInfoView, public: 70 // CookieInfoView, public:
145 71
146 CookieInfoView::CookieInfoView() 72 CookieInfoView::CookieInfoView()
147 : name_label_(NULL), 73 : name_label_(NULL),
148 name_value_field_(NULL), 74 name_value_field_(NULL),
149 content_label_(NULL), 75 content_label_(NULL),
150 content_value_field_(NULL), 76 content_value_field_(NULL),
151 domain_label_(NULL), 77 domain_label_(NULL),
(...skipping 188 matching lines...) Expand 10 before | Expand all | Expand 10 after
340 NULL, gfx::Rect(), cookies_view); 266 NULL, gfx::Rect(), cookies_view);
341 } 267 }
342 if (!instance_->IsVisible()) { 268 if (!instance_->IsVisible()) {
343 instance_->Show(); 269 instance_->Show();
344 } else { 270 } else {
345 instance_->Activate(); 271 instance_->Activate();
346 } 272 }
347 } 273 }
348 274
349 CookiesView::~CookiesView() { 275 CookiesView::~CookiesView() {
350 cookies_table_->SetModel(NULL); 276 cookies_tree_->SetModel(NULL);
351 }
352
353 void CookiesView::UpdateSearchResults() {
354 cookies_table_model_->UpdateSearchResults(search_field_->text());
355 remove_all_button_->SetEnabled(cookies_table_model_->RowCount() > 0);
356 } 277 }
357 278
358 /////////////////////////////////////////////////////////////////////////////// 279 ///////////////////////////////////////////////////////////////////////////////
359 // CookiesView, views::Buttonlistener implementation: 280 // CookiesView, views::Buttonlistener implementation:
360 281
361 void CookiesView::ButtonPressed( 282 void CookiesView::ButtonPressed(
362 views::Button* sender, const views::Event& event) { 283 views::Button* sender, const views::Event& event) {
363 if (sender == remove_button_) { 284 if (sender == remove_button_) {
364 cookies_table_->RemoveSelectedCookies(); 285 cookies_tree_->RemoveSelectedItems();
365 } else if (sender == remove_all_button_) { 286 } else if (sender == remove_all_button_) {
366 // Delete all the Cookies shown. 287 cookies_tree_model_->DeleteAllCookies();
367 cookies_table_model_->RemoveAllShownCookies();
368 UpdateForEmptyState(); 288 UpdateForEmptyState();
369 } else if (sender == clear_search_button_) {
370 ResetSearchQuery();
371 } 289 }
372 } 290 }
373 291
374 /////////////////////////////////////////////////////////////////////////////// 292 ///////////////////////////////////////////////////////////////////////////////
375 // CookiesView, views::TableViewObserver implementation:
376 void CookiesView::OnSelectionChanged() {
377 int selected_row_count = cookies_table_->SelectedRowCount();
378 if (selected_row_count == 1) {
379 int selected_index = cookies_table_->FirstSelectedRow();
380 if (selected_index >= 0 &&
381 selected_index < cookies_table_model_->RowCount()) {
382 info_view_->SetCookie(cookies_table_model_->GetDomainAt(selected_index),
383 cookies_table_model_->GetCookieAt(selected_index));
384 }
385 } else {
386 info_view_->ClearCookieDisplay();
387 }
388 remove_button_->SetEnabled(selected_row_count != 0);
389 if (cookies_table_->RowCount() == 0)
390 UpdateForEmptyState();
391 }
392
393 void CookiesView::OnTableViewDelete(views::TableView* table_view) {
394 cookies_table_->RemoveSelectedCookies();
395 }
396
397 ///////////////////////////////////////////////////////////////////////////////
398 // CookiesView, views::Textfield::Controller implementation:
399
400 void CookiesView::ContentsChanged(views::Textfield* sender,
401 const std::wstring& new_contents) {
402 clear_search_button_->SetEnabled(!search_field_->text().empty());
403 search_update_factory_.RevokeAll();
404 MessageLoop::current()->PostDelayedTask(FROM_HERE,
405 search_update_factory_.NewRunnableMethod(
406 &CookiesView::UpdateSearchResults), kSearchFilterDelayMs);
407 }
408
409 bool CookiesView::HandleKeystroke(views::Textfield* sender,
410 const views::Textfield::Keystroke& key) {
411 if (key.GetKeyboardCode() == base::VKEY_ESCAPE) {
412 ResetSearchQuery();
413 } else if (key.GetKeyboardCode() == base::VKEY_RETURN) {
414 search_update_factory_.RevokeAll();
415 UpdateSearchResults();
416 }
417 return false;
418 }
419
420 ///////////////////////////////////////////////////////////////////////////////
421 // CookiesView, views::DialogDelegate implementation: 293 // CookiesView, views::DialogDelegate implementation:
422 294
423 std::wstring CookiesView::GetWindowTitle() const { 295 std::wstring CookiesView::GetWindowTitle() const {
424 return l10n_util::GetString(IDS_COOKIES_WINDOW_TITLE); 296 return l10n_util::GetString(IDS_COOKIES_WEBSITE_PERMISSIONS_WINDOW_TITLE);
425 } 297 }
426 298
427 void CookiesView::WindowClosing() { 299 void CookiesView::WindowClosing() {
428 instance_ = NULL; 300 instance_ = NULL;
429 } 301 }
430 302
431 views::View* CookiesView::GetContentsView() { 303 views::View* CookiesView::GetContentsView() {
432 return this; 304 return this;
433 } 305 }
434 306
(...skipping 26 matching lines...) Expand all
461 } 333 }
462 334
463 void CookiesView::ViewHierarchyChanged(bool is_add, 335 void CookiesView::ViewHierarchyChanged(bool is_add,
464 views::View* parent, 336 views::View* parent,
465 views::View* child) { 337 views::View* child) {
466 if (is_add && child == this) 338 if (is_add && child == this)
467 Init(); 339 Init();
468 } 340 }
469 341
470 /////////////////////////////////////////////////////////////////////////////// 342 ///////////////////////////////////////////////////////////////////////////////
343 // CookiesView, views::TreeViewController overrides:
344
345 void CookiesView::OnTreeViewSelectionChanged(views::TreeView* tree_view) {
346 CookieTreeNode::DetailedInfo detailed_info =
347 static_cast<CookieTreeNode*>(tree_view->GetSelectedNode())->
348 GetDetailedInfo();
349 if (detailed_info.node_type == CookieTreeNode::DetailedInfo::TYPE_COOKIE) {
350 info_view_->SetCookie(detailed_info.cookie->first,
351 detailed_info.cookie->second);
352 } else {
353 info_view_->ClearCookieDisplay();
354 }
355 }
356
357 void CookiesView::OnTreeViewKeyDown(base::KeyboardCode keycode) {
358 if (keycode == base::VKEY_DELETE)
359 cookies_tree_->RemoveSelectedItems();
360 }
361
362 ///////////////////////////////////////////////////////////////////////////////
471 // CookiesView, private: 363 // CookiesView, private:
472 364
473 CookiesView::CookiesView(Profile* profile) 365 CookiesView::CookiesView(Profile* profile)
474 : search_label_(NULL), 366 :
475 search_field_(NULL),
476 clear_search_button_(NULL),
477 description_label_(NULL), 367 description_label_(NULL),
478 cookies_table_(NULL), 368 cookies_tree_(NULL),
479 info_view_(NULL), 369 info_view_(NULL),
480 remove_button_(NULL), 370 remove_button_(NULL),
481 remove_all_button_(NULL), 371 remove_all_button_(NULL),
482 profile_(profile), 372 profile_(profile) {
483 ALLOW_THIS_IN_INITIALIZER_LIST(search_update_factory_(this)) { 373 }
374
375 views::View* CookiesView::GetInitiallyFocusedView() {
376 return cookies_tree_;
484 } 377 }
485 378
486 void CookiesView::Init() { 379 void CookiesView::Init() {
487 search_label_ = new views::Label(
488 l10n_util::GetString(IDS_COOKIES_SEARCH_LABEL));
489 search_field_ = new views::Textfield;
490 search_field_->SetController(this);
491 clear_search_button_ = new views::NativeButton(
492 this, l10n_util::GetString(IDS_COOKIES_CLEAR_SEARCH_LABEL));
493 clear_search_button_->SetEnabled(false);
494 description_label_ = new views::Label( 380 description_label_ = new views::Label(
495 l10n_util::GetString(IDS_COOKIES_INFO_LABEL)); 381 l10n_util::GetString(IDS_COOKIES_INFO_LABEL));
496 description_label_->SetHorizontalAlignment(views::Label::ALIGN_LEFT); 382 description_label_->SetHorizontalAlignment(views::Label::ALIGN_LEFT);
497 383 cookies_tree_model_.reset(new CookiesTreeModel(profile_));
498 cookies_table_model_.reset(new CookiesTableModel(profile_));
499 info_view_ = new CookieInfoView; 384 info_view_ = new CookieInfoView;
500 std::vector<TableColumn> columns; 385 cookies_tree_ = new CookiesTreeView(cookies_tree_model_.get());
501 columns.push_back(TableColumn(IDS_COOKIES_DOMAIN_COLUMN_HEADER,
502 TableColumn::LEFT, 200, 0.5f));
503 columns.back().sortable = true;
504 columns.push_back(TableColumn(IDS_COOKIES_NAME_COLUMN_HEADER,
505 TableColumn::LEFT, 150, 0.5f));
506 columns.back().sortable = true;
507 cookies_table_ = new CookiesTableView(cookies_table_model_.get(), columns);
508 cookies_table_->SetObserver(this);
509 // Make the table initially sorted by domain.
510 views::TableView::SortDescriptors sort;
511 sort.push_back(
512 views::TableView::SortDescriptor(IDS_COOKIES_DOMAIN_COLUMN_HEADER,
513 true));
514 cookies_table_->SetSortDescriptors(sort);
515 remove_button_ = new views::NativeButton( 386 remove_button_ = new views::NativeButton(
516 this, l10n_util::GetString(IDS_COOKIES_REMOVE_LABEL)); 387 this, l10n_util::GetString(IDS_COOKIES_REMOVE_LABEL));
517 remove_all_button_ = new views::NativeButton( 388 remove_all_button_ = new views::NativeButton(
518 this, l10n_util::GetString(IDS_COOKIES_REMOVE_ALL_LABEL)); 389 this, l10n_util::GetString(IDS_COOKIES_REMOVE_ALL_LABEL));
519 390
520 using views::GridLayout; 391 using views::GridLayout;
521 using views::ColumnSet; 392 using views::ColumnSet;
522 393
523 GridLayout* layout = CreatePanelGridLayout(this); 394 GridLayout* layout = CreatePanelGridLayout(this);
524 SetLayoutManager(layout); 395 SetLayoutManager(layout);
525 396
526 const int five_column_layout_id = 0; 397 const int five_column_layout_id = 0;
527 ColumnSet* column_set = layout->AddColumnSet(five_column_layout_id); 398 ColumnSet* column_set = layout->AddColumnSet(five_column_layout_id);
528 column_set->AddColumn(GridLayout::FILL, GridLayout::CENTER, 0, 399 column_set->AddColumn(GridLayout::FILL, GridLayout::CENTER, 0,
529 GridLayout::USE_PREF, 0, 0); 400 GridLayout::USE_PREF, 0, 0);
530 column_set->AddPaddingColumn(0, kRelatedControlHorizontalSpacing); 401 column_set->AddPaddingColumn(0, kRelatedControlHorizontalSpacing);
531 column_set->AddColumn(GridLayout::FILL, GridLayout::FILL, 1, 402 column_set->AddColumn(GridLayout::FILL, GridLayout::FILL, 1,
532 GridLayout::USE_PREF, 0, 0); 403 GridLayout::USE_PREF, 0, 0);
533 column_set->AddPaddingColumn(0, kRelatedControlHorizontalSpacing); 404 column_set->AddPaddingColumn(0, kRelatedControlHorizontalSpacing);
534 column_set->AddColumn(GridLayout::FILL, GridLayout::FILL, 0, 405 column_set->AddColumn(GridLayout::FILL, GridLayout::FILL, 0,
535 GridLayout::USE_PREF, 0, 0); 406 GridLayout::USE_PREF, 0, 0);
536 407
537 const int single_column_layout_id = 1; 408 const int single_column_layout_id = 1;
538 column_set = layout->AddColumnSet(single_column_layout_id); 409 column_set = layout->AddColumnSet(single_column_layout_id);
539 column_set->AddColumn(GridLayout::FILL, GridLayout::FILL, 1, 410 column_set->AddColumn(GridLayout::FILL, GridLayout::FILL, 1,
540 GridLayout::USE_PREF, 0, 0); 411 GridLayout::USE_PREF, 0, 0);
541 412
542 layout->StartRow(0, five_column_layout_id);
543 layout->AddView(search_label_);
544 layout->AddView(search_field_);
545 layout->AddView(clear_search_button_);
546 layout->AddPaddingRow(0, kUnrelatedControlVerticalSpacing);
547 layout->StartRow(0, single_column_layout_id); 413 layout->StartRow(0, single_column_layout_id);
548 layout->AddView(description_label_); 414 layout->AddView(description_label_);
415
549 layout->AddPaddingRow(0, kRelatedControlVerticalSpacing); 416 layout->AddPaddingRow(0, kRelatedControlVerticalSpacing);
550 layout->StartRow(1, single_column_layout_id); 417 layout->StartRow(1, single_column_layout_id);
551 layout->AddView(cookies_table_); 418 layout->AddView(cookies_tree_);
419 cookies_tree_->ExpandAll();
420
421 cookies_tree_->SetController(this);
422
552 layout->AddPaddingRow(0, kRelatedControlVerticalSpacing); 423 layout->AddPaddingRow(0, kRelatedControlVerticalSpacing);
553 layout->StartRow(0, single_column_layout_id); 424 layout->StartRow(0, single_column_layout_id);
554 layout->AddView(info_view_); 425 layout->AddView(info_view_);
555 426
556 // Add the Remove/Remove All buttons to the ClientView 427 // Add the Remove/Remove All buttons to the ClientView
557 View* parent = GetParent(); 428 View* parent = GetParent();
558 parent->AddChildView(remove_button_); 429 parent->AddChildView(remove_button_);
559 parent->AddChildView(remove_all_button_); 430 parent->AddChildView(remove_all_button_);
560 431 if (!cookies_tree_model_.get()->GetRoot()->GetChildCount())
561 if (cookies_table_->RowCount() > 0) {
562 cookies_table_->Select(0);
563 } else {
564 UpdateForEmptyState(); 432 UpdateForEmptyState();
565 }
566 }
567
568 void CookiesView::ResetSearchQuery() {
569 search_field_->SetText(EmptyWString());
570 clear_search_button_->SetEnabled(false);
571 UpdateSearchResults();
572 } 433 }
573 434
574 void CookiesView::UpdateForEmptyState() { 435 void CookiesView::UpdateForEmptyState() {
575 info_view_->ClearCookieDisplay(); 436 info_view_->ClearCookieDisplay();
576 remove_button_->SetEnabled(false); 437 remove_button_->SetEnabled(false);
577 remove_all_button_->SetEnabled(false); 438 remove_all_button_->SetEnabled(false);
578 } 439 }
OLDNEW
« no previous file with comments | « chrome/browser/views/options/cookies_view.h ('k') | chrome/chrome.gyp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698