class BBS::Windows::Form
A form dialog with labeled input rows, optional textarea, and a status line for inline validation feedback.
BBS::Windows::Form.open(app, title: " Profile — #{u} ", width: 64, fields: [ { key: :signature, label: 'Signature', value: '...' }, { key: :location, label: 'Location', value: '...' }, { key: :notes, label: 'Notes', value: '...' }, ], on_submit: ->(values, form) { service.update(values); :close } )
A field descriptor is a Hash:
- key
-
the key of the field’s value in
values - label
-
the text left of an input, or the checkbox’s text
- value
-
the starting value (true/false for a checkbox)
- type
-
:input,:textareaor:checkbox - max_length
-
the longest value accepted (256 for an input, 8000 for a textarea)
- placeholder
-
the text an empty input shows
- password
-
masks an input’s text
- rows
-
a textarea’s height (default 6)
Field types:
- :input
-
(default) single-line TextInput; label on the left
- :textarea
-
multi-line TextArea; full width, label ignored
- :checkbox
-
Checkbox; the label is part of the widget
on_submit receives (values_hash, self). Return :keep to keep the window open (e.g. after form.error('...')); any other value closes.
hint: shows an info line above the fields (no label/value, no input).
Constants
- CHROME_ROWS
-
The rows that are not field rows besides the padding, the hint and the gaps between fields: the status line, its gap and the button row.
- DEFAULT_PADDING
-
The blank cells around the fields: columns on each side, rows above, and rows below the button row.
- OPTIONS
-
The options of
::newand their defaults.
Attributes
The BBS::Widgets::Label above the buttons used by error and info.
Public Class Methods
# File lib/bbs/windows/form.rb, line 91 def initialize(app:, title:, fields:, **options) unknown = options.keys - OPTIONS.keys raise ArgumentError, "unknown form options: #{unknown.inspect}" unless unknown.empty? @options = OPTIONS.merge(options) super(title: title, modal: false, maximizable: @options[:maximizable]) self.theme = app.theme @app = app @fields = fields.map { |d| Field.for(d) } @padding = DEFAULT_PADDING.merge(@options[:padding] || {}) build end
Creates the form window and its widgets, sized to fit the fields and centred on app‘s screen. It is not opened; see attach.
- app
-
the
BBS::Application - title
-
the window title
- fields
-
an Array of field descriptors
The options (OPTIONS):
- on_submit
-
called with
(values, form)by the submit button;niljust closes the window - hint
-
an info line above the fields
- width
-
the window width (default 60)
- height
-
the window height; by default it fits the fields
- submit_label
-
the submit button’s label (+&+ marks the hotkey)
- cancel_label
-
the cancel button’s label
- padding
-
a Hash overriding
DEFAULT_PADDINGentries - on_cancel
-
called with the form when cancel is pressed
- maximizable
-
gives the window the zoom gadget
Raises ArgumentError for an unknown option.
BBS::Window::new
Source
# File lib/bbs/windows/form.rb, line 63 def self.open(app, **) new(app: app, **).tap(&:attach) end
Public Instance Methods
Source
# File lib/bbs/windows/form.rb, line 107 def attach @app.open_window(self) reset_focus focus_manager.focus(@fields.first.widget) unless @fields.empty? self end
Opens the window on the application and focuses the first field.
Returns self.
Source
# File lib/bbs/windows/form.rb, line 119 def error(text) = status(text, :error)
Shows text on the status line in the error style.
Source
# File lib/bbs/windows/form.rb, line 122 def info(text) = status(text, :input_label)
Shows text on the status line in the label style.
Source
# File lib/bbs/windows/form.rb, line 130 def normal_rect w = [@options[:width], @app.cols - 4].min h = [@options[:height] || natural_height, @app.rows - 4].min [((@app.cols - w) / 2) + 1, ((@app.rows - h) / 2) + 1, w, h] end
Returns the un-maximized bounds as [x, y, width, height]: the requested size (or the fitted height), shrunk to leave a two-cell margin, centred on the screen.
Source
# File lib/bbs/windows/form.rb, line 139 def place(x, y, width, height) layout(x, y, width, height) left = x + @padding[:sides] inner = width - (@padding[:sides] * 2) row = place_hint(left, inner, y + @padding[:top]) place_fields(left, inner, row, field_heights(height)) @status_label.layout(left, y + height - 3, inner, 1) ButtonBar.place(self, @bar[:widgets], @bar_descriptors) if @bar end
Fields one under the other at the given size; a single textarea without its own :rows takes the height left over (always when the form has an explicit height or is maximized).
Source
# File lib/bbs/windows/form.rb, line 125 def resizable? = true
A form can be resized; place lays the fields out again.
Source
# File lib/bbs/windows/form.rb, line 116 def values = @fields.to_h { |f| [f.key, f.value] }
Returns a Hash of field key to the current value: a String for an input or textarea, true or false for a checkbox.