1 /*
2     Copyright © 2020, Inochi2D Project
3     Distributed under the 2-Clause BSD License, see LICENSE file.
4     
5     Authors: Luna Nielsen
6 */
7 module creator.widgets.inputtext;
8 import creator.widgets;
9 import creator.core;
10 import inochi2d;
11 import bindbc.sdl;
12 import std.stdio;
13 import core.memory : GC;
14 
15 private {
16     struct Str {
17         string str;
18     }
19 }
20 
21 /**
22     D compatible text input
23 */
24 bool incInputText(const(char)* label, ref string buffer, ImGuiInputTextFlags flags = ImGuiInputTextFlags.None) {
25     auto id = igGetID(label);
26     auto storage = igGetStateStorage();
27     auto available = incAvailableSpace();
28 
29     // We put a new string container on the heap and make sure the GC doesn't yeet it.
30     if (ImGuiStorage_GetVoidPtr(storage, id) is null) {
31         Str* cursedString = new Str(buffer~"\0");
32         GC.addRoot(cursedString);
33         ImGuiStorage_SetVoidPtr(storage, id, cursedString);
34     }
35 
36     // We get it
37     Str* str = cast(Str*)ImGuiStorage_GetVoidPtr(storage, id);
38 
39     igPushItemWidth(available.x);
40     if (igInputText(
41         label,
42         cast(char*)str.str.ptr, 
43         str.str.length,
44         flags | 
45             ImGuiInputTextFlags.CallbackResize,
46         cast(ImGuiInputTextCallback)(ImGuiInputTextCallbackData* data) {
47 
48             // Allow resizing strings on GC heap
49             if (data.EventFlag == ImGuiInputTextFlags.CallbackResize) {
50                 Str* str = (cast(Str*)data.UserData);
51                 str.str ~= "\0";
52                 str.str.length = data.BufTextLen;
53             }
54             return 1;
55         },
56         str
57     )) {
58 
59         // Apply string, without null terminator
60         buffer = str.str;
61         GC.removeRoot(ImGuiStorage_GetVoidPtr(storage, id));
62         ImGuiStorage_SetVoidPtr(storage, id, null);
63         return true;
64     }
65 
66     ImVec2 min, max;
67     igGetItemRectMin(&min);
68     igGetItemRectMax(&max);
69 
70     auto rect = SDL_Rect(
71         cast(int)min.x+32, 
72         cast(int)min.y, 
73         cast(int)max.x, 
74         32
75     );
76 
77     SDL_SetTextInputRect(&rect);
78     return false;
79 }
80 
81 // /**
82 //     D compatible text input
83 // */
84 // bool incInputTextEx(const(char)* label, ref string buffer, ImGuiInputTextFlags flags, uint limit) {
85 //     limit = clamp(limit, 1, uint.max);
86 //     return igInputText(
87 //         label, 
88 //         cast(char*)(buffer).ptr, 
89 //         clamp(buffer.length, 0, limit),
90 //         flags | 
91 //             ImGuiInputTextFlags.CallbackResize |
92 //             ImGuiInputTextFlags.EnterReturnsTrue,
93 //         cast(ImGuiInputTextCallback)(ImGuiInputTextCallbackData* data) {
94 //             if (data.EventFlag == ImGuiInputTextFlags.CallbackCompletion) {
95 
96 //             }
97 //             if (data.EventFlag == ImGuiInputTextFlags.CallbackResize) {
98 //                 string* str = (cast(string*)data.UserData);
99 //                 str.length = data.BufTextLen;
100 //                 (*str) ~= "\0";
101 //             }
102 //             return 1;
103 //         },
104 //         &buffer
105 //     );
106 // }