Class: Tuile::Component::Window

Inherits:
Tuile::Component show all
Includes:
HasContent
Defined in:
lib/tuile/component/window.rb

Overview

A window with a frame, a #caption and a content Tuile::Component. Doesn’t support overlapping with other windows: it paints its entire contents and doesn’t clip if there are other overlapping windows.

The window’s ‘content` is unset by default; assign one via #content=.

Window is considered invisible if #rect is empty. The window won’t draw when invisible. (Repaint of detached windows is short-circuited by #invalidate; subclasses don’t need to re-check.)

Direct Known Subclasses

InfoWindow, LogWindow, PickerWindow

Instance Attribute Summary collapse

Attributes included from HasContent

#content

Attributes inherited from Tuile::Component

#content_size, #key_shortcut, #on_theme_changed, #parent, #rect

Instance Method Summary collapse

Methods included from HasContent

#on_focus

Methods inherited from Tuile::Component

#active=, #active?, #attached?, #cursor_position, #depth, #find_shortcut_component, #focus, #keyboard_hint, #on_child_removed, #on_focus, #on_tree, #root, #screen, #tab_stop?

Constructor Details

#initialize(caption = "") ⇒ Window

Returns a new instance of Window.

Parameters:

  • caption (String) (defaults to: "")


18
19
20
21
22
23
24
25
26
27
28
# File 'lib/tuile/component/window.rb', line 18

def initialize(caption = "")
  super()
  @border_right = 1
  @caption = caption
  @content = nil
  # Optional bottom-row chrome that overlays the bottom border (e.g. a
  # search field).
  @footer = nil
  @footer_sizing = Sizing::FILL
  update_content_size
end

Instance Attribute Details

#captionString

Returns the current caption, empty by default.

Returns:

  • (String)

    the current caption, empty by default.



126
127
128
# File 'lib/tuile/component/window.rb', line 126

def caption
  @caption
end

Returns optional component overlaying the bottom border row.

Returns:

  • (Component, nil)

    optional component overlaying the bottom border row.



34
35
36
# File 'lib/tuile/component/window.rb', line 34

def footer
  @footer
end

Returns how the footer’s width is computed from the window’s inner width; defaults to Sizing::FILL (the footer spans the full inner width). The footer’s height is always 1 (the border row).

Returns:

  • (Sizing)

    how the footer’s width is computed from the window’s inner width; defaults to Sizing::FILL (the footer spans the full inner width). The footer’s height is always 1 (the border row).



39
40
41
# File 'lib/tuile/component/window.rb', line 39

def footer_sizing
  @footer_sizing
end

Instance Method Details

#childrenArray<Component>

Returns:



82
83
84
# File 'lib/tuile/component/window.rb', line 82

def children
  @footer.nil? ? super : super + [@footer]
end

#content=(new_content) ⇒ Object

Sets the new content. Also recomputes the window’s natural size.

Parameters:



138
139
140
141
# File 'lib/tuile/component/window.rb', line 138

def content=(new_content)
  super
  update_content_size
end

#focusable?Boolean

Returns:

  • (Boolean)


30
# File 'lib/tuile/component/window.rb', line 30

def focusable? = true

#handle_key(key) ⇒ Boolean

Parameters:

  • key (String)

Returns:

  • (Boolean)


88
89
90
91
92
# File 'lib/tuile/component/window.rb', line 88

def handle_key(key)
  return @footer.handle_key(key) if @footer&.active?

  super
end

#handle_mouse(event) ⇒ void

This method returns an undefined value.

Parameters:



96
97
98
99
100
101
102
# File 'lib/tuile/component/window.rb', line 96

def handle_mouse(event)
  if @footer&.rect&.contains?(event.point)
    @footer.handle_mouse(event)
  else
    super
  end
end

#key_shortcut=(key) ⇒ void

This method returns an undefined value.

Parameters:

  • key (String, nil)


185
186
187
188
189
190
# File 'lib/tuile/component/window.rb', line 185

def key_shortcut=(key)
  super
  # The shortcut key is shown in the caption — repaint.
  invalidate
  update_content_size
end

#on_child_content_size_changed(child) ⇒ void

This method returns an undefined value.

Re-lays-out a Sizing::WRAP_CONTENT footer when the footer’s natural size changes, and folds a content resize into the window’s own natural size (whose change then bubbles to the window’s parent — e.g. a Popup re-self-sizes). The footer deliberately does not participate in the window’s Tuile::Component#content_size: it is decoration overlaying the border, and must not drive the window’s size — if it doesn’t fit, it is clipped to the inner width.

Parameters:



152
153
154
155
156
157
158
159
160
161
162
163
# File 'lib/tuile/component/window.rb', line 152

def on_child_content_size_changed(child)
  if child.equal?(@footer)
    old_rect = @footer.rect
    layout_footer
    # Repaint on any footer geometry change: a shrinking footer vacates
    # border cells that must be re-dashed (a growing one merely
    # overdraws, but distinguishing isn't worth the code).
    invalidate if @footer.rect != old_rect
  else
    update_content_size
  end
end

#rect=(new_rect) ⇒ void

This method returns an undefined value.

Parameters:



106
107
108
109
# File 'lib/tuile/component/window.rb', line 106

def rect=(new_rect)
  super
  layout_footer
end

#repaintvoid

This method returns an undefined value.

Fully repaints the window: both frame and contents.

Window deliberately paints over its entire rect (border around the edge, content/footer over the interior), so we don’t need the Tuile::Component#repaint default’s auto-clear — but we do still want its “re-invalidate children” effect, since the border overpaints whatever the content/footer drew on the perimeter. Calling super handles both: the auto-clear is harmless (we re-paint over it), and the invalidation queues content + footer for repaint in the same cycle.



176
177
178
179
180
181
# File 'lib/tuile/component/window.rb', line 176

def repaint
  return if rect.empty?

  super
  repaint_border
end

#scrollbar=(value) ⇒ void

This method returns an undefined value.

Parameters:

  • value (Boolean)


113
114
115
116
117
118
119
120
121
122
123
# File 'lib/tuile/component/window.rb', line 113

def scrollbar=(value)
  unless content.respond_to?(:scrollbar_visibility=)
    raise Tuile::Error,
          "scrollbar= requires a content component that supports scrollbar_visibility=, got #{content.inspect}"
  end

  content.scrollbar_visibility = value ? :visible : :gone
  @border_right = value ? 0 : 1
  invalidate
  layout(content)
end