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 incInputText(const(char)* label, float width, ref string buffer, ImGuiInputTextFlags flags = ImGuiInputTextFlags.None) { 85 auto id = igGetID(label); 86 auto storage = igGetStateStorage(); 87 88 // We put a new string container on the heap and make sure the GC doesn't yeet it. 89 if (ImGuiStorage_GetVoidPtr(storage, id) is null) { 90 Str* cursedString = new Str(buffer~"\0"); 91 GC.addRoot(cursedString); 92 ImGuiStorage_SetVoidPtr(storage, id, cursedString); 93 } 94 95 // We get it 96 Str* str = cast(Str*)ImGuiStorage_GetVoidPtr(storage, id); 97 98 igPushItemWidth(width); 99 if (igInputText( 100 label, 101 cast(char*)str.str.ptr, 102 str.str.length, 103 flags | 104 ImGuiInputTextFlags.CallbackResize, 105 cast(ImGuiInputTextCallback)(ImGuiInputTextCallbackData* data) { 106 107 // Allow resizing strings on GC heap 108 if (data.EventFlag == ImGuiInputTextFlags.CallbackResize) { 109 Str* str = (cast(Str*)data.UserData); 110 str.str ~= "\0"; 111 str.str.length = data.BufTextLen; 112 } 113 return 1; 114 }, 115 str 116 )) { 117 118 // Apply string, without null terminator 119 buffer = str.str; 120 GC.removeRoot(ImGuiStorage_GetVoidPtr(storage, id)); 121 ImGuiStorage_SetVoidPtr(storage, id, null); 122 return true; 123 } 124 125 ImVec2 min, max; 126 igGetItemRectMin(&min); 127 igGetItemRectMax(&max); 128 129 auto rect = SDL_Rect( 130 cast(int)min.x+32, 131 cast(int)min.y, 132 cast(int)max.x, 133 32 134 ); 135 136 SDL_SetTextInputRect(&rect); 137 return false; 138 } 139 140 // /** 141 // D compatible text input 142 // */ 143 // bool incInputTextEx(const(char)* label, ref string buffer, ImGuiInputTextFlags flags, uint limit) { 144 // limit = clamp(limit, 1, uint.max); 145 // return igInputText( 146 // label, 147 // cast(char*)(buffer).ptr, 148 // clamp(buffer.length, 0, limit), 149 // flags | 150 // ImGuiInputTextFlags.CallbackResize | 151 // ImGuiInputTextFlags.EnterReturnsTrue, 152 // cast(ImGuiInputTextCallback)(ImGuiInputTextCallbackData* data) { 153 // if (data.EventFlag == ImGuiInputTextFlags.CallbackCompletion) { 154 155 // } 156 // if (data.EventFlag == ImGuiInputTextFlags.CallbackResize) { 157 // string* str = (cast(string*)data.UserData); 158 // str.length = data.BufTextLen; 159 // (*str) ~= "\0"; 160 // } 161 // return 1; 162 // }, 163 // &buffer 164 // ); 165 // }