mirror of
https://github.com/cyberarm/cyberarm_engine.git
synced 2025-12-16 13:12:34 +00:00
Added Link element which is basically a button without a border or background, WIP: Element border, margin, padding, and other styles are now easily changable; work is needed to make style changes survive a recalculation
This commit is contained in:
@@ -65,6 +65,15 @@ module CyberarmEngine
|
|||||||
font
|
font
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def swap_font(size, font_name = @font)
|
||||||
|
if @size != size || @font != font_name
|
||||||
|
@size = size
|
||||||
|
@font = font_name
|
||||||
|
|
||||||
|
@textobject = check_cache(size, font_name)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def text=(string)
|
def text=(string)
|
||||||
@rendered_shadow = nil
|
@rendered_shadow = nil
|
||||||
@text = string
|
@text = string
|
||||||
|
|||||||
@@ -23,7 +23,8 @@ module CyberarmEngine
|
|||||||
"Tagline",
|
"Tagline",
|
||||||
"Caption",
|
"Caption",
|
||||||
"Para",
|
"Para",
|
||||||
"Inscription"
|
"Inscription",
|
||||||
|
"Link"
|
||||||
].each do |const|
|
].each do |const|
|
||||||
define_method(:"#{const.downcase}") do |text, options = {}, &block|
|
define_method(:"#{const.downcase}") do |text, options = {}, &block|
|
||||||
options[:parent] = element_parent
|
options[:parent] = element_parent
|
||||||
|
|||||||
@@ -105,6 +105,55 @@ module CyberarmEngine
|
|||||||
@style.margin_bottom = default(:margin_bottom) || @style.margin
|
@style.margin_bottom = default(:margin_bottom) || @style.margin
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def update_styles(event = :default)
|
||||||
|
_style = @style.send(event)
|
||||||
|
|
||||||
|
if @text&.is_a?(CyberarmEngine::Text)
|
||||||
|
@text.color = _style&.dig(:color) || @style.color
|
||||||
|
@text.swap_font(_style&.dig(:text_size) || @style.text_size, _style&.dig(:font) || @style.font)
|
||||||
|
end
|
||||||
|
|
||||||
|
_padding = (_style&.dig(:padding) || @style.padding) || 0
|
||||||
|
|
||||||
|
@style.padding_left = _style&.dig(:padding_left) || _padding
|
||||||
|
@style.padding_right = _style&.dig(:padding_right) || _padding
|
||||||
|
@style.padding_top = _style&.dig(:padding_top) || _padding
|
||||||
|
@style.padding_bottom = _style&.dig(:padding_bottom) || _padding
|
||||||
|
|
||||||
|
_margin = (_style&.dig(:margin) || @style.margin) || 0
|
||||||
|
|
||||||
|
@style.margin_left = _style&.dig(:margin_left) || _margin
|
||||||
|
@style.margin_right = _style&.dig(:margin_right) || _margin
|
||||||
|
@style.margin_top = _style&.dig(:margin_top) || _margin
|
||||||
|
@style.margin_bottom = _style&.dig(:margin_bottom) || _margin
|
||||||
|
|
||||||
|
@style.background_canvas.background = _style&.dig(:background) || @style.background
|
||||||
|
|
||||||
|
_border_thickness = (_style&.dig(:border_thickness) || @style.border_thickness) || 0
|
||||||
|
|
||||||
|
@style.border_thickness_left = _style&.dig(:border_thickness_left) || _border_thickness
|
||||||
|
@style.border_thickness_right = _style&.dig(:border_thickness_right) || _border_thickness
|
||||||
|
@style.border_thickness_top = _style&.dig(:border_thickness_top) || _border_thickness
|
||||||
|
@style.border_thickness_bottom = _style&.dig(:border_thickness_bottom) || _border_thickness
|
||||||
|
|
||||||
|
_border_color = (_style&.dig(:border_color) || @style.border_color) || Gosu::Color::NONE
|
||||||
|
|
||||||
|
@style.border_color_left = _style&.dig(:border_color_left) || _border_color
|
||||||
|
@style.border_color_right = _style&.dig(:border_color_right) || _border_color
|
||||||
|
@style.border_color_top = _style&.dig(:border_color_top) || _border_color
|
||||||
|
@style.border_color_bottom = _style&.dig(:border_color_bottom) || _border_color
|
||||||
|
|
||||||
|
@style.border_canvas.color = [
|
||||||
|
@style.border_color_top,
|
||||||
|
@style.border_color_right,
|
||||||
|
@style.border_color_bottom,
|
||||||
|
@style.border_color_left
|
||||||
|
]
|
||||||
|
|
||||||
|
(root&.gui_state || @gui_state).request_recalculate
|
||||||
|
# recalculate
|
||||||
|
end
|
||||||
|
|
||||||
def default_events
|
def default_events
|
||||||
%i[left middle right].each do |button|
|
%i[left middle right].each do |button|
|
||||||
event(:"#{button}_mouse_button")
|
event(:"#{button}_mouse_button")
|
||||||
@@ -126,6 +175,62 @@ module CyberarmEngine
|
|||||||
event(:changed)
|
event(:changed)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def enter(_sender)
|
||||||
|
@focus = false unless window.button_down?(Gosu::MsLeft)
|
||||||
|
|
||||||
|
if !@enabled
|
||||||
|
update_styles(:disabled)
|
||||||
|
elsif @focus
|
||||||
|
update_styles(:active)
|
||||||
|
else
|
||||||
|
update_styles(:hover)
|
||||||
|
end
|
||||||
|
|
||||||
|
:handled
|
||||||
|
end
|
||||||
|
|
||||||
|
def left_mouse_button(_sender, _x, _y)
|
||||||
|
@focus = true
|
||||||
|
|
||||||
|
unless @enabled
|
||||||
|
update_styles(:disabled)
|
||||||
|
else
|
||||||
|
update_styles(:active)
|
||||||
|
end
|
||||||
|
|
||||||
|
window.current_state.focus = self
|
||||||
|
|
||||||
|
:handled
|
||||||
|
end
|
||||||
|
|
||||||
|
def released_left_mouse_button(sender, _x, _y)
|
||||||
|
enter(sender)
|
||||||
|
|
||||||
|
:handled
|
||||||
|
end
|
||||||
|
|
||||||
|
def clicked_left_mouse_button(_sender, _x, _y)
|
||||||
|
@block&.call(self) if @enabled
|
||||||
|
|
||||||
|
return :handled
|
||||||
|
end
|
||||||
|
|
||||||
|
def leave(_sender)
|
||||||
|
unless @enabled
|
||||||
|
update_styles(:disabled)
|
||||||
|
else
|
||||||
|
update_styles
|
||||||
|
end
|
||||||
|
|
||||||
|
:handled
|
||||||
|
end
|
||||||
|
|
||||||
|
def blur(_sender)
|
||||||
|
@focus = false
|
||||||
|
|
||||||
|
:handled
|
||||||
|
end
|
||||||
|
|
||||||
def enabled?
|
def enabled?
|
||||||
@enabled
|
@enabled
|
||||||
end
|
end
|
||||||
@@ -285,7 +390,7 @@ module CyberarmEngine
|
|||||||
end
|
end
|
||||||
|
|
||||||
def background=(_background)
|
def background=(_background)
|
||||||
@style.background_canvas.background = (_background)
|
@style.background_canvas.background = _background
|
||||||
update_background
|
update_background
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -308,11 +413,9 @@ module CyberarmEngine
|
|||||||
@root = parent
|
@root = parent
|
||||||
|
|
||||||
loop do
|
loop do
|
||||||
if @root.parent.nil?
|
break unless @root&.parent
|
||||||
break
|
|
||||||
else
|
@root = @root.parent
|
||||||
@root = @root.parent
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -34,69 +34,6 @@ module CyberarmEngine
|
|||||||
@text.draw
|
@text.draw
|
||||||
end
|
end
|
||||||
|
|
||||||
def enter(_sender)
|
|
||||||
@focus = false unless window.button_down?(Gosu::MsLeft)
|
|
||||||
|
|
||||||
if !@enabled
|
|
||||||
@style.background_canvas.background = @style.disabled[:background]
|
|
||||||
@text.color = @style.disabled[:color]
|
|
||||||
elsif @focus
|
|
||||||
@style.background_canvas.background = @style.active[:background]
|
|
||||||
@text.color = @style.active[:color]
|
|
||||||
else
|
|
||||||
@style.background_canvas.background = @style.hover[:background]
|
|
||||||
@text.color = @style.hover[:color]
|
|
||||||
end
|
|
||||||
|
|
||||||
:handled
|
|
||||||
end
|
|
||||||
|
|
||||||
def left_mouse_button(_sender, _x, _y)
|
|
||||||
@focus = true
|
|
||||||
|
|
||||||
unless @enabled
|
|
||||||
@style.background_canvas.background = @style.disabled[:background]
|
|
||||||
@text.color = @style.disabled[:color]
|
|
||||||
else
|
|
||||||
@style.background_canvas.background = @style.active[:background]
|
|
||||||
@text.color = @style.active[:color]
|
|
||||||
end
|
|
||||||
|
|
||||||
window.current_state.focus = self
|
|
||||||
|
|
||||||
:handled
|
|
||||||
end
|
|
||||||
|
|
||||||
def released_left_mouse_button(sender, _x, _y)
|
|
||||||
enter(sender)
|
|
||||||
|
|
||||||
:handled
|
|
||||||
end
|
|
||||||
|
|
||||||
def clicked_left_mouse_button(_sender, _x, _y)
|
|
||||||
@block.call(self) if @enabled && @block
|
|
||||||
|
|
||||||
:handled
|
|
||||||
end
|
|
||||||
|
|
||||||
def leave(_sender)
|
|
||||||
unless @enabled
|
|
||||||
@style.background_canvas.background = @style.disabled[:background]
|
|
||||||
@text.color = @style.disabled[:color]
|
|
||||||
else
|
|
||||||
@style.background_canvas.background = @style.background
|
|
||||||
@text.color = @style.color
|
|
||||||
end
|
|
||||||
|
|
||||||
:handled
|
|
||||||
end
|
|
||||||
|
|
||||||
def blur(_sender)
|
|
||||||
@focus = false
|
|
||||||
|
|
||||||
:handled
|
|
||||||
end
|
|
||||||
|
|
||||||
def recalculate
|
def recalculate
|
||||||
unless @enabled
|
unless @enabled
|
||||||
@style.background_canvas.background = @style.disabled[:background]
|
@style.background_canvas.background = @style.disabled[:background]
|
||||||
|
|||||||
@@ -5,8 +5,11 @@ module CyberarmEngine
|
|||||||
super(options, block)
|
super(options, block)
|
||||||
options[:toggled] = options[:checked]
|
options[:toggled] = options[:checked]
|
||||||
|
|
||||||
|
options[:parent] = self
|
||||||
@toggle_button = ToggleButton.new(options)
|
@toggle_button = ToggleButton.new(options)
|
||||||
@label = TextBlock.new(text, options)
|
|
||||||
|
options[:parent] = self
|
||||||
|
@label = TextBlock.new(text, options)
|
||||||
|
|
||||||
@label.subscribe(:holding_left_mouse_button) do |sender, x, y|
|
@label.subscribe(:holding_left_mouse_button) do |sender, x, y|
|
||||||
@toggle_button.left_mouse_button(sender, x, y)
|
@toggle_button.left_mouse_button(sender, x, y)
|
||||||
|
|||||||
@@ -1,156 +0,0 @@
|
|||||||
module CyberarmEngine
|
|
||||||
class Element
|
|
||||||
class TextBlock < Element
|
|
||||||
def initialize(text, options = {}, block = nil)
|
|
||||||
super(options, block)
|
|
||||||
|
|
||||||
@text = Text.new(
|
|
||||||
text, font: @options[:font], z: @z, color: @options[:color],
|
|
||||||
size: @options[:text_size], shadow: @options[:text_shadow],
|
|
||||||
shadow_size: @options[:text_shadow_size],
|
|
||||||
shadow_color: @options[:text_shadow_color]
|
|
||||||
)
|
|
||||||
|
|
||||||
@raw_text = text
|
|
||||||
end
|
|
||||||
|
|
||||||
def render
|
|
||||||
@text.draw
|
|
||||||
end
|
|
||||||
|
|
||||||
def clicked_left_mouse_button(_sender, _x, _y)
|
|
||||||
@block&.call(self) if @enabled
|
|
||||||
|
|
||||||
# return :handled
|
|
||||||
end
|
|
||||||
|
|
||||||
def recalculate
|
|
||||||
@width = 0
|
|
||||||
@height = 0
|
|
||||||
|
|
||||||
_width = dimensional_size(@style.width, :width)
|
|
||||||
_height = dimensional_size(@style.height, :height)
|
|
||||||
|
|
||||||
handle_text_wrapping(_width)
|
|
||||||
|
|
||||||
@width = _width || @text.width.round
|
|
||||||
@height = _height || @text.height.round
|
|
||||||
|
|
||||||
@text.y = @style.border_thickness_top + @style.padding_top + @y
|
|
||||||
@text.z = @z + 3
|
|
||||||
|
|
||||||
if (text_alignment = @options[:text_align])
|
|
||||||
case text_alignment
|
|
||||||
when :left
|
|
||||||
@text.x = @style.border_thickness_left + @style.padding_left + @x
|
|
||||||
when :center
|
|
||||||
@text.x = if @text.width <= outer_width
|
|
||||||
@x + outer_width / 2 - @text.width / 2
|
|
||||||
else # Act as left aligned
|
|
||||||
@style.border_thickness_left + @style.padding_left + @x
|
|
||||||
end
|
|
||||||
when :right
|
|
||||||
@text.x = @x + outer_width - (@text.width + @style.border_thickness_right + @style.padding_right)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
update_background
|
|
||||||
end
|
|
||||||
|
|
||||||
def handle_text_wrapping(max_width)
|
|
||||||
max_width ||= @parent&.width
|
|
||||||
max_width ||= @x - (window.width + noncontent_width)
|
|
||||||
wrap_behavior = style.text_wrap
|
|
||||||
copy = @raw_text.to_s.dup
|
|
||||||
|
|
||||||
if max_width >= line_width(copy[0]) && line_width(copy) > max_width && wrap_behavior != :none
|
|
||||||
breaks = []
|
|
||||||
line_start = 0
|
|
||||||
line_end = copy.length
|
|
||||||
|
|
||||||
while line_start != copy.length
|
|
||||||
if line_width(copy[line_start...line_end]) > max_width
|
|
||||||
line_end = ((line_end - line_start) / 2.0)
|
|
||||||
elsif line_end < copy.length && line_width(copy[line_start...line_end + 1]) < max_width
|
|
||||||
# To small, grow!
|
|
||||||
# TODO: find a more efficient way
|
|
||||||
line_end += 1
|
|
||||||
|
|
||||||
else # FOUND IT!
|
|
||||||
entering_line_end = line_end.floor
|
|
||||||
max_reach = line_end.floor - line_start < 63 ? line_end.floor - line_start : 63
|
|
||||||
reach = 0
|
|
||||||
|
|
||||||
if wrap_behavior == :word_wrap
|
|
||||||
max_reach.times do |i|
|
|
||||||
reach = i
|
|
||||||
break if copy[line_end.floor - i].to_s.match(/[[:punct:]]| /)
|
|
||||||
end
|
|
||||||
|
|
||||||
puts "Max width: #{max_width}/#{line_width(@raw_text)} Reach: {#{reach}/#{max_reach}} Line Start: #{line_start}/#{line_end.floor} (#{copy.length}|#{@raw_text.length}) [#{entering_line_end}] '#{copy}' {#{copy[line_start...line_end]}}"
|
|
||||||
line_end = line_end.floor - reach + 1 if reach != max_reach # Add +1 to walk in front of punctuation
|
|
||||||
end
|
|
||||||
|
|
||||||
breaks << line_end.floor
|
|
||||||
line_start = line_end.floor
|
|
||||||
line_end = copy.length
|
|
||||||
|
|
||||||
break if entering_line_end == copy.length || reach == max_reach
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
breaks.each_with_index do |pos, index|
|
|
||||||
copy.insert(pos + index, "\n") if pos + index >= 0 && pos + index < copy.length
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
@text.text = copy
|
|
||||||
end
|
|
||||||
|
|
||||||
def line_width(text)
|
|
||||||
(@x + @text.textobject.markup_width(text) + noncontent_width)
|
|
||||||
end
|
|
||||||
|
|
||||||
def value
|
|
||||||
@raw_text
|
|
||||||
end
|
|
||||||
|
|
||||||
def value=(value)
|
|
||||||
@raw_text = value.to_s.chomp
|
|
||||||
|
|
||||||
old_width = width
|
|
||||||
old_height = height
|
|
||||||
recalculate
|
|
||||||
|
|
||||||
root.gui_state.request_recalculate if old_width != width || old_height != height
|
|
||||||
|
|
||||||
publish(:changed, self.value)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
class Banner < TextBlock
|
|
||||||
end
|
|
||||||
|
|
||||||
class Title < TextBlock
|
|
||||||
end
|
|
||||||
|
|
||||||
class Subtitle < TextBlock
|
|
||||||
end
|
|
||||||
|
|
||||||
class Tagline < TextBlock
|
|
||||||
end
|
|
||||||
|
|
||||||
class Caption < TextBlock
|
|
||||||
end
|
|
||||||
|
|
||||||
class Para < TextBlock
|
|
||||||
end
|
|
||||||
|
|
||||||
class Inscription < TextBlock
|
|
||||||
end
|
|
||||||
|
|
||||||
# TODO: Remove in version 0.16.0+
|
|
||||||
class Label < TextBlock
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
@@ -18,12 +18,6 @@ module CyberarmEngine
|
|||||||
@text.draw
|
@text.draw
|
||||||
end
|
end
|
||||||
|
|
||||||
def clicked_left_mouse_button(_sender, _x, _y)
|
|
||||||
@block&.call(self) if @enabled
|
|
||||||
|
|
||||||
# return :handled
|
|
||||||
end
|
|
||||||
|
|
||||||
def recalculate
|
def recalculate
|
||||||
@width = 0
|
@width = 0
|
||||||
@height = 0
|
@height = 0
|
||||||
@@ -152,5 +146,8 @@ module CyberarmEngine
|
|||||||
|
|
||||||
class ToolTip < TextBlock
|
class ToolTip < TextBlock
|
||||||
end
|
end
|
||||||
|
|
||||||
|
class Link < TextBlock
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -159,6 +159,19 @@ module CyberarmEngine
|
|||||||
border_color: 0xffaaaaaa,
|
border_color: 0xffaaaaaa,
|
||||||
background: 0xff404040
|
background: 0xff404040
|
||||||
},
|
},
|
||||||
|
Link: { # < TextBlock
|
||||||
|
color: Gosu::Color::BLUE,
|
||||||
|
border_thickness: 1,
|
||||||
|
border_bottom_color: Gosu::Color::BLUE,
|
||||||
|
hover: {
|
||||||
|
color: 0xff_ff00ff,
|
||||||
|
border_bottom_color: 0xff_ff00ff
|
||||||
|
},
|
||||||
|
active: {
|
||||||
|
color: 0xff_ff0000,
|
||||||
|
border_bottom_color: 0xff_ff0000
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
ToggleButton: { # < Button
|
ToggleButton: { # < Button
|
||||||
checkmark: "√"
|
checkmark: "√"
|
||||||
|
|||||||
Reference in New Issue
Block a user