| 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 "chrome/browser/ui/views/options/exceptions_view.h" | |
| 6 | |
| 7 #include <algorithm> | |
| 8 #include <vector> | |
| 9 | |
| 10 #include "base/utf_string_conversions.h" | |
| 11 #include "chrome/browser/ui/views/options/content_exceptions_table_view.h" | |
| 12 #include "grit/generated_resources.h" | |
| 13 #include "grit/locale_settings.h" | |
| 14 #include "ui/base/l10n/l10n_util.h" | |
| 15 #include "ui/gfx/rect.h" | |
| 16 #include "views/controls/button/native_button.h" | |
| 17 #include "views/controls/label.h" | |
| 18 #include "views/controls/table/table_view.h" | |
| 19 #include "views/layout/grid_layout.h" | |
| 20 #include "views/layout/layout_constants.h" | |
| 21 #include "views/window/window.h" | |
| 22 | |
| 23 static const int kExceptionsViewInsetSize = 5; | |
| 24 static ExceptionsView* instances[CONTENT_SETTINGS_NUM_TYPES] = { NULL }; | |
| 25 | |
| 26 // static | |
| 27 void ExceptionsView::ShowExceptionsWindow( | |
| 28 gfx::NativeWindow parent, | |
| 29 HostContentSettingsMap* map, | |
| 30 HostContentSettingsMap* off_the_record_map, | |
| 31 ContentSettingsType content_type) { | |
| 32 if (!instances[content_type]) { | |
| 33 instances[content_type] = | |
| 34 new ExceptionsView(map, off_the_record_map, content_type); | |
| 35 views::Window::CreateChromeWindow(parent, gfx::Rect(), | |
| 36 instances[content_type]); | |
| 37 } | |
| 38 | |
| 39 // This will show invisible windows and bring visible windows to the front. | |
| 40 instances[content_type]->window()->Show(); | |
| 41 } | |
| 42 | |
| 43 ExceptionsView::~ExceptionsView() { | |
| 44 instances[model_.content_type()] = NULL; | |
| 45 table_->SetModel(NULL); | |
| 46 } | |
| 47 | |
| 48 void ExceptionsView::OnSelectionChanged() { | |
| 49 UpdateButtonState(); | |
| 50 } | |
| 51 | |
| 52 void ExceptionsView::OnDoubleClick() { | |
| 53 if (table_->SelectedRowCount() == 1) | |
| 54 Edit(); | |
| 55 } | |
| 56 | |
| 57 void ExceptionsView::OnTableViewDelete(views::TableView* table_view) { | |
| 58 Remove(); | |
| 59 } | |
| 60 | |
| 61 void ExceptionsView::ButtonPressed(views::Button* sender, | |
| 62 const views::Event& event) { | |
| 63 switch (sender->tag()) { | |
| 64 case IDS_EXCEPTIONS_ADD_BUTTON: | |
| 65 Add(); | |
| 66 break; | |
| 67 case IDS_EXCEPTIONS_EDIT_BUTTON: | |
| 68 Edit(); | |
| 69 break; | |
| 70 case IDS_EXCEPTIONS_REMOVEALL_BUTTON: | |
| 71 RemoveAll(); | |
| 72 break; | |
| 73 case IDS_EXCEPTIONS_REMOVE_BUTTON: | |
| 74 Remove(); | |
| 75 break; | |
| 76 default: | |
| 77 NOTREACHED(); | |
| 78 } | |
| 79 } | |
| 80 | |
| 81 void ExceptionsView::Layout() { | |
| 82 views::NativeButton* buttons[] = { add_button_, edit_button_, | |
| 83 remove_button_, remove_all_button_ }; | |
| 84 | |
| 85 // The buttons are placed in the parent, but we need to lay them out. | |
| 86 int max_y = | |
| 87 parent()->GetContentsBounds().bottom() - views::kButtonVEdgeMargin; | |
| 88 int x = views::kPanelHorizMargin; | |
| 89 | |
| 90 for (size_t i = 0; i < arraysize(buttons); ++i) { | |
| 91 gfx::Size pref = buttons[i]->GetPreferredSize(); | |
| 92 buttons[i]->SetBounds(x, max_y - pref.height(), pref.width(), | |
| 93 pref.height()); | |
| 94 x += pref.width() + views::kRelatedControlHorizontalSpacing; | |
| 95 } | |
| 96 | |
| 97 // Lay out the rest of this view. | |
| 98 View::Layout(); | |
| 99 } | |
| 100 | |
| 101 gfx::Size ExceptionsView::GetPreferredSize() { | |
| 102 return gfx::Size(views::Window::GetLocalizedContentsSize( | |
| 103 IDS_CONTENT_EXCEPTION_DIALOG_WIDTH_CHARS, | |
| 104 IDS_CONTENT_EXCEPTION_DIALOG_HEIGHT_LINES)); | |
| 105 } | |
| 106 | |
| 107 void ExceptionsView::ViewHierarchyChanged(bool is_add, | |
| 108 views::View* parent, | |
| 109 views::View* child) { | |
| 110 if (is_add && child == this) | |
| 111 Init(); | |
| 112 } | |
| 113 | |
| 114 std::wstring ExceptionsView::GetWindowTitle() const { | |
| 115 switch (model_.content_type()) { | |
| 116 case CONTENT_SETTINGS_TYPE_COOKIES: | |
| 117 return UTF16ToWide(l10n_util::GetStringUTF16(IDS_COOKIE_EXCEPTION_TITLE)); | |
| 118 case CONTENT_SETTINGS_TYPE_IMAGES: | |
| 119 return UTF16ToWide(l10n_util::GetStringUTF16(IDS_IMAGES_EXCEPTION_TITLE)); | |
| 120 case CONTENT_SETTINGS_TYPE_JAVASCRIPT: | |
| 121 return UTF16ToWide(l10n_util::GetStringUTF16(IDS_JS_EXCEPTION_TITLE)); | |
| 122 case CONTENT_SETTINGS_TYPE_PLUGINS: | |
| 123 return UTF16ToWide( | |
| 124 l10n_util::GetStringUTF16(IDS_PLUGINS_EXCEPTION_TITLE)); | |
| 125 case CONTENT_SETTINGS_TYPE_POPUPS: | |
| 126 return UTF16ToWide(l10n_util::GetStringUTF16(IDS_POPUP_EXCEPTION_TITLE)); | |
| 127 default: | |
| 128 NOTREACHED(); | |
| 129 } | |
| 130 return std::wstring(); | |
| 131 } | |
| 132 | |
| 133 void ExceptionsView::AcceptExceptionEdit( | |
| 134 const ContentSettingsPattern& pattern, | |
| 135 ContentSetting setting, | |
| 136 bool is_off_the_record, | |
| 137 int index, | |
| 138 bool is_new) { | |
| 139 DCHECK(!is_off_the_record || allow_off_the_record_); | |
| 140 | |
| 141 if (!is_new) | |
| 142 model_.RemoveException(index); | |
| 143 model_.AddException(pattern, setting, is_off_the_record); | |
| 144 | |
| 145 int new_index = model_.IndexOfExceptionByPattern(pattern, is_off_the_record); | |
| 146 DCHECK(new_index != -1); | |
| 147 table_->Select(new_index); | |
| 148 } | |
| 149 | |
| 150 ExceptionsView::ExceptionsView(HostContentSettingsMap* map, | |
| 151 HostContentSettingsMap* off_the_record_map, | |
| 152 ContentSettingsType type) | |
| 153 : model_(map, off_the_record_map, type), | |
| 154 allow_off_the_record_(off_the_record_map != NULL), | |
| 155 table_(NULL), | |
| 156 add_button_(NULL), | |
| 157 edit_button_(NULL), | |
| 158 remove_button_(NULL), | |
| 159 remove_all_button_(NULL) { | |
| 160 } | |
| 161 | |
| 162 void ExceptionsView::Init() { | |
| 163 if (table_) | |
| 164 return; // We've already Init'd. | |
| 165 | |
| 166 using views::GridLayout; | |
| 167 | |
| 168 std::vector<ui::TableColumn> columns; | |
| 169 columns.push_back( | |
| 170 ui::TableColumn(IDS_EXCEPTIONS_PATTERN_HEADER, ui::TableColumn::LEFT, -1, | |
| 171 .75)); | |
| 172 columns.back().sortable = true; | |
| 173 columns.push_back( | |
| 174 ui::TableColumn(IDS_EXCEPTIONS_ACTION_HEADER, ui::TableColumn::LEFT, -1, | |
| 175 .25)); | |
| 176 columns.back().sortable = true; | |
| 177 table_ = new ContentExceptionsTableView(&model_, columns); | |
| 178 views::TableView::SortDescriptors sort; | |
| 179 sort.push_back( | |
| 180 views::TableView::SortDescriptor(IDS_EXCEPTIONS_PATTERN_HEADER, true)); | |
| 181 table_->SetSortDescriptors(sort); | |
| 182 table_->SetObserver(this); | |
| 183 | |
| 184 add_button_ = new views::NativeButton( | |
| 185 this, UTF16ToWide(l10n_util::GetStringUTF16(IDS_EXCEPTIONS_ADD_BUTTON))); | |
| 186 add_button_->set_tag(IDS_EXCEPTIONS_ADD_BUTTON); | |
| 187 edit_button_ = new views::NativeButton( | |
| 188 this, UTF16ToWide(l10n_util::GetStringUTF16(IDS_EXCEPTIONS_EDIT_BUTTON))); | |
| 189 edit_button_->set_tag(IDS_EXCEPTIONS_EDIT_BUTTON); | |
| 190 remove_button_ = new views::NativeButton( | |
| 191 this, | |
| 192 UTF16ToWide(l10n_util::GetStringUTF16(IDS_EXCEPTIONS_REMOVE_BUTTON))); | |
| 193 remove_button_->set_tag(IDS_EXCEPTIONS_REMOVE_BUTTON); | |
| 194 remove_all_button_ = new views::NativeButton( | |
| 195 this, | |
| 196 UTF16ToWide(l10n_util::GetStringUTF16(IDS_EXCEPTIONS_REMOVEALL_BUTTON))); | |
| 197 remove_all_button_->set_tag(IDS_EXCEPTIONS_REMOVEALL_BUTTON); | |
| 198 | |
| 199 parent()->AddChildView(add_button_); | |
| 200 parent()->AddChildView(edit_button_); | |
| 201 parent()->AddChildView(remove_button_); | |
| 202 parent()->AddChildView(remove_all_button_); | |
| 203 | |
| 204 GridLayout* layout = new GridLayout(this); | |
| 205 layout->SetInsets(kExceptionsViewInsetSize, kExceptionsViewInsetSize, | |
| 206 kExceptionsViewInsetSize, kExceptionsViewInsetSize); | |
| 207 SetLayoutManager(layout); | |
| 208 | |
| 209 const int single_column_layout_id = 0; | |
| 210 views::ColumnSet* column_set = layout->AddColumnSet(single_column_layout_id); | |
| 211 column_set->AddPaddingColumn(0, views::kRelatedControlHorizontalSpacing); | |
| 212 column_set->AddColumn(GridLayout::FILL, GridLayout::FILL, 1, | |
| 213 GridLayout::USE_PREF, 0, 0); | |
| 214 layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing); | |
| 215 | |
| 216 layout->StartRow(1, single_column_layout_id); | |
| 217 layout->AddView(table_); | |
| 218 layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing); | |
| 219 | |
| 220 if (allow_off_the_record_) { | |
| 221 views::Label* label = new views::Label( | |
| 222 UTF16ToWide(l10n_util::GetStringUTF16(IDS_EXCEPTIONS_OTR_IN_ITALICS))); | |
| 223 label->SetHorizontalAlignment(views::Label::ALIGN_LEFT); | |
| 224 layout->StartRow(0, single_column_layout_id); | |
| 225 layout->AddView(label, 1, 1, GridLayout::LEADING, GridLayout::CENTER); | |
| 226 layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing); | |
| 227 } | |
| 228 | |
| 229 UpdateButtonState(); | |
| 230 } | |
| 231 | |
| 232 void ExceptionsView::UpdateButtonState() { | |
| 233 int selected_row_count = table_->SelectedRowCount(); | |
| 234 // TODO: 34177, support editing of more than one entry at a time. | |
| 235 edit_button_->SetEnabled(selected_row_count == 1); | |
| 236 remove_button_->SetEnabled(selected_row_count >= 1); | |
| 237 remove_all_button_->SetEnabled(model_.RowCount() > 0); | |
| 238 } | |
| 239 | |
| 240 void ExceptionsView::Add() { | |
| 241 ExceptionEditorView* view = | |
| 242 new ExceptionEditorView(this, &model_, allow_off_the_record_, -1, | |
| 243 ContentSettingsPattern(), | |
| 244 CONTENT_SETTING_BLOCK, false); | |
| 245 view->Show(window()->GetNativeWindow()); | |
| 246 | |
| 247 UpdateButtonState(); | |
| 248 } | |
| 249 | |
| 250 void ExceptionsView::Edit() { | |
| 251 DCHECK(table_->FirstSelectedRow() != -1); | |
| 252 int index = table_->FirstSelectedRow(); | |
| 253 const HostContentSettingsMap::PatternSettingPair& entry = | |
| 254 model_.entry_at(index); | |
| 255 ExceptionEditorView* view = | |
| 256 new ExceptionEditorView(this, &model_, allow_off_the_record_, index, | |
| 257 entry.first, entry.second, | |
| 258 model_.entry_is_off_the_record(index)); | |
| 259 view->Show(window()->GetNativeWindow()); | |
| 260 } | |
| 261 | |
| 262 void ExceptionsView::Remove() { | |
| 263 std::vector<int> indices; | |
| 264 for (views::TableView::iterator i = table_->SelectionBegin(); | |
| 265 i != table_->SelectionEnd(); ++i) { | |
| 266 indices.push_back(*i); | |
| 267 } | |
| 268 std::sort(indices.begin(), indices.end()); | |
| 269 for (std::vector<int>::reverse_iterator i = indices.rbegin(); | |
| 270 i != indices.rend(); ++i) { | |
| 271 model_.RemoveException(*i); | |
| 272 } | |
| 273 | |
| 274 UpdateButtonState(); | |
| 275 } | |
| 276 | |
| 277 void ExceptionsView::RemoveAll() { | |
| 278 model_.RemoveAll(); | |
| 279 | |
| 280 UpdateButtonState(); | |
| 281 } | |
| OLD | NEW |