1 /**
2 Copyright: Copyright (c) 2017-2018 Andrey Penechko.
3 License: $(WEB boost.org/LICENSE_1_0.txt, Boost License 1.0).
4 Authors: Andrey Penechko.
5 */
6 module voxelman.gui.textedit.messagelog;
7 
8 import voxelman.math;
9 import voxelman.container.chunkedbuffer;
10 import voxelman.gui.textedit.cursor;
11 import voxelman.gui.textedit.textmodel;
12 import voxelman.gui.textedit.linebuffer;
13 import voxelman.gui.textedit.texteditor;
14 
15 class MessageLogTextModel : TextModel
16 {
17 	MessageLog* text;
18 
19 	this(MessageLog* text) { this.text = text; }
20 	bool isEditable() { return false; }
21 
22 	int numLines() { return text.lines.numLines; }
23 	int lastLine() { return text.lines.lastLine; }
24 	ChunkedRange!char opSlice(size_t from, size_t to) { return (*text)[from..to]; }
25 	LineInfo lineInfo(int line) { return text.lineInfo(line); }
26 
27 	void onCommand(EditorCommand com) { text.onCommand(com); }
28 	void replaceSelection(const(char)[] str) {}
29 	ref Selection selection() { return text.selection; }
30 	//ivec2 textSizeInGlyphs() { return ivec2(0,0); }
31 	void moveSelectionCursor(MoveCommand com, bool extendSelection)
32 	{
33 		text.selection.end = text.moveCursor(text.selection.end, com);
34 		if (!extendSelection) text.selection.start = text.selection.end;
35 	}
36 }
37 
38 struct MessageLog
39 {
40 	import std.format : formattedWrite;
41 	private ChunkedBuffer!(char, 4096) textData;
42 	private LineInfoBuffer lines;
43 	Selection selection;
44 	mixin ReadHelpers!();
45 
46 	this(string text)
47 	{
48 		textData.put(text);
49 		lines.calc(text);
50 	}
51 
52 	ulong length() { return textData.length; }
53 	alias opDollar = length;
54 	LineInfo lineInfo(int line) { return lines.lineInfo(line); }
55 
56 	ChunkedRange!char opSlice(size_t from, size_t to)
57 	{
58 		return textData[from..to].toChunkedRange;
59 	}
60 
61 	void onCommand(EditorCommand com)
62 	{
63 		switch(com.type)
64 		{
65 			case EditorCommandType.copy:
66 				copySelection();
67 				break;
68 			case EditorCommandType.select_all:
69 				selection = Selection(Cursor(0,0), Cursor(lines.textEnd, lines.lastLine));
70 				break;
71 			default:
72 				break;
73 		}
74 	}
75 
76 	void clear()
77 	{
78 		lines.clear();
79 		textData.clear();
80 		selection = Selection();
81 	}
82 
83 	void put(in char[] str)
84 	{
85 		textData.put(str);
86 		lines.onPaste(Cursor(lines.textEnd, lines.lastLine), str);
87 	}
88 
89 	void putf(Args...)(const(char)[] fmt, Args args)
90 	{
91 		formattedWrite(&this, fmt, args);
92 	}
93 
94 	void putfln(Args...)(const(char)[] fmt, Args args)
95 	{
96 		formattedWrite(&this, fmt, args);
97 		put("\n");
98 	}
99 
100 	void putln(const(char)[] str)
101 	{
102 		put(str);
103 		put("\n");
104 	}
105 }
106 
107 unittest
108 {
109 	import std.algorithm : equal;
110 	import std.stdio;
111 	MessageLog log;
112 	log.putln("test1");
113 	log.putln("test2");
114 	log.putln("test3");
115 
116 	auto from = log.lineInfo(1).startOffset;
117 	auto to = log.lineInfo(2).endOffset;
118 	auto text = log[from..to].byItem;
119 
120 	assert(text.equal("test2\ntest3"));
121 }