Module: Umbra

Defined in:
lib/umbra/box.rb,
lib/umbra.rb,
lib/umbra/pad.rb,
lib/umbra/form.rb,
lib/umbra/menu.rb,
lib/umbra/field.rb,
lib/umbra/field.rb,
lib/umbra/label.rb,
lib/umbra/table.rb,
lib/umbra/button.rb,
lib/umbra/dialog.rb,
lib/umbra/widget.rb,
lib/umbra/window.rb,
lib/umbra/listbox.rb,
lib/umbra/tabular.rb,
lib/umbra/textbox.rb,
lib/umbra/version.rb,
lib/umbra/checkbox.rb,
lib/umbra/multiline.rb,
lib/umbra/messagebox.rb,
lib/umbra/buttongroup.rb,
lib/umbra/radiobutton.rb,
lib/umbra/eventhandler.rb,
lib/umbra/labeledfield.rb,
lib/umbra/togglebutton.rb,
lib/umbra/keymappinghandler.rb

Overview

—————————————————————————– #

       File: keymappinghandler.rb
Description: methods for mapping methods or blocks to keys
     Author: j kepler  http://github.com/mare-imbrium/canis/
       Date: 2018-04-05 - 08:34
    License: MIT
Last update: 2018-04-22 23:01

—————————————————————————– #

keymappinghandler.rb  Copyright (C) 2018 j kepler

Defined Under Namespace

Modules: EventHandler, KeyMappingHandler Classes: Box, Button, ButtonGroup, Checkbox, Dialog, Field, FieldValidationException, Form, InputDataEvent, Label, LabeledField, Listbox, Menu, MessageBox, Multiline, Pad, RadioButton, Table, Tabular, Textbox, ToggleButton, Widget, Window

Constant Summary collapse

BOLD =

attribute constants, use them to specify an attrib for a widget or window.

FFI::NCurses::A_BOLD
REVERSE =
FFI::NCurses::A_REVERSE
UNDERLINE =
FFI::NCurses::A_UNDERLINE
NORMAL =
FFI::NCurses::A_NORMAL
COLOR_BLACK =

color constants, use these when creating a color

FFI::NCurses::BLACK
COLOR_WHITE =
FFI::NCurses::WHITE
COLOR_BLUE =
FFI::NCurses::BLUE
COLOR_RED =
FFI::NCurses::RED
COLOR_GREEN =
FFI::NCurses::GREEN
COLOR_CYAN =
FFI::NCurses::CYAN
COLOR_MAGENTA =
FFI::NCurses::MAGENTA
KEY_ENTER =

key constants

13
KEY_RETURN =

FFI::NCurses::KEY_ENTER is 343 ???

10
CP_BLACK =

In case, the init_pairs are changed, then update these as well, so that the programs use the correct pairs.

0
CP_RED =
1
CP_GREEN =
2
CP_YELLOW =
3
CP_BLUE =
4
CP_MAGENTA =
5
CP_CYAN =
6
CP_WHITE =
7
VERSION =
"0.1.4"

Instance Method Summary collapse

Instance Method Details

#alert(str, config = {}) ⇒ Object



12
13
14
15
16
17
18
19
20
21
22
23
24
# File 'lib/umbra.rb', line 12

def alert str, config={}
  require 'umbra/dialog'

  config[:text]              ||= str
  config[:title]             ||= "Alert"
  config[:window_color_pair] ||=  create_color_pair( COLOR_BLUE, COLOR_WHITE )
  config[:window_attr]       ||= NORMAL
  config[:buttons]           ||= ["Ok"]

  #m = Dialog.new text: str, title: title, window_color_pair: cp, window_attr: attr
  m = Dialog.new config
  m.run
end

#confirm(str, config = {}) ⇒ Object

confirmation dialog which prompts message with Ok and Cancel and returns true or false.



27
28
29
30
31
32
33
34
35
36
37
38
39
# File 'lib/umbra.rb', line 27

def confirm str, config={}
  require 'umbra/dialog'

  config[:text]              ||= str
  config[:title]             ||= "Confirm"
  config[:window_color_pair] ||=  create_color_pair( COLOR_BLUE, COLOR_WHITE )
  config[:window_attr]       ||= NORMAL
  config[:buttons]           ||= ["Ok", "Cancel"]

  m = Dialog.new config
  ret = m.run
  return ret == 0
end

#create_centered_window(height, width, color_pair = 0, attrib = REVERSE) ⇒ Object

create a centered window. # {{{ NOTE: this should probably go into window class, or some util class.



169
170
171
172
173
174
175
176
177
# File 'lib/umbra/dialog.rb', line 169

def create_centered_window height, width, color_pair=0, attrib=REVERSE
  row = ((FFI::NCurses.LINES-height)/2).floor
  col = ((FFI::NCurses.COLS-width)/2).floor
  win = Window.new  height, width, row, col
  #FFI::NCurses.wbkgd(win.pointer, FFI::NCurses.COLOR_PAIR(0) | REVERSE); #  does not work on xterm-256color
  FFI::NCurses.wbkgd(win.pointer, FFI::NCurses.COLOR_PAIR(color_pair) | attrib); #  does not work on xterm-256color
  #FFI::NCurses.wbkgd(win.pointer, color_pair | attrib)
  return win
end

#create_color_pair(bgcolor, fgcolor) ⇒ Integer

create and return a color_pair for a combination of bg and fg. This will always return the same color_pair so a duplicate one will not be created.

Parameters:

  • bgcolor (Integer)

    color of background e.g., COLOR_BLACK

  • fgcolor (Integer)

    color of foreground e.g., COLOR_WHITE

Returns:

  • (Integer)
    • color_pair which can be passed to #printstring, or used directly as #COLOR_PAIR(int)



107
108
109
110
111
# File 'lib/umbra/window.rb', line 107

def create_color_pair(bgcolor, fgcolor)
  code = (bgcolor*10) + fgcolor
  FFI::NCurses.init_pair(code, fgcolor, bgcolor)
  return code
end

#create_logger(path, config = {}) ⇒ Object

create a logger instance given a path, return the logger NOTE: Ideally would like to set $log here to this, but what if user creates multiple.



89
90
91
92
93
94
95
96
97
98
# File 'lib/umbra.rb', line 89

def create_logger path, config={}
  require 'logger'
  _path   = File.open(path, File::WRONLY|File::TRUNC|File::CREAT) 
  logg = Logger.new(_path)
  raise "Could not create logger: #{path}" unless logg
  ## if not set, will default to 0 which is debug. Other values are 1 - info, 2 - warn
  logg.level = config[:level] ||  ENV["UMBRA_LOG_LEVEL"].to_i
  #logg.info "START -- #{$0} log level: #{logg.level}. To change log level, increase UMBRA_LOG_LEVEL in your environment to 1 or 2 or 3."
  return logg
end

#cursesObject



8
9
10
# File 'lib/umbra.rb', line 8

def curses
  FFI::NCurses
end

#get_string(label, config = {}) ⇒ Object



67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
# File 'lib/umbra.rb', line 67

def get_string label, config={}
  require 'umbra/messagebox'
  config[:title]             ||= "Entry"
  config[:buttons]           ||= ["Ok", "Cancel"]
  fld = nil
  mb = MessageBox.new config do 
    add Label.new text: label, row: 2, col: 2
    fld = Field.new name: "field", row: 3, col: 2
    add fld
  end
  index = mb.run
  if index == 0
    return fld.text
  else
    return nil
  end
end

#init_cursesObject

Initialize ncurses before any program. Reduce the value of $ncurses_timeout if you want a quicker response to Escape keys or continuous updates. I have set the default to 1000.



37
38
39
40
41
42
43
44
45
46
47
48
49
# File 'lib/umbra/window.rb', line 37

def init_curses
  FFI::NCurses.initscr
  FFI::NCurses.curs_set 1
  FFI::NCurses.raw
  FFI::NCurses.noecho
  FFI::NCurses.keypad FFI::NCurses.stdscr, true
  FFI::NCurses.scrollok FFI::NCurses.stdscr, true
  if FFI::NCurses.has_colors
    FFI::NCurses.start_color
    std_colors
  end

end

#main_loop(form) { ... } ⇒ Object

Trying out a key loop to simplify matters for user. NOT TESTED.

Yields:

  • key pressed if block given, else calls form.handle_key(ch).



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
127
128
129
130
131
132
133
134
135
136
137
# File 'lib/umbra.rb', line 102

def main_loop form, &block
  win = form.window
  form.repaint
  win.wrefresh
  stopping = false
  while true
    catch :close do
      while( ch = win.getkey) != 999
        next if ch == -1      ## should we put this here ???
        begin
          if ch == curses::KEY_CTRL_Q
            stopping = true 
            break
          end
          if block_given?
            yield ch
          else
            form.handle_key ch
          end
        rescue => err
          if $log
            $log.debug( "loop in umbra.rb handle_key rescue reached ")
            $log.debug( err.to_s) 
            $log.debug(err.backtrace.join("\n")) 
          end
          textdialog [err.to_s, *err.backtrace], :title => "Exception"
        end
        win.wrefresh
      end
      #stopping = win.fire_close_handler  ## TODO next version
      #win.wrefresh
      break if stopping
    end
    break if stopping
  end
end

#startupObject



301
302
303
304
305
306
307
308
309
310
311
# File 'lib/umbra/pad.rb', line 301

def startup
  require 'logger'
  require 'date'

  path = File.join(ENV["LOGDIR"] || "./" ,"v.log")
  file   = File.open(path, File::WRONLY|File::TRUNC|File::CREAT) 
  $log = Logger.new(path)
  $log.level = Logger::DEBUG
  today = Time.now.to_s
  $log.info "Pad demo #{$0} started on #{today}"
end

#std_colorsObject

defining various colors NOTE this should be done by application or else we will be changing this all the time.



71
72
73
74
75
76
77
78
79
80
81
82
83
# File 'lib/umbra/window.rb', line 71

def std_colors
  FFI::NCurses.use_default_colors
  # 2018-03-17 - changing it to ncurses defaults
  FFI::NCurses.init_pair(0,  FFI::NCurses::BLACK,   -1)
  FFI::NCurses.init_pair(1,  FFI::NCurses::RED,   -1)
  FFI::NCurses.init_pair(2,  FFI::NCurses::GREEN,     -1)
  FFI::NCurses.init_pair(3,  FFI::NCurses::YELLOW,   -1)
  FFI::NCurses.init_pair(4,  FFI::NCurses::BLUE,    -1)
  FFI::NCurses.init_pair(5,  FFI::NCurses::MAGENTA,  -1)
  FFI::NCurses.init_pair(6,  FFI::NCurses::CYAN,    -1)
  FFI::NCurses.init_pair(7,  FFI::NCurses::WHITE,    -1)
  FFI::NCurses.init_pair(14,  FFI::NCurses::WHITE,    FFI::NCurses::CYAN)
end

#textdialog(array, config = {}) ⇒ Object

Pop up a dialog with an array, such as an exception



42
43
44
45
46
47
48
49
50
51
# File 'lib/umbra.rb', line 42

def textdialog array, config={}
  require 'umbra/messagebox'
  config[:title]             ||= "Alert"
  config[:buttons]           ||= ["Ok"]

  mb = MessageBox.new config do
    text array
  end
  mb.run
end

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

view an array in a popup window



54
55
56
57
58
59
60
61
62
63
64
65
# File 'lib/umbra.rb', line 54

def view array, config={}, &block
  require 'umbra/pad'
  config[:title] ||= "Viewer"
  config[:color_pair] ||= create_color_pair( COLOR_BLUE, COLOR_WHITE )
  config[:attrib]     ||= NORMAL
  config[:list]       = array
  config[:height]     ||= FFI::NCurses.LINES-2
  config[:width]      ||= FFI::NCurses.COLS-10
  #m = Pad.new list: array, height: FFI::NCurses.LINES-2, width: FFI::NCurses.COLS-10, title: title, color_pair: cp, attrib: attr
  m = Pad.new config, &block
  m.run
end