OLD | NEW |
| (Empty) |
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 VIEWS_CONTROLS_TREE_TREE_VIEW_H_ | |
6 #define VIEWS_CONTROLS_TREE_TREE_VIEW_H_ | |
7 #pragma once | |
8 | |
9 #include <windows.h> | |
10 #include <commctrl.h> | |
11 | |
12 #include <map> | |
13 | |
14 #include "base/basictypes.h" | |
15 #include "base/compiler_specific.h" | |
16 #include "ui/base/keycodes/keyboard_codes.h" | |
17 #include "ui/base/models/tree_model.h" | |
18 #include "views/controls/native_control.h" | |
19 | |
20 namespace views { | |
21 | |
22 class TreeView; | |
23 | |
24 // TreeViewController --------------------------------------------------------- | |
25 | |
26 // Controller for the treeview. | |
27 class TreeViewController { | |
28 public: | |
29 // Notification that the selection of the tree view has changed. Use | |
30 // GetSelectedNode to find the current selection. | |
31 virtual void OnTreeViewSelectionChanged(TreeView* tree_view) = 0; | |
32 | |
33 // Returns true if the node can be edited. This is only used if the | |
34 // TreeView is editable. | |
35 virtual bool CanEdit(TreeView* tree_view, ui::TreeModelNode* node) { | |
36 return true; | |
37 } | |
38 | |
39 // Invoked when a key is pressed on the tree view. | |
40 virtual void OnTreeViewKeyDown(ui::KeyboardCode keycode) {} | |
41 }; | |
42 | |
43 // TreeView ------------------------------------------------------------------- | |
44 | |
45 // TreeView displays hierarchical data as returned from a TreeModel. The user | |
46 // can expand, collapse and edit the items. A Controller may be attached to | |
47 // receive notification of selection changes and restrict editing. | |
48 class VIEWS_EXPORT TreeView : public NativeControl, ui::TreeModelObserver { | |
49 public: | |
50 TreeView(); | |
51 virtual ~TreeView(); | |
52 | |
53 // Is dragging enabled? The default is false. | |
54 void set_drag_enabled(bool drag_enabled) { drag_enabled_ = drag_enabled; } | |
55 bool drag_enabled() const { return drag_enabled_; } | |
56 | |
57 // Sets the model. TreeView does not take ownership of the model. | |
58 void SetModel(ui::TreeModel* model); | |
59 ui::TreeModel* model() const { return model_; } | |
60 | |
61 // Sets whether to automatically expand children when a parent node is | |
62 // expanded. The default is false. If true, when a node in the tree is | |
63 // expanded for the first time, its children are also automatically expanded. | |
64 // If a node is subsequently collapsed and expanded again, the children | |
65 // will not be automatically expanded. | |
66 void set_auto_expand_children(bool auto_expand_children) { | |
67 auto_expand_children_ = auto_expand_children; | |
68 } | |
69 | |
70 // Sets whether the user can edit the nodes. The default is true. If true, | |
71 // the Controller is queried to determine if a particular node can be edited. | |
72 void SetEditable(bool editable); | |
73 | |
74 // Sets whether lines are drawn from the root node to child nodes (and | |
75 // whether plus boxes show up next to the root node.) The default is false. | |
76 // If root_shown_ is false, the children of the root act as the roots in the | |
77 // native control, and so this setting takes effect for them. | |
78 void set_lines_at_root(bool lines_at_root) { | |
79 lines_at_root_ = lines_at_root; | |
80 } | |
81 | |
82 // Overridden from View: | |
83 virtual void GetAccessibleState(ui::AccessibleViewState* state) OVERRIDE; | |
84 | |
85 // Edits the specified node. This cancels the current edit and expands | |
86 // all parents of node. | |
87 void StartEditing(ui::TreeModelNode* node); | |
88 | |
89 // Cancels the current edit. Does nothing if not editing. | |
90 void CancelEdit(); | |
91 | |
92 // Commits the current edit. Does nothing if not editing. | |
93 void CommitEdit(); | |
94 | |
95 // If the user is editing a node, it is returned. If the user is not | |
96 // editing a node, NULL is returned. | |
97 ui::TreeModelNode* GetEditingNode(); | |
98 | |
99 // Selects the specified node. This expands all the parents of node. | |
100 void SetSelectedNode(ui::TreeModelNode* node); | |
101 | |
102 // Returns the selected node, or NULL if nothing is selected. | |
103 ui::TreeModelNode* GetSelectedNode(); | |
104 | |
105 // Make sure node and all its parents are expanded. | |
106 void Expand(ui::TreeModelNode* node); | |
107 | |
108 // Invoked from ExpandAll(). Expands the supplied node and recursively | |
109 // invokes itself with all children. | |
110 void ExpandAll(ui::TreeModelNode* node); | |
111 | |
112 // Returns true if the specified node is expanded. | |
113 bool IsExpanded(ui::TreeModelNode* node); | |
114 | |
115 // Sets whether the root is shown. If true, the root node of the tree is | |
116 // shown, if false only the children of the root are shown. The default is | |
117 // true. | |
118 void SetRootShown(bool root_visible); | |
119 | |
120 // Begin TreeModelObserver implementation. | |
121 // These methods shouldn't be called directly. The model is responsible for | |
122 // firing them. | |
123 virtual void TreeNodesAdded(ui::TreeModel* model, | |
124 ui::TreeModelNode* parent, | |
125 int start, | |
126 int count) OVERRIDE; | |
127 virtual void TreeNodesRemoved(ui::TreeModel* model, | |
128 ui::TreeModelNode* parent, | |
129 int start, | |
130 int count) OVERRIDE; | |
131 virtual void TreeNodeChanged(ui::TreeModel* model, | |
132 ui::TreeModelNode* node) OVERRIDE; | |
133 // End TreeModelObserver implementation. | |
134 | |
135 // Sets the controller, which may be null. TreeView does not take ownership | |
136 // of the controller. | |
137 void SetController(TreeViewController* controller) { | |
138 controller_ = controller; | |
139 } | |
140 | |
141 // Sets whether enter is processed when not editing. If true, enter will | |
142 // expand/collapse the node. If false, enter is passed to the focus manager | |
143 // so that an enter accelerator can be enabled. The default is false. | |
144 // | |
145 // NOTE: Changing this has no effect after the hwnd has been created. | |
146 void SetProcessesEnter(bool process_enter) { | |
147 process_enter_ = process_enter; | |
148 } | |
149 bool GetProcessedEnter() { return process_enter_; } | |
150 | |
151 // Sets when the ContextMenuController is notified. If true, the | |
152 // ContextMenuController is only notified when a node is selected and the | |
153 // mouse is over a node. The default is true. | |
154 void SetShowContextMenuOnlyWhenNodeSelected(bool value) { | |
155 show_context_menu_only_when_node_selected_ = value; | |
156 } | |
157 bool GetShowContextMenuOnlyWhenNodeSelected() { | |
158 return show_context_menu_only_when_node_selected_; | |
159 } | |
160 | |
161 // If true, a right click selects the node under the mouse. The default | |
162 // is true. | |
163 void SetSelectOnRightMouseDown(bool value) { | |
164 select_on_right_mouse_down_ = value; | |
165 } | |
166 bool GetSelectOnRightMouseDown() { return select_on_right_mouse_down_; } | |
167 | |
168 protected: | |
169 // Overriden to return a location based on the selected node. | |
170 virtual gfx::Point GetKeyboardContextMenuLocation(); | |
171 | |
172 // Creates and configures the tree_view. | |
173 virtual HWND CreateNativeControl(HWND parent_container); | |
174 | |
175 // Invoked when the native control sends a WM_NOTIFY message to its parent. | |
176 // Handles a variety of potential TreeView messages. | |
177 virtual LRESULT OnNotify(int w_param, LPNMHDR l_param); | |
178 | |
179 // Invoked when the native control send a WM_DESTROY message to its parent. | |
180 virtual void OnDestroy(); | |
181 | |
182 // We pay attention to key down for two reasons: to circumvent VK_ENTER from | |
183 // toggling the expaned state when processes_enter_ is false, and to have F2 | |
184 // start editting. | |
185 virtual bool OnKeyDown(ui::KeyboardCode virtual_key_code); | |
186 | |
187 virtual void OnContextMenu(const POINT& location); | |
188 | |
189 // Returns the TreeModelNode for |tree_item|. | |
190 ui::TreeModelNode* GetNodeForTreeItem(HTREEITEM tree_item); | |
191 | |
192 // Returns the tree item for |node|. | |
193 HTREEITEM GetTreeItemForNode(ui::TreeModelNode* node); | |
194 | |
195 private: | |
196 // See notes in TableView::TableViewWrapper for why this is needed. | |
197 struct TreeViewWrapper { | |
198 explicit TreeViewWrapper(TreeView* view) : tree_view(view) { } | |
199 TreeView* tree_view; | |
200 }; | |
201 | |
202 // Internally used to track the state of nodes. NodeDetails are lazily created | |
203 // as the user expands nodes. | |
204 struct NodeDetails { | |
205 NodeDetails(int id, ui::TreeModelNode* node) | |
206 : id(id), node(node), tree_item(NULL), loaded_children(false) {} | |
207 | |
208 // Unique identifier for the node. This corresponds to the lParam of | |
209 // the tree item. | |
210 const int id; | |
211 | |
212 // The node from the model. | |
213 ui::TreeModelNode* node; | |
214 | |
215 // From the native TreeView. | |
216 // | |
217 // This should be treated as const, but can't due to timing in creating the | |
218 // entry. | |
219 HTREEITEM tree_item; | |
220 | |
221 // Whether the children have been loaded. | |
222 bool loaded_children; | |
223 }; | |
224 | |
225 // Cleanup all resources used by treeview. | |
226 void Cleanup(); | |
227 | |
228 // Make sure the tree view is observing the tree model. | |
229 void AddObserverToModel(); | |
230 | |
231 // Make sure the tree view is no longer observing the tree model. | |
232 void RemoveObserverFromModel(); | |
233 | |
234 // Deletes the root items from the treeview. This is used when the model | |
235 // changes. | |
236 void DeleteRootItems(); | |
237 | |
238 // Creates the root items in the treeview from the model. This is used when | |
239 // the model changes. | |
240 void CreateRootItems(); | |
241 | |
242 // Creates and adds an item to the treeview. parent_item identifies the | |
243 // parent and is null for root items. after dictates where among the | |
244 // children of parent_item the item is to be created. node is the node from | |
245 // the model. | |
246 void CreateItem(HTREEITEM parent_item, HTREEITEM after, | |
247 ui::TreeModelNode* node); | |
248 | |
249 // Removes entries from the map for item. This method will also | |
250 // remove the items from the TreeView because the process of | |
251 // deleting an item will send an TVN_GETDISPINFO message, consulting | |
252 // our internal map data. | |
253 void RecursivelyDelete(NodeDetails* node); | |
254 | |
255 // Returns the NodeDetails by node from the model. | |
256 NodeDetails* GetNodeDetails(ui::TreeModelNode* node); | |
257 | |
258 // Returns the NodeDetails by identifier (lparam of the HTREEITEM). | |
259 NodeDetails* GetNodeDetailsByID(int id); | |
260 | |
261 // Returns the NodeDetails by HTREEITEM. | |
262 NodeDetails* GetNodeDetailsByTreeItem(HTREEITEM tree_item); | |
263 | |
264 // Creates the image list to use for the tree. | |
265 HIMAGELIST CreateImageList(); | |
266 | |
267 // Returns the HTREEITEM for |node|. This is intended to be called when a | |
268 // model mutation event occur with |node| as the parent. This returns null | |
269 // if the user has never expanded |node| or all of its parents. | |
270 HTREEITEM GetTreeItemForNodeDuringMutation(ui::TreeModelNode* node); | |
271 | |
272 // The window function installed on the treeview. | |
273 static LRESULT CALLBACK TreeWndProc(HWND window, | |
274 UINT message, | |
275 WPARAM w_param, | |
276 LPARAM l_param); | |
277 | |
278 // Handle to the tree window. | |
279 HWND tree_view_; | |
280 | |
281 // The model, may be null. | |
282 ui::TreeModel* model_; | |
283 | |
284 // Maps from id to NodeDetails. | |
285 std::map<int, NodeDetails*> id_to_details_map_; | |
286 | |
287 // Maps from model entry to NodeDetails. | |
288 std::map<ui::TreeModelNode*, NodeDetails*> node_to_details_map_; | |
289 | |
290 // Whether to automatically expand children when a parent node is expanded. | |
291 bool auto_expand_children_; | |
292 | |
293 // Whether the user can edit the items. | |
294 bool editable_; | |
295 | |
296 // Next id to create. Any time an item is added this is incremented by one. | |
297 int next_id_; | |
298 | |
299 // The controller. | |
300 TreeViewController* controller_; | |
301 | |
302 // Node being edited. If null, not editing. | |
303 ui::TreeModelNode* editing_node_; | |
304 | |
305 // Whether or not the root is shown in the tree. | |
306 bool root_shown_; | |
307 | |
308 // Whether lines are drawn from the root to the children. | |
309 bool lines_at_root_; | |
310 | |
311 // Whether enter should be processed by the tree when not editing. | |
312 bool process_enter_; | |
313 | |
314 // Whether we notify context menu controller only when mouse is over node | |
315 // and node is selected. | |
316 bool show_context_menu_only_when_node_selected_; | |
317 | |
318 // Whether the selection is changed on right mouse down. | |
319 bool select_on_right_mouse_down_; | |
320 | |
321 // A wrapper around 'this', used for subclassing the TreeView control. | |
322 TreeViewWrapper wrapper_; | |
323 | |
324 // Original handler installed on the TreeView. | |
325 WNDPROC original_handler_; | |
326 | |
327 bool drag_enabled_; | |
328 | |
329 // Has an observer been added to the model? | |
330 bool observer_added_; | |
331 | |
332 // Did the model return a non-empty set of icons from GetIcons? | |
333 bool has_custom_icons_; | |
334 | |
335 HIMAGELIST image_list_; | |
336 | |
337 DISALLOW_COPY_AND_ASSIGN(TreeView); | |
338 }; | |
339 | |
340 } // namespace views | |
341 | |
342 #endif // VIEWS_CONTROLS_TREE_TREE_VIEW_H_ | |
OLD | NEW |