Class: RETerm::Window
- Inherits:
-
Object
- Object
- RETerm::Window
- Includes:
- EventDispatcher, LogHelpers
- Defined in:
- lib/reterm/window.rb
Overview
Windows are areas rendered on screen, associated with components to be rendered in them. They specify the position to start drawing component as well as the maximum width and height. A border may be drawn around a window and a ColorPair associated.
If Layout is added to a Window, children may subsequently be added. This should be performed via the Layout#add_child method.
Constant Summary
Constants included from LogHelpers
Instance Attribute Summary collapse
-
#children ⇒ Object
Returns the value of attribute children.
-
#cols ⇒ Object
Returns the value of attribute cols.
-
#component ⇒ Object
Returns the value of attribute component.
-
#hborder ⇒ Object
Returns the value of attribute hborder.
-
#parent ⇒ Object
readonly
Returns the value of attribute parent.
-
#rows ⇒ Object
Returns the value of attribute rows.
-
#vborder ⇒ Object
Returns the value of attribute vborder.
-
#win ⇒ Object
readonly
Returns the value of attribute win.
-
#window_id ⇒ Object
readonly
Returns the value of attribute window_id.
-
#x ⇒ Object
Returns the value of attribute x.
-
#y ⇒ Object
Returns the value of attribute y.
Class Method Summary collapse
-
.adjust_proportional(parent, rows, cols) ⇒ Object
Adjusts rows/cols in a context dependent manner TODO should proporational percentage be of remaining area?.
-
.align(parent, x, y, rows, cols) ⇒ Object
Adjusts x/y in context dependent manner.
-
.all ⇒ Object
Static method returning all tracked windows.
-
.fill_parent(parent, x, y, rows, cols) ⇒ Object
Adjusts rows / cols so as to fill parent.
-
.top ⇒ Object
Static method returning top level windows.
Instance Method Summary collapse
-
#activate!(*input) ⇒ Object
Activate window component.
-
#actual_cols ⇒ Object
Return window cols.
-
#actual_rows ⇒ Object
Return window rows.
-
#bold! ⇒ Object
Enable bold formatting.
-
#border! ⇒ Object
Draw Border around window.
-
#cdk? ⇒ Boolean
Return bool indicating if cdk is enabled for this window/component.
-
#cdk_scr ⇒ Object
Return cdk screen (only used by CDK components).
-
#child_containing(x, y, z) ⇒ Object
Return child containing specified screen coordiantes, else nil.
-
#children? ⇒ Boolean
Return boolean indicating if this window has children.
-
#clear! ⇒ Object
Clear window by removing all children and reinitializing window space.
-
#colored? ⇒ Boolean
Return bool indiciating if colors are set.
-
#colors=(c) ⇒ Object
Set window color.
-
#component? ⇒ Boolean
Return bool indicating if this window has a component associated with it.
-
#create_child(h = {}) ⇒ Object
Create child window, this method should not be invoked by end-user, rather it is is invoked the Layout#add_child is called.
-
#del_child(child) ⇒ Object
Remove child window, like #create_child, this is used internally and should not be invoked by the end user.
-
#dimensions ⇒ Object
Return window dimensions as an array containing rows & cols.
- #distance_from(win) ⇒ Object
-
#draw! ⇒ Object
Draw component in window.
-
#erase ⇒ Object
Erase window drawing area.
-
#erase_scr ⇒ Object
Erases window screen by overwriting it with blanks.
- #expand? ⇒ Boolean
-
#finalize! ⇒ Object
Invoke window finalization routine by destroying it and all children.
-
#first_child? ⇒ Boolean
Return boolean indicating if this window is the first child of its parent.
-
#getch ⇒ Object
Blocking call to capture next character from window.
-
#initialize(args = {}) ⇒ Window
constructor
Instantiate Window with given args.
-
#last_child? ⇒ Boolean
Return boolean indicating if this window is the last child of its parent.
- #must_expand? ⇒ Boolean
-
#mvaddstr(*a) ⇒ Object
Write string at specified loc.
-
#no_bold! ⇒ Object
Disable bold formatting.
-
#no_border! ⇒ Object
Remove Border around window.
-
#no_reverse! ⇒ Object
Disabled reverse formatting.
- #noutrefresh ⇒ Object
-
#parent? ⇒ Boolean
Return boolean if this window is a child of another.
-
#refresh ⇒ Object
Refresh / resynchronize window and all children.
- #request_expansion(r, c) ⇒ Object
- #resize(rows, cols) ⇒ Object
-
#reverse! ⇒ Object
Enable reverse formatting.
-
#root ⇒ Object
Return root window (recusively), self if parent is not set.
-
#sync! ⇒ Object
Dispatch to component synchronization.
-
#sync_getch ⇒ Object
Normal getch unless sync enabled in which case, timeout will be checked & components synchronized.
- #total_x ⇒ Object
- #total_y ⇒ Object
Methods included from LogHelpers
Methods included from EventDispatcher
Constructor Details
#initialize(args = {}) ⇒ Window
Instantiate Window with given args. None are required, but unless :rows, :cols, :x, or :y is specified, window will be created in it’s default position.
This method will generate a unique id for each window and add it to a static registry for subsequent tracking.
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 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 |
# File 'lib/reterm/window.rb', line 130 def initialize(args={}) @@registry ||= [] @@registry << self @@wid ||= 0 @@wid += 1 @window_id = @@wid @children = [] @x = args[:x] || 0 @y = args[:y] || 0 @vborder = args[:vborder] || 0 @hborder = args[:hborder] || 0 component = args[:component] @rows = args[:rows] || (component ? (component.requested_rows + component.extra_padding) : Terminal.rows) @cols = args[:cols] || (component ? (component.requested_cols + component.extra_padding) : Terminal.cols) if args[:parent] @parent = args[:parent] @rows, @cols = *Window.adjust_proportional(@parent, @rows, @cols) @x, @y = *Window.align(@parent, @x, @y, @rows, @cols) @win = parent.win.derwin(@rows, @cols, @y, @x) else @parent = nil @rows, @cols = *Window.adjust_proportional(Terminal, @rows, @cols) @x, @y = *Window.align(Terminal, @x, @y, @rows, @cols) @win = Ncurses::WINDOW.new(@rows, @cols, @y, @x) end raise ArgumentError, "could not create window" if !@win self.component = component if !!component Ncurses::keypad(@win, true) @win.timeout(SYNC_TIMEOUT) if sync_enabled? # XXX @expand = !!args[:expand] @must_expand = !!args[:must_expand] @fill = !!args[:fill] end |
Instance Attribute Details
#children ⇒ Object
Returns the value of attribute children.
43 44 45 |
# File 'lib/reterm/window.rb', line 43 def children @children end |
#cols ⇒ Object
Returns the value of attribute cols.
32 33 34 |
# File 'lib/reterm/window.rb', line 32 def cols @cols end |
#component ⇒ Object
Returns the value of attribute component.
38 39 40 |
# File 'lib/reterm/window.rb', line 38 def component @component end |
#hborder ⇒ Object
Returns the value of attribute hborder.
36 37 38 |
# File 'lib/reterm/window.rb', line 36 def hborder @hborder end |
#parent ⇒ Object (readonly)
Returns the value of attribute parent.
42 43 44 |
# File 'lib/reterm/window.rb', line 42 def parent @parent end |
#rows ⇒ Object
Returns the value of attribute rows.
32 33 34 |
# File 'lib/reterm/window.rb', line 32 def rows @rows end |
#vborder ⇒ Object
Returns the value of attribute vborder.
35 36 37 |
# File 'lib/reterm/window.rb', line 35 def vborder @vborder end |
#win ⇒ Object (readonly)
Returns the value of attribute win.
40 41 42 |
# File 'lib/reterm/window.rb', line 40 def win @win end |
#window_id ⇒ Object (readonly)
Returns the value of attribute window_id.
30 31 32 |
# File 'lib/reterm/window.rb', line 30 def window_id @window_id end |
#x ⇒ Object
Returns the value of attribute x.
33 34 35 |
# File 'lib/reterm/window.rb', line 33 def x @x end |
#y ⇒ Object
Returns the value of attribute y.
33 34 35 |
# File 'lib/reterm/window.rb', line 33 def y @y end |
Class Method Details
.adjust_proportional(parent, rows, cols) ⇒ Object
Adjusts rows/cols in a context dependent manner TODO should proporational percentage be of remaining area?
193 194 195 196 197 198 199 200 201 |
# File 'lib/reterm/window.rb', line 193 def self.adjust_proportional(parent, rows, cols) nr = rows nc = cols nr = parent.rows * nr if rows < 1 nc = parent.cols * nc if cols < 1 return nr, nc end |
.align(parent, x, y, rows, cols) ⇒ Object
Adjusts x/y in context dependent manner
204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 |
# File 'lib/reterm/window.rb', line 204 def self.align(parent, x, y, rows, cols) nx = x ny = y nx = 1 if x == :left ny = 1 if y == :top nx = parent.cols - cols - 1 if x == :right ny = parent.rows - rows - 1 if y == :bottom nx = parent.cols / 2 - cols / 2 if x == :center ny = parent.rows / 2 - rows / 2 if y == :center return nx, ny end |
.all ⇒ Object
Static method returning all tracked windows
303 304 305 306 |
# File 'lib/reterm/window.rb', line 303 def self.all @@registry ||= [] @@registry end |
.fill_parent(parent, x, y, rows, cols) ⇒ Object
Adjusts rows / cols so as to fill parent
221 222 223 224 225 226 227 228 229 230 231 |
# File 'lib/reterm/window.rb', line 221 def self.fill_parent(parent, x, y, rows, cols) if (y + rows) < parent.rows rows = parent.rows - y - 1 end if (x + cols) < parent.cols cols = parent.cols - x - 1 end return rows, cols end |
.top ⇒ Object
Static method returning top level windows
309 310 311 312 |
# File 'lib/reterm/window.rb', line 309 def self.top @@registry ||= [] @@registry.select { |w| !w.parent? } end |
Instance Method Details
#activate!(*input) ⇒ Object
Activate window component
530 531 532 |
# File 'lib/reterm/window.rb', line 530 def activate!(*input) component.activate!(*input) end |
#actual_cols ⇒ Object
Return window cols
520 521 522 |
# File 'lib/reterm/window.rb', line 520 def actual_cols dimensions[1] end |
#actual_rows ⇒ Object
Return window rows
515 516 517 |
# File 'lib/reterm/window.rb', line 515 def actual_rows dimensions[0] end |
#bold! ⇒ Object
Enable bold formatting
460 461 462 463 464 465 466 |
# File 'lib/reterm/window.rb', line 460 def bold! @win.attron(Ncurses::A_BOLD) return unless block_given? yield @win.attroff(Ncurses::A_BOLD) end |
#border! ⇒ Object
Draw Border around window
423 424 425 |
# File 'lib/reterm/window.rb', line 423 def border! @win.box(@vborder, @hborder) end |
#cdk? ⇒ Boolean
Return bool indicating if cdk is enabled for this window/component
296 297 298 |
# File 'lib/reterm/window.rb', line 296 def cdk? !!@cdk_scr end |
#cdk_scr ⇒ Object
Return cdk screen (only used by CDK components)
290 291 292 293 |
# File 'lib/reterm/window.rb', line 290 def cdk_scr enable_cdk! @cdk_scr ||= CDK::SCREEN.new(@win) end |
#child_containing(x, y, z) ⇒ Object
Return child containing specified screen coordiantes, else nil
336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 |
# File 'lib/reterm/window.rb', line 336 def child_containing(x, y, z) found = nil children.find { |c| next if found # recursively descend into layout children if c.component.kind_of?(Layout) found = c.child_containing(x, y, z) else found = c.total_x <= x && c.total_y <= y && # c.z >= z (c.total_x + c.cols) >= x && (c.total_y + c.rows) >= y found = c if found end } found end |
#children? ⇒ Boolean
Return boolean indicating if this window has children
67 68 69 |
# File 'lib/reterm/window.rb', line 67 def children? !@children.empty? end |
#clear! ⇒ Object
Clear window by removing all children and reinitializing window space
371 372 373 374 375 376 377 378 |
# File 'lib/reterm/window.rb', line 371 def clear! children.each { |c| del_child(c) } @children = [] erase end |
#colored? ⇒ Boolean
Return bool indiciating if colors are set
488 489 490 |
# File 'lib/reterm/window.rb', line 488 def colored? !!@colors end |
#colors=(c) ⇒ Object
Set window color
493 494 495 496 497 498 499 500 501 502 |
# File 'lib/reterm/window.rb', line 493 def colors=(c) @colors = c.is_a?(ColorPair) ? c : ColorPair.for(c).first @win.bkgd(Ncurses.COLOR_PAIR(@colors.id)) unless @win.nil? component.colors = @colors if component? children.each { |ch| ch.colors = c } end |
#component? ⇒ Boolean
Return bool indicating if this window has a component associated with it
47 48 49 |
# File 'lib/reterm/window.rb', line 47 def component? !!@component end |
#create_child(h = {}) ⇒ Object
Create child window, this method should not be invoked by end-user, rather it is is invoked the Layout#add_child is called.
319 320 321 322 323 324 |
# File 'lib/reterm/window.rb', line 319 def create_child(h={}) c = self.class.new h.merge(:parent => self) c.colors = @colors if colored? children << c c end |
#del_child(child) ⇒ Object
Remove child window, like #create_child, this is used internally and should not be invoked by the end user
328 329 330 331 332 333 |
# File 'lib/reterm/window.rb', line 328 def del_child(child) @children.delete(child) @@registry.delete(child) child.finalize! child.win.delwin if !!child.win end |
#dimensions ⇒ Object
Return window dimensions as an array containing rows & cols
505 506 507 508 509 510 511 512 |
# File 'lib/reterm/window.rb', line 505 def dimensions rows = [] cols = [] @win.getmaxyx(rows, cols) rows = rows.first cols = cols.first [rows, cols] end |
#distance_from(win) ⇒ Object
98 99 100 101 102 |
# File 'lib/reterm/window.rb', line 98 def distance_from(win) # FIXME: need to expand to compare each of 4 window coords # to each of 4 in other window Math.sqrt((x - win.x) ** 2 + (y - win.y) ** 2) end |
#draw! ⇒ Object
Draw component in window
525 526 527 |
# File 'lib/reterm/window.rb', line 525 def draw! component.draw! if component? end |
#erase ⇒ Object
Erase window drawing area
381 382 383 384 385 386 387 388 389 |
# File 'lib/reterm/window.rb', line 381 def erase children.each { |c| c.erase } @win.werase if @win component.component.erase if cdk? && component? && component.init? end |
#erase_scr ⇒ Object
Erases window screen by overwriting it with blanks
392 393 394 395 396 |
# File 'lib/reterm/window.rb', line 392 def erase_scr 0.upto(rows) { |r| mvaddstr(r, 1, " " * cols) } end |
#expand? ⇒ Boolean
251 252 253 |
# File 'lib/reterm/window.rb', line 251 def !!@expand end |
#finalize! ⇒ Object
Invoke window finalization routine by destroying it and all children
237 238 239 240 241 242 243 244 245 246 247 |
# File 'lib/reterm/window.rb', line 237 def finalize! erase @@registry.delete(self) children.each { |c| del_child c } cdk_scr.destroy if cdk? component.finalize! if component? end |
#first_child? ⇒ Boolean
Return boolean indicating if this window is the first child of its parent
73 74 75 76 |
# File 'lib/reterm/window.rb', line 73 def first_child? return true unless parent? parent.children.index(self) == 0 end |
#getch ⇒ Object
Blocking call to capture next character from window
428 429 430 |
# File 'lib/reterm/window.rb', line 428 def getch @win.getch end |
#last_child? ⇒ Boolean
Return boolean indicating if this window is the last child of its parent
80 81 82 83 |
# File 'lib/reterm/window.rb', line 80 def last_child? return true unless parent? parent.children.index(self) == (parent.children.size - 1) end |
#must_expand? ⇒ Boolean
255 256 257 |
# File 'lib/reterm/window.rb', line 255 def !!@must_expand end |
#mvaddstr(*a) ⇒ Object
Write string at specified loc
455 456 457 |
# File 'lib/reterm/window.rb', line 455 def mvaddstr(*a) @win.mvaddstr(*a) end |
#no_bold! ⇒ Object
Disable bold formatting
469 470 471 |
# File 'lib/reterm/window.rb', line 469 def no_bold! @win.attroff(Ncurses::A_BOLD) end |
#no_border! ⇒ Object
Remove Border around window
418 419 420 |
# File 'lib/reterm/window.rb', line 418 def no_border! @win.border(' '.ord, ' '.ord, ' '.ord, ' '.ord, ' '.ord, ' '.ord, ' '.ord, ' '.ord) end |
#no_reverse! ⇒ Object
Disabled reverse formatting
483 484 485 |
# File 'lib/reterm/window.rb', line 483 def no_reverse! @win.attroff(Ncurses::A_REVERSE) end |
#noutrefresh ⇒ Object
408 409 410 411 412 413 414 415 |
# File 'lib/reterm/window.rb', line 408 def noutrefresh @win.noutrefresh children.each { |c| c.noutrefresh } component.component.screen.noutrefresh if cdk? end |
#parent? ⇒ Boolean
Return boolean if this window is a child of another
62 63 64 |
# File 'lib/reterm/window.rb', line 62 def parent? !!@parent end |
#refresh ⇒ Object
Refresh / resynchronize window and all children
399 400 401 402 403 404 405 406 |
# File 'lib/reterm/window.rb', line 399 def refresh @win.refresh children.each { |c| c.refresh } component.component.screen.refresh if cdk? end |
#request_expansion(r, c) ⇒ Object
259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 |
# File 'lib/reterm/window.rb', line 259 def request_expansion(r, c) h = {:rows => r, :cols => c, :x => x, :y => y} if parent? if parent.component.exceeds_bounds_with?(h) if parent.component. parent.component.(h) else raise ArgumentError, "cannot expand" if return false end end else unless Terminal.contains?(h) raise ArgumentError, "terminal too small" if return false end end resize(r, c) true end |
#resize(rows, cols) ⇒ Object
358 359 360 361 362 363 364 365 366 |
# File 'lib/reterm/window.rb', line 358 def resize(rows, cols) r = win.resize rows, cols raise ArgumentError, "could not resize window" if r == -1 @rows = rows @cols = cols self end |
#reverse! ⇒ Object
Enable reverse formatting
474 475 476 477 478 479 480 |
# File 'lib/reterm/window.rb', line 474 def reverse! @win.attron(Ncurses::A_REVERSE) return unless block_given? yield @win.attroff(Ncurses::A_REVERSE) end |
#root ⇒ Object
Return root window (recusively), self if parent is not set
86 87 88 |
# File 'lib/reterm/window.rb', line 86 def root parent? ? parent.root : self end |
#sync! ⇒ Object
Dispatch to component synchronization
447 448 449 450 451 452 |
# File 'lib/reterm/window.rb', line 447 def sync! component.sync! if component? children.each { |c| c.sync! } end |
#sync_getch ⇒ Object
Normal getch unless sync enabled in which case, timeout will be checked & components synchronized
434 435 436 437 438 439 440 441 442 443 444 |
# File 'lib/reterm/window.rb', line 434 def sync_getch return self.getch unless sync_enabled? c = -1 while c == -1 && !shutdown? c = self.getch run_sync! end c end |
#total_x ⇒ Object
90 91 92 |
# File 'lib/reterm/window.rb', line 90 def total_x @tx ||= parent? ? (parent.total_x + x) : x end |
#total_y ⇒ Object
94 95 96 |
# File 'lib/reterm/window.rb', line 94 def total_y @ty ||= parent? ? (parent.total_y + y) : y end |