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

Side by Side Diff: chrome/browser/views/bookmark_table_view.cc

Issue 1730015: Windows/Views: delete native bookmark manager code. (Closed)
Patch Set: Patch with fixed file perms. Created 10 years, 8 months 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
« no previous file with comments | « chrome/browser/views/bookmark_table_view.h ('k') | chrome/browser/views/dialog_stubs_gtk.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright (c) 2010 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/views/bookmark_table_view.h"
6
7 #include <commctrl.h>
8
9 #include "app/drag_drop_types.h"
10 #include "app/l10n_util.h"
11 #include "app/os_exchange_data.h"
12 #include "app/os_exchange_data_provider_win.h"
13 #include "app/resource_bundle.h"
14 #include "base/base_drag_source.h"
15 #include "chrome/browser/bookmarks/bookmark_utils.h"
16 #include "chrome/browser/bookmarks/bookmark_model.h"
17 #include "chrome/browser/bookmarks/bookmark_table_model.h"
18 #include "chrome/browser/pref_service.h"
19 #include "chrome/browser/profile.h"
20 #include "chrome/common/pref_names.h"
21 #include "gfx/canvas.h"
22 #include "grit/generated_resources.h"
23 #include "views/controls/table/table_view_observer.h"
24 #include "views/view_constants.h"
25
26 namespace {
27
28 // Height of the drop indicator used when dropping between rows.
29 const int kDropHighlightHeight = 2;
30
31 int GetWidthOfColumn(const std::vector<TableColumn>& columns,
32 const std::vector<int> widths,
33 int column_id) {
34 for (size_t i = 0; i < columns.size(); ++i) {
35 if (columns[i].id == column_id)
36 return widths[i];
37 }
38 NOTREACHED();
39 return -1;
40 }
41
42 } // namespace
43
44 void BookmarkTableView::DropInfo::Scrolled() {
45 view_->UpdateDropInfo();
46 }
47
48 BookmarkTableView::BookmarkTableView(Profile* profile,
49 BookmarkTableModel* model)
50 : views::TableView(model, std::vector<TableColumn>(),
51 views::ICON_AND_TEXT, false, true, true),
52 profile_(profile),
53 show_path_column_(false) {
54 UpdateColumns();
55 }
56
57 bool BookmarkTableView::CanDrop(const OSExchangeData& data) {
58 if (!parent_node_ || !profile_->GetBookmarkModel()->IsLoaded())
59 return false;
60
61 BookmarkDragData drag_data;
62 if (!drag_data.Read(data))
63 return false;
64
65 // Don't allow the user to drop an ancestor of the parent node onto the
66 // parent node. This would create a cycle, which is definitely a no-no.
67 std::vector<const BookmarkNode*> nodes = drag_data.GetNodes(profile_);
68 for (size_t i = 0; i < nodes.size(); ++i) {
69 if (parent_node_->HasAncestor(nodes[i]))
70 return false;
71 }
72
73 drop_info_.reset(new DropInfo(this));
74 drop_info_->SetData(drag_data);
75 return true;
76 }
77
78 void BookmarkTableView::OnDragEntered(const views::DropTargetEvent& event) {
79 }
80
81 int BookmarkTableView::OnDragUpdated(const views::DropTargetEvent& event) {
82 if (!parent_node_ || !drop_info_.get()) {
83 drop_info_.reset(NULL);
84 return false;
85 }
86
87 drop_info_->Update(event);
88 return UpdateDropInfo();
89 }
90
91 void BookmarkTableView::OnDragExited() {
92 SetDropPosition(DropPosition());
93 drop_info_.reset();
94 }
95
96 int BookmarkTableView::OnPerformDrop(const views::DropTargetEvent& event) {
97 OnPerformDropImpl();
98 int drop_operation = drop_info_->drop_operation();
99 SetDropPosition(DropPosition());
100 drop_info_.reset();
101 return drop_operation;
102 }
103
104 BookmarkTableModel* BookmarkTableView::bookmark_table_model() const {
105 return static_cast<BookmarkTableModel*>(model());
106 }
107
108 void BookmarkTableView::SaveColumnConfiguration() {
109 PrefService* prefs = profile_->GetPrefs();
110 if (!prefs)
111 return;
112
113 if (show_path_column_) {
114 prefs->SetInteger(prefs::kBookmarkTableNameWidth2,
115 GetColumnWidth(IDS_BOOKMARK_TABLE_TITLE));
116 prefs->SetInteger(prefs::kBookmarkTableURLWidth2,
117 GetColumnWidth(IDS_BOOKMARK_TABLE_URL));
118 prefs->SetInteger(prefs::kBookmarkTablePathWidth,
119 GetColumnWidth(IDS_BOOKMARK_TABLE_PATH));
120 } else {
121 prefs->SetInteger(prefs::kBookmarkTableNameWidth1,
122 GetColumnWidth(IDS_BOOKMARK_TABLE_TITLE));
123 prefs->SetInteger(prefs::kBookmarkTableURLWidth1,
124 GetColumnWidth(IDS_BOOKMARK_TABLE_URL));
125 }
126 }
127
128 void BookmarkTableView::SetShowPathColumn(bool show_path_column) {
129 if (show_path_column == show_path_column_)
130 return;
131
132 SaveColumnConfiguration();
133
134 show_path_column_ = show_path_column;
135 UpdateColumns();
136 }
137
138 void BookmarkTableView::PostPaint() {
139 PaintAltText();
140
141 if (!drop_info_.get() || drop_info_->position().index == -1 ||
142 drop_info_->position().on) {
143 return;
144 }
145
146 RECT bounds = GetDropBetweenHighlightRect(drop_info_->position().index);
147 HDC dc = GetDC(GetNativeControlHWND());
148 HBRUSH brush = CreateSolidBrush(GetSysColor(COLOR_WINDOWTEXT));
149 FillRect(dc, &bounds, brush);
150 DeleteObject(brush);
151 ReleaseDC(GetNativeControlHWND(), dc);
152 }
153
154 LRESULT BookmarkTableView::OnNotify(int w_param, LPNMHDR l_param) {
155 switch (l_param->code) {
156 case LVN_BEGINDRAG:
157 BeginDrag();
158 return 0; // Return value doesn't matter for this message.
159 }
160
161 return TableView::OnNotify(w_param, l_param);
162 }
163
164 int BookmarkTableView::UpdateDropInfo() {
165 DropPosition position = CalculateDropPosition(drop_info_->last_y());
166
167 drop_info_->set_drop_operation(CalculateDropOperation(position));
168
169 if (drop_info_->drop_operation() == DragDropTypes::DRAG_NONE)
170 position = DropPosition();
171
172 SetDropPosition(position);
173
174 return drop_info_->drop_operation();
175 }
176
177 void BookmarkTableView::BeginDrag() {
178 std::vector<const BookmarkNode*> nodes_to_drag;
179 for (TableView::iterator i = SelectionBegin(); i != SelectionEnd(); ++i)
180 nodes_to_drag.push_back(bookmark_table_model()->GetNodeForRow(*i));
181 if (nodes_to_drag.empty())
182 return; // Nothing to drag.
183
184 // Reverse the nodes so that they are put on the clipboard in visual order.
185 // We do this as SelectionBegin starts at the end of the visual order.
186 std::reverse(nodes_to_drag.begin(), nodes_to_drag.end());
187
188 OSExchangeData data;
189 BookmarkDragData(nodes_to_drag).Write(profile_, &data);
190 scoped_refptr<BaseDragSource> drag_source(new BaseDragSource);
191 DWORD effects;
192 DoDragDrop(OSExchangeDataProviderWin::GetIDataObject(data), drag_source,
193 DROPEFFECT_LINK | DROPEFFECT_COPY | DROPEFFECT_MOVE, &effects);
194 }
195
196 int BookmarkTableView::CalculateDropOperation(const DropPosition& position) {
197 if (drop_info_->data().IsFromProfile(profile_)) {
198 // Data from the same profile. Prefer move, but do copy if the user wants
199 // that.
200 if (drop_info_->is_control_down())
201 return DragDropTypes::DRAG_COPY;
202
203 int real_drop_index;
204 const BookmarkNode* drop_parent = GetDropParentAndIndex(position,
205 &real_drop_index);
206 if (!bookmark_utils::IsValidDropLocation(
207 profile_, drop_info_->data(), drop_parent, real_drop_index)) {
208 return DragDropTypes::DRAG_NONE;
209 }
210 return DragDropTypes::DRAG_MOVE;
211 }
212 // We're going to copy, but return an operation compatible with the source
213 // operations so that the user can drop.
214 return bookmark_utils::PreferredDropOperation(
215 drop_info_->source_operations(),
216 DragDropTypes::DRAG_COPY | DragDropTypes::DRAG_LINK);
217 }
218
219 void BookmarkTableView::OnPerformDropImpl() {
220 int drop_index;
221 const BookmarkNode* drop_parent = GetDropParentAndIndex(
222 drop_info_->position(), &drop_index);
223 BookmarkModel* model = profile_->GetBookmarkModel();
224 int min_selection;
225 int max_selection;
226 // If the data is not from this profile we return an operation compatible
227 // with the source. As such, we need to need to check the data here too.
228 if (!drop_info_->data().IsFromProfile(profile_) ||
229 drop_info_->drop_operation() == DragDropTypes::DRAG_COPY) {
230 bookmark_utils::CloneDragData(model, drop_info_->data().elements,
231 drop_parent, drop_index);
232 min_selection = drop_index;
233 max_selection = drop_index +
234 static_cast<int>(drop_info_->data().elements.size());
235 } else {
236 // else, move.
237 std::vector<const BookmarkNode*> nodes =
238 drop_info_->data().GetNodes(profile_);
239 if (nodes.empty())
240 return;
241
242 for (size_t i = 0; i < nodes.size(); ++i) {
243 model->Move(nodes[i], drop_parent, drop_index);
244 // Reset the drop_index, just in case the index didn't really change.
245 drop_index = drop_parent->IndexOfChild(nodes[i]) + 1;
246 }
247 min_selection = drop_parent->IndexOfChild(nodes[0]);
248 max_selection = min_selection + static_cast<int>(nodes.size());
249 }
250 if (drop_info_->position().on) {
251 // The user dropped on a folder, select it.
252 int index = parent_node_->IndexOfChild(drop_parent);
253 if (index != -1)
254 Select(index);
255 } else if (min_selection < RowCount() && max_selection <= RowCount()) {
256 // Select the moved/copied rows.
257 Select(min_selection);
258 if (min_selection + 1 < max_selection) {
259 // SetSelectedState doesn't send notification, so we manually do it.
260 for (int i = min_selection + 1; i < max_selection; ++i)
261 SetSelectedState(i, true);
262 if (observer())
263 observer()->OnSelectionChanged();
264 }
265 }
266 }
267
268 void BookmarkTableView::SetDropPosition(const DropPosition& position) {
269 if (drop_info_->position().equals(position))
270 return;
271
272 UpdateDropIndicator(drop_info_->position(), false);
273
274 drop_info_->set_position(position);
275
276 UpdateDropIndicator(drop_info_->position(), true);
277 }
278
279 void BookmarkTableView::UpdateDropIndicator(const DropPosition& position,
280 bool turn_on) {
281 if (position.index == -1)
282 return;
283
284 if (position.on) {
285 ListView_SetItemState(GetNativeControlHWND(), position.index,
286 turn_on ? LVIS_DROPHILITED : 0, LVIS_DROPHILITED);
287 } else {
288 RECT bounds = GetDropBetweenHighlightRect(position.index);
289 InvalidateRect(GetNativeControlHWND(), &bounds, FALSE);
290 }
291 }
292
293 BookmarkTableView::DropPosition
294 BookmarkTableView::CalculateDropPosition(int y) {
295 HWND hwnd = GetNativeControlHWND();
296 int row_count = RowCount();
297 int top_index = ListView_GetTopIndex(hwnd);
298 if (row_count == 0 || top_index < 0)
299 return DropPosition(0, false);
300
301 for (int i = top_index; i < row_count; ++i) {
302 RECT bounds;
303 ListView_GetItemRect(hwnd, i, &bounds, LVIR_BOUNDS);
304 if (y < bounds.top)
305 return DropPosition(i, false);
306 if (y < bounds.bottom) {
307 if (bookmark_table_model()->GetNodeForRow(i)->is_folder()) {
308 if (y < bounds.top + views::kDropBetweenPixels)
309 return DropPosition(i, false);
310 if (y >= bounds.bottom - views::kDropBetweenPixels)
311 return DropPosition(i + 1, false);
312 return DropPosition(i, true);
313 }
314 if (y < (bounds.bottom - bounds.top) / 2 + bounds.top)
315 return DropPosition(i, false);
316 return DropPosition(i + 1, false);
317 }
318 }
319 return DropPosition(row_count, false);
320 }
321
322 const BookmarkNode* BookmarkTableView::GetDropParentAndIndex(
323 const DropPosition& position,
324 int* index) {
325 if (position.on) {
326 const BookmarkNode* parent = parent_node_->GetChild(position.index);
327 *index = parent->GetChildCount();
328 return parent;
329 }
330 *index = position.index;
331 return parent_node_;
332 }
333
334 RECT BookmarkTableView::GetDropBetweenHighlightRect(int index) {
335 RECT bounds = { 0 };
336 if (RowCount() == 0) {
337 bounds.top = content_offset();
338 bounds.left = 0;
339 bounds.right = width();
340 } else if (index >= RowCount()) {
341 ListView_GetItemRect(GetNativeControlHWND(), index - 1, &bounds,
342 LVIR_BOUNDS);
343 bounds.top = bounds.bottom - kDropHighlightHeight / 2;
344 } else {
345 ListView_GetItemRect(GetNativeControlHWND(), index, &bounds, LVIR_BOUNDS);
346 bounds.top -= kDropHighlightHeight / 2;
347 }
348 bounds.bottom = bounds.top + kDropHighlightHeight;
349 return bounds;
350 }
351
352 void BookmarkTableView::UpdateColumns() {
353 PrefService* prefs = profile_->GetPrefs();
354 TableColumn name_column =
355 TableColumn(IDS_BOOKMARK_TABLE_TITLE, TableColumn::LEFT, -1);
356 TableColumn url_column =
357 TableColumn(IDS_BOOKMARK_TABLE_URL, TableColumn::LEFT, -1);
358 TableColumn path_column =
359 TableColumn(IDS_BOOKMARK_TABLE_PATH, TableColumn::LEFT, -1);
360
361 std::vector<TableColumn> columns;
362 if (show_path_column_) {
363 int name_width = -1;
364 int url_width = -1;
365 int path_width = -1;
366 if (prefs) {
367 name_width = prefs->GetInteger(prefs::kBookmarkTableNameWidth2);
368 url_width = prefs->GetInteger(prefs::kBookmarkTableURLWidth2);
369 path_width = prefs->GetInteger(prefs::kBookmarkTablePathWidth);
370 }
371 if (name_width != -1 && url_width != -1 && path_width != -1) {
372 name_column.width = name_width;
373 url_column.width = url_width;
374 path_column.width = path_width;
375 } else {
376 name_column.percent = .5;
377 url_column.percent = .25;
378 path_column.percent= .25;
379 }
380 columns.push_back(name_column);
381 columns.push_back(url_column);
382 columns.push_back(path_column);
383 } else {
384 int name_width = -1;
385 int url_width = -1;
386 if (prefs) {
387 name_width = prefs->GetInteger(prefs::kBookmarkTableNameWidth1);
388 url_width = prefs->GetInteger(prefs::kBookmarkTableURLWidth1);
389 }
390 if (name_width != -1 && url_width != -1) {
391 name_column.width = name_width;
392 url_column.width = url_width;
393 } else {
394 name_column.percent = .5;
395 url_column.percent = .5;
396 }
397 columns.push_back(name_column);
398 columns.push_back(url_column);
399 }
400 SetColumns(columns);
401 for (size_t i = 0; i < columns.size(); ++i)
402 SetColumnVisibility(columns[i].id, true);
403 OnModelChanged();
404 }
OLDNEW
« no previous file with comments | « chrome/browser/views/bookmark_table_view.h ('k') | chrome/browser/views/dialog_stubs_gtk.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698