Module: RubyCurses::WidgetShortcuts

Included in:
App
Defined in:
lib/rbcurse/core/util/widgetshortcuts.rb

Defined Under Namespace

Classes: Ws, WsFlow, WsStack

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.def_widget(path, klass, short = nil) ⇒ Object

create a shortcut for a class path is path of file to use in require starting with rbcurse klass is name of class to instantiate



91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
# File 'lib/rbcurse/core/util/widgetshortcuts.rb', line 91

def self.def_widget(path, klass, short=nil)
  p=""
   if path
    p="require \"#{path}\""
  end
   short ||= klass.to_s.downcase
    eval %{
      def #{short}(config={}, &block)
        if config.is_a? String
           _s = config
           config = {}
           config[:text] = _s
        end
        #{p}
        w = #{klass}.new nil, config
        _position w
        w.command &block if block_given?
        return w
      end
    }
end

Instance Method Details

#_configure(s) ⇒ Object

This configures a stack or flow not the objects inside



460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
# File 'lib/rbcurse/core/util/widgetshortcuts.rb', line 460

def _configure s
  s[:row] ||= 0
  s[:col] ||= 0
  s[:row] += (s[:margin_top] || 0)
  s[:col] += (s[:margin_left] || 0)
  s[:width] = FFI::NCurses.COLS-s[:col] if s[:width] == :expand
  s[:height] = FFI::NCurses.LINES-s[:row] if s[:height] == :expand # 2011-11-30 
  last = @_ws_active.last
  if last
    if s[:width_pc]
      if last.is_a? WsStack
        s[:width] =           (last[:width] * (s[:width_pc].to_i * 0.01)).floor
      else
        # i think this width is picked up by next stack in this flow
        last[:item_width] =   (last[:width] * (s[:width_pc].to_i* 0.01)).floor
      end
    end
    if s[:height_pc]
      if last.is_a? WsFlow
        s[:height] =       ( (last[:height] * s[:height_pc].to_i)/100).floor
      else
        # this works only for flows within stacks not for an object unless
        # you put a single object in a flow
        s[:item_height] =  ( (last[:height] * s[:height_pc].to_i)/100).floor
      end
        #alert "item height set as #{s[:height]} for #{s} "
    end
    if last.is_a? WsStack
      s[:row] += (last[:row] || 0)
      s[:col] += (last[:col] || 0)  
    else
      s[:row] += (last[:row] || 0)
      s[:col] += (last[:col] || 0)  # we are updating with item_width as each st finishes
      s[:width] ||= last[:item_width] # 
    end
  else
    # this should be outer most flow or stack, if nothing mentioned
    # trying this out
    s[:width] ||= :expand
    s[:height] ||= :expand
    s[:width] = FFI::NCurses.COLS-s[:col] if s[:width] == :expand
    s[:height] = FFI::NCurses.LINES-s[:row] if s[:height] == :expand # 2011-11-30 
  end
  s[:components] = []
end

#_position(w) ⇒ Object



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
322
323
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
# File 'lib/rbcurse/core/util/widgetshortcuts.rb', line 288

def _position w
  if @_ws_active.nil? || @_ws_active.empty?
    # no stack or flow, this is independent usage, or else we are outside stacks and flows
    #
    # this is outside any stack or flow, so we do the minimal
    # user should specify row and col
    w.row ||= 0
    w.col ||= 0
    #$log.debug "XXX:  LABEL #{w.row} , #{w.col} "
    w.set_form @form if @form # temporary,, only set if not inside an object FIXME
    if w.width == :expand  # calculate from current col, not 0 FIXME
      w.width = FFI::NCurses.COLS-w.col # or take windows width since this could be in a message box
    end
    if w.height == :expand
      # take from current row, and not zero  FIXME
      w.height = FFI::NCurses.LINES-w.row # or take windows width since this could be in a message box
    end
    return

  end
  # -------------------------- there is a stack or flow -------------------- #
  #
  cur = @_ws_active.last
  unless cur
    raise "This should have been handled previously.Somethings wrong, check/untested"
  end
  r = cur[:row] || 0
  c = cur[:col] || 0
  w.row = r
  w.col = c
  # if flow then take flows height, else use dummy value
  if w.height_pc
    w.height =       ( (cur[:height] * w.height_pc.to_i)/100).floor
  end
  if w.height == :expand
    if cur.is_a? WsFlow
      w.height = cur[:height] || 8 #or raise "height not known for flow"
    else
      w.height = cur[:item_height] || 8 #or raise "height not known for flow"
    end
    #alert "setting ht to #{w.height}, #{cur[:height]} , for #{cur} "
  end
  if w.width == :expand
    if cur.is_a? WsFlow
      if cur[:item_width]
        w.width = cur[:item_width] #or raise "item_Width not known for flow #{cur.class}, #{cur[:item_width]}, #{cur[:width]} , #{w.width_pc}  "
      elsif w.width_pc
        #w.width = w.width_pc * cur[:width]
        w.width = (cur[:width] * (w.width_pc.to_i * 0.01)).floor
      else
        w.width = cur[:width] 
      end
      raise "width could not be calculated. i need flow width and item width_pc" if w.width == :expand
    else
      w.width = cur[:width] or raise "Width not known for stack #{cur.class}, #{cur[:width]} "
    end
  end
  if cur.is_a? WsStack
    r += w.height || 1   # NOTE, we need to have height for this purpose defined BEFORE calling for list/text
    cur[:row] = r
  else
    wid = cur[:item_width] || w.width || 10
    c += wid + 1
    cur[:col] = c
  end
  #alert "set width to #{w.width} ,cur: #{cur[:width]} ,iw: #{cur[:item_width]} "
  if cur.is_a? WsFlow
    unless w.height
      w.height = cur[:height] #or raise "Height not known for flow"
    end
  end
  w.color   ||= cur[:color]
  w.bgcolor ||= cur[:bgcolor]
  w.set_form @form if @form # temporary
  @_ws_components << w
  cur[:components] << w
end

#app_header(title, config = {}, &block) ⇒ Object



123
124
125
126
# File 'lib/rbcurse/core/util/widgetshortcuts.rb', line 123

def app_header title, config={}, &block
  require 'rbcurse/core/widgets/applicationheader'
  header = ApplicationHeader.new @form, title, config, &block
end

#blankObject



55
56
57
# File 'lib/rbcurse/core/util/widgetshortcuts.rb', line 55

def blank
  label :text => ""
end

#box(config = {}, &block) ⇒ Object

flow and stack could have a border option NOTE: box takes one row below too, so :expand overwrites that line



418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
# File 'lib/rbcurse/core/util/widgetshortcuts.rb', line 418

def box config={}, &block
  require 'rbcurse/core/widgets/box'
  # take current stacks row and col
  # advance row by one and col by one
  # at end note row and advance by one
  # draw a box around using these coordinates. width should be
  # provided unless we have item width or something.
  @_ws_active ||= []
  last = @_ws_active.last
  if last
    r = last[:row]
    c = last[:col]
    config[:row] = r
    config[:col] = c
    last[:row] += config[:margin_top] || 1
    last[:col] += config[:margin_left] || 1
    _box = Box.new @form, config # needs to be created first or will overwrite area after others painted
    yield_or_eval &block if block_given?
    # FIXME last[height] needs to account for row
    h = config[:height] || last[:height] || (last[:row] - r)
    h = 2 if h < 2
    w = config[:width] || last[:width] || 15 # tmp
    case last
    when WsFlow
      w = last[:col]
    when WsStack
      #h += 1
    end
    config[:row] = r
    config[:col] = c
    config[:height] = h
    config[:width] = w
    _box.row r
    _box.col c
    _box.height h
    _box.width w
    last[:row] += 1
    last[:col] += 1 # ??? XXX if flow we need to increment properly or not ?
  end
end

#dock(labels, config = {}, &block) ⇒ Object

prints pine-like key labels



189
190
191
192
# File 'lib/rbcurse/core/util/widgetshortcuts.rb', line 189

def dock labels, config={}, &block
  require 'rbcurse/core/widgets/keylabelprinter'
  klp = RubyCurses::KeyLabelPrinter.new @form, labels, config, &block
end

#flow(config = {}, &block) ⇒ Object

item_width - width to use per item

but the item width may apply to stacks inside not to items


394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
# File 'lib/rbcurse/core/util/widgetshortcuts.rb', line 394

def flow config={}, &block
  s = WsFlow.new config
  @_ws_active ||= []
  _configure s
  @_ws_active << s
  yield_or_eval &block if block_given?
  @_ws_active.pop 
  last = @_ws_active.last
  if last 
    case last
    when WsStack
      if s[:height]
        last[:row] += s[:height] 
      else
        #last[:row] += last[:highest_row]  
        last[:row] += 1
      end
    when WsFlow
      last[:col] += last[:item_width] || 0 
    end
  end
end

#line(config = {}) ⇒ Object



58
59
60
61
62
63
64
65
66
67
68
69
# File 'lib/rbcurse/core/util/widgetshortcuts.rb', line 58

def line config={}
  #horizontal line TODO
  #row = config[:row] || @app_row
  #width = config[:width] || 20
  #_position config
  #col = config[:col] || 1
  #@color_pair = config[:color_pair] || $datacolor
  #@attrib = config[:attrib] || Ncurses::A_NORMAL
  #@window.attron(Ncurses.COLOR_PAIR(@color_pair) | @attrib)
  #@window.mvwhline( row, col, FFI::NCurses::ACS_HLINE, width)
  #@window.attron(Ncurses.COLOR_PAIR(@color_pair) | @attrib)
end


194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
# File 'lib/rbcurse/core/util/widgetshortcuts.rb', line 194

def link config={}, &block
      if config.is_a? String
         _s = config
         config = {}
         config[:text] = _s
      end
  require 'rbcurse/core/widgets/rlink'
  events = [ :PRESS,  :LEAVE, :ENTER ]
  block_event = :PRESS
  config[:highlight_foreground] = "yellow"
  config[:highlight_background] = "red"
  toggle = Link.new nil, config
  _position(toggle)
  if block
    toggle.bind(block_event, toggle, &block)
  end
  return toggle
end

#listbox(config = {}, &block) ⇒ Object



169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
# File 'lib/rbcurse/core/util/widgetshortcuts.rb', line 169

def listbox config={}, &block
  events = [ :PRESS, :ENTER_ROW, :LEAVE, :ENTER ]
  block_event = events[0]
  #_process_args args, config, block_event, events
  #config[:width] = config[:display_length] unless config.has_key? :width
  # if no width given, expand to flows width
  #config[:width] ||= @stack.last.width if @stack.last
  useform = nil
  #useform = @form if @current_object.empty?
  w = List.new useform, config
  w.width = :expand unless w.width
  w.height ||= :expand # TODO We may need to push this before _position so it can be accounted for in stack
  _position(w)
  # need to expand to stack's width or flows itemwidth if given
  if block
    w.bind(block_event, &block)
  end
  return w
end


119
120
121
122
# File 'lib/rbcurse/core/util/widgetshortcuts.rb', line 119

def menubar &block
  require 'rbcurse/core/widgets/rmenu'
  RubyCurses::MenuBar.new &block
end


212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
# File 'lib/rbcurse/core/util/widgetshortcuts.rb', line 212

def menulink config={}, &block
      if config.is_a? String
         _s = config
         config = {}
         config[:text] = _s
      end
  require 'rbcurse/core/widgets/rmenulink'
  events = [ :PRESS,  :LEAVE, :ENTER ]
  block_event = :PRESS
  config[:highlight_foreground] = "yellow"
  config[:highlight_background] = "red"
  #config[:hotkey] = true
  w = MenuLink.new nil, config
  _position(w)
  if block
    w.bind(block_event, w, &block)
  end
  return w
end

#radio(config = {}, &block) ⇒ Object

horizontal line TODO row = config || @app_row width = config || 20 _position config col = config || 1 @window.attron(Ncurses.COLOR_PAIR(@color_pair) | @attrib) @window.mvwhline( row, col, FFI::NCurses::ACS_HLINE, width) @window.attron(Ncurses.COLOR_PAIR(@color_pair) | @attrib)



70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
# File 'lib/rbcurse/core/util/widgetshortcuts.rb', line 70

def radio config={}, &block
  a = config[:group]
  # should we not check for a nil
  if @variables.has_key? a
    v = @variables[a]
  else
    v = Variable.new
    @variables[a] = v
  end
  config[:variable] = v
  config.delete(:group)
  w = RadioButton.new nil, config #, &block
  _position w
  if block
    w.bind(:PRESS, &block)
  end
  return w
end

#stack(config = {}, &block) ⇒ Object

make it as simple as possible, don’t try to be intelligent or clever, put as much on the user



367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
# File 'lib/rbcurse/core/util/widgetshortcuts.rb', line 367

def stack config={}, &block
  s = WsStack.new config
  @_ws_active ||= []
  _configure s
  @_ws_active << s
  yield_or_eval &block if block_given?
  @_ws_active.pop 
  
  # ---- stack is finished now
  last = @_ws_active.last
  if last 
    case last
    when WsStack
    when WsFlow
      last[:col] += last[:item_width] || 0 
      # this tries to set height of outer flow based on highest row
      # printed, however that does not account for height of object,
      # so user should give a height to the flow.
      last[:height] = s[:row] if s[:row] > (last[:height]||0)
      $log.debug "XXX: STACK setting col to #{s[:col]} "
    end
  end

end

#tabular_widget(config = {}, &block) ⇒ Object Also known as: table

creates a simple readonly table, that allows users to click on rows and also on the header. Header clicking is for column-sorting.



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

def tabular_widget config={}, &block
  require 'rbcurse/core/widgets/tabularwidget'
  events = [:PROPERTY_CHANGE, :LEAVE, :ENTER, :CHANGE, :ENTER_ROW, :PRESS ]
  block_event = nil
  # if no width given, expand to stack width
  #config.delete :title
  useform = nil

  w = TabularWidget.new useform, config # NO BLOCK GIVEN
  w.width ||= :expand 
  w.height ||= :expand # TODO This has to come before other in stack next one will overwrite.
  _position(w)
  if block_given?
    #@current_object << w
    yield_or_eval &block
    #@current_object.pop
  end
  return w
end

#textarea(config = {}, &block) ⇒ Object

editable text area



128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
# File 'lib/rbcurse/core/util/widgetshortcuts.rb', line 128

def textarea config={}, &block
  require 'rbcurse/core/widgets/rtextarea'
  # TODO confirm events many more
  events = [ :CHANGE,  :LEAVE, :ENTER ]
  block_event = events[0]
  #_process_args args, config, block_event, events
  #config[:width] = config[:display_length] unless config.has_key? :width
  # if no width given, expand to flows width
  #config[:width] ||= @stack.last.width if @stack.last
  useform = nil
  #useform = @form if @current_object.empty?
  w = TextArea.new useform, config
  w.width = :expand unless w.width
  w.height ||= :expand # TODO This has to come before other in stack next one will overwrite.
  _position(w)
  w.height ||= 8 # TODO
  # need to expand to stack's width or flows itemwidth if given
  if block
    w.bind(block_event, &block)
  end
  return w
end

#textview(config = {}, &block) ⇒ Object



150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
# File 'lib/rbcurse/core/util/widgetshortcuts.rb', line 150

def textview config={}, &block
  events = [ :LEAVE, :ENTER ]
  block_event = events[0]
  #_process_args args, config, block_event, events
  #config[:width] = config[:display_length] unless config.has_key? :width
  # if no width given, expand to flows width
  #config[:width] ||= @stack.last.width if @stack.last
  useform = nil
  #useform = @form if @current_object.empty?
  w = TextView.new useform, config
  w.width = :expand unless w.width
  w.height ||= :expand # TODO This has to come before other in stack next one will overwrite.
  _position(w)
  # need to expand to stack's width or flows itemwidth if given
  if block
    w.bind(block_event, &block)
  end
  return w
end

#tree(config = {}, &block) ⇒ Object



231
232
233
234
235
236
237
238
239
240
241
242
243
244
# File 'lib/rbcurse/core/util/widgetshortcuts.rb', line 231

def tree config={}, &block
  require 'rbcurse/core/widgets/rtree'
  events = [:TREE_WILL_EXPAND_EVENT, :TREE_EXPANDED_EVENT, :TREE_SELECTION_EVENT, :PROPERTY_CHANGE, :LEAVE, :ENTER ]
  block_event = nil
  #config[:height] ||= 10
  # if no width given, expand to flows width
  useform = nil
  #useform = @form if @current_object.empty?
  w = Tree.new useform, config, &block
  w.width ||= :expand 
  w.height ||= :expand # TODO This has to come before other in stack next one will overwrite.
  _position w
  return w
end

#vimsplit(config = {}, &block) ⇒ Object

NOTE UNTESTED



268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
# File 'lib/rbcurse/core/util/widgetshortcuts.rb', line 268

def vimsplit config={}, &block
  require 'rbcurse/extras/widgets/rvimsplit'
  #TODO check these
  events = [:PROPERTY_CHANGE, :LEAVE, :ENTER ]
  block_event = nil
  config[:height] ||= 10
  # if no width given, expand to flows width
  #config.delete :title
  useform = nil

  w = VimSplit.new useform, config # NO BLOCK GIVEN
  _position(w)
  if block_given?
    #@current_object << w
    #instance_eval &block if block_given?
    yield w
    #@current_object.pop
  end
  return w
end

#widget_shortcuts_initObject



48
49
50
51
52
53
54
# File 'lib/rbcurse/core/util/widgetshortcuts.rb', line 48

def widget_shortcuts_init
  @_ws_app_row = @_ws_app_col = 0
  #@_ws_active = []
  @_ws_active = nil # so we can use shortcuts if no stack used
  @_ws_components = []
  @variables = {}
end