Class: Canis::Widget

Inherits:
Object show all
Includes:
ConfigSetup, EventHandler, Io, Utils
Defined in:
lib/canis/core/util/app.rb,
lib/canis/core/widgets/rwidget.rb

Overview

{{{

Since:

  • 1.2.0

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from Io

#__create_footer_window, #clear_this, #get_file, #print_this, #rb_getchar, #rb_gets, #rb_getstr, #warn

Methods included from Utils

#ORIG_process_key, #ORIGbind_key, #ORIGkeycode_tos, #_process_key, #bind_composite_mapping, #bind_key, #bind_keys, #check_composite_mapping, #create_logger, #define_key, #define_prefix_command, #execute_mapping, #get_attrib, #get_color, #key, #key_tos, #print_key_bindings, #repeatm, #run_command, #shell_out, #shell_output, #suspend, #view, #xxxbind_composite_mapping

Methods included from ConfigSetup

#config_setup, #variable_set

Methods included from EventHandler

#bind, #event?, #event_list, #fire_handler, #fire_property_change, #register_events

Constructor Details

#initialize(aform, aconfig = {}, &block) ⇒ Widget

Returns a new instance of Widget.

Since:

  • 1.2.0



1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
# File 'lib/canis/core/widgets/rwidget.rb', line 1131

def initialize aform, aconfig={}, &block
  # I am trying to avoid passing the nil when you don't want to give a form.
  # I hope this does not create new issues 2011-11-20 
  if aform.is_a? Hash
    # presumable there's nothing coming in in hash, or else we will have to merge
    aconfig = aform
    @form = nil
  else
    #raise "got a #{aform.class} "
    @form = aform
  end
  @row_offset ||= 0
  @col_offset ||= 0
  #@ext_row_offset = @ext_col_offset = 0 # 2010-02-07 20:18  # removed on 2011-09-29 
  @state = :NORMAL

  @handler = nil # we can avoid firing if nil
  #@event_args = {} # 2014-04-22 - 18:47 declared in bind_key
  # These are standard events for most widgets which will be fired by 
  # Form. In the case of CHANGED, form fires if it's editable property is set, so
  # it does not apply to all widgets.
  register_events( [:ENTER, :LEAVE, :CHANGED, :PROPERTY_CHANGE])

  config_setup aconfig # @config.each_pair { |k,v| variable_set(k,v) }
  #instance_eval &block if block_given?
  if block_given?
    if block.arity > 0
      yield self
    else
      self.instance_eval(&block)
    end
  end
  # 2010-09-20 13:12 moved down, so it does not create problems with other who want to set their
  # own default
  #@bgcolor ||=  "black" # 0
  #@color ||= "white" # $datacolor
  set_form(@form) if @form
end

Instance Attribute Details

#_object_createdObject

2010-09-16 12:12 to prevent needless property change firing when object being set

Since:

  • 1.2.0



1115
1116
1117
# File 'lib/canis/core/widgets/rwidget.rb', line 1115

def _object_created
  @_object_created
end

#col_offsetObject (readonly)

where should the cursor be placed to start with

Since:

  • 1.2.0



1109
1110
1111
# File 'lib/canis/core/widgets/rwidget.rb', line 1109

def col_offset
  @col_offset
end

#configObject (readonly)

can be used for popping user objects too

Since:

  • 1.2.0



1106
1107
1108
# File 'lib/canis/core/widgets/rwidget.rb', line 1106

def config
  @config
end

#curposObject

cursor position inside object - column, not row.

Since:

  • 1.2.0



1105
1106
1107
# File 'lib/canis/core/widgets/rwidget.rb', line 1105

def curpos
  @curpos
end

#focussedObject

sometimes inside a container there’s no way of knowing if an individual comp is in focus other than to explicitly set it and inquire . 2010-09-02 14:47 @since 1.1.5 NOTE state takes care of this and is set by form. boolean

Since:

  • 1.2.0



1122
1123
1124
# File 'lib/canis/core/widgets/rwidget.rb', line 1122

def focussed
  @focussed
end

#formObject

made accessor 2008-11-27 22:32 so menu can set

Since:

  • 1.2.0



1107
1108
1109
# File 'lib/canis/core/widgets/rwidget.rb', line 1107

def form
  @form
end

#handlerObject (readonly)

event handler

Since:

  • 1.2.0



1129
1130
1131
# File 'lib/canis/core/widgets/rwidget.rb', line 1129

def handler
  @handler
end

#idObject

, :zorder

Since:

  • 1.2.0



1104
1105
1106
# File 'lib/canis/core/widgets/rwidget.rb', line 1104

def id
  @id
end

#key_labelObject (readonly)

descriptions for each key set in _key_map

Since:

  • 1.2.0



1128
1129
1130
# File 'lib/canis/core/widgets/rwidget.rb', line 1128

def key_label
  @key_label
end

#parent_componentObject

added 2010-01-12 23:28 BUFFERED - to bubble up

Since:

  • 1.2.0



1117
1118
1119
# File 'lib/canis/core/widgets/rwidget.rb', line 1117

def parent_component
  @parent_component
end

#row_offsetObject (readonly)

where should the cursor be placed to start with

Since:

  • 1.2.0



1109
1110
1111
# File 'lib/canis/core/widgets/rwidget.rb', line 1109

def row_offset
  @row_offset
end

#stateObject

normal, selected, highlighted

Since:

  • 1.2.0



1108
1109
1110
# File 'lib/canis/core/widgets/rwidget.rb', line 1108

def state
  @state
end

Instance Method Details

#action_managerObject

return an object of actionmanager class, creating if required Widgets and apps may add_action and show_menu using the same

Since:

  • 1.2.0



1511
1512
1513
1514
# File 'lib/canis/core/widgets/rwidget.rb', line 1511

def action_manager
  require 'canis/core/include/actionmanager'
  @action_manager ||= ActionManager.new
end

#bgcolor(*val) ⇒ Object

returns widgets bgcolor, or form’s color. This ensures that all widgets use form’s color

unless user has overriden the color.

This is to be used whenever a widget is rendering to check the color at this moment.

Since:

  • 1.2.0



1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
# File 'lib/canis/core/widgets/rwidget.rb', line 1214

def bgcolor( *val )
  if val.empty?
    return @bgcolor if @bgcolor
    return @form.bgcolor if @form
    return $def_bg_color
  else
    @color_pair = nil
    return property_set :bgcolor, val
  end
end

#changed(*args, &block) ⇒ Object



46
47
48
# File 'lib/canis/core/util/app.rb', line 46

def changed *args, &block
  bind :CHANGED, *args, &block
end

#click(*args, &block) ⇒ Object

actually we already have command() for buttons



56
57
58
# File 'lib/canis/core/util/app.rb', line 56

def click *args, &block
  bind :PRESS, *args, &block
end

#color(*val) ⇒ Object

returns widgets color, or if not set then app default Ideally would have returned form’s color, but it seems that form does not have color any longer.

Since:

  • 1.2.0



1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
# File 'lib/canis/core/widgets/rwidget.rb', line 1201

def color( *val )
  if val.empty?
    return @color if @color
    return @form.color if @form
    return $def_fg_color
  else
    @color_pair = nil
    return property_set :color, val
  end
end

#color_pair(*val) ⇒ Object

2011-11-12 trying to make color setting a bit sane You may set as a color_pair using get_color which gives a fixnum or you may give 2 color symbols so i can update color, bgcolor and colorpair in one shot if one of them is nil, i just use the existing value

Since:

  • 1.2.0



1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
# File 'lib/canis/core/widgets/rwidget.rb', line 1475

def color_pair(*val)
  if val.empty?
    #return @color_pair 
    return @color_pair || get_color($datacolor, color(), bgcolor())
  end

  oldvalue = @color_pair
  case val.size
  when 1
    raise ArgumentError, "Expecting fixnum for color_pair." unless val[0].is_a? Fixnum
    @color_pair = val[0]
    @color, @bgcolor = ColorMap.get_colors_for_pair @color_pair
  when 2
    @color = val.first if val.first
    @bgcolor = val.last if val.last
    @color_pair = get_color $datacolor, @color, @bgcolor
  end
  if oldvalue != @color_pair
    fire_property_change(:color_pair, oldvalue, @color_pair)
    @property_changed = true
    repaint_all true
  end
  self
end

#command(*args, &block) ⇒ Object

a general method for all widgets to override with their favorite or most meaninful event Ideally this is where the block in the constructor should land up.

Since:

  • 1.5.0 2011-11-21



1502
1503
1504
1505
1506
1507
1508
# File 'lib/canis/core/widgets/rwidget.rb', line 1502

def command *args, &block
  if event? :PRESS
    bind :PRESS, *args, &block
  else
    bind :CHANGED, *args, &block
  end
end

#destroyObject

Since:

  • 1.2.0



1292
1293
1294
1295
1296
1297
# File 'lib/canis/core/widgets/rwidget.rb', line 1292

def destroy
  $log.debug "DESTROY : widget #{@name} "
  panel = @window.panel
  Ncurses::Panel.del_panel(panel.pointer) if !panel.nil?   
  @window.delwin if !@window.nil?
end

#enter(*args, &block) ⇒ Object



52
53
54
# File 'lib/canis/core/util/app.rb', line 52

def enter *args, &block
  bind :ENTER, *args, &block
end

#focusObject

moves focus to this field we must look into running on_leave of previous field

Since:

  • 1.2.0



1355
1356
1357
1358
1359
1360
# File 'lib/canis/core/widgets/rwidget.rb', line 1355

def focus
  return if !@focusable
  if @form.validate_field != -1
    @form.select_field @id
  end
end

#focusable(*val) ⇒ Object

set or unset focusable (boolean). Whether a widget can get keyboard focus.

Since:

  • 1.2.0



1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
# File 'lib/canis/core/widgets/rwidget.rb', line 1362

def focusable(*val)
  return @focusable if val.empty?
  oldv = @focusable
  @focusable = val[0]

  return self if oldv.nil? || @_object_created.nil?
  # once the form has been painted then any changes will trigger update of focusables.
  @form.update_focusables if @form
  # actually i should only set the forms focusable_modified flag rather than call this. FIXME
  self
end

#focusable?Boolean

is this widget accessible from keyboard or not.

Returns:

  • (Boolean)

Since:

  • 1.2.0



1375
1376
1377
# File 'lib/canis/core/widgets/rwidget.rb', line 1375

def focusable?
  @focusable
end

#getvalueObject

return the value of the widget.

In cases where selection is possible, should return selected value/s

Since:

  • 1.2.0



1265
1266
1267
1268
# File 'lib/canis/core/widgets/rwidget.rb', line 1265

def getvalue
  #@text_variable && @text_variable.value || @text
  @text
end

#getvalue_for_paintObject

Am making a separate method since often value for print differs from actual value

Since:

  • 1.2.0



1271
1272
1273
# File 'lib/canis/core/widgets/rwidget.rb', line 1271

def getvalue_for_paint
  getvalue
end

#handle_key(ch) ⇒ Object

to be added at end of handle_key of widgets so instlalled actions can be checked

Since:

  • 1.2.0



1394
1395
1396
1397
1398
# File 'lib/canis/core/widgets/rwidget.rb', line 1394

def handle_key(ch)
  ret = process_key ch, self
  return :UNHANDLED if ret == :UNHANDLED
  0
end

#hideObject

Since:

  • 1.2.0



1338
1339
1340
# File 'lib/canis/core/widgets/rwidget.rb', line 1338

def hide
  @visible = false
end

#init_varsObject

Since:

  • 1.2.0



1169
1170
1171
1172
# File 'lib/canis/core/widgets/rwidget.rb', line 1169

def init_vars
  # just in case anyone does a super. Not putting anything here
  # since i don't want anyone accidentally overriding
end

#leave(*args, &block) ⇒ Object



49
50
51
# File 'lib/canis/core/util/app.rb', line 49

def leave *args, &block
  bind :LEAVE, *args, &block
end

#modified?Boolean

modified

typically read will be overridden to check if value changed from what it was on enter. getter and setter for modified (added 2009-01-18 12:31 )

Returns:

  • (Boolean)

Since:

  • 1.2.0



1230
1231
1232
# File 'lib/canis/core/widgets/rwidget.rb', line 1230

def modified?
  @modified
end

#move(row, col) ⇒ Object

is this required can we remove

Since:

  • 1.2.0



1348
1349
1350
1351
# File 'lib/canis/core/widgets/rwidget.rb', line 1348

def move row, col
  @row = row
  @col = col
end

#on_enterObject

got left out by mistake 2008-11-26 20:20

Since:

  • 1.2.0



1240
1241
1242
1243
1244
1245
1246
# File 'lib/canis/core/widgets/rwidget.rb', line 1240

def on_enter
  @state = :HIGHLIGHTED    # duplicating since often these are inside containers
  @focussed = true
  if @handler && @handler.has_key?(:ENTER)
    fire_handler :ENTER, self
  end
end

#on_leaveObject

got left out by mistake 2008-11-26 20:20

Since:

  • 1.2.0



1248
1249
1250
1251
1252
1253
1254
# File 'lib/canis/core/widgets/rwidget.rb', line 1248

def on_leave
  @state = :NORMAL    # duplicating since often these are inside containers
  @focussed = false
  if @handler && @handler.has_key?(:LEAVE)
    fire_handler :LEAVE, self
  end
end

#override_graphic(gr) ⇒ Object

When an enclosing component creates a pad (buffer) and the child component + should write onto the same pad, then the enclosing component should override + the default graphic of child. This applies mainly to editor components in + listboxes and tables. added 2010-01-05 15:25

Parameters:

  • graphic

    graphic object to use for writing contents

See Also:

  • in rlistbox.

Since:

  • 1.2.0



1420
1421
1422
# File 'lib/canis/core/widgets/rwidget.rb', line 1420

def override_graphic gr
  @graphic = gr
end

#process_key(keycode, object) ⇒ Object

e.g. process_key ch, self returns UNHANDLED if no block for it after form handles basic keys, it gives unhandled key to current field, if current field returns unhandled, then it checks this map.

Since:

  • 1.2.0



1389
1390
1391
# File 'lib/canis/core/widgets/rwidget.rb', line 1389

def process_key keycode, object
  return _process_key keycode, object, @graphic
end

#property_set(sym, val) ⇒ Object

this is supposed to be a duplicate of what dsl_property generates for cases when

we need to customise the get portion but not copy the set part. just call this.

Since:

  • 1.2.0



1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
# File 'lib/canis/core/widgets/rwidget.rb', line 1175

def property_set sym, val
  oldvalue = instance_variable_get "@#{sym}"
  tmp = val.size == 1 ? val[0] : val
  newvalue = tmp
  if oldvalue.nil? || @_object_created.nil?
    #@#{sym} = tmp
    instance_variable_set "@#{sym}", tmp
  end
  return(self) if oldvalue.nil? || @_object_created.nil?

  if oldvalue != newvalue
    # trying to reduce calls to fire, when object is being created
    begin
      @property_changed = true
      fire_property_change("#{sym}", oldvalue, newvalue) if !oldvalue.nil?
      #@#{sym} = tmp
      instance_variable_set "@#{sym}", tmp
      #@config["#{sym}"]=@#{sym}
    rescue PropertyVetoException
      $log.warn "PropertyVetoException for #{sym}:" + oldvalue.to_s + "->  "+ newvalue.to_s
    end
  end # if old
  self
end

#removeObject

Since:

  • 1.2.0



1344
1345
1346
# File 'lib/canis/core/widgets/rwidget.rb', line 1344

def remove
  @form.remove_widget(self)
end

#repaintObject

default repaint method. Called by form for all widgets.

widget does not have display_length.

Since:

  • 1.2.0



1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
# File 'lib/canis/core/widgets/rwidget.rb', line 1277

def repaint
    r,c = rowcol
    #@bgcolor ||= $def_bg_color # moved down 2011-11-5 
    #@color   ||= $def_fg_color
    _bgcolor = bgcolor()
    _color = color()
    $log.debug("widget repaint : r:#{r} c:#{c} col:#{_color}" )
    value = getvalue_for_paint
    len = @width || value.length
    acolor = @color_pair || get_color($datacolor, _color, _bgcolor)
    @graphic.printstring r, c, "%-*s" % [len, value], acolor, attr()
    # next line should be in same color but only have @att so we can change att is nec
    #@form.window.mvchgat(y=r, x=c, max=len, Ncurses::A_NORMAL, @bgcolor, nil)
end

#repaint_all(tf = true) ⇒ Object

Since:

  • 1.2.0



1407
1408
1409
1410
# File 'lib/canis/core/widgets/rwidget.rb', line 1407

def repaint_all(tf=true)
  @repaint_all = tf
  @repaint_required = tf
end

#repaint_required(tf = true) ⇒ Object

to give simple access to other components, (eg, parent) to tell a comp to either paint its data, or to paint all - borders, headers, footers due to a big change (ht/width)

Since:

  • 1.2.0



1404
1405
1406
# File 'lib/canis/core/widgets/rwidget.rb', line 1404

def repaint_required(tf=true)
  @repaint_required = tf
end

#rowcolObject

row and col is where a widget starts. offsets usually take into account borders. the offsets typically are where the cursor should be positioned inside, upon on_enter.

Returns:

  • row and col of a widget where painting data actually starts

Since:

  • 1.2.0



1259
1260
1261
1262
# File 'lib/canis/core/widgets/rwidget.rb', line 1259

def rowcol
# $log.debug "widgte rowcol : #{@row+@row_offset}, #{@col+@col_offset}"
  return @row+@row_offset, @col+@col_offset
end

#set_form(form) ⇒ Object

in those cases where we create widget without a form, and later give it to some other program which sets the form. Dirty, we should perhaps create widgets without forms, and add explicitly.

Since:

  • 1.2.0



1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
# File 'lib/canis/core/widgets/rwidget.rb', line 1301

def set_form form
  raise "Form is nil in set_form" if form.nil?
  @form = form
  @id = form.add_widget(self) if !form.nil? and form.respond_to? :add_widget
  # 2009-10-29 15:04 use form.window, unless buffer created
  # should not use form.window so explicitly everywhere.
  # added 2009-12-27 20:05 BUFFERED in case child object needs a form.
  # We don;t wish to overwrite the graphic object
  if @graphic.nil?
    #$log.debug " setting graphic to form window for #{self.class}, #{form} "
    @graphic = form.window unless form.nil? # use screen for writing, not buffer
  end
  # execute those actions delayed due to absence of form -- used internally 
  # mostly by buttons and labels to bind hotkey to form
  fire_handler(:FORM_ATTACHED, self) if event? :FORM_ATTACHED
end

#set_form_col(col1 = @curpos) ⇒ Object

set cursor on correct column, widget Ideally, this should be overriden, as it is not likely to be correct. NOTE: this is okay for some widgets but NOT for containers that will call their own components SFR and SFC

Since:

  • 1.2.0



1331
1332
1333
1334
1335
1336
1337
# File 'lib/canis/core/widgets/rwidget.rb', line 1331

def set_form_col col1=@curpos
  @curpos = col1 || 0 # 2010-01-14 21:02 
  #@form.col = @col + @col_offset + @curpos
  c = @col + @col_offset + @curpos
  #$log.warn " #{@name} empty set_form_col #{c}, curpos #{@curpos}  , #{@col} + #{@col_offset} #{@form} "
  setrowcol nil, c
end

#set_form_rowObject

puts cursor on correct row.

Since:

  • 1.2.0



1319
1320
1321
1322
1323
1324
1325
1326
# File 'lib/canis/core/widgets/rwidget.rb', line 1319

def set_form_row
#  @form.row = @row + 1 + @winrow
  #@form.row = @row + 1 
  r, c = rowcol
  #$log.warn " empty set_form_row in widget #{self} r = #{r} , c = #{c}  "
  #raise "trying to set 0, maybe called repaint before container has set value" if row <= 0
  setrowcol row, nil
end

#set_modified(tf = true) ⇒ Object Also known as: modified

Since:

  • 1.2.0



1233
1234
1235
1236
# File 'lib/canis/core/widgets/rwidget.rb', line 1233

def set_modified tf=true
  @modified = tf
  @form.modified = true if tf
end

#setformrowcol(r, c) ⇒ Object

passing a cursor up and adding col and row offsets Added 2010-01-13 13:27 I am checking this out. I would rather pass the value down and store it than do this recursive call + for each cursor display

See Also:

Since:

  • 1.2.0



1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
# File 'lib/canis/core/widgets/rwidget.rb', line 1429

def setformrowcol r, c
      @form.row = r unless r.nil?
      @form.col = c unless c.nil?
      # this is stupid, going through this route i was losing windows top and left
      # And this could get repeated if there are mult objects. 
   if !@parent_component.nil? and @parent_component != self
      r+= @parent_component.form.window.top unless  r.nil?
      c+= @parent_component.form.window.left unless c.nil?
      $log.debug " (#{@name}) calling parents setformrowcol #{r}, #{c} pa: #{@parent_component.name} self: #{name}, #{self.class}, poff #{@parent_component.row_offset}, #{@parent_component.col_offset}, top:#{@form.window.left} left:#{@form.window.left} "
      @parent_component.setformrowcol r, c
   else
      # no more parents, now set form
      $log.debug " name NO MORE parents setting #{r}, #{c}    in #{@form} "
      @form.setrowcol r, c
   end
end

#setrowcol(r, c) ⇒ Object

widget: i am putting one extra level of indirection so i can switch here between form#setrowcol and setformrowcol, since i am not convinced either are giving the accurate result. i am not sure what the issue is.

Since:

  • 1.2.0



1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
# File 'lib/canis/core/widgets/rwidget.rb', line 1448

def setrowcol r, c
    # 2010-02-07 21:32 is this where i should add ext_offsets
   #$log.debug " #{@name}  w.setrowcol #{r} + #{@ext_row_offset}, #{c} + #{@ext_col_offset}  "
   # commented off 2010-02-15 18:22 
   #r += @ext_row_offset unless r.nil?
   #c += @ext_col_offset unless c.nil?
   if @form
     @form.setrowcol r, c
   #elsif @parent_component
   else
     raise "Parent component not defined for #{self}, #{self.class} " unless @parent_component
     @parent_component.setrowcol r, c
   end
   #setformrowcol r,c 
end

#showObject

Since:

  • 1.2.0



1341
1342
1343
# File 'lib/canis/core/widgets/rwidget.rb', line 1341

def show
  @visible = true
end

#unbind_key(keycode) ⇒ Object

remove a binding that you don’t want

Since:

  • 1.2.0



1380
1381
1382
1383
# File 'lib/canis/core/widgets/rwidget.rb', line 1380

def unbind_key keycode
  @_key_args.delete keycode unless @_key_args.nil?
  @_key_map.delete keycode unless @_key_map.nil?
end