summaryrefslogtreecommitdiffstatshomepage
path: root/3rdparty/bgfx/3rdparty/remotery/vis/Code/Console.js
blob: a18f3dce49e85231ccb6a12fcd5f77327ed65d3e (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
Console = (function()
{
	var BORDER = 10;
	var HEIGHT = 200;


	function Console(wm, server)
	{
		// Create the window and its controls
		this.Window = wm.AddWindow("Console", 10, 10, 100, 100);
		this.PageContainer = this.Window.AddControlNew(new WM.Container(10, 10, 400, 160));
		DOM.Node.AddClass(this.PageContainer.Node, "ConsoleText");
		this.AppContainer = this.Window.AddControlNew(new WM.Container(10, 10, 400, 160));
		DOM.Node.AddClass(this.AppContainer.Node, "ConsoleText");
		this.UserInput = this.Window.AddControlNew(new WM.EditBox(10, 5, 400, 30, "Input", ""));
		this.UserInput.SetChangeHandler(Bind(ProcessInput, this));
		this.Window.ShowNoAnim();

		// This accumulates log text as fast as is required
		this.PageTextBuffer = "";
		this.LastPageTextBufferLen = 0;
		this.AppTextBuffer = "";
		this.LastAppTextBufferLen = 0;

		// Setup command history control
		this.CommandHistory = LocalStore.Get("App", "Global", "CommandHistory", [ ]);
		this.CommandIndex = 0;
		this.MaxNbCommands = 200;
		DOM.Event.AddHandler(this.UserInput.EditNode, "keydown", Bind(OnKeyPress, this));
		DOM.Event.AddHandler(this.UserInput.EditNode, "focus", Bind(OnFocus, this));

		// At a much lower frequency this will update the console window
		window.setInterval(Bind(UpdateHTML, this), 500);

		// Setup log requests from the server
		this.Server = server;
		server.SetConsole(this);
		server.AddMessageHandler("LOG", Bind(OnLog, this));
	}


	Console.prototype.Log = function(text)
	{
		this.PageTextBuffer = LogText(this.PageTextBuffer, text);
	}


	Console.prototype.WindowResized = function(width, height)
	{
		// Place window
		this.Window.SetPosition(BORDER, height - BORDER - 200);
		this.Window.SetSize(width - 2 * BORDER, HEIGHT);

		// Place controls
		var parent_size = this.Window.Size;
		var mid_w = parent_size[0] / 3;
		this.UserInput.SetPosition(BORDER, parent_size[1] - 2 * BORDER - 30);
		this.UserInput.SetSize(parent_size[0] - 100, 18);
		var output_height = this.UserInput.Position[1] - 2 * BORDER;
		this.PageContainer.SetPosition(BORDER, BORDER);
		this.PageContainer.SetSize(mid_w - 2 * BORDER, output_height);
		this.AppContainer.SetPosition(mid_w, BORDER);
		this.AppContainer.SetSize(parent_size[0] - mid_w - BORDER, output_height);
	}


	function OnLog(self, socket, message)
	{
		self.AppTextBuffer = LogText(self.AppTextBuffer, message.text);
	}


	function LogText(existing_text, new_text)
	{
		// Filter the text a little to make it safer
		if (new_text == null)
			new_text = "NULL";

		// Find and convert any HTML entities, ensuring the browser doesn't parse any embedded HTML code
		// This also allows the log to contain arbitrary C++ code (e.g. assert comparison operators)
		new_text = Convert.string_to_html_entities(new_text);

		// Prefix date and end with new line
		var d = new Date();
		new_text = "[" + d.toLocaleTimeString() + "] " + new_text + "<br>";

		// Append to local text buffer and ensure clip the oldest text to ensure a max size
		existing_text = existing_text + new_text;
		var max_len = 10 * 1024;
		var len = existing_text.length;
		if (len > max_len)
			existing_text = existing_text.substr(len - max_len, max_len);

		return existing_text;
	}


	function UpdateHTML(self)
	{
		// Reset the current text buffer as html

		if (self.LastPageTextBufferLen != self.PageTextBuffer.length)
		{
			var page_node = self.PageContainer.Node;
			page_node.innerHTML = self.PageTextBuffer;
			page_node.scrollTop = page_node.scrollHeight;
			self.LastPageTextBufferLen = self.PageTextBuffer.length;
		}

		if (self.LastAppTextBufferLen != self.AppTextBuffer.length)
		{		
			var app_node = self.AppContainer.Node;
			app_node.innerHTML = self.AppTextBuffer;
			app_node.scrollTop = app_node.scrollHeight;
			self.LastAppTextBufferLen = self.AppTextBuffer.length;
		}
	}


	function ProcessInput(self, node)
	{
		// Send the message exactly
		var msg = node.value;
		self.Server.Send("CONI" + msg);

		// Emit to console and clear
		self.Log("> " + msg);
		self.UserInput.SetValue("");

		// Keep track of recently issued commands, with an upper bound
		self.CommandHistory.push(msg);
		var extra_commands = self.CommandHistory.length - self.MaxNbCommands;
		if (extra_commands > 0)
			self.CommandHistory.splice(0, extra_commands);

		// Set command history index to the most recent command
		self.CommandIndex = self.CommandHistory.length;

		// Backup to local store
		LocalStore.Set("App", "Global", "CommandHistory", self.CommandHistory);

		// Keep focus with the edit box
		return true;
	}


	function OnKeyPress(self, evt)
	{
		evt = DOM.Event.Get(evt);

		if (evt.keyCode == Keyboard.Codes.UP)
		{
			if (self.CommandHistory.length > 0)
			{
				// Cycle backwards through the command history
				self.CommandIndex--;
				if (self.CommandIndex < 0)
					self.CommandIndex = self.CommandHistory.length - 1;
				var command = self.CommandHistory[self.CommandIndex];
				self.UserInput.SetValue(command);
			}

			// Stops default behaviour of moving cursor to the beginning
			DOM.Event.StopDefaultAction(evt);
		}

		else if (evt.keyCode == Keyboard.Codes.DOWN)
		{
			if (self.CommandHistory.length > 0)
			{
				// Cycle fowards through the command history
				self.CommandIndex = (self.CommandIndex + 1) % self.CommandHistory.length;
				var command = self.CommandHistory[self.CommandIndex];
				self.UserInput.SetValue(command);
			}

			// Stops default behaviour of moving cursor to the end
			DOM.Event.StopDefaultAction(evt);
		}
	}


	function OnFocus(self)
	{
		// Reset command index on focus
		self.CommandIndex = self.CommandHistory.length;
	}


	return Console;
})();