OLD | NEW |
| (Empty) |
1 // Copyright (c) 2006-2008 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/bookmarks/bookmark_folder_tree_model.h" | |
6 | |
7 #include "app/l10n_util.h" | |
8 #include "app/resource_bundle.h" | |
9 #include "chrome/browser/bookmarks/bookmark_model.h" | |
10 #include "grit/generated_resources.h" | |
11 #include "grit/theme_resources.h" | |
12 #include "third_party/skia/include/core/SkBitmap.h" | |
13 | |
14 BookmarkFolderTreeModel::BookmarkFolderTreeModel(BookmarkModel* model) | |
15 : TreeNodeModel<FolderNode>(new FolderNode(NULL)), | |
16 model_(model), | |
17 recently_bookmarked_node_(new FolderNode(NULL)), | |
18 search_node_(new FolderNode(NULL)) { | |
19 recently_bookmarked_node_->SetTitle( | |
20 l10n_util::GetString(IDS_BOOKMARK_TREE_RECENTLY_BOOKMARKED_NODE_TITLE)); | |
21 search_node_->SetTitle( | |
22 l10n_util::GetString(IDS_BOOKMARK_TREE_SEARCH_NODE_TITLE)); | |
23 if (model_->IsLoaded()) | |
24 AddRootChildren(); | |
25 model_->AddObserver(this); | |
26 } | |
27 | |
28 BookmarkFolderTreeModel::~BookmarkFolderTreeModel() { | |
29 if (model_) | |
30 model_->RemoveObserver(this); | |
31 } | |
32 | |
33 BookmarkFolderTreeModel::NodeType BookmarkFolderTreeModel::GetNodeType( | |
34 TreeModelNode* node) { | |
35 if (node == recently_bookmarked_node_) | |
36 return RECENTLY_BOOKMARKED; | |
37 if (node == search_node_) | |
38 return SEARCH; | |
39 if (node == GetRoot()) | |
40 return NONE; | |
41 return BOOKMARK; | |
42 } | |
43 | |
44 FolderNode* BookmarkFolderTreeModel::GetFolderNodeForBookmarkNode( | |
45 const BookmarkNode* node) { | |
46 if (!node->is_folder()) | |
47 return NULL; | |
48 | |
49 return GetFolderNodeForBookmarkNode(AsNode(GetRoot()), node); | |
50 } | |
51 | |
52 const BookmarkNode* BookmarkFolderTreeModel::TreeNodeAsBookmarkNode( | |
53 TreeModelNode* node) { | |
54 if (GetNodeType(node) != BOOKMARK) | |
55 return NULL; | |
56 return AsNode(node)->value; | |
57 } | |
58 | |
59 void BookmarkFolderTreeModel::Loaded(BookmarkModel* model) { | |
60 AddRootChildren(); | |
61 } | |
62 | |
63 void BookmarkFolderTreeModel::BookmarkModelBeingDeleted(BookmarkModel* model) { | |
64 DCHECK(model_); | |
65 model_->RemoveObserver(this); | |
66 model_ = NULL; | |
67 } | |
68 | |
69 void BookmarkFolderTreeModel::BookmarkNodeMoved(BookmarkModel* model, | |
70 const BookmarkNode* old_parent, | |
71 int old_index, | |
72 const BookmarkNode* new_parent, | |
73 int new_index) { | |
74 const BookmarkNode* moved_node = new_parent->GetChild(new_index); | |
75 if (!moved_node->is_folder()) | |
76 return; // We're only showing folders, so we can ignore this. | |
77 | |
78 FolderNode* moved_folder_node = GetFolderNodeForBookmarkNode(moved_node); | |
79 DCHECK(moved_folder_node); | |
80 int old_folder_index = | |
81 moved_folder_node->GetParent()->IndexOfChild(moved_folder_node); | |
82 Remove(moved_folder_node->GetParent(), old_folder_index); | |
83 int new_folder_index = CalculateIndexForChild(moved_node); | |
84 Add(GetFolderNodeForBookmarkNode(new_parent), new_folder_index, | |
85 moved_folder_node); | |
86 } | |
87 | |
88 void BookmarkFolderTreeModel::BookmarkNodeAdded(BookmarkModel* model, | |
89 const BookmarkNode* parent, | |
90 int index) { | |
91 const BookmarkNode* new_node = parent->GetChild(index); | |
92 if (!new_node->is_folder()) | |
93 return; // We're only showing folders, so we can ignore this. | |
94 | |
95 int folder_index = CalculateIndexForChild(new_node); | |
96 Add(GetFolderNodeForBookmarkNode(parent), folder_index, | |
97 CreateFolderNode(new_node)); | |
98 } | |
99 | |
100 void BookmarkFolderTreeModel::BookmarkNodeRemoved(BookmarkModel* model, | |
101 const BookmarkNode* parent, | |
102 int index, | |
103 const BookmarkNode* node) { | |
104 if (!node->is_folder()) | |
105 return; // We're only showing folders. | |
106 | |
107 FolderNode* folder_node = GetFolderNodeForBookmarkNode(parent); | |
108 DCHECK(folder_node); | |
109 for (int i = 0; i < folder_node->GetChildCount(); ++i) { | |
110 if (folder_node->GetChild(i)->value == node) { | |
111 scoped_ptr<FolderNode> removed_node(Remove(folder_node, i)); | |
112 return; | |
113 } | |
114 } | |
115 | |
116 // If we get here it means a folder was removed that we didn't know about, | |
117 // which shouldn't happen. | |
118 NOTREACHED(); | |
119 } | |
120 | |
121 void BookmarkFolderTreeModel::BookmarkNodeChanged(BookmarkModel* model, | |
122 const BookmarkNode* node) { | |
123 if (!node->is_folder()) | |
124 return; | |
125 | |
126 FolderNode* folder_node = GetFolderNodeForBookmarkNode(node); | |
127 if (!folder_node) | |
128 return; | |
129 | |
130 folder_node->SetTitle(node->GetTitle()); | |
131 FOR_EACH_OBSERVER(TreeModelObserver, | |
132 observer_list(), | |
133 TreeNodeChanged(this, folder_node)); | |
134 } | |
135 | |
136 void BookmarkFolderTreeModel::BookmarkNodeChildrenReordered( | |
137 BookmarkModel* model, | |
138 const BookmarkNode* node) { | |
139 FolderNode* folder_node = GetFolderNodeForBookmarkNode(node); | |
140 DCHECK(folder_node); | |
141 if (folder_node->GetChildCount() <= 1) | |
142 return; // Order won't have changed if 1 or fewer nodes. | |
143 | |
144 // Build a map between folder node and bookmark node. | |
145 std::map<const BookmarkNode*, FolderNode*> bn_to_folder; | |
146 for (int i = 0; i < folder_node->GetChildCount(); ++i) | |
147 bn_to_folder[folder_node->GetChild(i)->value] = folder_node->GetChild(i); | |
148 | |
149 // Remove all the folder nodes. | |
150 int original_count = folder_node->GetChildCount(); | |
151 folder_node->RemoveAll(); | |
152 | |
153 // And add them back in the new order. | |
154 for (int i = 0; i < node->GetChildCount(); ++i) { | |
155 const BookmarkNode* child = node->GetChild(i); | |
156 if (child->is_folder()) { | |
157 DCHECK(bn_to_folder.find(child) != bn_to_folder.end()); | |
158 folder_node->Add(folder_node->GetChildCount(), bn_to_folder[child]); | |
159 } | |
160 } | |
161 // The new count better match the original count, otherwise we're leaking and | |
162 // treeview is likely to get way out of sync. | |
163 DCHECK(original_count == folder_node->GetChildCount()); | |
164 | |
165 // Finally, notify observers. | |
166 FOR_EACH_OBSERVER(TreeModelObserver, | |
167 observer_list(), | |
168 TreeNodeChildrenReordered(this, folder_node)); | |
169 } | |
170 | |
171 void BookmarkFolderTreeModel::GetIcons(std::vector<SkBitmap>* icons) { | |
172 ResourceBundle& rb = ResourceBundle::GetSharedInstance(); | |
173 icons->push_back(*rb.GetBitmapNamed(IDR_BOOKMARK_MANAGER_RECENT_ICON)); | |
174 icons->push_back(*rb.GetBitmapNamed(IDR_BOOKMARK_MANAGER_SEARCH_ICON)); | |
175 } | |
176 | |
177 int BookmarkFolderTreeModel::GetIconIndex(TreeModelNode* node) { | |
178 if (node == recently_bookmarked_node_) | |
179 return 0; | |
180 if (node == search_node_) | |
181 return 1; | |
182 | |
183 // Return -1 to use the default. | |
184 return -1; | |
185 } | |
186 | |
187 void BookmarkFolderTreeModel::AddRootChildren() { | |
188 Add(AsNode(GetRoot()), 0, CreateFolderNode(model_->GetBookmarkBarNode())); | |
189 Add(AsNode(GetRoot()), 1, CreateFolderNode(model_->other_node())); | |
190 Add(AsNode(GetRoot()), 2, recently_bookmarked_node_); | |
191 Add(AsNode(GetRoot()), 3, search_node_); | |
192 } | |
193 | |
194 FolderNode* BookmarkFolderTreeModel::GetFolderNodeForBookmarkNode( | |
195 FolderNode* folder_node, | |
196 const BookmarkNode* node) { | |
197 DCHECK(node->is_folder()); | |
198 if (folder_node->value == node) | |
199 return folder_node; | |
200 for (int i = 0; i < folder_node->GetChildCount(); ++i) { | |
201 FolderNode* result = | |
202 GetFolderNodeForBookmarkNode(folder_node->GetChild(i), node); | |
203 if (result) | |
204 return result; | |
205 } | |
206 return NULL; | |
207 } | |
208 | |
209 FolderNode* BookmarkFolderTreeModel::CreateFolderNode( | |
210 const BookmarkNode* node) { | |
211 DCHECK(node->is_folder()); | |
212 FolderNode* folder_node = new FolderNode(node); | |
213 folder_node->SetTitle(node->GetTitle()); | |
214 | |
215 // And clone the children folders. | |
216 for (int i = 0; i < node->GetChildCount(); ++i) { | |
217 const BookmarkNode* child = node->GetChild(i); | |
218 if (child->is_folder()) | |
219 folder_node->Add(folder_node->GetChildCount(), CreateFolderNode(child)); | |
220 } | |
221 return folder_node; | |
222 } | |
223 | |
224 int BookmarkFolderTreeModel::CalculateIndexForChild(const BookmarkNode* node) { | |
225 const BookmarkNode* parent = node->GetParent(); | |
226 DCHECK(parent); | |
227 for (int i = 0, folder_count = 0; i < parent->GetChildCount(); ++i) { | |
228 const BookmarkNode* child = parent->GetChild(i); | |
229 if (child == node) | |
230 return folder_count; | |
231 if (child->is_folder()) | |
232 folder_count++; | |
233 } | |
234 NOTREACHED(); | |
235 return 0; | |
236 } | |
OLD | NEW |