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 21 namespace views { 22 class Label; 23 class Menu2; 24 class NativeButton; 25 class Window; 26 } 27 28 class BookmarkEditorViewTest; 29 class GURL; 30 class Menu; 31 class 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 43 class 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: EditorTreeModel(EditorNode * root)60 explicit EditorTreeModel(EditorNode* root) 61 : ui::TreeNodeModel<EditorNode>(root) {} 62 SetTitle(ui::TreeModelNode * node,const string16 & title)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); HandleKeyEvent(views::Textfield * sender,const views::KeyEvent & key_event)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. Loaded(BookmarkModel * 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); BookmarkNodeChanged(BookmarkModel * model,const BookmarkNode * node)153 virtual void BookmarkNodeChanged(BookmarkModel* model, 154 const BookmarkNode* node) {} 155 virtual void BookmarkNodeChildrenReordered(BookmarkModel* model, 156 const BookmarkNode* node); BookmarkNodeFaviconLoaded(BookmarkModel * model,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