/
VFSTreePopulator.h
145 lines (128 loc) · 5.25 KB
/
VFSTreePopulator.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
#pragma once
#include <map>
#include <string>
#include <set>
#include "TreeModel.h"
#include <wx/dataview.h>
namespace wxutil
{
/**
* Utility class to construct a TreeModel from a series of string paths
* in the form "models/first/second/object.lwo" or similar. The class accepts
* the Tree Store and then string paths, one by one, adding each one to the
* tree in the appropriate place.
*
* Since the VFSTreePopulator has no knowledge of the column data to be inserted
* into the tree, it does not set any of the values but merely calls
* TreeStore::AddItem() to get an iterator pointing to the newly-added
* row. In order to insert the data, the calling code must then call the
* visitor function which will provide the visitor with two objects - the
* created iterator and the full input string which the visitor can then
* use to populate the data appropriately.
*
* When the VFSTreePopulator is destroyed it will free any temporary structures
* used during tree creation, such as the hashtable of iterator objects
* used to locate parent nodes. The TreeModel will not be destroyed since it
* is owned by the calling code.
*/
class VFSTreePopulator
{
// The tree store to populate
TreeModel::Ptr _store;
// Toplevel node to add children under
wxDataViewItem _topLevel;
// Maps of names to corresponding treemodel iterators, for both intermediate
// paths and explicitly presented paths
typedef std::map<std::string, wxDataViewItem> NamedIterMap;
NamedIterMap _iters;
// Set of paths that are passed in through addPath(), to distinguish them
// from intermediate constructed paths
std::set<std::string> _explicitPaths;
public:
/**
* Construct a VFSTreePopulator which will populate the given tree store.
*
* @param store
* Tree store to populate.
*
* @param toplevel
* TreeModel::iterator pointing to the toplevel node, under which all paths should
* be added. Default is empty to indicate that paths should be added under
* the tree root.
*/
VFSTreePopulator(const TreeModel::Ptr& store, const wxDataViewItem& toplevel = wxDataViewItem());
/** Destroy the VFSTreePopulator and all temporary data.
*/
virtual ~VFSTreePopulator();
// wxDataViewItem pointing to the toplevel node, under which all paths should
// be added.Default is empty to indicate that paths should be added under
void setTopLevelItem(const wxDataViewItem& topLevel);
/** Add a single VFS string to the tree, which will be split automatically
* and inserted at the correct place in the tree.
*/
void addPath(const std::string& path);
// Column population function. The inserted Row will be passed as argument.
typedef std::function<void(TreeModel::Row& row,
const std::string& path,
const std::string& leafName,
bool isFolder)> ColumnPopulationCallback;
/**
* Like addPath() above this method also takes a function object as
* argument to allow for immediate population of the TreeStore's column values.
* As soon as the item has been created in the correct spot of the tree
* the callback will be invoked passing the TreeModel::Row as argument.
*
* Note that the callback can be invoked multiple times for one single addPath()
* call, since this method will automatically insert missing parent folder items
* when it encounters them.
*
* Client code needs to decide between this or the regular addPath() method
* and cannot mix between these two, as this variant here does not keep track
* of the "path-is-explicit" property and therefore doesn't support the
* forEachNode() method being called with a Visitor.
*
* Note: the callback needs to invoke row.SendItemAdded() when done.
*/
void addPath(const std::string& path, const ColumnPopulationCallback& func);
/** Visitor interface.
*/
struct Visitor
{
virtual ~Visitor() {}
/**
* Visit callback function, called for each node in the tree.
*
* @param store
* The tree store to insert into.
*
* @param row
* The row to be processed.
*
* @param path
* Full VFS path of the current node, as presented to addPath().
*
* @param isExplicit
* true if the path was explicitly inserted via addPath(), false if the
* path was created as an intermediate parent of another explicit path.
*/
virtual void visit(TreeModel& store,
wxutil::TreeModel::Row& row,
const std::string& path,
bool isExplicit) = 0;
};
/**
* Visit each node in the constructed tree, passing the wxDataViewItem and
* the VFS string to the visitor object so that data can be inserted.
* Note that this method is not meant to be used if the addPath() overload
* taking a ColumnPopulationCallback has been used earlier on.
*/
void forEachNode(Visitor& visitor);
private:
// Main recursive add function. Accepts a VFS path and adds the new node,
// calling itself if necessary to add all of the parent directories, then
// returns a wxDataViewItem pointing to the new node.
const wxDataViewItem& addRecursive(const std::string& path,
const ColumnPopulationCallback& func,
int recursionLevel = 0);
};
} // namespace