Revert of Add button to add new FSP services to Files app. (patchset #8 id:140001...
[chromium-blink-merge.git] / chrome / browser / ui / views / bookmarks / bookmark_editor_view.cc
blob0ef71fe27d97776129831f1dc275610c20adf1f7
1 // Copyright (c) 2012 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.
5 #include "chrome/browser/ui/views/bookmarks/bookmark_editor_view.h"
7 #include <string>
9 #include "base/basictypes.h"
10 #include "base/logging.h"
11 #include "base/prefs/pref_service.h"
12 #include "base/strings/string_util.h"
13 #include "base/strings/utf_string_conversions.h"
14 #include "chrome/browser/bookmarks/bookmark_model_factory.h"
15 #include "chrome/browser/profiles/profile.h"
16 #include "chrome/browser/ui/bookmarks/bookmark_utils.h"
17 #include "chrome/grit/generated_resources.h"
18 #include "chrome/grit/locale_settings.h"
19 #include "components/bookmarks/browser/bookmark_model.h"
20 #include "components/bookmarks/browser/bookmark_utils.h"
21 #include "components/constrained_window/constrained_window_views.h"
22 #include "components/history/core/browser/history_service.h"
23 #include "components/url_fixer/url_fixer.h"
24 #include "components/user_prefs/user_prefs.h"
25 #include "ui/accessibility/ax_view_state.h"
26 #include "ui/base/l10n/l10n_util.h"
27 #include "ui/events/event.h"
28 #include "ui/views/background.h"
29 #include "ui/views/controls/button/label_button.h"
30 #include "ui/views/controls/label.h"
31 #include "ui/views/controls/menu/menu_runner.h"
32 #include "ui/views/controls/textfield/textfield.h"
33 #include "ui/views/controls/tree/tree_view.h"
34 #include "ui/views/focus/focus_manager.h"
35 #include "ui/views/layout/grid_layout.h"
36 #include "ui/views/layout/layout_constants.h"
37 #include "ui/views/widget/widget.h"
38 #include "ui/views/window/dialog_client_view.h"
39 #include "url/gurl.h"
41 using bookmarks::BookmarkExpandedStateTracker;
42 using bookmarks::BookmarkModel;
43 using bookmarks::BookmarkNode;
44 using views::GridLayout;
46 namespace {
48 // Background color of text field when URL is invalid.
49 const SkColor kErrorColor = SkColorSetRGB(0xFF, 0xBC, 0xBC);
51 } // namespace
53 // static
54 void BookmarkEditor::Show(gfx::NativeWindow parent_window,
55 Profile* profile,
56 const EditDetails& details,
57 Configuration configuration) {
58 DCHECK(profile);
59 BookmarkEditorView* editor = new BookmarkEditorView(profile,
60 details.parent_node, details, configuration);
61 editor->Show(parent_window);
64 BookmarkEditorView::BookmarkEditorView(
65 Profile* profile,
66 const BookmarkNode* parent,
67 const EditDetails& details,
68 BookmarkEditor::Configuration configuration)
69 : profile_(profile),
70 tree_view_(NULL),
71 url_label_(NULL),
72 url_tf_(NULL),
73 title_label_(NULL),
74 title_tf_(NULL),
75 parent_(parent),
76 details_(details),
77 bb_model_(BookmarkModelFactory::GetForProfile(profile)),
78 running_menu_for_root_(false),
79 show_tree_(configuration == SHOW_TREE) {
80 DCHECK(profile);
81 DCHECK(bb_model_);
82 DCHECK(bb_model_->client()->CanBeEditedByUser(parent));
83 Init();
86 BookmarkEditorView::~BookmarkEditorView() {
87 // The tree model is deleted before the view. Reset the model otherwise the
88 // tree will reference a deleted model.
89 if (tree_view_)
90 tree_view_->SetModel(NULL);
91 bb_model_->RemoveObserver(this);
94 base::string16 BookmarkEditorView::GetDialogButtonLabel(
95 ui::DialogButton button) const {
96 if (button == ui::DIALOG_BUTTON_OK)
97 return l10n_util::GetStringUTF16(IDS_SAVE);
98 return views::DialogDelegateView::GetDialogButtonLabel(button);
101 bool BookmarkEditorView::IsDialogButtonEnabled(ui::DialogButton button) const {
102 if (button == ui::DIALOG_BUTTON_OK) {
103 if (!bb_model_->loaded())
104 return false;
106 if (details_.GetNodeType() != BookmarkNode::FOLDER)
107 return GetInputURL().is_valid();
109 return true;
112 views::View* BookmarkEditorView::CreateExtraView() {
113 return new_folder_button_.get();
116 ui::ModalType BookmarkEditorView::GetModalType() const {
117 return ui::MODAL_TYPE_WINDOW;
120 bool BookmarkEditorView::CanResize() const {
121 return true;
124 base::string16 BookmarkEditorView::GetWindowTitle() const {
125 return l10n_util::GetStringUTF16(details_.GetWindowTitleId());
128 bool BookmarkEditorView::Accept() {
129 if (!IsDialogButtonEnabled(ui::DIALOG_BUTTON_OK)) {
130 if (details_.GetNodeType() != BookmarkNode::FOLDER) {
131 // The url is invalid, focus the url field.
132 url_tf_->SelectAll(true);
133 url_tf_->RequestFocus();
135 return false;
137 // Otherwise save changes and close the dialog box.
138 ApplyEdits();
139 return true;
142 gfx::Size BookmarkEditorView::GetPreferredSize() const {
143 if (!show_tree_)
144 return views::View::GetPreferredSize();
146 return gfx::Size(views::Widget::GetLocalizedContentsSize(
147 IDS_EDITBOOKMARK_DIALOG_WIDTH_CHARS,
148 IDS_EDITBOOKMARK_DIALOG_HEIGHT_LINES));
151 void BookmarkEditorView::OnTreeViewSelectionChanged(
152 views::TreeView* tree_view) {
155 bool BookmarkEditorView::CanEdit(views::TreeView* tree_view,
156 ui::TreeModelNode* node) {
157 // Only allow editting of children of the bookmark bar node and other node.
158 EditorNode* bb_node = tree_model_->AsNode(node);
159 return (bb_node->parent() && bb_node->parent()->parent());
162 void BookmarkEditorView::ContentsChanged(views::Textfield* sender,
163 const base::string16& new_contents) {
164 UserInputChanged();
167 bool BookmarkEditorView::HandleKeyEvent(views::Textfield* sender,
168 const ui::KeyEvent& key_event) {
169 return false;
172 void BookmarkEditorView::GetAccessibleState(ui::AXViewState* state) {
173 views::DialogDelegateView::GetAccessibleState(state);
174 state->name =
175 l10n_util::GetStringUTF16(IDS_BOOKMARK_EDITOR_TITLE);
178 void BookmarkEditorView::ButtonPressed(views::Button* sender,
179 const ui::Event& event) {
180 DCHECK_EQ(new_folder_button_.get(), sender);
181 NewFolder();
184 bool BookmarkEditorView::IsCommandIdChecked(int command_id) const {
185 return false;
188 bool BookmarkEditorView::IsCommandIdEnabled(int command_id) const {
189 switch (command_id) {
190 case IDS_EDIT:
191 case IDS_DELETE:
192 return !running_menu_for_root_;
193 case IDS_BOOKMARK_EDITOR_NEW_FOLDER_MENU_ITEM:
194 return true;
195 default:
196 NOTREACHED();
197 return false;
201 bool BookmarkEditorView::GetAcceleratorForCommandId(
202 int command_id,
203 ui::Accelerator* accelerator) {
204 return GetWidget()->GetAccelerator(command_id, accelerator);
207 void BookmarkEditorView::ExecuteCommand(int command_id, int event_flags) {
208 DCHECK(tree_view_->GetSelectedNode());
209 if (command_id == IDS_EDIT) {
210 tree_view_->StartEditing(tree_view_->GetSelectedNode());
211 } else if (command_id == IDS_DELETE) {
212 EditorNode* node = tree_model_->AsNode(tree_view_->GetSelectedNode());
213 if (!node)
214 return;
215 if (node->value != 0) {
216 const BookmarkNode* b_node =
217 bookmarks::GetBookmarkNodeByID(bb_model_, node->value);
218 if (!b_node->empty() &&
219 !chrome::ConfirmDeleteBookmarkNode(b_node,
220 GetWidget()->GetNativeWindow())) {
221 // The folder is not empty and the user didn't confirm.
222 return;
224 deletes_.push_back(node->value);
226 tree_model_->Remove(node->parent(), node);
227 } else {
228 DCHECK_EQ(IDS_BOOKMARK_EDITOR_NEW_FOLDER_MENU_ITEM, command_id);
229 NewFolder();
233 void BookmarkEditorView::Show(gfx::NativeWindow parent) {
234 constrained_window::CreateBrowserModalDialogViews(this, parent);
235 UserInputChanged();
236 if (show_tree_ && bb_model_->loaded())
237 ExpandAndSelect();
238 GetWidget()->Show();
239 // Select all the text in the name Textfield.
240 title_tf_->SelectAll(true);
241 // Give focus to the name Textfield.
242 title_tf_->RequestFocus();
245 void BookmarkEditorView::ShowContextMenuForView(
246 views::View* source,
247 const gfx::Point& point,
248 ui::MenuSourceType source_type) {
249 DCHECK_EQ(tree_view_, source);
250 if (!tree_view_->GetSelectedNode())
251 return;
252 running_menu_for_root_ =
253 (tree_model_->GetParent(tree_view_->GetSelectedNode()) ==
254 tree_model_->GetRoot());
256 context_menu_runner_.reset(new views::MenuRunner(
257 GetMenuModel(),
258 views::MenuRunner::HAS_MNEMONICS | views::MenuRunner::CONTEXT_MENU));
260 if (context_menu_runner_->RunMenuAt(source->GetWidget()->GetTopLevelWidget(),
261 NULL,
262 gfx::Rect(point, gfx::Size()),
263 views::MENU_ANCHOR_TOPRIGHT,
264 source_type) ==
265 views::MenuRunner::MENU_DELETED) {
266 return;
270 const char* BookmarkEditorView::GetClassName() const {
271 return "BookmarkEditorView";
274 void BookmarkEditorView::BookmarkNodeMoved(BookmarkModel* model,
275 const BookmarkNode* old_parent,
276 int old_index,
277 const BookmarkNode* new_parent,
278 int new_index) {
279 Reset();
282 void BookmarkEditorView::BookmarkNodeAdded(BookmarkModel* model,
283 const BookmarkNode* parent,
284 int index) {
285 Reset();
288 void BookmarkEditorView::BookmarkNodeRemoved(
289 BookmarkModel* model,
290 const BookmarkNode* parent,
291 int index,
292 const BookmarkNode* node,
293 const std::set<GURL>& removed_urls) {
294 if ((details_.type == EditDetails::EXISTING_NODE &&
295 details_.existing_node->HasAncestor(node)) ||
296 (parent_ && parent_->HasAncestor(node))) {
297 // The node, or its parent was removed. Close the dialog.
298 GetWidget()->Close();
299 } else {
300 Reset();
304 void BookmarkEditorView::BookmarkAllUserNodesRemoved(
305 BookmarkModel* model,
306 const std::set<GURL>& removed_urls) {
307 Reset();
310 void BookmarkEditorView::BookmarkNodeChildrenReordered(
311 BookmarkModel* model,
312 const BookmarkNode* node) {
313 Reset();
316 void BookmarkEditorView::Init() {
317 bb_model_->AddObserver(this);
319 title_label_ = new views::Label(
320 l10n_util::GetStringUTF16(IDS_BOOKMARK_EDITOR_NAME_LABEL));
322 base::string16 title;
323 GURL url;
324 if (details_.type == EditDetails::EXISTING_NODE) {
325 title = details_.existing_node->GetTitle();
326 url = details_.existing_node->url();
327 } else if (details_.type == EditDetails::NEW_FOLDER) {
328 title = l10n_util::GetStringUTF16(IDS_BOOKMARK_EDITOR_NEW_FOLDER_NAME);
329 } else if (details_.type == EditDetails::NEW_URL) {
330 url = details_.url;
331 title = details_.title;
333 title_tf_ = new views::Textfield;
334 title_tf_->SetAccessibleName(
335 l10n_util::GetStringUTF16(IDS_BOOKMARK_AX_EDITOR_NAME_LABEL));
336 title_tf_->SetText(title);
337 title_tf_->set_controller(this);
339 if (show_tree_) {
340 tree_view_ = new views::TreeView;
341 tree_view_->SetRootShown(false);
342 tree_view_->set_context_menu_controller(this);
344 new_folder_button_.reset(new views::LabelButton(this,
345 l10n_util::GetStringUTF16(IDS_BOOKMARK_EDITOR_NEW_FOLDER_BUTTON)));
346 new_folder_button_->SetStyle(views::Button::STYLE_BUTTON);
347 new_folder_button_->set_owned_by_client();
348 new_folder_button_->SetEnabled(false);
351 GridLayout* layout = GridLayout::CreatePanel(this);
352 SetLayoutManager(layout);
354 const int labels_column_set_id = 0;
355 const int single_column_view_set_id = 1;
356 const int buttons_column_set_id = 2;
358 views::ColumnSet* column_set = layout->AddColumnSet(labels_column_set_id);
359 column_set->AddColumn(GridLayout::LEADING, GridLayout::CENTER, 0,
360 GridLayout::USE_PREF, 0, 0);
361 column_set->AddPaddingColumn(0, views::kRelatedControlHorizontalSpacing);
362 column_set->AddColumn(GridLayout::FILL, GridLayout::CENTER, 1,
363 GridLayout::USE_PREF, 0, 0);
365 column_set = layout->AddColumnSet(single_column_view_set_id);
366 column_set->AddColumn(GridLayout::FILL, GridLayout::FILL, 1,
367 GridLayout::USE_PREF, 0, 0);
369 column_set = layout->AddColumnSet(buttons_column_set_id);
370 column_set->AddColumn(GridLayout::FILL, GridLayout::LEADING, 0,
371 GridLayout::USE_PREF, 0, 0);
372 column_set->AddPaddingColumn(1, views::kRelatedControlHorizontalSpacing);
373 column_set->AddColumn(GridLayout::FILL, GridLayout::LEADING, 0,
374 GridLayout::USE_PREF, 0, 0);
375 column_set->AddPaddingColumn(0, views::kRelatedControlHorizontalSpacing);
376 column_set->AddColumn(GridLayout::FILL, GridLayout::LEADING, 0,
377 GridLayout::USE_PREF, 0, 0);
378 column_set->LinkColumnSizes(0, 2, 4, -1);
380 layout->StartRow(0, labels_column_set_id);
381 layout->AddView(title_label_);
382 layout->AddView(title_tf_);
384 if (details_.GetNodeType() != BookmarkNode::FOLDER) {
385 url_label_ = new views::Label(
386 l10n_util::GetStringUTF16(IDS_BOOKMARK_EDITOR_URL_LABEL));
388 url_tf_ = new views::Textfield;
389 PrefService* prefs =
390 profile_ ? user_prefs::UserPrefs::Get(profile_) : NULL;
391 url_tf_->SetText(chrome::FormatBookmarkURLForDisplay(url, prefs));
392 url_tf_->set_controller(this);
393 url_tf_->SetAccessibleName(
394 l10n_util::GetStringUTF16(IDS_BOOKMARK_AX_EDITOR_URL_LABEL));
396 layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
398 layout->StartRow(0, labels_column_set_id);
399 layout->AddView(url_label_);
400 layout->AddView(url_tf_);
403 if (show_tree_) {
404 layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
405 layout->StartRow(1, single_column_view_set_id);
406 layout->AddView(tree_view_->CreateParentIfNecessary());
409 layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
411 if (!show_tree_ || bb_model_->loaded())
412 Reset();
415 void BookmarkEditorView::Reset() {
416 if (!show_tree_) {
417 if (parent())
418 UserInputChanged();
419 return;
422 new_folder_button_->SetEnabled(true);
424 // Do this first, otherwise when we invoke SetModel with the real one
425 // tree_view will try to invoke something on the model we just deleted.
426 tree_view_->SetModel(NULL);
428 EditorNode* root_node = CreateRootNode();
429 tree_model_.reset(new EditorTreeModel(root_node));
431 tree_view_->SetModel(tree_model_.get());
432 tree_view_->SetController(this);
434 context_menu_runner_.reset();
436 if (parent())
437 ExpandAndSelect();
440 GURL BookmarkEditorView::GetInputURL() const {
441 if (details_.GetNodeType() == BookmarkNode::FOLDER)
442 return GURL();
443 return url_fixer::FixupURL(base::UTF16ToUTF8(url_tf_->text()), std::string());
446 void BookmarkEditorView::UserInputChanged() {
447 if (details_.GetNodeType() != BookmarkNode::FOLDER) {
448 const GURL url(GetInputURL());
449 if (!url.is_valid())
450 url_tf_->SetBackgroundColor(kErrorColor);
451 else
452 url_tf_->UseDefaultBackgroundColor();
454 GetDialogClientView()->UpdateDialogButtons();
457 void BookmarkEditorView::NewFolder() {
458 // Create a new entry parented to the selected item, or the bookmark
459 // bar if nothing is selected.
460 EditorNode* parent = tree_model_->AsNode(tree_view_->GetSelectedNode());
461 if (!parent) {
462 NOTREACHED();
463 return;
466 tree_view_->StartEditing(AddNewFolder(parent));
469 BookmarkEditorView::EditorNode* BookmarkEditorView::AddNewFolder(
470 EditorNode* parent) {
471 EditorNode* new_node = new EditorNode(
472 l10n_util::GetStringUTF16(IDS_BOOKMARK_EDITOR_NEW_FOLDER_NAME), 0);
473 // |new_node| is now owned by |parent|.
474 tree_model_->Add(parent, new_node, parent->child_count());
475 return new_node;
478 void BookmarkEditorView::ExpandAndSelect() {
479 BookmarkExpandedStateTracker::Nodes expanded_nodes =
480 bb_model_->expanded_state_tracker()->GetExpandedNodes();
481 for (BookmarkExpandedStateTracker::Nodes::const_iterator i(
482 expanded_nodes.begin()); i != expanded_nodes.end(); ++i) {
483 EditorNode* editor_node =
484 FindNodeWithID(tree_model_->GetRoot(), (*i)->id());
485 if (editor_node)
486 tree_view_->Expand(editor_node);
489 const BookmarkNode* to_select = parent_;
490 if (details_.type == EditDetails::EXISTING_NODE)
491 to_select = details_.existing_node->parent();
492 int64 folder_id_to_select = to_select->id();
493 EditorNode* b_node =
494 FindNodeWithID(tree_model_->GetRoot(), folder_id_to_select);
495 if (!b_node)
496 b_node = tree_model_->GetRoot()->GetChild(0); // Bookmark bar node.
498 tree_view_->SetSelectedNode(b_node);
501 BookmarkEditorView::EditorNode* BookmarkEditorView::CreateRootNode() {
502 EditorNode* root_node = new EditorNode(base::string16(), 0);
503 const BookmarkNode* bb_root_node = bb_model_->root_node();
504 CreateNodes(bb_root_node, root_node);
505 DCHECK(root_node->child_count() >= 2 && root_node->child_count() <= 4);
506 DCHECK_EQ(BookmarkNode::BOOKMARK_BAR, bb_root_node->GetChild(0)->type());
507 DCHECK_EQ(BookmarkNode::OTHER_NODE, bb_root_node->GetChild(1)->type());
508 if (root_node->child_count() >= 3)
509 DCHECK_EQ(BookmarkNode::MOBILE, bb_root_node->GetChild(2)->type());
510 return root_node;
513 void BookmarkEditorView::CreateNodes(const BookmarkNode* bb_node,
514 BookmarkEditorView::EditorNode* b_node) {
515 for (int i = 0; i < bb_node->child_count(); ++i) {
516 const BookmarkNode* child_bb_node = bb_node->GetChild(i);
517 if (child_bb_node->IsVisible() && child_bb_node->is_folder() &&
518 bb_model_->client()->CanBeEditedByUser(child_bb_node)) {
519 EditorNode* new_b_node = new EditorNode(child_bb_node->GetTitle(),
520 child_bb_node->id());
521 b_node->Add(new_b_node, b_node->child_count());
522 CreateNodes(child_bb_node, new_b_node);
527 BookmarkEditorView::EditorNode* BookmarkEditorView::FindNodeWithID(
528 BookmarkEditorView::EditorNode* node,
529 int64 id) {
530 if (node->value == id)
531 return node;
532 for (int i = 0; i < node->child_count(); ++i) {
533 EditorNode* result = FindNodeWithID(node->GetChild(i), id);
534 if (result)
535 return result;
537 return NULL;
540 void BookmarkEditorView::ApplyEdits() {
541 DCHECK(bb_model_->loaded());
543 if (tree_view_)
544 tree_view_->CommitEdit();
546 EditorNode* parent = show_tree_ ?
547 tree_model_->AsNode(tree_view_->GetSelectedNode()) : NULL;
548 if (show_tree_ && !parent) {
549 NOTREACHED();
550 return;
552 ApplyEdits(parent);
555 void BookmarkEditorView::ApplyEdits(EditorNode* parent) {
556 DCHECK(!show_tree_ || parent);
558 // We're going to apply edits to the bookmark bar model, which will call us
559 // back. Normally when a structural edit occurs we reset the tree model.
560 // We don't want to do that here, so we remove ourselves as an observer.
561 bb_model_->RemoveObserver(this);
563 GURL new_url(GetInputURL());
564 base::string16 new_title(title_tf_->text());
566 if (!show_tree_) {
567 BookmarkEditor::ApplyEditsWithNoFolderChange(
568 bb_model_, parent_, details_, new_title, new_url);
569 return;
572 // Create the new folders and update the titles.
573 const BookmarkNode* new_parent = NULL;
574 ApplyNameChangesAndCreateNewFolders(
575 bb_model_->root_node(), tree_model_->GetRoot(), parent, &new_parent);
577 BookmarkEditor::ApplyEditsWithPossibleFolderChange(
578 bb_model_, new_parent, details_, new_title, new_url);
580 BookmarkExpandedStateTracker::Nodes expanded_nodes;
581 UpdateExpandedNodes(tree_model_->GetRoot(), &expanded_nodes);
582 bb_model_->expanded_state_tracker()->SetExpandedNodes(expanded_nodes);
584 // Remove the folders that were removed. This has to be done after all the
585 // other changes have been committed.
586 bookmarks::DeleteBookmarkFolders(bb_model_, deletes_);
589 void BookmarkEditorView::ApplyNameChangesAndCreateNewFolders(
590 const BookmarkNode* bb_node,
591 BookmarkEditorView::EditorNode* b_node,
592 BookmarkEditorView::EditorNode* parent_b_node,
593 const BookmarkNode** parent_bb_node) {
594 if (parent_b_node == b_node)
595 *parent_bb_node = bb_node;
596 for (int i = 0; i < b_node->child_count(); ++i) {
597 EditorNode* child_b_node = b_node->GetChild(i);
598 const BookmarkNode* child_bb_node = NULL;
599 if (child_b_node->value == 0) {
600 // New folder.
601 child_bb_node = bb_model_->AddFolder(bb_node,
602 bb_node->child_count(), child_b_node->GetTitle());
603 child_b_node->value = child_bb_node->id();
604 } else {
605 // Existing node, reset the title (BookmarkModel ignores changes if the
606 // title is the same).
607 for (int j = 0; j < bb_node->child_count(); ++j) {
608 const BookmarkNode* node = bb_node->GetChild(j);
609 if (node->is_folder() && node->id() == child_b_node->value) {
610 child_bb_node = node;
611 break;
614 DCHECK(child_bb_node);
615 bb_model_->SetTitle(child_bb_node, child_b_node->GetTitle());
617 ApplyNameChangesAndCreateNewFolders(child_bb_node, child_b_node,
618 parent_b_node, parent_bb_node);
622 void BookmarkEditorView::UpdateExpandedNodes(
623 EditorNode* editor_node,
624 BookmarkExpandedStateTracker::Nodes* expanded_nodes) {
625 if (!tree_view_->IsExpanded(editor_node))
626 return;
628 // The root is 0.
629 if (editor_node->value != 0) {
630 expanded_nodes->insert(
631 bookmarks::GetBookmarkNodeByID(bb_model_, editor_node->value));
634 for (int i = 0; i < editor_node->child_count(); ++i)
635 UpdateExpandedNodes(editor_node->GetChild(i), expanded_nodes);
638 ui::SimpleMenuModel* BookmarkEditorView::GetMenuModel() {
639 if (!context_menu_model_.get()) {
640 context_menu_model_.reset(new ui::SimpleMenuModel(this));
641 context_menu_model_->AddItemWithStringId(IDS_EDIT, IDS_EDIT);
642 context_menu_model_->AddItemWithStringId(IDS_DELETE, IDS_DELETE);
643 context_menu_model_->AddItemWithStringId(
644 IDS_BOOKMARK_EDITOR_NEW_FOLDER_MENU_ITEM,
645 IDS_BOOKMARK_EDITOR_NEW_FOLDER_MENU_ITEM);
647 return context_menu_model_.get();
650 void BookmarkEditorView::EditorTreeModel::SetTitle(
651 ui::TreeModelNode* node,
652 const base::string16& title) {
653 if (!title.empty())
654 ui::TreeNodeModel<EditorNode>::SetTitle(node, title);