Class: RNDK::Graph

Inherits:
Widget show all
Defined in:
lib/rndk/graph.rb

Overview

TODO Fix how this widget is displayed onscreen.

Signals

For info, see Signals section on Widget class.

:before_set_data

  • when: right before Graph#set_values fix the new values into the widget.
  • argument: The new data to be fixed
  • effect when return false: Interrupt fixing the data, old data is kept.

:after_set_data

  • when: right after Graph#set_values does it's job.
  • argument: The new data as an argument.

Instance Attribute Summary

Attributes inherited from Widget

#BXAttr, #HZChar, #LLChar, #LRChar, #ULChar, #URChar, #VTChar, #accepts_focus, #binding_list, #border_size, #box, #exit_type, #has_focus, #is_visible, #screen, #screen_index, #supported_signals, #widget_type

Instance Method Summary collapse

Methods inherited from Widget

#Screen_XPOS, #Screen_YPOS, #after_processing, #before_processing, #bind_key, #bind_signal, #bindable_widget, #clean_bindings, #clean_title, #draw_title, #focus, #get_box, #getch, #inject, #is_bound?, #refresh_data, #run_key_binding, #run_signal_binding, #save_data, #setBXattr, #setHZchar, #setLLchar, #setLRchar, #setULchar, #setURchar, #setVTchar, #set_box, #set_exit_type, #set_title, #unbind_key, #unfocus, #valid?, #valid_type?

Constructor Details

#initialize(screen, config = {}) ⇒ Graph

Returns a new instance of Graph.



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
# File 'lib/rndk/graph.rb', line 26

def initialize(screen, config={})
  super()
  @widget_type = :graph
  @supported_signals += [:before_set_data, :after_set_data]

  x      = 0
  y      = 0
  width  = 0
  height = 0
  title  = "  graph"  # MUST HAVE TWO SPACES BECAUSE OF FUCK
  xtitle = "x"
  ytitle = "y"
  box    = true

  config.each do |key, val|
    x      = val if key == :x
    y      = val if key == :y
    width  = val if key == :width
    height = val if key == :height
    title  = val if key == :title
    xtitle = val if key == :xtitle
    ytitle = val if key == :ytitle
    box    = val if key == :box
  end

  parent_width = Ncurses.getmaxx screen.window
  parent_height = Ncurses.getmaxy screen.window

  self.set_box(false)

  box_height = RNDK.set_widget_dimension(parent_height, height, 3)
  box_width = RNDK.set_widget_dimension(parent_width, width, 0)
  box_width = self.set_title(title, box_width)
  box_height += @title_lines
  box_width = [parent_width, box_width].min
  box_height = [parent_height, box_height].min

  # Rejustify the x and y positions if we need to
  xtmp = [x]
  ytmp = [y]
  RNDK.alignxy(screen.window, xtmp, ytmp, box_width, box_height)
  xpos = xtmp[0]
  ypos = ytmp[0]

  # Create the widget pointer
  @screen = screen
  @parent = screen.window
  @win = Ncurses.newwin(box_height, box_width, ypos, xpos)
  @box_height = box_height
  @box_width = box_width
  @minx = 0
  @maxx = 0
  @xscale = 0
  @yscale = 0
  @count = 0
  @display_type = :LINE
  @box = box

  if @win.nil?
    self.destroy
    return nil
  end
  Ncurses.keypad(@win, true)

  # Translate the X axis title string to a chtype array
  if !(xtitle.nil?) && xtitle.size > 0
    xtitle_len = []
    xtitle_pos = []
    @xtitle = RNDK.char2Chtype(xtitle, xtitle_len, xtitle_pos)
    @xtitle_len = xtitle_len[0]
    @xtitle_pos = RNDK.justifyString(@box_height,
                                    @xtitle_len, xtitle_pos[0])
  else
    xtitle_len = []
    xtitle_pos = []
    @xtitle = RNDK.char2Chtype("<C></5>X Axis", xtitle_len, xtitle_pos)
    @xtitle_len = title_len[0]
    @xtitle_pos = RNDK.justifyString(@box_height,
                                    @xtitle_len, xtitle_pos[0])
  end

  # Translate the Y Axis title string to a chtype array
  if !(ytitle.nil?) && ytitle.size > 0
    ytitle_len = []
    ytitle_pos = []
    @ytitle = RNDK.char2Chtype(ytitle, ytitle_len, ytitle_pos)
    @ytitle_len = ytitle_len[0]
    @ytitle_pos = RNDK.justifyString(@box_width, @ytitle_len, ytitle_pos[0])
  else
    ytitle_len = []
    ytitle_pos = []
    @ytitle = RNDK.char2Chtype("<C></5>Y Axis", ytitle_len, ytitle_pos)
    @ytitle_len = ytitle_len[0]
    @ytitle_pos = RNDK.justifyString(@box_width, @ytitle_len, ytitle_pos[0])
  end

  @graph_char = 0
  @values = []

  screen.register(@widget_type, self)
end

Instance Method Details

#activate(actions = []) ⇒ Object

This was added for the builder.



129
130
131
# File 'lib/rndk/graph.rb', line 129

def activate(actions=[])
  self.draw
end

#destroyObject



421
422
423
424
425
426
# File 'lib/rndk/graph.rb', line 421

def destroy
  self.clean_title
  self.clean_bindings
  @screen.unregister self
  RNDK.window_delete(@win)
end

#draw(box = false) ⇒ Object

Draw the graph widget



324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
# File 'lib/rndk/graph.rb', line 324

def draw(box=false)
  adj = 2 + (if @xtitle.nil? || @xtitle.size == 0 then 0 else 1 end)
  spacing = 0
  attrib = ' '.ord | RNDK::Color[:reverse]

  if box
    Draw.drawObjBox(@win, self)
  end

  # Draw in the vertical axis
  Draw.drawLine(@win,
                2,
                @title_lines + 1,
                2,
                @box_height - 3,
                Ncurses::ACS_VLINE)

  # Draw in the horizontal axis
  Draw.drawLine(@win,
                3,
                @box_height - 3,
                @box_width,
                @box_height - 3,
                Ncurses::ACS_HLINE)

  self.draw_title(@win)

  # Draw in the X axis title.
  if !(@xtitle.nil?) && @xtitle.size > 0
    Draw.writeChtype(@win, 0, @xtitle_pos, @xtitle, RNDK::VERTICAL, 0, @xtitle_len)
    attrib = @xtitle[0] & RNDK::Color[:extract]
  end

  # Draw in the X axis high value
  temp = "%d" % [@maxx]
  Draw.writeCharAttrib(@win, 1, @title_lines + 1, temp, attrib,
                       RNDK::VERTICAL, 0, temp.size)

  # Draw in the X axis low value.
  temp = "%d" % [@minx]
  Draw.writeCharAttrib(@win, 1, @box_height - 2 - temp.size, temp, attrib,
                       RNDK::VERTICAL, 0, temp.size)

  # Draw in the Y axis title
  if !(@ytitle.nil?) && @ytitle.size > 0
    Draw.writeChtype(@win, @ytitle_pos, @box_height - 1, @ytitle,
                     RNDK::HORIZONTAL, 0, @ytitle_len)
  end

  # Draw in the Y axis high value.
  temp = "%d" % [@count]
  Draw.writeCharAttrib(@win, @box_width - temp.size - adj,
                       @box_height - 2, temp, attrib, RNDK::HORIZONTAL, 0, temp.size)

  # Draw in the Y axis low value.
  Draw.writeCharAttrib(@win, 3, @box_height - 2, "0", attrib,
                       RNDK::HORIZONTAL, 0, "0".size)

  # If the count is zero then there aren't any points.
  if @count == 0
    Ncurses.wrefresh @win
    return
  end

  spacing = (@box_width - 3) / @count  # FIXME magic number (TITLE_LM)

  # Draw in the graph line/plot points.
  (0...@count).each do |y|
    colheight = (@values[y] / @xscale) - 1
    # Add the marker on the Y axis.
    Ncurses.mvwaddch(@win, @box_height - 3, (y + 1) * spacing + adj,
                     Ncurses::ACS_TTEE)

    # If this is a plot graph, all we do is draw a dot.
    if @display_type == :PLOT
      xpos = @box_height - 4 - colheight
      ypos = (y + 1) * spacing + adj
      Ncurses.mvwaddch(@win, xpos, ypos, @graph_char[y])
    else
      (0..@yscale).each do |x|
        xpos = @box_height - 3
        ypos = (y + 1) * spacing - adj
        Draw.drawLine(@win, ypos, xpos - colheight, ypos, xpos,
                      @graph_char[y])
      end
    end
  end

  # Draw in the axis corners.
  Ncurses.mvwaddch(@win, @title_lines, 2, Ncurses::ACS_URCORNER)
  Ncurses.mvwaddch(@win, @box_height - 3, 2, Ncurses::ACS_LLCORNER)
  Ncurses.mvwaddch(@win, @box_height - 3, @box_width, Ncurses::ACS_URCORNER)

  # Refresh and lets see it
  Ncurses.wrefresh @win
end

#eraseObject



428
429
430
431
432
# File 'lib/rndk/graph.rb', line 428

def erase
  if self.valid?
    RNDK.window_erase(@win)
  end
end

#getCharacter(index) ⇒ Object



267
268
269
# File 'lib/rndk/graph.rb', line 267

def getCharacter(index)
  return graph_char[index]
end

#getCharactersObject



241
242
243
# File 'lib/rndk/graph.rb', line 241

def getCharacters
  return @graph_char
end

#getDisplayTypeObject



276
277
278
# File 'lib/rndk/graph.rb', line 276

def getDisplayType
  @display_type
end

#getValue(index) ⇒ Object



224
225
226
# File 'lib/rndk/graph.rb', line 224

def getValue(index)
  if index >= 0 && index < @count then @values[index] else 0 end
end

#getValues(size) ⇒ Object



198
199
200
201
# File 'lib/rndk/graph.rb', line 198

def getValues(size)
  size << @count
  @values
end

#move(x, y, relative, refresh_flag) ⇒ Object

Move the graph field to the given location.



286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
# File 'lib/rndk/graph.rb', line 286

def move(x, y, relative, refresh_flag)
  current_x = Ncurses.getbegx(@win)
  current_y = Ncurses.getbegy(@win)
  xpos = x
  ypos = y

  # If this is a relative move, then we will adjust where we want
  # to move to
  if relative
    xpos = Ncurses.getbegx(@win) + x
    ypos = Ncurses.getbegy(@win) + y
  end

  # Adjust the window if we need to.
  xtmp = [xpos]
  tymp = [ypos]
  RNDK.alignxy(@screen.window, xtmp, ytmp, @box_width, @box_height)
  xpos = xtmp[0]
  ypos = ytmp[0]

  # Get the difference
  xdiff = current_x - xpos
  ydiff = current_y - ypos

  # Move the window to the new location.
  RNDK.window_move(@win, -xdiff, -ydiff)
  RNDK.window_move(@shadow_win, -xdiff, -ydiff)

  # Touch the windows so they 'move'.
  RNDK.window_refresh(@screen.window)

  # Reraw the windowk if they asked for it
  if refresh_flag
    self.draw
  end
end

#positionObject



434
435
436
# File 'lib/rndk/graph.rb', line 434

def position
  super(@win)
end

#set(values, graph_char, start_at_zero, display_type) ⇒ Object

Set multiple attributes of the widget



134
135
136
137
138
139
# File 'lib/rndk/graph.rb', line 134

def set(values, graph_char, start_at_zero, display_type)
  ret = self.set_values(values, start_at_zero)
  self.setCharacters(graph_char)
  self.setDisplayType(display_type)
  return ret
end

#set_bg_color(attrib) ⇒ Object

Set the background attribute of the widget.



281
282
283
# File 'lib/rndk/graph.rb', line 281

def set_bg_color(attrib)
  Ncurses.wbkgd(@win, attrib)
end

#set_scalesObject

Set the scale factors for the graph after wee have loaded new values.



142
143
144
145
146
147
148
149
150
151
152
# File 'lib/rndk/graph.rb', line 142

def set_scales
  @xscale = (@maxx - @minx) / [1, @box_height - @title_lines - 5].max
  if @xscale <= 0
    @xscale = 1
  end

  @yscale = (@box_width - 4) / [1, @count].max
  if @yscale <= 0
    @yscale = 1
  end
end

#set_value(index, value, start_at_zero) ⇒ Object

Set the value of the graph at the given index.



204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
# File 'lib/rndk/graph.rb', line 204

def set_value(index, value, start_at_zero)
  # Make sure the index is within range.
  if index < 0 || index >= @count
    return false
  end

  # Set the min, max, and value for the graph
  @minx = [value, @minx].min
  @maxx = [value, @maxx].max
  @values[index] = value

  # Check the start at zero status
  if start_at_zero
    @minx = 0
  end

  self.set_scales
  true
end

#set_values(values, start_at_zero) ⇒ Object

Set the values of the graph.



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
193
194
195
196
# File 'lib/rndk/graph.rb', line 155

def set_values(values, start_at_zero)
  count = values.size

  min = 2**30
  max = -2**30

  # Make sure everything is happy.
  if count < 0
    return false
  end

  keep_going = self.run_signal_binding(:before_set_data)
  return if not keep_going

  if !(@values.nil?) && @values.size > 0
    @values = []
    @count = 0
  end

  # Copy the X values
  values.each do |value|
    min = [value, @minx].min
    max = [value, @maxx].max

    # Copy the value.
    @values << value
  end

  # Keep the count and min/max values
  @count = count
  @minx = min
  @maxx = max

  # Check the start at zero status.
  if start_at_zero
    @minx = 0
  end

  self.set_scales
  self.run_signal_binding(:after_set_data)
  true
end

#setCharacter(index, character) ⇒ Object

Set the character of the graph widget of the given index.



246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
# File 'lib/rndk/graph.rb', line 246

def setCharacter(index, character)
  # Make sure the index is within range
  if index < 0 || index > @count
    return false
  end

  # Convert the string given to us
  char_count = []
  new_tokens = RNDK.char2Chtype(character, char_count, [])

  # Check if the number of characters back is the same as the number
  # of elements in the list.
  if char_count[0] != @count
    return false
  end

  # Everything OK so far. Set the value of the array.
  @graph_char[index] = new_tokens[0]
  return true
end

#setCharacters(characters) ⇒ Object

Set the characters of the graph widget.



229
230
231
232
233
234
235
236
237
238
239
# File 'lib/rndk/graph.rb', line 229

def setCharacters(characters)
  char_count = []
  new_tokens = RNDK.char2Chtype(characters, char_count, [])

  if char_count[0] != @count
    return false
  end

  @graph_char = new_tokens
  return true
end

#setDisplayType(type) ⇒ Object

Set the display type of the graph.



272
273
274
# File 'lib/rndk/graph.rb', line 272

def setDisplayType(type)
  @display_type = type
end