1 /** 2 Copyright: Copyright (c) 2015-2017 Andrey Penechko. 3 License: $(WEB boost.org/LICENSE_1_0.txt, Boost License 1.0). 4 Authors: Andrey Penechko. 5 */ 6 module voxelman.utils.linebuffer; 7 8 struct LineBuffer 9 { 10 import derelict.imgui.imgui; 11 import std.array : empty; 12 import std.format : formattedWrite; 13 import voxelman.container.buffer; 14 15 Buffer!char lines; 16 Buffer!size_t lineSizes; 17 bool scrollToBottom; 18 19 void clear() 20 { 21 lines.clear(); 22 lineSizes.clear(); 23 } 24 25 void put(in char[] str) 26 { 27 import std.regex : ctRegex, splitter; 28 import std.algorithm : map; 29 import std.range; 30 31 if (str.empty) return; 32 auto splittedLines = splitter(str, ctRegex!"(\r\n|\r|\n|\v|\f)"); 33 34 foreach(first; splittedLines.takeOne()) 35 { 36 lines.put(first); 37 if (!lineSizes.data.empty) 38 { 39 lineSizes.data[$-1] += first.length; 40 } 41 else 42 { 43 lineSizes.put(first.length); 44 } 45 } 46 47 // process other lines 48 foreach(line; splittedLines.drop(1)) 49 { 50 ++lineSizes.data[$-1]; 51 lines.put("\n"); 52 lines.put(line); 53 lineSizes.put(line.length); 54 } 55 56 lines.stealthPut('\0'); 57 58 scrollToBottom = true; 59 } 60 61 void putf(Args...)(const(char)[] fmt, Args args) 62 { 63 formattedWrite(&this, fmt, args); 64 } 65 66 void putfln(Args...)(const(char)[] fmt, Args args) 67 { 68 formattedWrite(&this, fmt, args); 69 put("\n"); 70 } 71 72 void putln(const(char)[] str) 73 { 74 put(str); 75 put("\n"); 76 } 77 78 void draw() 79 { 80 char* lineStart = lines.data.ptr; 81 foreach(lineSize; lineSizes.data) 82 if (lineSize > 0) 83 { 84 igPushTextWrapPos(igGetWindowContentRegionWidth()); 85 igTextUnformatted(lineStart, lineStart+lineSize); 86 igPopTextWrapPos(); 87 lineStart += lineSize; 88 } 89 90 if (scrollToBottom) 91 igSetScrollHere(1.0f); 92 scrollToBottom = false; 93 } 94 95 void drawSelectable() 96 { 97 igPushStyleVarVec(ImGuiStyleVar_FramePadding, ImVec2(6,6)); 98 99 ImVec2 size; 100 igGetContentRegionAvail(&size); 101 size.x -= 12; 102 size.y -= 12; 103 104 igPushStyleColor(ImGuiCol_FrameBg, ImVec4(0, 0, 0, 0)); 105 if (lines.data.length) 106 igInputTextMultiline("##multiline", lines.data.ptr, lines.data.length, size, ImGuiInputTextFlags_ReadOnly); 107 else 108 { 109 char[1] str; 110 igInputTextMultiline("##multiline", str.ptr, 0, size, ImGuiInputTextFlags_ReadOnly); 111 } 112 igPopStyleColor(); 113 114 igPopStyleVar(); 115 116 if (scrollToBottom) 117 igSetScrollHere(1.0f); 118 scrollToBottom = false; 119 } 120 }