cosmos 3.9.1 → 3.9.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (63) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +4 -3
  3. data/Manifest.txt +7 -0
  4. data/autohotkey/tools/cmd_extractor.ahk +17 -0
  5. data/autohotkey/tools/tlm_extractor.ahk +62 -1
  6. data/bin/cosmos +182 -12
  7. data/data/crc.txt +35 -34
  8. data/demo/config/data/crc.txt +6 -2
  9. data/demo/config/targets/INST/screens/adcs.txt +1 -1
  10. data/demo/config/tools/cmd_tlm_server/cmd_tlm_server2.txt +1 -1
  11. data/demo/config/tools/example_application.css +58 -0
  12. data/demo/config/tools/launcher/launcher.css +7 -0
  13. data/demo/config/tools/launcher/launcher2.css +10 -0
  14. data/demo/config/tools/test_runner/test_runner.css +45 -0
  15. data/ext/cosmos/ext/packet/packet.c +6 -0
  16. data/lib/cosmos/gui/dialogs/scroll_text_dialog.rb +15 -6
  17. data/lib/cosmos/gui/qt_tool.rb +58 -8
  18. data/lib/cosmos/gui/text/ruby_editor.rb +54 -6
  19. data/lib/cosmos/gui/utilities/analyze_log.rb +153 -0
  20. data/lib/cosmos/interfaces/interface.rb +6 -0
  21. data/lib/cosmos/packets/packet_item_limits.rb +14 -2
  22. data/lib/cosmos/packets/structure_item.rb +22 -3
  23. data/lib/cosmos/script/cmd_tlm_server.rb +28 -0
  24. data/lib/cosmos/script/extract.rb +10 -9
  25. data/lib/cosmos/script/tools.rb +10 -4
  26. data/lib/cosmos/system/system.rb +2 -1
  27. data/lib/cosmos/tools/cmd_extractor/cmd_extractor.rb +12 -0
  28. data/lib/cosmos/tools/cmd_tlm_server/api.rb +84 -0
  29. data/lib/cosmos/tools/cmd_tlm_server/cmd_tlm_server.rb +3 -2
  30. data/lib/cosmos/tools/cmd_tlm_server/commanding.rb +9 -0
  31. data/lib/cosmos/tools/cmd_tlm_server/gui/interfaces_tab.rb +2 -2
  32. data/lib/cosmos/tools/cmd_tlm_server/interface_thread.rb +26 -17
  33. data/lib/cosmos/tools/cmd_tlm_server/interfaces.rb +26 -0
  34. data/lib/cosmos/tools/cmd_tlm_server/packet_logging.rb +29 -0
  35. data/lib/cosmos/tools/cmd_tlm_server/routers.rb +33 -0
  36. data/lib/cosmos/tools/data_viewer/data_viewer.rb +1 -1
  37. data/lib/cosmos/tools/launcher/launcher.rb +14 -25
  38. data/lib/cosmos/tools/limits_monitor/limits_monitor.rb +3 -7
  39. data/lib/cosmos/tools/packet_viewer/packet_viewer.rb +6 -4
  40. data/lib/cosmos/tools/script_runner/script_runner.rb +58 -9
  41. data/lib/cosmos/tools/script_runner/script_runner_frame.rb +45 -19
  42. data/lib/cosmos/tools/table_manager/table_manager.rb +7 -7
  43. data/lib/cosmos/tools/test_runner/test_runner.rb +6 -0
  44. data/lib/cosmos/tools/tlm_extractor/tlm_extractor.rb +145 -8
  45. data/lib/cosmos/tools/tlm_extractor/tlm_extractor_config.rb +89 -19
  46. data/lib/cosmos/tools/tlm_grapher/tabbed_plots_tool/tabbed_plots_config.rb +14 -0
  47. data/lib/cosmos/tools/tlm_grapher/tabbed_plots_tool/tabbed_plots_realtime_thread.rb +1 -1
  48. data/lib/cosmos/tools/tlm_viewer/screen.rb +15 -3
  49. data/lib/cosmos/tools/tlm_viewer/tlm_viewer.rb +23 -12
  50. data/lib/cosmos/version.rb +4 -4
  51. data/spec/packets/packet_item_limits_spec.rb +33 -6
  52. data/spec/packets/packet_item_spec.rb +9 -9
  53. data/spec/packets/packet_spec.rb +18 -6
  54. data/spec/packets/structure_item_spec.rb +22 -4
  55. data/spec/script/cmd_tlm_server_spec.rb +66 -0
  56. data/spec/script/extract_spec.rb +144 -0
  57. data/spec/script/tools_spec.rb +17 -2
  58. data/spec/system/system_spec.rb +1 -1
  59. data/spec/tools/cmd_tlm_server/api_spec.rb +6 -0
  60. data/spec/tools/cmd_tlm_server/cmd_tlm_server_spec.rb +1 -1
  61. data/spec/tools/table_manager/table_item_parser_spec.rb +61 -0
  62. data/spec/tools/table_manager/table_item_spec.rb +1 -1
  63. metadata +9 -2
@@ -20,7 +20,7 @@
20
20
  "config/targets/INST/screens/limits.txt" 0x98430974
21
21
  "config/targets/INST/screens/ground.txt" 0x2D89624D
22
22
  "config/targets/INST/screens/block.txt" 0x77C3F2F0
23
- "config/targets/INST/screens/adcs.txt" 0xBF096628
23
+ "config/targets/INST/screens/adcs.txt" 0x73D61F93
24
24
  "config/targets/INST/screens/other.txt" 0x2F7A1014
25
25
  "config/targets/INST/screens/tabs.txt" 0x8C8BB548
26
26
  "config/targets/INST/cmd_tlm_server.txt" 0x3FC45604
@@ -67,8 +67,11 @@
67
67
  "config/data/vswitchon.gif" 0xD747AC45
68
68
  "config/system/system.txt" 0xFA24EDAA
69
69
  "config/system/system2.txt" 0xC75EBA65
70
+ "config/tools/launcher/launcher2.css" 0x69DA47AB
70
71
  "config/tools/launcher/launcher.txt" 0x1B96FE7C
71
72
  "config/tools/launcher/launcher2.txt" 0xB0B9B1D1
73
+ "config/tools/launcher/launcher.css" 0x6314C0C0
74
+ "config/tools/example_application.css" 0x2987FE3F
72
75
  "config/tools/table_manager/MCConfigurationTable_fsw1_def.txt" 0x6531613A
73
76
  "config/tools/table_manager/ConfigTables_def.txt" 0xC38DCB2A
74
77
  "config/tools/table_manager/ExampleTableDefinition.txt" 0x59060429
@@ -78,12 +81,13 @@
78
81
  "config/tools/tlm_viewer/tlm_viewer.txt" 0x825AF31C
79
82
  "config/tools/data_viewer/data_viewer.txt" 0xCAC3B017
80
83
  "config/tools/test_runner/test_runner.txt" 0x1EB7E49C
84
+ "config/tools/test_runner/test_runner.css" 0x06987062
81
85
  "config/tools/tlm_extractor/tlm_extractor4.txt" 0x068824C2
82
86
  "config/tools/tlm_extractor/tlm_extractor3.txt" 0x475006AA
83
87
  "config/tools/tlm_extractor/tlm_extractor.txt" 0x0B97FA7D
84
88
  "config/tools/tlm_extractor/_adcs_time.txt" 0x3DAD5094
85
89
  "config/tools/tlm_extractor/tlm_extractor2.txt" 0x5C780BD2
86
- "config/tools/cmd_tlm_server/cmd_tlm_server2.txt" 0xF1C5C3B4
90
+ "config/tools/cmd_tlm_server/cmd_tlm_server2.txt" 0x20C1091B
87
91
  "config/tools/cmd_tlm_server/cmd_tlm_server.txt" 0xFAE90F35
88
92
  "config/tools/tlm_grapher/README.txt" 0x93B2C07E
89
93
  "config/tools/opengl_builder/README.txt" 0x93B2C07E
@@ -1,4 +1,4 @@
1
- SCREEN AUTO AUTO 1.0
1
+ SCREEN AUTO AUTO 1.0 FIXED
2
2
 
3
3
  VERTICAL
4
4
 
@@ -1,4 +1,4 @@
1
- TITLE 'COSMOS Command and Telemetry Server - Demo Configuration'
1
+ TITLE 'COSMOS Command and Telemetry Server - Demo Configuration 2'
2
2
 
3
3
  PACKET_LOG_WRITER DEFAULT meta_packet_log_writer.rb META DATA config/data/meta_init.txt
4
4
  PACKET_LOG_WRITER COSMOSLOG packet_log_writer.rb cosmos
@@ -0,0 +1,58 @@
1
+ /* Rename this file to application.css to set a global style */
2
+ QMainWindow {
3
+ background-color: #d1d1d2;
4
+ }
5
+ QLabel {
6
+ font-size: 14px;
7
+ font-family: Arial;
8
+ }
9
+ QPushButton {
10
+ font-size: 12px;
11
+ padding: 4px;
12
+ border: 1px solid black;
13
+ border-radius: 4px;
14
+ background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #b1bac4, stop: 1 #767c83);
15
+ }
16
+ QPushButton:hover:!pressed
17
+ {
18
+ background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #4cbdff, stop: 1 #3585b3);
19
+ }
20
+ QPushButton:pressed {
21
+ background-color: #3585b3
22
+ }
23
+ QTableView {
24
+ background-color: #d1d1d2;
25
+ }
26
+ QHeaderView::section:horizontal {
27
+ background-color: #3585b3;
28
+ }
29
+ QHeaderView::section:vertical {
30
+ background-color: #767c83;
31
+ color: white;
32
+ }
33
+ QTabWidget:pane { /* The tab widget frame */
34
+ border-top: 2px solid #C2C7CB;
35
+ }
36
+ QTabWidget::tab-bar {
37
+ left: 10px; /* move to the right */
38
+ }
39
+ /* Style the tab using the tab sub-control. Note that it reads QTabBar _not_ QTabWidget */
40
+ QTabBar::tab {
41
+ border: 2px solid #C4C4C3;
42
+ border-bottom-color: #C2C7CB; /* same as the pane color */
43
+ border-top-left-radius: 4px;
44
+ border-top-right-radius: 4px;
45
+ min-width: 8ex;
46
+ padding: 2px;
47
+ }
48
+ QTabBar::tab:selected, QTabBar::tab:hover {
49
+ background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #fafafa, stop: 0.4 #f4f4f4, stop: 0.5 #e7e7e7, stop: 1.0 #fafafa);
50
+ }
51
+ QTabBar::tab:selected {
52
+ border-color: #9B9B9B;
53
+ border-bottom-color: #C2C7CB; /* same as pane color */
54
+ }
55
+ QTabBar::tab:!selected {
56
+ margin-top: 2px; /* make non-selected tabs look smaller */
57
+ }
58
+
@@ -0,0 +1,7 @@
1
+ #Label {
2
+ font-size: 20px;
3
+ }
4
+ #Divider {
5
+ border: 2px solid #3585b3;
6
+ border-radius: 1px;
7
+ }
@@ -0,0 +1,10 @@
1
+ QMainWindow {
2
+ background-color: #9a1f20;
3
+ }
4
+ #Label {
5
+ font-size: 20px;
6
+ }
7
+ #Divider {
8
+ border: 2px solid #3585b3;
9
+ border-radius: 1px;
10
+ }
@@ -0,0 +1,45 @@
1
+ QLabel {
2
+ font-size: 14px;
3
+ }
4
+ QCheckBox {
5
+ font-size: 14px;
6
+ }
7
+ #PauseOnError {
8
+ color: blue;
9
+ }
10
+ #ContinueTestCaseAfterError {
11
+ color: purple;
12
+ }
13
+ #AbortTestingAfterError {
14
+ color: green;
15
+ }
16
+ #Manual {
17
+ color: darkblue;
18
+ }
19
+ #LoopTesting {
20
+ color: magenta;
21
+ }
22
+ #BreakLoopAfterError {
23
+ color: maroon;
24
+ }
25
+ QPushButton {
26
+ border: 1px solid #8f8f91;
27
+ border-radius: 6px;
28
+ background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #f6f7ff, stop: 1 #c0dbff);
29
+ min-width: 80px;
30
+ font-size: 14px;
31
+ padding: 2px 5px;
32
+ }
33
+ QPushButton:hover:!pressed
34
+ {
35
+ background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #f6f7ff, stop: 1 #80abff);
36
+ }
37
+ QPushButton:pressed {
38
+ background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #c0dbff, stop: 1 #f6f7ff);
39
+ }
40
+ QPushButton:flat {
41
+ border: none;
42
+ }
43
+ QPushButton:default {
44
+ border-color: #80abff;
45
+ }
@@ -191,9 +191,15 @@ static VALUE received_time_equals(VALUE self, VALUE received_time) {
191
191
  * received */
192
192
  static VALUE received_count_equals(VALUE self, VALUE received_count) {
193
193
  volatile VALUE read_conversion_cache = rb_ivar_get(self, id_ivar_read_conversion_cache);
194
+ #ifdef RUBY_INTEGER_UNIFICATION /* Ruby 2.4.0 unified Fixnum and Bignum into Integer. This check allows the code to build pre- and post-2.4.0. */
195
+ if (rb_funcall(received_count, id_method_class, 0) != rb_cInteger) {
196
+ rb_raise(rb_eArgError, "received_count must be an Integer but is a %s", RSTRING_PTR(rb_funcall(rb_funcall(received_count, id_method_class, 0), id_method_to_s, 0)));
197
+ }
198
+ #else
194
199
  if (rb_funcall(received_count, id_method_class, 0) != rb_cFixnum) {
195
200
  rb_raise(rb_eArgError, "received_count must be a Fixnum but is a %s", RSTRING_PTR(rb_funcall(rb_funcall(received_count, id_method_class, 0), id_method_to_s, 0)));
196
201
  }
202
+ #endif
197
203
  rb_ivar_set(self, id_ivar_received_count, received_count);
198
204
  if (RTEST(read_conversion_cache)) {
199
205
  rb_funcall(read_conversion_cache, id_method_clear, 0);
@@ -13,23 +13,32 @@ require 'cosmos/gui/qt'
13
13
  module Cosmos
14
14
  # Dialog which creates a read only list of text
15
15
  class ScrollTextDialog < Qt::Dialog
16
+ TEXT_MARGIN = 30
17
+ SCREEN_WIDTH_MARGIN = 40
18
+ SCREEN_HEIGHT_MARGIN = 100
19
+
16
20
  # @param parent [Qt::Widget] Parent of this dialog
17
21
  # @param title [String] Dialog title
18
22
  # @param text [String] Text to display
19
23
  def initialize(parent, title, text)
20
24
  super(parent, Qt::WindowTitleHint | Qt::WindowSystemMenuHint)
21
- setMinimumWidth(700)
22
- setMinimumHeight(400)
23
-
24
25
  setWindowTitle(title)
25
- # Intentionally don't load icon as this can cause loop of unexpected output running with --debug
26
26
 
27
27
  layout = Qt::VBoxLayout.new
28
- text.gsub!("\n","<br>")
29
- @text_edit = Qt::TextEdit.new(text, self)
28
+ @text_edit = Qt::TextEdit.new(text.gsub("\n","<br>"), self)
30
29
  @text_edit.setReadOnly(true)
31
30
  layout.addWidget(@text_edit)
32
31
 
32
+ rec = Qt::Application::desktop.screenGeometry()
33
+ font = @text_edit.document().defaultFont()
34
+ font_metrics = Qt::FontMetrics.new(font)
35
+ text_size = font_metrics.size(0, text)
36
+ text_width = text_size.width + TEXT_MARGIN
37
+ text_height = text_size.height + TEXT_MARGIN
38
+ width = text_width > rec.width ? rec.width - SCREEN_WIDTH_MARGIN : text_width
39
+ height = text_height > rec.height ? rec.height - SCREEN_HEIGHT_MARGIN : text_height
40
+ @text_edit.setMinimumSize(width, height)
41
+
33
42
  self.setLayout(layout)
34
43
  self.raise
35
44
  self.exec
@@ -36,21 +36,57 @@ module Cosmos
36
36
  def initialize(options)
37
37
  # Call QT::MainWindow constructor
38
38
  super() # MUST BE FIRST - All code before super is executed twice in RubyQt Based classes
39
+ @options = options
40
+ @about_string = nil
39
41
 
40
42
  # Add Path for plugins
41
43
  Qt::Application.instance.addLibraryPath(Qt::PLUGIN_PATH) if Kernel.is_windows?
42
-
43
44
  # Prevent killing the parent process from killing this GUI application
44
45
  Process.setpgrp unless Kernel.is_windows?
45
46
 
46
- self.class.redirect_io if options.redirect_io
47
+ self.class.redirect_io if @options.redirect_io
48
+ self.window_title = @options.title
49
+ Cosmos.load_cosmos_icon
47
50
 
48
- # Configure instance variables
49
- @options = options
50
- @about_string = nil
51
+ # Read the application wide stylesheet if it exists
52
+ app_style = File.join(Cosmos::USERPATH, 'config', 'tools', 'application.css')
53
+ @stylesheet = ''
54
+ @stylesheet = File.read(app_style) if File.exist? app_style
55
+
56
+ # Get the source file location of the tool calling this method
57
+ location = self.class.instance_method(:initialize).source_location[0]
58
+ tool_name = location.split('/')[-2]
59
+ config_dir = File.join(Cosmos::USERPATH, 'config', 'tools', tool_name)
60
+ if File.exist? config_dir
61
+ @options.config_dir = config_dir
62
+ @options.config_file = config_path(@options.config_file, ".txt", tool_name)
63
+ @options.stylesheet = config_path(@options.stylesheet, ".css", tool_name)
64
+ end
65
+ end
51
66
 
52
- self.window_title = options.title
53
- Cosmos.load_cosmos_icon
67
+ # Creates a path to a configuration file. If the file is given it is
68
+ # checked for an absolute path. If it is not absolute, the configuration
69
+ # directory is prepended to the filename. If no file is given a default is
70
+ # generated based on the application name.
71
+ #
72
+ # @param filename [String] Path to a configuration file
73
+ # @param type [String] File extension, e.g. '.txt'
74
+ # @param tool_name [String] Name of the tool calling this method
75
+ # @return [String|nil] Path to a configuration file or nil if none found
76
+ def config_path(filename, type, tool_name)
77
+ return filename if filename && File.exist?(filename)
78
+ if filename
79
+ # Add the configuration dir onto the filename
80
+ filename = File.join(@options.config_dir, filename)
81
+ else
82
+ # No file passed so default to a file named after the class
83
+ filename = File.join(@options.config_dir, "#{tool_name}#{type}")
84
+ end
85
+ if File.exist? filename
86
+ filename
87
+ else
88
+ nil
89
+ end
54
90
  end
55
91
 
56
92
  # Create the exit_action and the about_action. The exit_action is not
@@ -127,6 +163,11 @@ module Cosmos
127
163
  # position of the windows for subsequent launches of the application.
128
164
  # Finally it can initally show the application as minimized or maximized.
129
165
  def complete_initialize
166
+ if @options.stylesheet
167
+ @stylesheet << File.read(@options.stylesheet)
168
+ end
169
+ setStyleSheet(@stylesheet)
170
+
130
171
  # Handle manually sizing the window
131
172
  resize(@options.width, @options.height) unless @options.auto_size
132
173
 
@@ -294,9 +335,18 @@ module Cosmos
294
335
  end
295
336
 
296
337
  # Create the system option
297
- option_parser.on("--system VALUE", "Use an alternative system.txt file") do |arg|
338
+ option_parser.on("--system FILE", "Use an alternative system.txt file") do |arg|
298
339
  System.instance(File.join(USERPATH, 'config', 'system', arg))
299
340
  end
341
+ option_parser.on("-c", "--config FILE", "Use the specified configuration file") do |arg|
342
+ options.config_file = arg
343
+ end
344
+ option_parser.on("--stylesheet FILE", "Use the specified stylesheet") do |arg|
345
+ options.stylesheet = arg
346
+ end
347
+
348
+ option_parser.separator("")
349
+ option_parser.separator("Window Size Options:")
300
350
 
301
351
  # Create the minimized option
302
352
  option_parser.on("--minimized", "Start the tool minimized") do |arg|
@@ -17,7 +17,7 @@ module Cosmos
17
17
 
18
18
  class RubyEditor < CompletionTextEdit
19
19
  # private slot used to connect to the blockCountChanged signal
20
- slots 'line_count_changed()'
20
+ slots 'line_count_changed(int)'
21
21
  # private slot used to connect to the updateRequest signal
22
22
  slots 'update_line_number_area(const QRect &, int)'
23
23
 
@@ -26,6 +26,7 @@ module Cosmos
26
26
  signals 'breakpoints_cleared()'
27
27
 
28
28
  attr_accessor :enable_breakpoints
29
+ attr_accessor :filename
29
30
 
30
31
  # This works but slows down the GUI significantly when
31
32
  # pasting a large (10k line) block of code into the editor
@@ -153,6 +154,8 @@ module Cosmos
153
154
  end
154
155
 
155
156
  CHAR_57 = Qt::Char.new(57)
157
+ BREAKPOINT_SET = 1
158
+ BREAKPOINT_CLEAR = -1
156
159
 
157
160
  def initialize(parent)
158
161
  super(parent)
@@ -171,10 +174,10 @@ module Cosmos
171
174
  @syntax = RubySyntax.new(document())
172
175
  @lineNumberArea = LineNumberArea.new(self)
173
176
 
174
- connect(self, SIGNAL('blockCountChanged(int)'), self, SLOT('line_count_changed()'))
177
+ connect(self, SIGNAL('blockCountChanged(int)'), self, SLOT('line_count_changed(int)'))
175
178
  connect(self, SIGNAL('updateRequest(const QRect &, int)'), self, SLOT('update_line_number_area(const QRect &, int)'))
176
179
 
177
- line_count_changed()
180
+ line_count_changed(-1)
178
181
  end
179
182
 
180
183
  def dispose
@@ -196,19 +199,61 @@ module Cosmos
196
199
 
197
200
  def add_breakpoint(line)
198
201
  @breakpoints << line
202
+ block = document.findBlockByNumber(line-1)
203
+ block.setUserState(BREAKPOINT_SET)
204
+ block.dispose
205
+ block = nil
199
206
  @lineNumberArea.repaint
200
207
  end
201
208
 
202
209
  def clear_breakpoint(line)
203
210
  @breakpoints.delete(line)
211
+ block = document.findBlockByNumber(line-1)
212
+ block.setUserState(BREAKPOINT_CLEAR)
213
+ block.dispose
214
+ block = nil
204
215
  @lineNumberArea.repaint
205
216
  end
206
217
 
207
218
  def clear_breakpoints
208
219
  @breakpoints = []
220
+ block = document.firstBlock()
221
+ while (block.isValid())
222
+ block.setUserState(BREAKPOINT_CLEAR)
223
+ next_block = block.next()
224
+ block.dispose
225
+ block = next_block
226
+ end
227
+ block.dispose
228
+ block = nil
209
229
  @lineNumberArea.repaint
210
230
  end
211
231
 
232
+ def update_breakpoints
233
+ return if @breakpoints.empty?
234
+
235
+ breakpoints = []
236
+ block = document.firstBlock()
237
+ while (block.isValid())
238
+ if block.userState() == BREAKPOINT_SET
239
+ line = block.firstLineNumber() + 1
240
+ breakpoints << line
241
+ end
242
+ next_block = block.next()
243
+ block.dispose
244
+ block = next_block
245
+ end
246
+ block.dispose
247
+ block = nil
248
+
249
+ # Only emit signals if the breakpoints have changed.
250
+ if @breakpoints.sort != breakpoints.sort
251
+ emit breakpoints_cleared
252
+ breakpoints.each {|line| emit breakpoint_set(line)}
253
+ @breakpoints = breakpoints
254
+ end
255
+ end
256
+
212
257
  def comment_or_uncomment_lines
213
258
  cursor = textCursor
214
259
  no_selection = cursor.hasSelection ? false : true
@@ -281,7 +326,7 @@ module Cosmos
281
326
  Qt::AlignRight, # flags
282
327
  number.to_s) # text
283
328
 
284
- if @enable_breakpoints and @breakpoints.include?(number)
329
+ if @enable_breakpoints and block.userState() == BREAKPOINT_SET
285
330
  painter.setBrush(Cosmos::RED)
286
331
  painter.drawEllipse(2,
287
332
  top+2,
@@ -312,7 +357,10 @@ module Cosmos
312
357
 
313
358
  private
314
359
 
315
- def line_count_changed
360
+ def line_count_changed(new_block_count)
361
+ if new_block_count >= 0
362
+ update_breakpoints()
363
+ end
316
364
  setViewportMargins(line_number_area_width(), 0, 0, 0)
317
365
  update
318
366
  end
@@ -325,7 +373,7 @@ module Cosmos
325
373
  end
326
374
  my_viewport = viewport()
327
375
  viewport_rect = my_viewport.rect()
328
- line_count_changed() if (rect.contains(viewport_rect))
376
+ line_count_changed(-1) if (rect.contains(viewport_rect))
329
377
  viewport_rect.dispose
330
378
  end
331
379