3.4 KB、98行 表示 生 Blame 履歴
1# User Data
2
3The text editor provides an option to add user data to select lines or every line
4in a document. This mechanism is useful when the editor is part of an IDE
5where line operations like setting breakpoints are required.
6
7User data is an abstract void pointer that must be managed externally. A number of
8APIs are available to manage and use user data. First there are the **SetUserData**
9and **GetUserData** methods to attach user data to a specified line or retrieve it.
10This is useful when only select lines need user data. Once data is attached, it will
11stay with that line until the line is deleted. Inserting or deleting lines has no
12effect on the association. Undo will not restore user data.
13
14There is also a mechanism to attach callbacks (**SetInsertor** and **SetDeletor**)
15for when lines are inserted or deleted in a document. This can be used to allocate
16and deallocate user data on each line. Given that these callbacks are independent, the
17Deletor callback could also be used to manage user data on select lines like removing
18breakpoints from deleted lines. The callbacks can be turned off by calling (**SetInsertor** and **SetDeletor**) again with nullptr as the argument. If the callbacks are in place when loading text, you'll get a callback for each line. If
19they are in place when clearing or disposing an editor instance, you get a callback
20for each deleted line. It is therefore important to (re)set callbacks at the right
21time to get the desired effect.
22
23User data pointers are also passed to the optional decorator callback allowing
24integrators to quickly access their data when rendering line decorations. Last but
25not least, there is a user data iterator (**IterateUserData**) which calls a
26callback on each line that has user data attached.
27
28So to use these mechanisms to manage user data on each line you can use a
29pattern like:
30
31```c++
32struct UserData {
33 int somethingImportant;
34 float somethingEvenMoreImportant;
35};
36
37editor.SetInsertor([]([[maybe_unused]] int line) {
38 auto data = new UserData();
39 return static_cast<void*>(data);
40});
41
42editor.SetDeletor([]([[maybe_unused]] int line, void* userData) {
43 auto data = static_cast<UserData*>(userData);
44 delete data;
45});
46
47editor.SetLineDecorator(40.0f, [](TextEditor::Decorator& decorator) {
48 auto data = static_cast<UserData*>(decorator.userData);
49
50 if (data.somethingImportant) {
51 // do something
52 }
53});
54```
55
56To only use these mechanisms for notifications, use a pattern like this:
57
58```c++
59editor.SetInsertor([](int line) {
60 std::cout << "Inserted line " << line << std::endl;
61 // we must return a value so we just use nullptr
62 return nullptr;
63});
64
65editor.SetDeletor([](int line, [[maybe_unused]] void* userData) {
66 std::cout << "Deleted line " << line << std::endl;
67});
68
69To only apply these mechanisms to a few lines, use a pattern like:
70
71```c++
72struct BreakPoint {
73 bool active = false;
74};
75
76auto breakpoint = new BreakPoint();
77editor.SetUserData(10, static_cast<void*>(breakpoint));
78
79editor.SetDeletor([]([[maybe_unused]] int line, void* userData) {
80 if (userData) {
81 auto data = static_cast<BreakPoint*>(userData);
82 delete data;
83 }
84});
85
86editor.SetLineDecorator(40.0f, [](TextEditor::Decorator& decorator) {
87 if (decorator.userData) {
88 auto data = static_cast<UserData*>(decorator.userData);
89 // render breakpoint based on user data
90 }
91});
92
93// summarize all breakpoints
94editor.IterateUserData([](int line, void* userData){
95 auto data= static_cast<BreakPoint*>(userData);
96 // do something
97});
98```