Class: RNDK::Screen
- Inherits:
-
Object
- Object
- RNDK::Screen
- Defined in:
- lib/rndk/core/screen.rb,
lib/rndk/core/quick_widgets.rb
Overview
Placeholder for RNDK Widgets.
Since all Widgets are bonded to a Screen, you pretty much won't need to call any of the methods here.
The only methods you should worry about are:
- Screen#initialize
- Screen#finish
- Screen#draw or #refresh
- Screen#erase
Developer Notes
When a Widget is created, it calls Screen#register with it's type and self pointer.
That adds the widget pointer to an Array @widget
that
contains all the widgets inside this screen.
During it's lifetime, most widgets would call only Screen#erase and Screen#refresh.
When Widget#destroy is called, we call Screen#unregister to
remove it from the @widget
array.
Now, what happens when the Ruby garbage collector kills the widget?
Constant Summary collapse
- NOEXIT =
0
- EXITOK =
1
- EXITCANCEL =
2
Instance Attribute Summary collapse
-
#exit_status ⇒ Object
Nothing...
-
#widget ⇒ Object
Array with all the widgets currently on the screen.
-
#widget_count ⇒ Object
How many widgets we currently have.
-
#widget_focus ⇒ Object
Index of the current focused widget.
-
#widget_limit ⇒ Object
Maximum widget capacity of the screen (always expands).
-
#window ⇒ Object
Raw Ncurses window that represents this Screen.
Class Method Summary collapse
-
.finish ⇒ Object
Shuts down RNDK and Ncurses, plus destroying all the widgets ever created.
-
.height ⇒ Object
Returns the whole terminal screen height.
-
.lower_widget(widget) ⇒ Object
Has the opposite effect of #raise_widget.
-
.raise_widget(widget) ⇒ Object
Raises the Widget to the top of the screen.
-
.width ⇒ Object
Returns the whole terminal screen width.
Instance Method Summary collapse
-
#cleanly(&block) ⇒ Object
Executes a block of code without modifying the screen state.
-
#destroy ⇒ Object
Destroys this Screen.
-
#destroy_widgets ⇒ Object
Destroys all the Widgets inside this Screen.
-
#draw ⇒ Object
Redraws all Widgets inside this Screen.
-
#erase ⇒ Object
Erases all Widgets inside this Screen.
-
#get_list_index(title, list, numbers) ⇒ Object
Display a scrollable
list
of strings in a Dialog, allowing the user to select one. -
#get_string(title, label, initial_text = "") ⇒ Object
Pops up an Entry Widget and returns the value supplied by the user.
-
#initialize(ncurses_window = nil) ⇒ Screen
constructor
Takes a Ncurses
WINDOW*
pointer and creates a CDKScreen. -
#popup_dialog(message, buttons) ⇒ Object
Shows a centered pop-up Dialog box with
message
label and each button label onbuttons
. -
#popup_label(message) ⇒ Object
Quickly pops up a
message
. -
#popup_label_color(message, attrib) ⇒ Object
Quickly pops up a
message
, usingattrib
for the background of the dialog. -
#refresh ⇒ Object
Redraws all Widgets inside this Screen.
-
#register(rndktype, widget) ⇒ Object
Adds a Widget to this Screen.
-
#select_file(title) ⇒ Object
Displays a file-selection dialog with
title
. -
#unregister(widget) ⇒ Object
Removes a Widget from this Screen.
-
#view_file(title, filename, buttons) ⇒ Object
Reads
filename
's contents and display it on a Viewer Widget. -
#view_info(title, info, buttons, hide_control_chars = true) ⇒ Object
Display a long string set
info
in a Viewer Widget.
Constructor Details
#initialize(ncurses_window = nil) ⇒ Screen
Takes a Ncurses WINDOW*
pointer and creates a CDKScreen.
This also starts Ncurses, if it wasn't started before or
no WINDOW*
were provided
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 |
# File 'lib/rndk/core/screen.rb', line 72 def initialize(ncurses_window=nil) # If the user didn't start Ncurses for us, # we'll do it anyway. if RNDK::ALL_SCREENS.empty? or ncurses_window.nil? ## Why is this here? # Set up basic curses settings. # #ifdef HAVE_SETLOCALE # setlocale (LC_ALL, ""); # #endif ncurses_window = Ncurses.initscr Ncurses.noecho Ncurses.cbreak Ncurses.keypad(ncurses_window, true) end RNDK::ALL_SCREENS << self @widget_count = 0 @widget_limit = 2 @widget = Array.new(@widget_limit, nil) @window = ncurses_window @widget_focus = 0 end |
Instance Attribute Details
#exit_status ⇒ Object
Nothing... for now
51 52 53 |
# File 'lib/rndk/core/screen.rb', line 51 def exit_status @exit_status end |
#widget ⇒ Object
Array with all the widgets currently on the screen
45 46 47 |
# File 'lib/rndk/core/screen.rb', line 45 def @widget end |
#widget_count ⇒ Object
How many widgets we currently have
39 40 41 |
# File 'lib/rndk/core/screen.rb', line 39 def @widget_count end |
#widget_focus ⇒ Object
Index of the current focused widget
36 37 38 |
# File 'lib/rndk/core/screen.rb', line 36 def @widget_focus end |
#widget_limit ⇒ Object
Maximum widget capacity of the screen (always expands)
42 43 44 |
# File 'lib/rndk/core/screen.rb', line 42 def @widget_limit end |
#window ⇒ Object
Raw Ncurses window that represents this Screen
48 49 50 |
# File 'lib/rndk/core/screen.rb', line 48 def window @window end |
Class Method Details
.finish ⇒ Object
Shuts down RNDK and Ncurses, plus destroying all the widgets ever created.
100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 |
# File 'lib/rndk/core/screen.rb', line 100 def self.finish ## If I do this it gives me a segmentation fault. ## I guess that would happen because of the ## ruby garbage collector. ## ## What should I do instead? # # RNDK::ALL_WIDGETS.each { |obj| obj.destroy } # RNDK::ALL_SCREENS.each { |scr| scr.destroy } Ncurses.echo Ncurses.nocbreak Ncurses.endwin end |
.height ⇒ Object
Returns the whole terminal screen height.
63 64 65 |
# File 'lib/rndk/core/screen.rb', line 63 def self.height Ncurses.LINES end |
.lower_widget(widget) ⇒ Object
Has the opposite effect of #raise_widget.
194 195 196 197 198 |
# File 'lib/rndk/core/screen.rb', line 194 def self. return unless .valid_type? .screen.swap_indexes(.screen_index, 0) end |
.raise_widget(widget) ⇒ Object
Raises the Widget to the top of the screen. It will now overlap any other obstructing Widgets.
rndktype
states what RNDK Widget type this widget is.
widget
is a pointer to the Widget itself.
186 187 188 189 190 191 |
# File 'lib/rndk/core/screen.rb', line 186 def self. return unless .valid_type? screen = .screen screen.swap_indexes(.screen_index, screen. - 1) end |
.width ⇒ Object
Returns the whole terminal screen width.
58 59 60 |
# File 'lib/rndk/core/screen.rb', line 58 def self.width Ncurses.COLS end |
Instance Method Details
#cleanly(&block) ⇒ Object
Executes a block of code without modifying the screen state.
See usage right below.
32 33 34 35 36 37 38 39 40 |
# File 'lib/rndk/core/quick_widgets.rb', line 32 def cleanly &block prev_state = Ncurses.curs_set 0 yield Ncurses.curs_set prev_state self.erase self.refresh end |
#destroy ⇒ Object
It does nothing to the widgets inside it. You must either destroy them separatedly or call #destroy_widgets before.
Destroys this Screen.
276 277 278 |
# File 'lib/rndk/core/screen.rb', line 276 def destroy RNDK::ALL_SCREENS.delete self end |
#destroy_widgets ⇒ Object
Destroys all the Widgets inside this Screen.
258 259 260 261 262 263 264 265 266 267 268 269 |
# File 'lib/rndk/core/screen.rb', line 258 def (0...@widget_count).each do |x| obj = @widget[x] before = @widget_count if obj.valid_type? obj.erase obj.destroy x -= (@widget_count - before) end end end |
#draw ⇒ Object
Redraws all Widgets inside this Screen.
201 202 203 |
# File 'lib/rndk/core/screen.rb', line 201 def draw self.refresh end |
#erase ⇒ Object
Erase in the sense of clearing the actual characters on the terminal screen. This does NOT destroy any widgets.
Erases all Widgets inside this Screen.
249 250 251 252 253 254 255 |
# File 'lib/rndk/core/screen.rb', line 249 def erase (0...@widget_count).each do |x| obj = @widget[x] obj.erase if obj.valid_type? end Ncurses.wrefresh(@window) end |
#get_list_index(title, list, numbers) ⇒ Object
list
must be Arrays of Strings.
Display a scrollable list
of strings in a Dialog, allowing
the user to select one.
If numbers
is true, the displayed list items will
be numbered.
227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 |
# File 'lib/rndk/core/quick_widgets.rb', line 227 def get_list_index(title, list, numbers) return nil if list.class != Array or list.empty? selected = -1 height = 10 width = -1 len = 0 # Determine the height of the list. if list.size < 10 height = list.size + if title.size == 0 then 2 else 3 end end # Determine the width of the list. list.each { |item| width = [width, item.size + 10].max } width = [width, title.size].max width += 5 scrollp = RNDK::Scroll.new(self, { :x => RNDK::CENTER, :y => RNDK::CENTER, :width => width, :height => height, :title => title, :items => list, :numbers => numbers }) if scrollp.nil? self.refresh return -1 end selected = scrollp.activate # Check how they exited. if scrollp.exit_type != :NORMAL selected = -1 end scrollp.destroy self.refresh selected end |
#get_string(title, label, initial_text = "") ⇒ Object
Pops up an Entry Widget and returns the value supplied by the user.
title
, label
and initial_text
are passed to the Widget.
277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 |
# File 'lib/rndk/core/quick_widgets.rb', line 277 def get_string(title, label, initial_text="") = RNDK::Entry.new(self, { :x => RNDK::CENTER, :y => RNDK::CENTER, :title => title, :label => label, :field_width => 40, :initial_text => initial_text }) value = .activate # Make sure they exited normally. if .exit_type != :NORMAL .destroy return nil end # Return a copy of the string typed in. value = .get_text.clone .destroy value end |
#popup_dialog(message, buttons) ⇒ Object
Shows a centered pop-up Dialog box with message
label and
each button label on buttons
.
@note: message
and buttons
must be Arrays of Strings.
93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 |
# File 'lib/rndk/core/quick_widgets.rb', line 93 def popup_dialog(, ) return nil if .empty? or .empty? choice = 0 self.cleanly do popup = RNDK::Dialog.new(self, { :x => RNDK::CENTER, :y => RNDK::CENTER, :text => , :buttons => }) popup.draw choice = popup.activate popup.destroy end choice end |
#popup_label(message) ⇒ Object
Quickly pops up a message
.
Creates a centered pop-up Label Widget that waits until the user hits a character.
@note: message
must be a String or an Array of Strings.
48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 |
# File 'lib/rndk/core/quick_widgets.rb', line 48 def popup_label self.cleanly do popup = RNDK::Label.new(self, { :x => RNDK::CENTER, :y => RNDK::CENTER, :text => }) popup.draw # Wait for some input. Ncurses.keypad(popup.win, true) popup.getch popup.destroy end end |
#popup_label_color(message, attrib) ⇒ Object
Quickly pops up a message
, using attrib
for
the background of the dialog.
@note: message
must be an array of strings.
68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 |
# File 'lib/rndk/core/quick_widgets.rb', line 68 def popup_label_color(, attrib) self.cleanly do popup = RNDK::Label.new(self, { :x => RNDK::CENTER, :y => RNDK::CENTER, :text => }) popup.set_bg_color attrib popup.draw # Wait for some input Ncurses.keypad(popup.win, true) popup.getch popup.destroy end end |
#refresh ⇒ Object
Redraws all Widgets inside this Screen.
206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 |
# File 'lib/rndk/core/screen.rb', line 206 def refresh focused = -1 visible = -1 RNDK.window_refresh(@window) # We erase all the invisible widgets, then only draw it all back, so # that the widgets can overlap, and the visible ones will always be # drawn after all the invisible ones are erased (0...@widget_count).each do |x| obj = @widget[x] if obj.valid_type? if obj.is_visible if visible < 0 visible = x end if obj.has_focus && focused < 0 focused = x end else obj.erase end end end (0...@widget_count).each do |x| obj = @widget[x] if obj.valid_type? obj.has_focus = (x == focused) if obj.is_visible obj.draw end end end end |
#register(rndktype, widget) ⇒ Object
This is called automatically when a widget is created.
Adds a Widget to this Screen.
rndktype
states what RNDK Widget type this widget is.widget
is a pointer to the Widget itself.
123 124 125 126 127 128 129 130 131 132 133 134 135 136 |
# File 'lib/rndk/core/screen.rb', line 123 def register(rndktype, ) # Expanding the limit by 2 if (@widget_count + 1) >= @widget_limit @widget_limit += 2 @widget_limit *= 2 @widget.concat Array.new(@widget_limit - @widget.size, nil) end if .valid_type? self.set_screen_index(@widget_count, ) @widget_count += 1 end end |
#select_file(title) ⇒ Object
Displays a file-selection dialog with title
.
TODO FIXME This widget is VERY buggy.
192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 |
# File 'lib/rndk/core/quick_widgets.rb', line 192 def select_file title fselect = RNDK::Fselect.new(self, { :x => RNDK::CENTER, :y => RNDK::CENTER, :width =>-20, :height => -4, :title => title, :label => 'File: ' }) filename = fselect.activate # Check the way the user exited the selector. if fselect.exit_type != :NORMAL fselect.destroy self.refresh return nil end # Otherwise... fselect.destroy self.refresh filename end |
#unregister(widget) ⇒ Object
This is called automatically when a widget is destroyed.
Removes a Widget from this Screen.
This does NOT destroy the widget, it removes the Widget from any further refreshes by Screen#refresh.
rndktype
states what RNDK Widget type this widget is.
widget
is a pointer to the Widget itself.
148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 |
# File 'lib/rndk/core/screen.rb', line 148 def unregister return unless (.valid_type? and (.screen_index >= 0)) index = .screen_index .screen_index = -1 # Resequence the widgets (index...self. - 1).each do |x| self.set_screen_index(x, self.[x+1]) end if self. <= 1 # if no more widgets, remove the array self. = [] self. = 0 self. = 0 else self.[self.] = nil self. -= 1 # Update the widget-focus if self. == index self. -= 1 Traverse.set_next_focus(screen) elsif self. > index self. -= 1 end end end |
#view_file(title, filename, buttons) ⇒ Object
Reads filename
's contents and display it on a Viewer Widget.
title
and buttons
are applied to the Widget.
The viewer shows the contents of the file supplied by the
filename
value.
It returns the index of the button selected, or -1 if the file does not exist or if the widget was exited early.
166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 |
# File 'lib/rndk/core/quick_widgets.rb', line 166 def view_file(title, filename, ) info = [] result = 0 # Open the file and read the contents. lines = RNDK.read_file filename # If we couldn't read the file, return an error. if lines == -1 result = lines else result = self.view_info(title, info, , true) end result end |
#view_info(title, info, buttons, hide_control_chars = true) ⇒ Object
info
and buttons
must be Arrays of Strings.
Display a long string set info
in a Viewer Widget.
title
and buttons
are applied to the Widget.
hide_control_chars
tells if we want to hide those
ugly ^J
, ^M
chars.
121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 |
# File 'lib/rndk/core/quick_widgets.rb', line 121 def view_info(title, info, , hide_control_chars=true) return nil if info.class != Array or info.empty? return nil if .class != Array or .empty? selected = -1 # Create the file viewer to view the file selected. viewer = RNDK::Viewer.new(self, { :x => RNDK::CENTER, :y => RNDK::CENTER, :width => -6, :height => -16, :buttons => , :shadow => true }) # Set up the viewer title, and the contents of the widget. viewer.set({ :title => title, :items => info, :hide_control_chars => hide_control_chars }) selected = viewer.activate # Make sure they exited normally. if viewer.exit_type != :NORMAL viewer.destroy return -1 end # Clean up and return the button index selected viewer.destroy selected end |