1 /** 2 Copyright: Copyright (c) 2015-2016 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 : Appender, empty; 12 import std.format : formattedWrite; 13 14 Appender!(char[]) lines; 15 Appender!(size_t[]) lineSizes; 16 bool scrollToBottom; 17 18 void clear() 19 { 20 lines.clear(); 21 lineSizes.clear(); 22 } 23 24 void put(in char[] str) 25 { 26 import std.regex : ctRegex, splitter; 27 import std.algorithm : map; 28 if (str.empty) return; 29 auto splittedLines = splitter(str, ctRegex!"(\r\n|\r|\n|\v|\f)"); 30 auto lengths = splittedLines.map!(a => a.length); 31 if (!lineSizes.data.empty) 32 { 33 lineSizes.data[$-1] += lengths.front; 34 lengths.popFront(); 35 } 36 lineSizes.put(lengths); 37 foreach(line; splittedLines) 38 lines.put(line); 39 scrollToBottom = true; 40 } 41 42 void putf(Args...)(const(char)[] fmt, Args args) 43 { 44 formattedWrite(&this, fmt, args); 45 } 46 47 void putfln(Args...)(const(char)[] fmt, Args args) 48 { 49 formattedWrite(&this, fmt, args); 50 put("\n"); 51 } 52 53 void putln(const(char)[] str) 54 { 55 put(str); 56 put("\n"); 57 } 58 59 void draw() 60 { 61 char* lineStart = lines.data.ptr; 62 foreach(lineSize; lineSizes.data) 63 if (lineSize > 0) 64 { 65 igPushTextWrapPos(igGetWindowContentRegionWidth()); 66 igTextUnformatted(lineStart, lineStart+lineSize); 67 igPopTextWrapPos(); 68 lineStart += lineSize; 69 } 70 71 if (scrollToBottom) 72 igSetScrollHere(1.0f); 73 scrollToBottom = false; 74 } 75 }