console_view.vala 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224
  1. /*
  2. * Copyright(c) 2012-2015 Daniele Bartolini and individual contributors.
  3. * License: https://github.com/dbartolini/crown/blob/master/LICENSE-GPLv2
  4. */
  5. using Gtk;
  6. namespace Crown
  7. {
  8. public class EntryHistory
  9. {
  10. public uint _capacity;
  11. public uint _size;
  12. public uint _index;
  13. public string[] _data;
  14. // Creates a new history with room for capacity records.
  15. public EntryHistory(uint capacity)
  16. {
  17. _capacity = capacity;
  18. _size = 0;
  19. _index = 0;
  20. _data = new string[capacity];
  21. }
  22. // Push a new string into the history.
  23. public void push(string text)
  24. {
  25. // Add command to history
  26. _data[_index] = text;
  27. _index = (_index + 1) % _capacity;
  28. if (_size < _capacity)
  29. ++_size;
  30. }
  31. public void clear()
  32. {
  33. _size = 0;
  34. _index = 0;
  35. }
  36. // Returns the element at @a distance slots from the current index.
  37. // Distance must be in the [1; _size] range.
  38. public string element(uint distance)
  39. {
  40. if (distance < 1 || distance > _size)
  41. return "ERROR";
  42. if (_index >= distance)
  43. return _data[_index - distance];
  44. else
  45. return _data[_capacity - (distance - _index)];
  46. }
  47. }
  48. public class ConsoleView : Gtk.Box
  49. {
  50. // Data
  51. public EntryHistory _entry_history;
  52. public uint _distance;
  53. public Project _project;
  54. // Widgets
  55. public Gtk.ScrolledWindow _scrolled_window;
  56. public Gtk.TextView _text_view;
  57. public Gtk.Entry _entry;
  58. public Gtk.Box _entry_hbox;
  59. public ConsoleView(Project project, Gtk.ComboBoxText combo)
  60. {
  61. Object(orientation: Gtk.Orientation.VERTICAL, spacing: 0);
  62. // Data
  63. _entry_history = new EntryHistory(256);
  64. _distance = 0;
  65. _project = project;
  66. // Widgets
  67. _text_view = new Gtk.TextView();
  68. _text_view.editable = false;
  69. _text_view.can_focus = false;
  70. // // Create tags for color-formatted text
  71. Gtk.TextTag tag_info = new Gtk.TextTag("info");
  72. tag_info.foreground_rgba = { 0.7, 0.7, 0.7, 1.0 };
  73. Gtk.TextTag tag_warning = new Gtk.TextTag("warning");
  74. tag_warning.foreground_rgba = { 1.0, 1.0, 0.4, 1.0 };
  75. Gtk.TextTag tag_error = new Gtk.TextTag("error");
  76. tag_error.foreground_rgba = { 1.0, 0.4, 0.4, 1.0 };
  77. Gtk.TextBuffer tb = _text_view.buffer;
  78. tb.tag_table.add(tag_info);
  79. tb.tag_table.add(tag_warning);
  80. tb.tag_table.add(tag_error);
  81. _scrolled_window = new Gtk.ScrolledWindow(null, null);
  82. _scrolled_window.add(_text_view);
  83. _entry = new Gtk.Entry();
  84. _entry.key_press_event.connect(on_entry_key_pressed);
  85. _entry.activate.connect(on_entry_activated);
  86. _entry_hbox = new Gtk.Box(Gtk.Orientation.HORIZONTAL, 0);
  87. _entry_hbox.pack_start(_entry, true, true);
  88. _entry_hbox.pack_end(combo, false, false);
  89. this.pack_start(_scrolled_window, true, true, 0);
  90. this.pack_start(_entry_hbox, false, true, 0);
  91. this.show.connect(on_show);
  92. this.get_style_context().add_class("console-view");
  93. this.show_all();
  94. }
  95. private void on_entry_activated()
  96. {
  97. string text = _entry.text;
  98. text = text.strip();
  99. if (text.length > 0)
  100. {
  101. _entry_history.push(text);
  102. _distance = 0;
  103. Gtk.Application app = ((Gtk.Window)this.get_toplevel()).application;
  104. ConsoleClient? client = ((LevelEditorApplication)app).current_selected_client();
  105. if (text[0] == ':')
  106. {
  107. string[] args = text[1:text.length].split(" ");
  108. if (args.length > 0)
  109. {
  110. if (client != null)
  111. client.send(DeviceApi.command(args));
  112. }
  113. }
  114. else
  115. {
  116. if (client != null)
  117. client.send_script(text);
  118. }
  119. }
  120. _entry.text = "";
  121. }
  122. private bool on_entry_key_pressed(Gdk.EventKey ev)
  123. {
  124. if (ev.keyval == Gdk.Key.Down)
  125. {
  126. if (_distance > 1)
  127. {
  128. --_distance;
  129. _entry.text = _entry_history.element(_distance);
  130. }
  131. else
  132. {
  133. _entry.text = "";
  134. }
  135. }
  136. else if (ev.keyval == Gdk.Key.Up)
  137. {
  138. if (_distance < _entry_history._size)
  139. {
  140. ++_distance;
  141. _entry.text = _entry_history.element(_distance);
  142. }
  143. }
  144. else
  145. return false;
  146. _entry.set_position(_entry.text.length);
  147. return true;
  148. }
  149. private void on_show()
  150. {
  151. _entry.grab_focus_without_selecting();
  152. }
  153. public void logi(string system, string text)
  154. {
  155. log(system, text, "info");
  156. }
  157. public void logw(string system, string text)
  158. {
  159. log(system, text, "warning");
  160. }
  161. public void loge(string system, string text)
  162. {
  163. log(system, text, "error");
  164. }
  165. public void log(string system, string text, string severity)
  166. {
  167. string msg = text;
  168. // Replace IDs with human-readable names
  169. int id_index = text.index_of("#ID(");
  170. if (id_index != -1)
  171. {
  172. string id = text.substring(id_index + 4, 16);
  173. string name = _project.id_to_name(id);
  174. msg = text.replace("#ID(%s)".printf(id), "'%s'".printf(name));
  175. }
  176. string line = system + ": " + msg + "\n";
  177. Gtk.TextBuffer buffer = _text_view.buffer;
  178. Gtk.TextIter end_iter;
  179. buffer.get_end_iter(out end_iter);
  180. buffer.insert(ref end_iter, line, line.length);
  181. end_iter.backward_chars(line.length);
  182. Gtk.TextIter start_iter = end_iter;
  183. buffer.get_end_iter(out end_iter);
  184. buffer.apply_tag(buffer.tag_table.lookup(severity), start_iter, end_iter);
  185. _text_view.scroll_to_mark(buffer.create_mark("bottom", end_iter, false), 0, true, 0.0, 1.0);
  186. }
  187. }
  188. }