Class: Teek::Window
- Inherits:
-
Object
- Object
- Teek::Window
- Defined in:
- lib/teek/window.rb
Overview
A single toplevel window, addressed by its Tk path - the window-scoped
counterpart to Widget (which covers any widget of any type). Groups
every wm subcommand alongside composite window-lifecycle behaviors
(on_close, grab_set/grab_release, modal) that would otherwise keep
growing as more and more +window:+-kwarg methods flattened onto App
app.window(path).thingreads better than threadingwindow:through a dozen unrelated top-level methods, and gives callers (like teek-ui's DSL) one coherent object per window instead of loose parts.
App#wm (Wm) and App's own window_title/set_window_title/etc.
convenience methods, plus App#on_close/#grab_set/#grab_release/
#modal, all delegate here internally - nothing about those public
methods changed, this is where their actual work happens now.
Instance Attribute Summary collapse
-
#path ⇒ Object
readonly
Returns the value of attribute path.
Instance Method Summary collapse
-
#deiconify ⇒ void
Show the window (map it if withdrawn/iconified).
-
#geometry ⇒ String
Geometry string (e.g. +"400x300+0+0"+).
-
#grab_release ⇒ void
Release a grab previously set with #grab_set.
-
#grab_set(global: false) ⇒ void
Set the input grab on the window - while held, mouse and keyboard events outside it (and its descendants) are redirected to it, the building block #modal uses.
-
#initialize(app, path) ⇒ Window
constructor
private
A new instance of Window.
-
#modal(global: false) { ... } ⇒ void
Make the window modal: grabs input and sets focus on it immediately.
-
#on_close { ... } ⇒ void
Register a handler for the window manager's close button (WM_DELETE_WINDOW - the titlebar close box, Cmd-W, Alt-F4, etc., depending on platform).
-
#resizable ⇒ Array(Boolean, Boolean)
[width_resizable, height_resizable].
-
#set_geometry(value) ⇒ String
The geometry.
- #set_resizable(width, height) ⇒ void
-
#set_title(value) ⇒ String
The title.
-
#title ⇒ String
The window's current title.
-
#to_s ⇒ String
The Tk window path.
-
#withdraw ⇒ void
Hide the window without destroying it.
Constructor Details
#initialize(app, path) ⇒ Window
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Returns a new instance of Window.
24 25 26 27 |
# File 'lib/teek/window.rb', line 24 def initialize(app, path) @app = app @path = path.to_s end |
Instance Attribute Details
#path ⇒ Object (readonly)
Returns the value of attribute path.
21 22 23 |
# File 'lib/teek/window.rb', line 21 def path @path end |
Instance Method Details
#deiconify ⇒ void
This method returns an undefined value.
Show the window (map it if withdrawn/iconified).
73 74 75 |
# File 'lib/teek/window.rb', line 73 def deiconify @app.tcl_invoke('wm', 'deiconify', @path) end |
#geometry ⇒ String
Returns geometry string (e.g. +"400x300+0+0"+).
48 49 50 |
# File 'lib/teek/window.rb', line 48 def geometry @app.tcl_invoke('wm', 'geometry', @path) end |
#grab_release ⇒ void
This method returns an undefined value.
Release a grab previously set with #grab_set. Safe to call even if the window never held the grab - Tk itself treats that as a no-op.
131 132 133 134 |
# File 'lib/teek/window.rb', line 131 def grab_release @app.tcl_invoke('grab', 'release', @path) nil end |
#grab_set(global: false) ⇒ void
This method returns an undefined value.
Set the input grab on the window - while held, mouse and keyboard
events outside it (and its descendants) are redirected to it, the
building block #modal uses. grab is its own Tcl command family,
separate from wm.
120 121 122 123 124 125 126 |
# File 'lib/teek/window.rb', line 120 def grab_set(global: false) args = ['grab', 'set'] args << '-global' if global args << @path @app.tcl_invoke(*args) nil end |
#modal(global: false) { ... } ⇒ void
This method returns an undefined value.
Make the window modal: grabs input and sets focus on it immediately. Release it explicitly with #grab_release (typically from the window's own dismiss/close handling) when the dialog is done - the grab is NOT released automatically just because this method returns, since a modal dialog is meant to stay grabbed for its whole visible lifetime, not just its setup.
Two safety nets guard against a stuck grab locking out the rest of
the display: if the window is destroyed while still grabbed (a crash
mid-modal, or just forgetting to call #grab_release first), a
161 162 163 164 165 166 167 168 169 170 171 172 173 174 |
# File 'lib/teek/window.rb', line 161 def modal(global: false) grab_set(global: global) # -force: a modal dialog should own keyboard focus immediately, not # merely be first in line whenever the app next happens to get it # (plain `focus` only takes effect once the app already has input # focus at the OS/WM level). @app.tcl_invoke('focus', '-force', @path) @app.bind(@path, 'Destroy') { grab_release } yield if block_given? nil rescue grab_release raise end |
#on_close { ... } ⇒ void
This method returns an undefined value.
Register a handler for the window manager's close button (WM_DELETE_WINDOW - the titlebar close box, Cmd-W, Alt-F4, etc., depending on platform).
Tk's own default behavior (destroy the window) only applies when nothing else has claimed this protocol - setting a handler here replaces it, so the block is entirely responsible for deciding whether the window actually closes. Call App#destroy yourself if you want it to; do nothing (or show a confirmation first) if you don't.
104 105 106 107 108 |
# File 'lib/teek/window.rb', line 104 def on_close(&block) cb = @app.register_callback(block, relay_break_continue: false) @app.callback_registry.reconcile([:wm_protocol, @path]) { |before| before.merge('WM_DELETE_WINDOW' => cb) } @app.tcl_eval("wm protocol #{@path} WM_DELETE_WINDOW {ruby_callback #{cb}}") end |
#resizable ⇒ Array(Boolean, Boolean)
Returns [width_resizable, height_resizable].
59 60 61 62 |
# File 'lib/teek/window.rb', line 59 def resizable parts = @app.tcl_invoke('wm', 'resizable', @path).split [@app.tcl_to_bool(parts[0]), @app.tcl_to_bool(parts[1])] end |
#set_geometry(value) ⇒ String
Returns the geometry.
54 55 56 |
# File 'lib/teek/window.rb', line 54 def set_geometry(value) @app.tcl_invoke('wm', 'geometry', @path, value.to_s) end |
#set_resizable(width, height) ⇒ void
This method returns an undefined value.
67 68 69 |
# File 'lib/teek/window.rb', line 67 def set_resizable(width, height) @app.tcl_invoke('wm', 'resizable', @path, @app.bool_to_tcl(width), @app.bool_to_tcl(height)) end |
#set_title(value) ⇒ String
Returns the title.
43 44 45 |
# File 'lib/teek/window.rb', line 43 def set_title(value) @app.tcl_invoke('wm', 'title', @path, value.to_s) end |
#title ⇒ String
Returns the window's current title.
37 38 39 |
# File 'lib/teek/window.rb', line 37 def title @app.tcl_invoke('wm', 'title', @path) end |
#to_s ⇒ String
Returns the Tk window path.
30 31 32 |
# File 'lib/teek/window.rb', line 30 def to_s @path end |
#withdraw ⇒ void
This method returns an undefined value.
Hide the window without destroying it.
79 80 81 |
# File 'lib/teek/window.rb', line 79 def withdraw @app.tcl_invoke('wm', 'withdraw', @path) end |