cosmos 3.3.3 → 3.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (109) hide show
  1. checksums.yaml +4 -4
  2. data/.gitattributes +2 -0
  3. data/.travis.yml +2 -1
  4. data/Gemfile +4 -3
  5. data/Manifest.txt +22 -0
  6. data/autohotkey/tools/handbook_creator.ahk +9 -0
  7. data/autohotkey/tools/packet_viewer.ahk +4 -0
  8. data/bin/exchndl20-x64.dll +0 -0
  9. data/bin/exchndl20.dll +0 -0
  10. data/bin/exchndl21-x64.dll +0 -0
  11. data/bin/exchndl21.dll +0 -0
  12. data/bin/exchndl22-x64.dll +0 -0
  13. data/bin/exchndl22.dll +0 -0
  14. data/bin/mgwhelp-x64.dll +0 -0
  15. data/bin/mgwhelp.dll +0 -0
  16. data/cosmos.gemspec +1 -0
  17. data/data/crc.txt +30 -24
  18. data/demo/config/data/crc.txt +3 -3
  19. data/demo/config/tools/handbook_creator/templates/command_packets.html.erb +3 -1
  20. data/demo/config/tools/handbook_creator/templates/telemetry_packets.html.erb +3 -1
  21. data/demo/procedures/cosmos_api_test.rb +1 -1
  22. data/ext/cosmos/ext/low_fragmentation_array/low_fragmentation_array.c +4 -0
  23. data/ext/cosmos/ext/platform/platform.c +22 -2
  24. data/ext/cosmos/ext/structure/structure.c +631 -104
  25. data/ext/cosmos/ext/telemetry/telemetry.c +3 -2
  26. data/lib/cosmos/gui/line_graph/line_graph_drawing.rb +71 -92
  27. data/lib/cosmos/gui/line_graph/overview_graph.rb +1 -1
  28. data/lib/cosmos/gui/qt.rb +38 -24
  29. data/lib/cosmos/gui/text/ruby_editor.rb +1 -1
  30. data/lib/cosmos/packets/binary_accessor.rb +1 -288
  31. data/lib/cosmos/packets/telemetry.rb +2 -1
  32. data/lib/cosmos/script/cmd_tlm_server.rb +110 -0
  33. data/lib/cosmos/script/commands.rb +166 -0
  34. data/lib/cosmos/script/extract.rb +2 -2
  35. data/lib/cosmos/script/limits.rb +108 -0
  36. data/lib/cosmos/script/script.rb +28 -1487
  37. data/lib/cosmos/script/scripting.rb +889 -0
  38. data/lib/cosmos/script/telemetry.rb +174 -0
  39. data/lib/cosmos/script/tools.rb +138 -0
  40. data/lib/cosmos/streams/stream_protocol.rb +9 -6
  41. data/lib/cosmos/system/target.rb +55 -38
  42. data/lib/cosmos/tools/cmd_tlm_server/api.rb +6 -3
  43. data/lib/cosmos/tools/cmd_tlm_server/connections.rb +0 -1
  44. data/lib/cosmos/tools/cmd_tlm_server/gui/interfaces_tab.rb +17 -7
  45. data/lib/cosmos/tools/cmd_tlm_server/interface_thread.rb +15 -4
  46. data/lib/cosmos/tools/handbook_creator/handbook_creator.rb +15 -8
  47. data/lib/cosmos/tools/handbook_creator/handbook_creator_config.rb +41 -13
  48. data/lib/cosmos/tools/packet_viewer/packet_viewer.rb +18 -1
  49. data/lib/cosmos/tools/tlm_viewer/widgets/canvasline_widget.rb +1 -1
  50. data/lib/cosmos/tools/tlm_viewer/widgets/canvaslinevalue_widget.rb +1 -1
  51. data/lib/cosmos/tools/tlm_viewer/widgets/limitsbar_widget.rb +1 -1
  52. data/lib/cosmos/tools/tlm_viewer/widgets/rangebar_widget.rb +1 -1
  53. data/lib/cosmos/top_level.rb +1 -1
  54. data/lib/cosmos/utilities/ruby_lex_utils.rb +1 -1
  55. data/lib/cosmos/version.rb +5 -5
  56. data/spec/gui/line_graph/line_clip_spec.rb +6 -6
  57. data/spec/gui/qt_spec.rb +102 -0
  58. data/spec/interfaces/interface_spec.rb +9 -9
  59. data/spec/interfaces/linc_interface_spec.rb +72 -15
  60. data/spec/interfaces/serial_interface_spec.rb +9 -9
  61. data/spec/interfaces/simulated_target_interface_spec.rb +7 -7
  62. data/spec/interfaces/stream_interface_spec.rb +4 -4
  63. data/spec/interfaces/tcpip_client_interface_spec.rb +8 -8
  64. data/spec/interfaces/tcpip_server_interface_spec.rb +9 -9
  65. data/spec/interfaces/udp_interface_spec.rb +20 -20
  66. data/spec/io/json_drb_spec.rb +4 -4
  67. data/spec/io/raw_logger_pair_spec.rb +20 -20
  68. data/spec/io/raw_logger_spec.rb +3 -3
  69. data/spec/io/tcpip_server_spec.rb +9 -9
  70. data/spec/io/udp_sockets_spec.rb +2 -2
  71. data/spec/io/win32_serial_driver_spec.rb +2 -2
  72. data/spec/packets/binary_accessor_spec.rb +143 -6
  73. data/spec/packets/commands_spec.rb +5 -5
  74. data/spec/packets/limits_spec.rb +15 -15
  75. data/spec/packets/packet_config_spec.rb +19 -19
  76. data/spec/packets/packet_item_limits_spec.rb +3 -3
  77. data/spec/packets/packet_item_spec.rb +4 -4
  78. data/spec/packets/packet_spec.rb +33 -33
  79. data/spec/packets/structure_item_spec.rb +19 -19
  80. data/spec/packets/telemetry_spec.rb +6 -6
  81. data/spec/script/cmd_tlm_server_spec.rb +110 -0
  82. data/spec/script/commands_disconnect_spec.rb +270 -0
  83. data/spec/script/commands_spec.rb +288 -0
  84. data/spec/script/limits_spec.rb +153 -0
  85. data/spec/script/script_spec.rb +32 -696
  86. data/spec/script/scripting_spec.rb +436 -0
  87. data/spec/script/telemetry_spec.rb +130 -0
  88. data/spec/script/tools_spec.rb +117 -0
  89. data/spec/spec_helper.rb +10 -5
  90. data/spec/streams/preidentified_stream_protocol_spec.rb +4 -4
  91. data/spec/streams/serial_stream_spec.rb +8 -8
  92. data/spec/streams/stream_protocol_spec.rb +4 -4
  93. data/spec/streams/tcpip_client_stream_spec.rb +3 -3
  94. data/spec/streams/tcpip_socket_stream_spec.rb +7 -7
  95. data/spec/streams/template_stream_protocol_spec.rb +1 -1
  96. data/spec/system/system_spec.rb +6 -6
  97. data/spec/system/target_spec.rb +2 -0
  98. data/spec/tools/cmd_tlm_server/api_spec.rb +17 -17
  99. data/spec/tools/cmd_tlm_server/cmd_tlm_server_config_spec.rb +5 -5
  100. data/spec/tools/cmd_tlm_server/interface_thread_spec.rb +3 -3
  101. data/spec/top_level/top_level_spec.rb +8 -8
  102. data/spec/utilities/csv_spec.rb +3 -3
  103. data/spec/utilities/message_log_spec.rb +3 -3
  104. data/spec/utilities/ruby_lex_utils_spec.rb +7 -7
  105. data/test/performance/config/tools/launcher/launcher_threads.txt +8 -1
  106. data/test/performance/tools/CmdTlmServerMemProf +1 -1
  107. data/test/performance/tools/TlmGrapherMemProf +19 -0
  108. data/test/performance/tools/TlmGrapherMemProf.bat +59 -0
  109. metadata +38 -2
@@ -171,8 +171,9 @@ static VALUE value(int argc, VALUE* argv, VALUE self)
171
171
  * can be passed which will convert all items the same way. Or
172
172
  * an array of symbols can be passed to control how each item is
173
173
  * converted.
174
- * @return [Array, Array] The first array contains the item values and the
175
- * second their limits state
174
+ * @return [Array, Array, Array] The first array contains the item values, the
175
+ * second their limits state, and the third the limits settings which includes
176
+ * red, yellow, and green (if given) limits values.
176
177
  */
177
178
  static VALUE values_and_limits_states(int argc, VALUE* argv, VALUE self) {
178
179
  VALUE item_array = Qnil;
@@ -33,7 +33,7 @@ module Cosmos
33
33
  calculate_scaling_factors()
34
34
 
35
35
  # Draw overall graph and origin lines
36
- clear_canvas_and_draw_graph_rectangle(@painter)
36
+ draw_graph_background(@painter)
37
37
  draw_origin_lines(@painter)
38
38
 
39
39
  # Draw gridlines and titles
@@ -45,7 +45,6 @@ module Cosmos
45
45
  draw_y_axis_title(@painter, :LEFT)
46
46
  draw_y_axis_title(@painter, :RIGHT)
47
47
 
48
- # Draw legend and lines
49
48
  draw_legend(@painter)
50
49
 
51
50
  draw_lines(@painter, :LEFT)
@@ -54,7 +53,6 @@ module Cosmos
54
53
 
55
54
  # Draws the graph to the screen
56
55
  def draw_graph_to_screen
57
- # Draw frame around graph
58
56
  draw_frame(@painter)
59
57
 
60
58
  # Draw cursor line and popups if present
@@ -64,16 +62,10 @@ module Cosmos
64
62
  draw_error_icon(@painter)
65
63
  end # def draw_graph_to_screen
66
64
 
67
- # Clears the entire canvas and then draws the colored rectangle for the graph
68
- def clear_canvas_and_draw_graph_rectangle(dc)
69
- # Draw graph background
70
- color = Cosmos::getColor(@graph_back_color)
71
- dc.setPen(color)
72
- dc.setBrush(Cosmos.getBrush(@@gradient))
73
- dc.drawRect(@graph_left_x,@graph_top_y,@graph_right_x - @graph_left_x,@graph_bottom_y - @graph_top_y)
74
- # Draw the graph border
75
- dc.addRectColor(@graph_left_x, @graph_top_y, @graph_right_x - @graph_left_x, @graph_bottom_y - @graph_top_y, @label_and_border_color)
76
- end # def clear_canvas_and_draw_graph_rectangle
65
+ # Draws the colored rectangle for the graph
66
+ def draw_graph_background(dc)
67
+ dc.addRectColorFill(@graph_left_x, @graph_top_y, @graph_right_x - @graph_left_x, @graph_bottom_y - @graph_top_y, @label_and_border_color, @@gradient)
68
+ end
77
69
 
78
70
  # Draws origin lines if they fall on the graph
79
71
  def draw_origin_lines(dc)
@@ -93,14 +85,19 @@ module Cosmos
93
85
 
94
86
  # Draws the gridlines for a y-axis
95
87
  def draw_y_axis_grid_lines(dc)
88
+ grid_lines = []
96
89
  @y_grid_lines.each_with_index do |value, index|
97
90
  # Don't draw gridlines that are too close to 0
98
91
  if ((value > (@y_grid_line_scale / 2.0)) || (value < (@y_grid_line_scale / -2.0)))
99
- draw_y_label_and_grid_line(dc, value, index, true)
92
+ grid_lines << draw_y_label(dc, value, index)
100
93
  else
101
- draw_y_label_and_grid_line(dc, 0, index, true)
94
+ grid_lines << draw_y_label(dc, 0, index)
102
95
  end
103
96
  end
97
+ # Now draw all the grid lines so we can use a single Pen for all
98
+ grid_lines.each do |y|
99
+ dc.addLineColor(@graph_left_x, y, @graph_right_x, y, Cosmos::DASHLINE_PEN)
100
+ end
104
101
  end # def draw_y_axis_grid_lines
105
102
 
106
103
  # Calcuate the Y axis labels as well as their width and adjust the size of
@@ -144,10 +141,8 @@ module Cosmos
144
141
  @graph_right_x -= (right_widths.max + GRAPH_SPACER)
145
142
  end
146
143
 
147
- # This function is used to draw a horizontal line on the graph with a label.
148
- # This line is not clipped so the value must fall on the graph. Uses the
149
- # label values calculated in calculate_y_labels.
150
- def draw_y_label_and_grid_line(dc, value, index, show_line)
144
+ # This function is used to draw the y labels.
145
+ def draw_y_label(dc, value, index)
151
146
  left_value = value
152
147
  right_value = value
153
148
  left_text = @left_text[index]
@@ -193,28 +188,29 @@ module Cosmos
193
188
  y + (@font_size / 2))
194
189
  end
195
190
  end
196
-
197
- if show_line and y
198
- dc.addLineColor(@graph_left_x, y, @graph_right_x, y, Cosmos::DASHLINE_PEN)
199
- end
200
-
201
- end # def draw_y_label_and_grid_line
191
+ return y
192
+ end
202
193
 
203
194
  # Draws the gridlines for the x-axis
204
195
  def draw_x_axis_grid_lines(dc)
196
+ grid_lines = []
205
197
  @x_grid_lines.each do |value, label|
206
198
  # If the line has states or is far enough away from the origin
207
199
  if @lines.x_states || ((value > (@x_grid_line_scale / 2.0)) || (value < (@x_grid_line_scale / -2.0)))
208
- draw_x_label_and_grid_line(dc, value, label, true)
200
+ grid_lines << draw_x_label(dc, value, label)
209
201
  else
210
- draw_x_label_and_grid_line(dc, 0, nil, true)
202
+ grid_lines << draw_x_label(dc, 0, nil)
211
203
  end
212
204
  end
205
+ # Now draw all the grid lines so we can use a single Pen for all
206
+ grid_lines.each do |x1, y1, x2, y2|
207
+ dc.addLineColor(x1, y1, x2, y2, Cosmos::DASHLINE_PEN)
208
+ end
213
209
  end # def draw_x_axis_grid_lines
214
210
 
215
- # This function is used to draw a vertical line on the graph with a label.
216
- # This line is not clipped so the value must fall on the graph
217
- def draw_x_label_and_grid_line(dc, value, label, show_line)
211
+ # This function is used to draw the x labels and returns the line
212
+ # positions.
213
+ def draw_x_label(dc, value, label)
218
214
  if label
219
215
  text = label.to_s
220
216
  else
@@ -231,13 +227,8 @@ module Cosmos
231
227
  if (x1 > @graph_right_x)
232
228
  x1 = @graph_right_x
233
229
  end
234
- if show_line
235
- y2 = @graph_top_y
236
- else
237
- y2 = @graph_bottom_y
238
- end
230
+ y2 = @graph_top_y
239
231
  x2 = x1
240
- dc.addLineColor(x1, y1, x2, y2, Cosmos::DASHLINE_PEN)
241
232
 
242
233
  # Only display the label if we have room. This really only affects the
243
234
  # right side of the graph since that's where new grid lines appear. The
@@ -245,10 +236,11 @@ module Cosmos
245
236
  # white space on the right side of the graph.
246
237
  if (x1 == @graph_right_x) || (x1 < (@graph_right_x - (1.25 * text_width)))
247
238
  # Shift the far right label left a bit to eliminate white space
248
- x1 -= text_width / 4 if x1 == @graph_right_x
249
- x1 -= text_width / 2 # center the text
250
- dc.addSimpleTextAt(text, x1, @graph_bottom_y + text_height + GRAPH_SPACER)
239
+ text_x = x1 - text_width / 4 if x1 == @graph_right_x
240
+ text_x = x1 - text_width / 2 # center the text
241
+ dc.addSimpleTextAt(text, text_x, @graph_bottom_y + text_height + GRAPH_SPACER)
251
242
  end
243
+ [x1, y1, x2, y2]
252
244
  end # def draw_x_label_and_grid_line
253
245
 
254
246
  # Converts a x value into text with a max number of characters
@@ -286,7 +278,7 @@ module Cosmos
286
278
  end
287
279
  end
288
280
 
289
- # Draw the overall graph title
281
+ # Draw the overall graph title above the graph
290
282
  def draw_title(dc)
291
283
  if @title
292
284
  metrics = Cosmos.getFontMetrics(@title_font)
@@ -294,9 +286,9 @@ module Cosmos
294
286
  dc.addSimpleTextAt(@title, (self.width / 2) - (metrics.width(@title) / 2), metrics.height)
295
287
  dc.setFont(@font)
296
288
  end
297
- end # def draw_title
289
+ end
298
290
 
299
- # Draws the title for the X-axis
291
+ # Draws the x axis title below the graph
300
292
  def draw_x_axis_title(dc)
301
293
  if @x_axis_title
302
294
  metrics = Cosmos.getFontMetrics(@font)
@@ -306,9 +298,9 @@ module Cosmos
306
298
  (((@graph_right_x - @graph_left_x) / 2) + @graph_left_x) - (text_width / 2),
307
299
  @graph_bottom_y + (2 * text_height) + GRAPH_SPACER)
308
300
  end
309
- end # def draw_x_axis_title
301
+ end
310
302
 
311
- # Draws a title for a Y-axis
303
+ # Draws titles to the left and right of the Y axis
312
304
  def draw_y_axis_title(dc, axis)
313
305
  metrics = Cosmos.getFontMetrics(@font)
314
306
  if axis == :LEFT
@@ -330,58 +322,46 @@ module Cosmos
330
322
  dc.addSimpleTextAt(character, graph_x + ((max_width - cur_width) / 2), start_height + text_height * index)
331
323
  end
332
324
  end
333
- end # def draw_y_axis_title
325
+ end
334
326
 
335
327
  # Draws the legend on the bottom of the graph
336
328
  def draw_legend(dc)
329
+ return if !@show_legend || @lines.empty?
330
+
331
+ text_x, text_y, legend_width, legend_height = get_legend_position()
332
+ if @lines.axes == :BOTH
333
+ draw_legend_text(dc, :LEFT, text_x, text_y, legend_height)
334
+ draw_legend_text(dc, :RIGHT, text_x + (legend_width / 2), text_y, legend_height)
335
+ else
336
+ draw_legend_text(dc, false, text_x, text_y, legend_height)
337
+ end
338
+ end
339
+
340
+ # Calculate the legend x, y, width and height
341
+ def get_legend_position
337
342
  metrics = Cosmos.getFontMetrics(@font)
338
- # Draw Legend
339
- if @show_legend && !@lines.empty?
340
- if @lines.axes == :BOTH
341
- both_axis = true
342
- else
343
- both_axis = false
344
- end
345
- legend_width = 0
346
- @lines.legend.each do |legend_text, color, axis|
347
- text_width = metrics.width(legend_text)
348
- legend_width = text_width if text_width > legend_width
349
- end
350
- legend_width += (GRAPH_SPACER * 2)
351
- legend_width *= 2 if both_axis
352
- legend_graph_x = (self.width - legend_width) / 2
353
-
354
- text_x = legend_graph_x + GRAPH_SPACER
355
- text_y = self.height - metrics.height
356
-
357
- # Draw legend text for each line
358
- if both_axis
359
- left_text_x = text_x
360
- right_text_x = text_x + (legend_width / 2)
361
- left_text_y = text_y
362
- right_text_y = text_y
363
- @lines.legend.reverse_each do |legend_text, color, axis|
364
- if axis == :LEFT
365
- dc.addSimpleTextAt(legend_text, left_text_x, left_text_y, color)
366
- left_text_y -= metrics.height
367
- else
368
- dc.addSimpleTextAt(legend_text, right_text_x, right_text_y, color)
369
- right_text_y -= metrics.height
370
- end
371
- end
372
- if left_text_y < right_text_y
373
- text_y = left_text_y
374
- else
375
- text_y = right_text_y
376
- end
377
- else
378
- @lines.legend.reverse_each do |legend_text, color, axis|
379
- dc.addSimpleTextAt(legend_text, text_x, text_y, color)
380
- text_y -= metrics.height
381
- end
343
+ legend_width = 0
344
+ @lines.legend.each do |legend_text, color, axis|
345
+ text_width = metrics.width(legend_text)
346
+ legend_width = text_width if text_width > legend_width
347
+ end
348
+ legend_width += (GRAPH_SPACER * 2)
349
+ legend_width *= 2 if @lines.axes == :BOTH
350
+ legend_graph_x = (self.width - legend_width) / 2
351
+
352
+ text_x = legend_graph_x + GRAPH_SPACER
353
+ text_y = self.height - metrics.height
354
+ return [text_x, text_y, legend_width, metrics.height]
355
+ end
356
+
357
+ def draw_legend_text(dc, specific_axis, text_x, text_y, line_height)
358
+ @lines.legend.reverse_each do |legend_text, color, axis|
359
+ if !specific_axis || specific_axis == axis
360
+ dc.addSimpleTextAt(legend_text, text_x, text_y, color)
361
+ text_y -= line_height
382
362
  end
383
363
  end
384
- end # def draw_legend
364
+ end
385
365
 
386
366
  # Draws all lines for the given axis
387
367
  # def draw_lines(dc, axis)
@@ -438,9 +418,8 @@ module Cosmos
438
418
  end # unless popups.empty?
439
419
  end
440
420
 
441
- # Draws the overall frame around the canvas
421
+ # Draws the overall frame around the graph, legend, labels, etc
442
422
  def draw_frame(dc)
443
- # Draw Frame Rectangle around canvas
444
423
  dc.addRectColor(0,0,self.width-1,self.height-1, @frame_color)
445
424
  end
446
425
 
@@ -400,7 +400,7 @@ module Cosmos
400
400
 
401
401
  def draw_graph_into_back_buffer
402
402
  # Draw overall graph and origin lines and graph lines
403
- clear_canvas_and_draw_graph_rectangle(@painter)
403
+ draw_graph_background(@painter)
404
404
  draw_origin_lines(@painter)
405
405
  draw_lines(@painter, :LEFT)
406
406
 
@@ -94,6 +94,7 @@ module Cosmos
94
94
  color = nil
95
95
  key = color_r
96
96
  key = key.to_i if key.is_a? Qt::Enum
97
+
97
98
  if color_r && color_g && color_b
98
99
  key = (color_r.to_i << 24) + (color_g.to_i << 16) + (color_b.to_i << 8)
99
100
  end
@@ -112,6 +113,8 @@ module Cosmos
112
113
  end
113
114
 
114
115
  def self.getBrush(color)
116
+ return nil unless color
117
+ return color if color.is_a? Qt::Brush
115
118
  brush = nil
116
119
  color = Cosmos.getColor(color)
117
120
  brush = BRUSHES[color]
@@ -280,10 +283,16 @@ class Qt::TableWidget
280
283
  resizeRowsToContents()
281
284
  setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff)
282
285
  setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff)
283
- setMinimumSize(2*frameWidth() + horizontalHeader.length + verticalHeader.width,
284
- 2*frameWidth() + verticalHeader.length + horizontalHeader.height)
285
- setMaximumSize(2*frameWidth() + horizontalHeader.length + verticalHeader.width,
286
- 2*frameWidth() + verticalHeader.length + horizontalHeader.height)
286
+ setMinimumSize(fullWidth, fullHeight)
287
+ setMaximumSize(fullWidth, fullHeight)
288
+ end
289
+
290
+ def fullWidth
291
+ 2*frameWidth() + horizontalHeader.length + verticalHeader.width
292
+ end
293
+
294
+ def fullHeight
295
+ 2*frameWidth() + verticalHeader.length + horizontalHeader.height
287
296
  end
288
297
  end
289
298
 
@@ -669,47 +678,52 @@ class Qt::ColorListWidget < Qt::ListWidget
669
678
  end
670
679
 
671
680
  class Qt::Painter
681
+ def setPen(pen_color)
682
+ super(Cosmos::getColor(pen_color))
683
+ @pen_color = pen_color
684
+ end
685
+ def setBrush(brush)
686
+ super(Cosmos::getBrush(brush))
687
+ @brush = brush
688
+ end
689
+
672
690
  def addLineColor(x, y, w, h, color = Cosmos::BLACK)
673
- setPenColor(color)
691
+ setPen(color) if color != @pen_color
674
692
  drawLine(x,y,w,h)
675
693
  end
676
694
 
677
695
  def addRectColor(x, y, w, h, color = Cosmos::BLACK)
678
- setPenColor(color)
679
- setBrush(nil)
696
+ setPen(color) if color != @pen_color
697
+ setBrush(nil) if @brush
680
698
  drawRect(x,y,w,h)
681
699
  end
682
700
 
683
- def addRectColorFill(x, y, w, h, color = Cosmos::BLACK)
684
- setPenColor(color)
685
- setBrush(Cosmos.getBrush(color))
701
+ # Note if brush_color is not specified it will be the same as pen_color
702
+ def addRectColorFill(x, y, w, h, pen_color = Cosmos::BLACK, brush_color = nil)
703
+ setPen(pen_color) if pen_color != @pen_color
704
+ brush_color = pen_color unless brush_color
705
+ setBrush(brush_color) if brush_color != @brush
686
706
  drawRect(x,y,w,h)
687
707
  end
688
708
 
689
709
  def addSimpleTextAt(text, x, y, color = Cosmos::BLACK)
690
- setPenColor(color)
710
+ setPen(color) if color != @pen_color
691
711
  drawText(x,y,text)
692
712
  end
693
713
 
694
714
  def addEllipseColor(x, y, w, h, color = Cosmos::BLACK)
695
- setPenColor(color)
696
- setBrush(nil)
715
+ setPen(color) if color != @pen_color
716
+ setBrush(nil) if @brush
697
717
  drawEllipse(x,y,w,h)
698
718
  end
699
719
 
700
- def addEllipseColorFill(x, y, w, h, color = Cosmos::BLACK)
701
- setPenColor(color)
702
- setBrush(Cosmos.getBrush(color))
720
+ # Note if brush_color is not specified it will be the same as pen_color
721
+ def addEllipseColorFill(x, y, w, h, pen_color = Cosmos::BLACK, brush_color = nil)
722
+ setPen(pen_color) if pen_color != @pen_color
723
+ brush_color = pen_color unless brush_color
724
+ setBrush(brush_color) if brush_color != @brush
703
725
  drawEllipse(x,y,w,h)
704
726
  end
705
-
706
- private
707
-
708
- def setPenColor(color)
709
- color = Cosmos::getColor(color)
710
- setPen(color)
711
- end
712
-
713
727
  end
714
728
 
715
729
  class Qt::MatrixLayout < Qt::GridLayout
@@ -363,7 +363,7 @@ module Cosmos
363
363
  number.to_s) # text
364
364
 
365
365
  if @enable_breakpoints and @breakpoints.include?(number)
366
- painter.setBrush(Cosmos.getBrush(Cosmos::RED))
366
+ painter.setBrush(Cosmos::RED)
367
367
  painter.drawEllipse(2,
368
368
  top+2,
369
369
  ellipse_width,
@@ -111,294 +111,7 @@ module Cosmos
111
111
  # @param endianness [Symbol] {ENDIANNESS}
112
112
  # @param overflow [Symbol] {OVERFLOW_TYPES}
113
113
  # @return [Integer] value passed in as a parameter
114
- def self.write(value, bit_offset, bit_size, data_type, buffer, endianness, overflow)
115
- # Save given values of bit offset and bit size
116
- given_bit_offset = bit_offset
117
- given_bit_size = bit_size
118
-
119
- # Handle negative and zero bit sizes
120
- if bit_size <= 0
121
- if data_type == :STRING or data_type == :BLOCK
122
- if given_bit_offset < 0
123
- raise ArgumentError, "negative or zero bit_sizes (#{given_bit_size}) cannot be given with negative bit_offsets (#{given_bit_offset})"
124
- else
125
- bit_size = value.to_s.length * 8
126
- end
127
- else
128
- raise ArgumentError, "bit_size #{given_bit_size} must be positive for data types other than :STRING and :BLOCK"
129
- end
130
- end
131
-
132
- # Handle negative bit offsets
133
- if bit_offset < 0
134
- bit_offset = ((buffer.length * 8) + bit_offset)
135
- raise_buffer_error(:write, buffer, data_type, given_bit_offset, given_bit_size) if bit_offset < 0
136
- end
137
-
138
- # Define bounds of string to access this item
139
- lower_bound = bit_offset / 8
140
- upper_bound = (bit_offset + bit_size - 1) / 8
141
-
142
- # Check for byte alignment
143
- byte_aligned = ((bit_offset % 8) == 0)
144
-
145
- # Sanity check buffer size
146
- if upper_bound >= buffer.length and given_bit_size > 0
147
- # Check special case of little endian bit field
148
- if endianness == :LITTLE_ENDIAN and (data_type == :INT or data_type == :UINT) and !(byte_aligned and (bit_size == 8 or bit_size == 16 or bit_size == 32 or bit_size == 64)) and lower_bound < buffer.length
149
- # Ok little endian bit field
150
- else
151
- raise_buffer_error(:write, buffer, data_type, given_bit_offset, given_bit_size)
152
- end
153
- end
154
-
155
- # Check overflow type
156
- raise "unknown overflow type #{overflow}" unless OVERFLOW_TYPES.include?(overflow)
157
-
158
- case data_type
159
- when :STRING, :BLOCK
160
- #######################################
161
- # Handle :STRING and :BLOCK data types
162
- #######################################
163
-
164
- # Ensure value is the correct type
165
- value = value.to_s
166
-
167
- if byte_aligned
168
- temp = value
169
- if given_bit_size <= 0
170
- end_bytes = -(given_bit_size / 8)
171
- old_upper_bound = buffer.length - 1 - end_bytes
172
- if old_upper_bound < lower_bound
173
- # String was completely empty
174
- if end_bytes > 0
175
- # Preserve bytes at end of buffer
176
- buffer_length = buffer.length
177
- buffer << ZERO_STRING * value.length
178
- buffer[(lower_bound + value.length)..(buffer.length - 1)] = buffer[lower_bound..(buffer_length - 1)]
179
- end
180
- elsif bit_size == 0
181
- # Remove entire string
182
- buffer[lower_bound..old_upper_bound] = ''
183
- elsif upper_bound < old_upper_bound
184
- # Remove extra bytes from old string
185
- buffer[(upper_bound + 1)..old_upper_bound] = ''
186
- elsif upper_bound > old_upper_bound and end_bytes > 0
187
- # Preserve bytes at end of buffer
188
- buffer_length = buffer.length
189
- diff = upper_bound - old_upper_bound
190
- buffer << ZERO_STRING * diff
191
- buffer[(upper_bound + 1)..(buffer.length - 1)] = buffer[(old_upper_bound + 1)..(buffer_length - 1)]
192
- end
193
- else
194
- byte_size = bit_size / 8
195
- if value.length < byte_size
196
- temp = value.ljust(byte_size, ZERO_STRING)
197
- elsif value.length > byte_size
198
- if overflow == :TRUNCATE
199
- temp = value[0..(byte_size - 1)]
200
- else
201
- raise ArgumentError, "value of #{value.length} bytes does not fit into #{byte_size} bytes for data_type #{data_type}"
202
- end
203
- else
204
- temp = value
205
- end
206
- end
207
- buffer[lower_bound..upper_bound] = temp if bit_size != 0
208
- else
209
- raise ArgumentError, "bit_offset #{given_bit_offset} is not byte aligned for data_type #{data_type}"
210
- end
211
-
212
- when :INT, :UINT
213
- ###################################
214
- # Handle :INT and :UINT data types
215
- ###################################
216
-
217
- # Ensure value is the correct type
218
- value = Integer(value)
219
-
220
- if byte_aligned and (bit_size == 8 or bit_size == 16 or bit_size == 32 or bit_size == 64)
221
- ###########################################################
222
- # Handle byte-aligned 8, 16, 32, and 64 bit :INT and :UINT
223
- ###########################################################
224
-
225
- case bit_size
226
- when 8
227
- if data_type == :INT
228
- value = self.check_overflow(value, -128, 127, 255, bit_size, data_type, overflow)
229
- else
230
- value = self.check_overflow(value, 0, 255, 255, bit_size, data_type, overflow)
231
- end
232
- buffer.setbyte(lower_bound, value % 256)
233
-
234
- when 16
235
- if data_type == :INT
236
- value = self.check_overflow(value, -32768, 32767, 65535, bit_size, data_type, overflow)
237
- if endianness == HOST_ENDIANNESS
238
- buffer[lower_bound..upper_bound] = [value].pack(PACK_NATIVE_16_BIT_INT)
239
- else # endianness != HOST_ENDIANNESS
240
- buffer[lower_bound..upper_bound] = [value].pack(PACK_NATIVE_16_BIT_INT).reverse
241
- end
242
- else # data_type == :UINT
243
- value = self.check_overflow(value, 0, 65535, 65535, bit_size, data_type, overflow)
244
- if endianness == :BIG_ENDIAN
245
- buffer[lower_bound..upper_bound] = [value].pack(PACK_BIG_ENDIAN_16_BIT_UINT)
246
- else # endianness == :LITTLE_ENDIAN
247
- buffer[lower_bound..upper_bound] = [value].pack(PACK_LITTLE_ENDIAN_16_BIT_UINT)
248
- end
249
- end
250
-
251
- when 32
252
- if data_type == :INT
253
- # Note signed integers must allow up to the maximum unsigned value to support values given in hex
254
- value = self.check_overflow(value, -2147483648, 2147483647, 4294967295, bit_size, data_type, overflow)
255
- if endianness == HOST_ENDIANNESS
256
- buffer[lower_bound..upper_bound] = [value].pack(PACK_NATIVE_32_BIT_INT)
257
- else # endianness != HOST_ENDIANNESS
258
- buffer[lower_bound..upper_bound] = [value].pack(PACK_NATIVE_32_BIT_INT).reverse
259
- end
260
- elsif data_type == :UINT
261
- value = self.check_overflow(value, 0, 4294967295, 4294967295, bit_size, data_type, overflow)
262
- if endianness == :BIG_ENDIAN
263
- buffer[lower_bound..upper_bound] = [value].pack(PACK_BIG_ENDIAN_32_BIT_UINT)
264
- else # endianness == :LITTLE_ENDIAN
265
- buffer[lower_bound..upper_bound] = [value].pack(PACK_LITTLE_ENDIAN_32_BIT_UINT)
266
- end
267
- end
268
-
269
- when 64
270
- if data_type == :INT
271
- # Note signed integers must allow up to the maximum unsigned value to support values given in hex
272
- value = self.check_overflow(value, -9223372036854775808, 9223372036854775807, 18446744073709551615, bit_size, data_type, overflow)
273
- if endianness == HOST_ENDIANNESS
274
- buffer[lower_bound..upper_bound] = [value].pack(PACK_NATIVE_64_BIT_INT)
275
- else # endianness != HOST_ENDIANNESS
276
- buffer[lower_bound..upper_bound] = [value].pack(PACK_NATIVE_64_BIT_INT).reverse
277
- end
278
- elsif data_type == :UINT
279
- value = self.check_overflow(value, 0, 18446744073709551615, 18446744073709551615, bit_size, data_type, overflow)
280
- if endianness == HOST_ENDIANNESS
281
- buffer[lower_bound..upper_bound] = [value].pack(PACK_NATIVE_64_BIT_UINT)
282
- else # endianness != HOST_ENDIANNESS
283
- buffer[lower_bound..upper_bound] = [value].pack(PACK_NATIVE_64_BIT_UINT).reverse
284
- end
285
- end
286
- end
287
-
288
- else
289
- ##################################
290
- # Handle :INT and :UINT Bitfields
291
- ##################################
292
-
293
- if data_type == :INT
294
- # Note signed integers must allow up to the maximum unsigned value to support values given in hex
295
- if bit_size > 1
296
- min_value = -(2 ** (bit_size - 1))
297
- max_value = -min_value - 1
298
- hex_max_value = (2 ** bit_size) - 1
299
- else
300
- min_value = -1
301
- max_value = 1
302
- hex_max_value = 1
303
- end
304
- value = self.check_overflow(value, min_value, max_value, hex_max_value, bit_size, data_type, overflow)
305
- else
306
- max_value = (2 ** bit_size) - 1
307
- value = self.check_overflow(value, 0, max_value, max_value, bit_size, data_type, overflow)
308
- end
309
-
310
- # Extract Existing Data
311
- if endianness == :LITTLE_ENDIAN
312
- # Bitoffset always refers to the most significant bit of a bitfield
313
- num_bytes = (((bit_offset % 8) + bit_size - 1) / 8) + 1
314
- upper_bound = bit_offset / 8
315
- lower_bound = upper_bound - num_bytes + 1
316
-
317
- if lower_bound < 0
318
- raise ArgumentError, "LITTLE_ENDIAN bitfield with bit_offset #{given_bit_offset} and bit_size #{given_bit_size} is invalid"
319
- end
320
-
321
- temp_data = buffer[lower_bound..upper_bound].reverse
322
- else
323
- temp_data = buffer[lower_bound..upper_bound]
324
- end
325
-
326
- # Determine temp upper bound
327
- temp_upper = upper_bound - lower_bound
328
-
329
- # Determine Values needed to Handle Bitfield
330
- start_bits = bit_offset % 8
331
- start_mask = (0xFF << (8 - start_bits))
332
- total_bits = (temp_upper + 1) * 8
333
- end_bits = total_bits - start_bits - bit_size
334
- end_mask = ~(0xFF << end_bits)
335
-
336
- # Add in Start Bits
337
- temp = temp_data.getbyte(0) & start_mask
338
-
339
- # Adjust value to correct number of bits
340
- temp_mask = (2 ** bit_size) - 1
341
- temp_value = value.to_i & temp_mask
342
-
343
- # Add in New Data
344
- temp = (temp << (bit_size - (8 - start_bits))) + temp_value
345
-
346
- # Add in Remainder of Existing Data
347
- temp = (temp << end_bits) + (temp_data.getbyte(temp_upper) & end_mask)
348
-
349
- # Extract into an array of bytes
350
- temp_array = []
351
- (0..temp_upper).each { temp_array.insert(0, (temp & 0xFF)); temp = temp >> 8 }
352
-
353
- # Store into buffer
354
- if endianness == :LITTLE_ENDIAN
355
- buffer[lower_bound..upper_bound] = temp_array.pack(PACK_8_BIT_UINT_ARRAY).reverse
356
- else
357
- buffer[lower_bound..upper_bound] = temp_array.pack(PACK_8_BIT_UINT_ARRAY)
358
- end
359
- end
360
-
361
- when :FLOAT
362
- ##########################
363
- # Handle :FLOAT data type
364
- ##########################
365
-
366
- # Ensure value is the correct type
367
- value = Float(value)
368
-
369
- if byte_aligned
370
- case bit_size
371
- when 32
372
- if endianness == :BIG_ENDIAN
373
- buffer[lower_bound..upper_bound] = [value].pack(PACK_BIG_ENDIAN_32_BIT_FLOAT)
374
- else # endianness == :LITTLE_ENDIAN
375
- buffer[lower_bound..upper_bound] = [value].pack(PACK_LITTLE_ENDIAN_32_BIT_FLOAT)
376
- end
377
-
378
- when 64
379
- if endianness == :BIG_ENDIAN
380
- buffer[lower_bound..upper_bound] = [value].pack(PACK_BIG_ENDIAN_64_BIT_FLOAT)
381
- else # endianness == :LITTLE_ENDIAN
382
- buffer[lower_bound..upper_bound] = [value].pack(PACK_LITTLE_ENDIAN_64_BIT_FLOAT)
383
- end
384
-
385
- else
386
- raise ArgumentError, "bit_size is #{given_bit_size} but must be 32 or 64 for data_type #{data_type}"
387
- end
388
- else
389
- raise ArgumentError, "bit_offset #{given_bit_offset} is not byte aligned for data_type #{data_type}"
390
- end
391
-
392
- else
393
- ############################
394
- # Handle Unknown data types
395
- ############################
396
-
397
- raise ArgumentError, "data_type #{data_type} is not recognized"
398
- end
399
-
400
- value
401
- end # def self.write
114
+ # def self.write(value, bit_offset, bit_size, data_type, buffer, endianness, overflow)
402
115
 
403
116
  # Reads an array of binary data of any data type from a buffer
404
117
  #