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