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#ifndef CHROME_BROWSER_UI_VIEWS_BOOKMARKS_BOOKMARK_EDITOR_VIEW_H_
6#define CHROME_BROWSER_UI_VIEWS_BOOKMARKS_BOOKMARK_EDITOR_VIEW_H_
7#pragma once
8
9#include "base/string16.h"
10#include "chrome/browser/bookmarks/bookmark_editor.h"
11#include "chrome/browser/bookmarks/bookmark_model_observer.h"
12#include "testing/gtest/include/gtest/gtest_prod.h"
13#include "ui/base/models/simple_menu_model.h"
14#include "ui/base/models/tree_node_model.h"
15#include "views/controls/button/button.h"
16#include "views/controls/textfield/textfield.h"
17#include "views/controls/textfield/textfield_controller.h"
18#include "views/controls/tree/tree_view.h"
19#include "views/window/dialog_delegate.h"
20
21namespace views {
22class Label;
23class Menu2;
24class NativeButton;
25class Window;
26}
27
28class BookmarkEditorViewTest;
29class GURL;
30class Menu;
31class Profile;
32
33// View that allows the user to edit a bookmark/starred URL. The user can
34// change the URL, title and where the bookmark appears as well as adding
35// new folders and changing the name of other folders. The editor is used for
36// both editing a url bookmark, as well as editing a folder bookmark when
37// created from 'Bookmark all tabs'.
38//
39// Edits are applied to the BookmarkModel when the user presses 'OK'.
40//
41// To use BookmarkEditorView invoke the static show method.
42
43class BookmarkEditorView : public BookmarkEditor,
44                           public views::View,
45                           public views::ButtonListener,
46                           public views::TreeViewController,
47                           public views::DialogDelegate,
48                           public views::TextfieldController,
49                           public views::ContextMenuController,
50                           public ui::SimpleMenuModel::Delegate,
51                           public BookmarkModelObserver {
52 public:
53  // Type of node in the tree. Public purely for testing.
54  typedef ui::TreeNodeWithValue<int64> EditorNode;
55
56  // Model for the TreeView. Trivial subclass that doesn't allow titles with
57  // empty strings. Public purely for testing.
58  class EditorTreeModel : public ui::TreeNodeModel<EditorNode> {
59   public:
60    explicit EditorTreeModel(EditorNode* root)
61        : ui::TreeNodeModel<EditorNode>(root) {}
62
63    virtual void SetTitle(ui::TreeModelNode* node,
64                          const string16& title) {
65      if (!title.empty())
66        TreeNodeModel::SetTitle(node, title);
67    }
68
69   private:
70    DISALLOW_COPY_AND_ASSIGN(EditorTreeModel);
71  };
72
73  BookmarkEditorView(Profile* profile,
74                     const BookmarkNode* parent,
75                     const EditDetails& details,
76                     BookmarkEditor::Configuration configuration);
77
78  virtual ~BookmarkEditorView();
79
80  // DialogDelegate methods:
81  virtual bool IsDialogButtonEnabled(
82      MessageBoxFlags::DialogButton button) const;
83  virtual bool IsModal() const;
84  virtual bool CanResize() const;
85  virtual std::wstring GetWindowTitle() const;
86  virtual bool Accept();
87  virtual bool AreAcceleratorsEnabled(MessageBoxFlags::DialogButton button);
88  virtual views::View* GetContentsView();
89
90  // views::View.
91  virtual void Layout();
92  virtual gfx::Size GetPreferredSize();
93  virtual void ViewHierarchyChanged(bool is_add,
94                                    views::View* parent,
95                                    views::View* child);
96
97  // views::TreeViewObserver.
98  virtual void OnTreeViewSelectionChanged(views::TreeView* tree_view);
99  virtual bool CanEdit(views::TreeView* tree_view, ui::TreeModelNode* node);
100
101  // views::TextfieldController:
102  virtual void ContentsChanged(views::Textfield* sender,
103                               const std::wstring& new_contents);
104  virtual bool HandleKeyEvent(views::Textfield* sender,
105                              const views::KeyEvent& key_event) {
106    return false;
107  }
108
109  // views::ButtonListener:
110  virtual void ButtonPressed(views::Button* sender, const views::Event& event);
111
112  // ui::SimpleMenuModel::Delegate:
113  virtual bool IsCommandIdChecked(int command_id) const;
114  virtual bool IsCommandIdEnabled(int command_id) const;
115  virtual bool GetAcceleratorForCommandId(int command_id,
116                                          ui::Accelerator* accelerator);
117  virtual void ExecuteCommand(int command_id);
118
119  // Creates a Window and adds the BookmarkEditorView to it. When the window is
120  // closed the BookmarkEditorView is deleted.
121  void Show(HWND parent_hwnd);
122
123  // Closes the dialog.
124  void Close();
125
126  // Shows the context menu.
127  virtual void ShowContextMenuForView(View* source,
128                                      const gfx::Point& p,
129                                      bool is_mouse_gesture);
130
131 private:
132  friend class BookmarkEditorViewTest;
133
134  // Creates the necessary sub-views, configures them, adds them to the layout,
135  // and requests the entries to display from the database.
136  void Init();
137
138  // BookmarkModel observer methods. Any structural change results in
139  // resetting the tree model.
140  virtual void Loaded(BookmarkModel* model) { }
141  virtual void BookmarkNodeMoved(BookmarkModel* model,
142                                 const BookmarkNode* old_parent,
143                                 int old_index,
144                                 const BookmarkNode* new_parent,
145                                 int new_index);
146  virtual void BookmarkNodeAdded(BookmarkModel* model,
147                                 const BookmarkNode* parent,
148                                 int index);
149  virtual void BookmarkNodeRemoved(BookmarkModel* model,
150                                   const BookmarkNode* parent,
151                                   int index,
152                                   const BookmarkNode* node);
153  virtual void BookmarkNodeChanged(BookmarkModel* model,
154                                   const BookmarkNode* node) {}
155  virtual void BookmarkNodeChildrenReordered(BookmarkModel* model,
156                                             const BookmarkNode* node);
157  virtual void BookmarkNodeFaviconLoaded(BookmarkModel* model,
158                                         const BookmarkNode* node) {}
159
160  // Resets the model of the tree and updates the various buttons appropriately.
161  void Reset();
162
163  // Expands all the nodes in the tree and selects the parent node of the
164  // url we're editing or the most recent parent if the url being editted isn't
165  // starred.
166  void ExpandAndSelect();
167
168  // Creates a returns the new root node. This invokes CreateNodes to do
169  // the real work.
170  EditorNode* CreateRootNode();
171
172  // Adds and creates a child node in b_node for all children of bb_node that
173  // are folders.
174  void CreateNodes(const BookmarkNode* bb_node, EditorNode* b_node);
175
176  // Returns the node with the specified id, or NULL if one can't be found.
177  EditorNode* FindNodeWithID(BookmarkEditorView::EditorNode* node, int64 id);
178
179  // Invokes ApplyEdits with the selected node.
180  void ApplyEdits();
181
182  // Applies the edits done by the user. |parent| gives the parent of the URL
183  // being edited.
184  void ApplyEdits(EditorNode* parent);
185
186  // Recursively adds newly created folders and sets the title of nodes to
187  // match the user edited title.
188  //
189  // bb_node gives the BookmarkNode the edits are to be applied to, with b_node
190  // the source of the edits.
191  //
192  // If b_node == parent_b_node, parent_bb_node is set to bb_node. This is
193  // used to determine the new BookmarkNode parent based on the EditorNode
194  // parent.
195  void ApplyNameChangesAndCreateNewFolders(
196      const BookmarkNode* bb_node,
197      BookmarkEditorView::EditorNode* b_node,
198      BookmarkEditorView::EditorNode* parent_b_node,
199      const BookmarkNode** parent_bb_node);
200
201  // Returns the current url the user has input.
202  GURL GetInputURL() const;
203
204  // Returns the title the user has input.
205  std::wstring GetInputTitle() const;
206
207  // Invoked when the url or title has possibly changed. Updates the background
208  // of Textfields and ok button appropriately.
209  void UserInputChanged();
210
211  // Creates a new folder as a child of the selected node. If no node is
212  // selected, the new folder is added as a child of the bookmark node. Starts
213  // editing on the new gorup as well.
214  void NewFolder();
215
216  // Creates a new EditorNode as the last child of parent. The new node is
217  // added to the model and returned. This does NOT start editing. This is used
218  // internally by NewFolder and broken into a separate method for testing.
219  EditorNode* AddNewFolder(EditorNode* parent);
220
221  // Profile the entry is from.
222  Profile* profile_;
223
224  // Model driving the TreeView.
225  scoped_ptr<EditorTreeModel> tree_model_;
226
227  // Displays star folder.
228  views::TreeView* tree_view_;
229
230  // Used to create a new folder.
231  scoped_ptr<views::NativeButton> new_folder_button_;
232
233  // The label for the url text field.
234  views::Label* url_label_;
235
236  // Used for editing the URL.
237  views::Textfield url_tf_;
238
239  // The label for the title text field.
240  views::Label* title_label_;
241
242  // Used for editing the title.
243  views::Textfield title_tf_;
244
245  // Initial parent to select. Is only used if |details_.existing_node| is
246  // NULL.
247  const BookmarkNode* parent_;
248
249  const EditDetails details_;
250
251  // The context menu.
252  scoped_ptr<ui::SimpleMenuModel> context_menu_contents_;
253  scoped_ptr<views::Menu2> context_menu_;
254
255  // Mode used to create nodes from.
256  BookmarkModel* bb_model_;
257
258  // If true, we're running the menu for the bookmark bar or other bookmarks
259  // nodes.
260  bool running_menu_for_root_;
261
262  // Is the tree shown?
263  bool show_tree_;
264
265  DISALLOW_COPY_AND_ASSIGN(BookmarkEditorView);
266};
267
268#endif  // CHROME_BROWSER_UI_VIEWS_BOOKMARKS_BOOKMARK_EDITOR_VIEW_H_
269