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 }