ncumbra 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,71 @@
1
+ # ----------------------------------------------------------------------------- #
2
+ # File: radiobutton.rb
3
+ # Description: a member of a group of buttons, only one can be selected at a time.
4
+ # Author: j kepler http://github.com/mare-imbrium/canis/
5
+ # Date: 2018-04-02 - 10:37
6
+ # License: MIT
7
+ # Last update: 2018-04-03 14:22
8
+ # ----------------------------------------------------------------------------- #
9
+ # radiobutton.rb Copyright (C) 2012-2018 j kepler
10
+
11
+ module Umbra
12
+ ##
13
+ # A selectable button that has a text value. It is based on a Variable that
14
+ # is shared by other radio buttons. Only one is selected at a time, unlike checkbox
15
+ # +text+ is the value to display, which can include an ampersand for a hotkey
16
+ # +value+ is the value returned if selected, which usually is similar to text (or a short word)
17
+ # +width+ is helpful if placing the brackets to right of text, used to align round brackets
18
+ # By default, radio buttons place the button on the left of the text.
19
+ #
20
+ # Typically, the variable's update_command is passed a block to execute whenever any of the
21
+ # radiobuttons of this group is fired.
22
+
23
+ class RadioButton < ToggleButton
24
+ attr_accessor :align_right # the button will be on the right
25
+ attr_accessor :button_group # group that this button belongs to.
26
+
27
+ def initialize config={}, &block
28
+ @surround_chars = ['(', ')'] if @surround_chars.nil?
29
+ super
30
+ $log.warn "XXX: FIXME Please set 'value' for radiobutton. If not sure, try setting it to the same value as 'text'" unless @value
31
+ @value ||= @text
32
+ end
33
+
34
+ # all radio buttons will return the value of the selected value, not the offered value
35
+ def getvalue
36
+ @button_group.value
37
+ end
38
+
39
+ def getvalue_for_paint
40
+ buttontext = getvalue() == @value ? "o" : " "
41
+ $log.debug "called get_value_for paint for buttong #{@value} :#{buttontext} "
42
+ dtext = @width.nil? ? text : "%-*s" % [@width, text]
43
+ if @align_right
44
+ @text_offset = 0
45
+ @col_offset = dtext.length + @surround_chars[0].length + 1
46
+ return "#{dtext} " + @surround_chars[0] + buttontext + @surround_chars[1]
47
+ else
48
+ pretext = @surround_chars[0] + buttontext + @surround_chars[1]
49
+ @text_offset = pretext.length + 1
50
+ @col_offset = @surround_chars[0].length
51
+ return pretext + " #{dtext}"
52
+ end
53
+ end
54
+
55
+ def toggle
56
+ fire
57
+ end
58
+
59
+ ##
60
+ # If user has pressed on this then set the group to this button.
61
+ def checked tf
62
+
63
+ if @button_group.value == value
64
+ @button_group.value = ""
65
+ else
66
+ @button_group.value = value
67
+ end
68
+ end
69
+
70
+ end # class radio
71
+ end # module
@@ -0,0 +1,417 @@
1
+ # ----------------------------------------------------------------------------- #
2
+ # File: textbox.rb
3
+ # Description: a multiline text view
4
+ # Author: j kepler http://github.com/mare-imbrium/canis/
5
+ # Date: 2018-03-24 - 12:39
6
+ # License: MIT
7
+ # Last update: 2018-04-20 12:58
8
+ # ----------------------------------------------------------------------------- #
9
+ # textbox.rb Copyright (C) 2012-2018 j kepler
10
+ ## TODO -----------------------------------
11
+ # improve the object sent when row change or cursor movement
12
+ #
13
+ #
14
+ # ----------------------------------------
15
+ ## CHANGELOG
16
+ #
17
+ # ----------------------------------------
18
+ require 'umbra/widget'
19
+ module Umbra
20
+ class Textbox < Widget
21
+ attr_reader :list # list containing data
22
+ attr_accessor :file_name # filename passed in for reading
23
+ attr_accessor :selection_key # key used to select a row
24
+ attr_accessor :selected_index # row selected, may change to plural
25
+ attr_accessor :selected_color_pair # row selected color_pair
26
+ attr_accessor :selected_attr # row selected color_pair
27
+ #attr_accessor :cursor # position of cursor in line ??
28
+ =begin
29
+ attr_accessor :selected_mark # row selected character
30
+ attr_accessor :unselected_mark # row unselected character (usually blank)
31
+ attr_accessor :current_mark # row current character (default is >)
32
+ =end
33
+
34
+ def initialize config={}, &block
35
+ @focusable = false # will only be set true if data is set
36
+ @editable = false
37
+ @pstart = 0 # which row does printing start from
38
+ @current_index = 0 # index of row on which cursor is
39
+ @selected_index = nil # index of row selected
40
+ @selection_key = 0 # presently no selection. Actually 0 is Ctrl-Space.
41
+ @highlight_attr = FFI::NCurses::A_BOLD
42
+ @to_print_border = false
43
+ @row_offset = 0
44
+ @col_offset = 0
45
+ @pcol = 0
46
+ @curpos = 0 # current cursor position in buffer (NOT screen/window/field)
47
+ =begin
48
+
49
+ @selected_color_pair = CP_RED
50
+ @selected_attr = REVERSE
51
+ @selected_mark = 'x' # row selected character
52
+ @unselected_mark = ' ' # row unselected character (usually blank)
53
+ @current_mark = '>' # row current character (default is >)
54
+ =end
55
+ register_events([:ENTER_ROW, :LEAVE_ROW, :CURSOR_MOVE]) #
56
+ super
57
+
58
+ map_keys
59
+ # internal width and height
60
+ @repaint_required = true
61
+ end
62
+ def _calculate_dimensions
63
+ @int_width = @width
64
+ @int_height = @height # used here only
65
+ @scroll_lines ||= @int_height/2 # fix these to be perhaps half and one of ht
66
+ @page_lines = @int_height
67
+ @calculate_dimensions = true
68
+ end
69
+ # set list of data to be displayed.
70
+ # NOTE this can be called again and again, so we need to take care of change in size of data
71
+ # as well as things like current_index and selected_index or indices.
72
+ def list=(alist)
73
+ if !alist or alist.size == 0
74
+ self.focusable=(false)
75
+ else
76
+ self.focusable=(true)
77
+ end
78
+ @list = alist
79
+ @repaint_required = true
80
+ @pstart = @current_index = 0
81
+ @selected_index = nil
82
+ @focusable = true # too late since form is not rechecking its array
83
+ end
84
+ def file_name=(fp)
85
+ raise "File #{fp} not readable" unless File.readable? fp
86
+ return Dir.new(fp).entries if File.directory? fp
87
+ case File.extname(fp)
88
+ when '.tgz','.gz'
89
+ cmd = "tar -ztvf #{fp}"
90
+ content = %x[#{cmd}]
91
+ when '.zip'
92
+ cmd = "unzip -l #{fp}"
93
+ content = %x[#{cmd}]
94
+ when '.jar', '.gem'
95
+ cmd = "tar -tvf #{fp}"
96
+ content = %x[#{cmd}]
97
+ when '.png', '.out','.jpg', '.gif','.pdf'
98
+ content = "File #{fp} not displayable"
99
+ when '.sqlite'
100
+ cmd = "sqlite3 #{fp} 'select name from sqlite_master;'"
101
+ content = %x[#{cmd}]
102
+ else
103
+ #content = File.open(fp,"r").readlines # this keeps newlines which mess with output
104
+ content = File.open(fp,"r").read.split("\n")
105
+ end
106
+ self.list = content
107
+ raise "list not set" unless @list
108
+
109
+ end
110
+
111
+ def repaint
112
+ _calculate_dimensions unless @calculate_dimensions
113
+ return unless @repaint_required
114
+ return unless @list
115
+ win = @graphic
116
+ r,c = @row, @col
117
+ _attr = @attr || NORMAL
118
+ _color = @color_pair || CP_WHITE
119
+ #_bordercolor = @border_color_pair || CP_BLUE
120
+ rowpos = 1
121
+ coffset = 0
122
+ #width = win.width-1
123
+ width = @width
124
+ files = @list
125
+
126
+ #ht = win.height-2
127
+ ht = @height
128
+ cur = @current_index
129
+ st = pstart = @pstart # previous start
130
+ pend = pstart + ht -1 #- previous end
131
+ if cur > pend
132
+ st = (cur -ht) + 1 #+
133
+ elsif cur < pstart
134
+ st = cur
135
+ end
136
+ $log.debug "LISTBOX: cur = #{cur} st = #{st} pstart = #{pstart} pend = #{pend} listsize = #{@list.size} "
137
+ hl = cur
138
+ y = 0
139
+ ctr = 0
140
+ filler = " "*(width)
141
+ files.each_with_index {|f, y|
142
+ next if y < st
143
+ colr = CP_WHITE # white on bg -1
144
+ mark = @unselected_mark
145
+ if y == hl
146
+ attr = @highlight_attr #FFI::NCurses::A_REVERSE
147
+ mark = @current_mark
148
+ rowpos = ctr
149
+ else
150
+ attr = FFI::NCurses::A_NORMAL
151
+ end
152
+ if y == @selected_index
153
+ colr = @selected_color_pair
154
+ attr = @selected_attr
155
+ mark = @selected_mark
156
+ end
157
+ #ff = "#{mark} #{f}"
158
+ ff = f
159
+ if ff
160
+ if ff.size > width
161
+ #ff = ff[0...width]
162
+ # pcol can be greater than width then we get null
163
+ if @pcol < ff.size
164
+ ff = ff[@pcol..@pcol+width-1]
165
+ else
166
+ ff = ""
167
+ end
168
+ else
169
+ if @pcol < ff.size
170
+ ff = ff[@pcol..-1]
171
+ else
172
+ ff = ""
173
+ end
174
+ end
175
+ end
176
+ ff = "" unless ff
177
+
178
+ win.printstring(ctr + r, coffset+c, filler, colr )
179
+ win.printstring(ctr + r, coffset+c, ff, colr, attr)
180
+ ctr += 1
181
+ @pstart = st
182
+ break if ctr >= ht #-
183
+ }
184
+ ## if counter < ht then we need to clear the rest in case there was data earlier {{{
185
+ if ctr < ht
186
+ while ctr < ht
187
+ win.printstring(ctr + r, coffset+c, filler, _color )
188
+ ctr += 1
189
+ end
190
+ end # }}}
191
+ @row_offset = rowpos
192
+ #@col_offset = coffset # this way form can pick it up XXX can't override it like this
193
+ @repaint_required = false
194
+ end
195
+
196
+ def getvalue
197
+ @list
198
+ end
199
+
200
+ # ensure text has been passed or action
201
+ def getvalue_for_paint
202
+ raise
203
+ ret = getvalue
204
+ #@text_offset = @surround_chars[0].length
205
+ #@surround_chars[0] + ret + @surround_chars[1]
206
+ end
207
+
208
+
209
+ def map_keys
210
+ return if @keys_mapped
211
+ bind_keys([?k,FFI::NCurses::KEY_UP], "Up") { cursor_up }
212
+ bind_keys([?j,FFI::NCurses::KEY_DOWN], "Down") { cursor_down }
213
+ bind_keys([?l,FFI::NCurses::KEY_RIGHT], "Right") { cursor_forward }
214
+ bind_keys([?h,FFI::NCurses::KEY_LEFT], "Left") { cursor_backward }
215
+ bind_key(?g, 'goto_start') { goto_start }
216
+ bind_key(?G, 'goto_end') { goto_end }
217
+ bind_key(FFI::NCurses::KEY_CTRL_A, 'cursor_home') { cursor_home }
218
+ bind_key(FFI::NCurses::KEY_CTRL_E, 'cursor_end') { cursor_end }
219
+ bind_key(FFI::NCurses::KEY_CTRL_F, 'page_forward') { page_forward }
220
+ bind_key(32, 'page_forward') { page_forward }
221
+ bind_key(FFI::NCurses::KEY_CTRL_B, 'page_backward'){ page_backward }
222
+ bind_key(FFI::NCurses::KEY_CTRL_U, 'scroll_up') { scroll_up }
223
+ bind_key(FFI::NCurses::KEY_CTRL_D, 'scroll_down') { scroll_down }
224
+ @keys_mapped = true
225
+ end
226
+
227
+ # listbox key handling
228
+ def handle_key ch
229
+ return :UNHANDLED unless @list
230
+ # save old positions so we know movement has happened
231
+ old_current_index = @current_index
232
+ old_pcol = @pcol
233
+ old_col_offset = @col_offset
234
+
235
+ begin
236
+ case ch
237
+ when @selection_key
238
+ @repaint_required = true
239
+ if @selected_index == @current_index
240
+ @selected_index = nil
241
+ else
242
+ @selected_index = @current_index
243
+ end
244
+ else
245
+ ret = super
246
+ return ret
247
+ end
248
+ ensure
249
+ @current_index = 0 if @current_index < 0
250
+ @current_index = @list.size-1 if @current_index >= @list.size
251
+ @repaint_required = true if @current_index != old_current_index
252
+ if @current_index != old_current_index or @pcol != old_pcol or @col_offset != old_col_offset
253
+ if @current_index != old_current_index
254
+ on_leave_row old_current_index
255
+ on_enter_row @current_index
256
+ #fire_handler(:CHANGE_ROW, [old_current_index, @current_index, ch ]) # 2018-03-26 - improve this
257
+ end
258
+ @repaint_required = true
259
+ fire_handler(:CURSOR_MOVE, [@col_offset, @current_index, @curpos, @pcol, ch ]) # 2018-03-25 - improve this
260
+ end
261
+ end
262
+ end
263
+ # advance col_offset (where cursor will be displayed on screen)
264
+ # @param [Integer] advance by n (can be negative or positive)
265
+ # @return -1 if cannot advance
266
+ private def add_col_offset num
267
+ x = @col_offset + num
268
+ return -1 if x < 0
269
+ return -1 if x > @int_width
270
+ # is it a problem that i am directly changing col_offset ??? XXX
271
+ @col_offset += num
272
+ end
273
+ # returns current row
274
+ def current_row
275
+ @list[@current_index]
276
+ end
277
+
278
+ # move cursor forward one character, called with KEY_RIGHT action.
279
+ def cursor_forward
280
+ blen = current_row().size-1
281
+ if @curpos < blen
282
+ if add_col_offset(1)==-1 # go forward if you can, else scroll
283
+ #@pcol += 1 if @pcol < @width
284
+ @pcol += 1 if @pcol < blen
285
+ end
286
+ @curpos += 1
287
+ end
288
+ end
289
+ def cursor_backward
290
+
291
+ if @col_offset > 0
292
+ @curpos -= 1
293
+ add_col_offset -1
294
+ else
295
+ # cur is on the first col, then scroll left
296
+ if @pcol > 0
297
+ @pcol -= 1
298
+ @curpos -= 1
299
+ else
300
+ # do nothing
301
+ end
302
+ end
303
+ end
304
+ # position cursor at start of field
305
+ def cursor_home
306
+ @curpos = 0
307
+ @pcol = 0
308
+ set_col_offset 0
309
+ end
310
+ # goto end of line.
311
+ # This should be consistent with moving the cursor to the end of the row with right arrow
312
+ def cursor_end
313
+ blen = current_row().length
314
+ if blen < @int_width
315
+ set_col_offset blen # just after the last character
316
+ @pcol = 0
317
+ else
318
+ @pcol = blen-@int_width
319
+ set_col_offset blen
320
+ end
321
+ @curpos = blen # this is position in array where editing or motion is to happen regardless of what you see
322
+ # regardless of pcol (panning)
323
+ end
324
+ # go to start of file (first line)
325
+ def goto_start
326
+ @current_index = 0
327
+ @pcol = @curpos = 0
328
+ set_col_offset 0
329
+ end
330
+ # go to end of file (last line)
331
+ def goto_end
332
+ @current_index = @list.size-1
333
+ end
334
+ def scroll_down
335
+ @current_index += @scroll_lines
336
+ end
337
+ def scroll_up
338
+ @current_index -= @scroll_lines
339
+ end
340
+ def page_backward
341
+ @current_index -= @page_lines
342
+ end
343
+ def page_forward
344
+ @current_index += @page_lines
345
+ end
346
+ # sets the visual cursor on the window at correct place
347
+ # NOTE be careful of curpos - pcol being less than 0
348
+ # @param [Integer] position in data on the line
349
+ private def set_col_offset x=@curpos
350
+ @curpos = x || 0 # NOTE we set the index of cursor here - WHY TWO THINGS ??? XXX
351
+ #return -1 if x < 0
352
+ #return -1 if x > @width
353
+ if x >= @int_width
354
+ x = @int_width
355
+ @col_offset = @int_width
356
+ return
357
+ end
358
+ @col_offset = x
359
+ @col_offset = @int_width if @col_offset > @int_width
360
+ return
361
+ end
362
+ def cursor_up
363
+ @current_index -= 1
364
+ end
365
+ # go to next row
366
+ def cursor_down
367
+ @current_index += 1
368
+ end
369
+ def on_enter
370
+ super
371
+ return unless @list
372
+ on_enter_row @current_index
373
+ end
374
+ def on_leave
375
+ super
376
+ on_leave_row @current_index
377
+ end
378
+ # called when object leaves a row and when object is exited.
379
+ def on_leave_row index
380
+ fire_handler(:LEAVE_ROW, [index]) # 2018-03-26 - improve this
381
+ end
382
+ # called whenever a row entered.
383
+ # Call when object entered, also.
384
+ def on_enter_row index
385
+ #fire_handler(:ENTER_ROW, [old_current_index, @current_index, ch ]) # 2018-03-26 - improve this
386
+ fire_handler(:ENTER_ROW, [@current_index]) # 2018-03-26 - improve this
387
+ # if cursor ahead of blen then fix it
388
+ blen = current_row().size-1
389
+ if @curpos > blen
390
+ @col_offset = blen - @pcol
391
+ @curpos = blen
392
+ if @pcol > blen
393
+ @pcol = blen - @int_width
394
+ @pcol = 0 if @pcol < 0
395
+ @col_offset = blen - @pcol
396
+ end
397
+ end
398
+ @col_offset = 0 if @col_offset < 0
399
+ end
400
+ ## border {{{
401
+ private def print_border row, col, height, width, color, att=FFI::NCurses::A_NORMAL
402
+ raise
403
+ pointer = @graphic.pointer
404
+ FFI::NCurses.wattron(pointer, FFI::NCurses.COLOR_PAIR(color) | att)
405
+ FFI::NCurses.mvwaddch pointer, row, col, FFI::NCurses::ACS_ULCORNER
406
+ FFI::NCurses.mvwhline( pointer, row, col+1, FFI::NCurses::ACS_HLINE, width-2)
407
+ FFI::NCurses.mvwaddch pointer, row, col+width-1, FFI::NCurses::ACS_URCORNER
408
+ FFI::NCurses.mvwvline( pointer, row+1, col, FFI::NCurses::ACS_VLINE, height-2)
409
+
410
+ FFI::NCurses.mvwaddch pointer, row+height-1, col, FFI::NCurses::ACS_LLCORNER
411
+ FFI::NCurses.mvwhline(pointer, row+height-1, col+1, FFI::NCurses::ACS_HLINE, width-2)
412
+ FFI::NCurses.mvwaddch pointer, row+height-1, col+width-1, FFI::NCurses::ACS_LRCORNER
413
+ FFI::NCurses.mvwvline( pointer, row+1, col+width-1, FFI::NCurses::ACS_VLINE, height-2)
414
+ FFI::NCurses.wattroff(pointer, FFI::NCurses.COLOR_PAIR(color) | att)
415
+ end # }}}
416
+ end
417
+ end # module
@@ -0,0 +1,140 @@
1
+ require 'umbra/button'
2
+ ##
3
+ # ----------------------------------------------------------------------------- #
4
+ # File: togglebutton.rb
5
+ # Description: a button that has two states, on and off
6
+ # Author: j kepler http://github.com/mare-imbrium/umbra/
7
+ # Date: 2018-03-17 - 22:50
8
+ # License: MIT
9
+ # Last update: 2018-04-07 23:08
10
+ # ----------------------------------------------------------------------------- #
11
+ # togglebutton.rb Copyright (C) 2012-2018 j kepler
12
+ #
13
+ #
14
+ module Umbra
15
+ ##
16
+ # an event fired when an item that can be selected is toggled/selected
17
+ class ItemEvent # {{{
18
+ # http://java.sun.com/javase/6/docs/api/java/awt/event/ItemEvent.html
19
+ attr_reader :state # :SELECTED :DESELECTED
20
+ attr_reader :item # the item pressed such as toggle button
21
+ attr_reader :item_selectable # item originating event such as list or collection
22
+ attr_reader :item_first # if from a list
23
+ attr_reader :item_last #
24
+ attr_reader :param_string # for debugging etc
25
+ =begin
26
+ def initialize item, item_selectable, state, item_first=-1, item_last=-1, paramstring=nil
27
+ @item, @item_selectable, @state, @item_first, @item_last =
28
+ item, item_selectable, state, item_first, item_last
29
+ @param_string = "Item event fired: #{item}, #{state}"
30
+ end
31
+ =end
32
+ # i think only one is needed per object, so create once only
33
+ def initialize item, item_selectable
34
+ @item, @item_selectable =
35
+ item, item_selectable
36
+ end
37
+ def set state, item_first=-1, item_last=-1, param_string=nil
38
+ @state, @item_first, @item_last, @param_string =
39
+ state, item_first, item_last, param_string
40
+ @param_string = "Item event fired: #{item}, #{state}" if param_string.nil?
41
+ end
42
+ end # }}}
43
+ # A button that may be switched off an on.
44
+ # Extended by RadioButton and checkbox.
45
+ # WARNING, pls do not override +text+ otherwise checkboxes etc will stop functioning.
46
+ # TODO: add editable here nd prevent toggling if not so.
47
+ class ToggleButton < Button
48
+ # text for on value and off value
49
+ attr_accessor :onvalue, :offvalue
50
+ # boolean, which value to use currently, onvalue or offvalue
51
+ attr_accessor :value
52
+ # characters to use for surround, array, default square brackets
53
+ attr_accessor :surround_chars
54
+ # 2018-04-02 - removing variable
55
+ #attr_accessor :variable # value linked to this variable which is a boolean
56
+ # background to use when selected, if not set then default
57
+ # 2018-04-02 - unused so commenting off. color_pair is not used here or in checkbox
58
+ #attr_accessor :selected_bgcolor
59
+ #attr_accessor :selected_color
60
+ attr_accessor :selected_color_pair
61
+
62
+ def initialize config={}, &block
63
+ super
64
+
65
+ #@value ||= (@variable.nil? ? false : @variable.get_value(@name)==true)
66
+ # TODO may need to do this when this is added to button_group
67
+ end
68
+ def getvalue
69
+ @value ? @onvalue : @offvalue
70
+ end
71
+
72
+ # WARNING, pls do not override +text+ otherwise checkboxes etc will stop functioning.
73
+
74
+ # added for some standardization 2010-09-07 20:28
75
+ # alias :text :getvalue # NEXT VERSION
76
+ # change existing text to label
77
+ ##
78
+ # is the button on or off
79
+ # added 2008-12-09 19:05
80
+ def checked?
81
+ @value
82
+ end
83
+ alias :selected? :checked?
84
+
85
+ def getvalue_for_paint
86
+ # when the width is set externally then the surround chars sit outside the width
87
+ #unless @width
88
+ if @onvalue && @offvalue
89
+ @width = [ @onvalue.length, @offvalue.length ].max
90
+ end
91
+ #end
92
+ buttontext = getvalue().center(@width)
93
+ @text_offset = @surround_chars[0].length
94
+ @surround_chars[0] + buttontext + @surround_chars[1]
95
+ end
96
+
97
+ # toggle button handle key
98
+ # @param [int] key received
99
+ #
100
+ def handle_key ch
101
+ if ch == 32
102
+ toggle
103
+ @repaint_required = true # need to change the label
104
+ else
105
+ super
106
+ end
107
+ end
108
+
109
+ ##
110
+ # toggle the button value
111
+ def toggle
112
+ fire
113
+ end
114
+
115
+ # called on :PRESS event
116
+ # caller should check state of itemevent passed to block
117
+ # NOTE i have not brought ItemEvent in here.
118
+ def fire
119
+ checked(!@value)
120
+ @item_event = ItemEvent.new self, self if @item_event.nil?
121
+ @item_event.set(@value ? :SELECTED : :DESELECTED)
122
+ fire_handler :PRESS, @item_event # should the event itself be ITEM_EVENT
123
+ end
124
+ ##
125
+ # set the value to true or false
126
+ # user may programmatically want to check or uncheck
127
+ def checked tf
128
+ @value = tf
129
+ =begin
130
+ if @variable
131
+ if @value
132
+ @variable.set_value((@onvalue || 1), @name)
133
+ else
134
+ @variable.set_value((@offvalue || 0), @name)
135
+ end
136
+ end
137
+ =end
138
+ end
139
+ end # class
140
+ end # module
@@ -0,0 +1,3 @@
1
+ module Umbra
2
+ VERSION = "0.1.0"
3
+ end