Class: Hokusai::Painter

Inherits:
Object
  • Object
show all
Defined in:
ui/src/hokusai/painter.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(root, input) ⇒ Painter

Returns a new instance of Painter.



29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
# File 'ui/src/hokusai/painter.rb', line 29

def initialize(root, input)
  state = CursorState.new

  @root = root
  @input = input
  @events = {
    hover: HoverEvent.new(input, state),
    wheel: WheelEvent.new(input, state),
    click: ClickEvent.new(input, state),
    mousemove: MouseMoveEvent.new(input, state),
    mouseout: MouseOutEvent.new(input, state),
    mouseup: MouseUpEvent.new(input, state),
    mousedown: MouseDownEvent.new(input, state),
    keyup: KeyUpEvent.new(input, state),
    keypress: KeyPressEvent.new(input, state)
  }
end

Instance Attribute Details

#after_renderObject (readonly)

Returns the value of attribute after_render.



26
27
28
# File 'ui/src/hokusai/painter.rb', line 26

def after_render
  @after_render
end

#before_renderObject (readonly)

Returns the value of attribute before_render.



26
27
28
# File 'ui/src/hokusai/painter.rb', line 26

def before_render
  @before_render
end

#eventsObject (readonly)

Returns the value of attribute events.



26
27
28
# File 'ui/src/hokusai/painter.rb', line 26

def events
  @events
end

#inputObject (readonly)

Returns the value of attribute input.



26
27
28
# File 'ui/src/hokusai/painter.rb', line 26

def input
  @input
end

#rootObject (readonly)

Returns the value of attribute root.



26
27
28
# File 'ui/src/hokusai/painter.rb', line 26

def root
  @root
end

Instance Method Details

#capture_events(block, canvas, hovered: false) ⇒ Object



186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
# File 'ui/src/hokusai/painter.rb', line 186

def capture_events(block, canvas, hovered: false)
  if block.node.portal.nil?
    return
  end

  rect = canvas.to_hoku_rect
  block_is_hovered = LibHokusai.hoku_input_is_hovered(input.raw, rect)

  if block_is_hovered
    events[:hover].capture(block, canvas)
    events[:click].capture(block, canvas)
    events[:wheel].capture(block, canvas)
    events[:mousedown].capture(block, canvas)
    events[:mouseup].capture(block, canvas)
  else
    events[:mouseout].capture(block, canvas)
  end

  events[:mousemove].capture(block, canvas)

  if block_is_hovered || block.node.meta.focused
    events[:keyup].capture(block, canvas)
    events[:keypress].capture(block, canvas)
  end
end

#measure(children, canvas) ⇒ Object



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
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
# File 'ui/src/hokusai/painter.rb', line 121

def measure(children, canvas)
  x = canvas.x || 0.0
  y = canvas.y || 0.0
  width = canvas.width
  height = canvas.height
  vertical = canvas.vertical

  count = 0
  wcount = 0
  hcount = 0
  wsum = 0.0
  hsum = 0.0

  children.each do |block|
    # children.each do |block|
    h = block.node.meta.get_prop?(:height)&.to_f
    w = block.node.meta.get_prop?(:width)&.to_f

    if w
      wsum += w
      wcount = wcount.succ
    end

    if h
      hsum += h
      hcount = hcount.succ
    end

    count = count.succ
  end

  neww = width
  newh = height

  if vertical
    c = (count - hcount)
    newh = (newh - hsum)  / (c.zero? ? 1 : c)
  else
    c = (count - wcount)
    neww = (neww - wsum) / (c.zero? ? 1 : c)
  end

  entries = []

  children.each do |block|
    # nw, nh = ntuple
    w = block.node.meta.get_prop?(:width)&.to_f || neww
    h = block.node.meta.get_prop?(:height)&.to_f || newh

    # local_canvas = Hokusai::Canvas.new(w, h, x, y)
    # block.node.meta.props[:height] ||= h
    # block.node.meta.props[:width] ||= w

    entries << PainterEntry.new(block, x, y, w, h).freeze

    if vertical
      y += h
    else
      x += w
    end
  end

  entries
end

#on_after_render(&block) ⇒ Object



51
52
53
# File 'ui/src/hokusai/painter.rb', line 51

def on_after_render(&block)
  @after_render = block
end

#on_before_render(&block) ⇒ Object



47
48
49
# File 'ui/src/hokusai/painter.rb', line 47

def on_before_render(&block)
  @before_render = block
end

#render(canvas, resize = false, capture: true) ⇒ Array(Commands::Base)

Returns the command list.

Returns:



56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
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
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
# File 'ui/src/hokusai/painter.rb', line 56

def render(canvas, resize = false, capture: true)
  return if root.children.empty?

  @root.on_resize(canvas) if resize

  before_render&.call([root, nil], canvas, input)

  root_children = (canvas.reverse? ? root.children?&.reverse.dup : root.children?&.dup) || []
  groups = []
  groups << [root, measure(root_children, canvas)]

  mouse_y = input.mouse.pos[:y]
  can_capture = mouse_y >= (canvas.y || 0.0) && mouse_y <= (canvas.y || 0.0) + canvas.height

  hovered = false

  while payload = groups.pop
    group_parent, group_children = payload

    while group = group_children.shift
      canvas.reset(group.x, group.y, group.w, group.h)

      before_render&.call([group.block, group.parent], canvas, input.raw)

      if capture
        capture_events(group.block, canvas, hovered: hovered)
      end

      if resize
        group.block.on_resize(canvas)
      end

      breaked = false

      group.block.render(canvas) do |local_canvas|
        local_children = (local_canvas.reverse? ? group.block.children?&.reverse : group.block.children?)

        unless local_children.nil?
          groups << [group_parent, group_children]
          groups << [group.block, measure(local_children, local_canvas)]
          breaked = true
        else
          breaked = false
        end
      end

      break if breaked
    end
  end

  if capture
    events[:hover].bubble
    events[:wheel].bubble
    events[:click].bubble
    events[:keyup].bubble
    events[:keypress].bubble
    events[:mousemove].bubble
    events[:mouseout].bubble
    events[:mousedown].bubble
    events[:mouseup].bubble
  end

  after_render&.call
end