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 // }