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 |