mirror of
https://github.com/Insality/druid.git
synced 2025-09-27 10:02:18 +02:00
Update Rich Input with selection/arrows control. Add template and nodes to self:get_druid
This commit is contained in:
@@ -81,11 +81,10 @@ local const = require("druid.const")
|
||||
local helper = require("druid.helper")
|
||||
local utf8_lua = require("druid.system.utf8")
|
||||
local component = require("druid.component")
|
||||
local utf8 = utf8 or utf8_lua
|
||||
local utf8 = utf8 or utf8_lua --[[@as utf8]]
|
||||
|
||||
local Text = component.create("text")
|
||||
|
||||
|
||||
local function update_text_size(self)
|
||||
local size = vmath.vector3(
|
||||
self.start_size.x * (self.start_scale.x / self.scale.x),
|
||||
@@ -110,13 +109,12 @@ local function is_fit_info_area(self, metrics)
|
||||
return metrics.width * self.scale.x <= self.text_area.x and
|
||||
metrics.height * self.scale.y <= self.text_area.y
|
||||
end
|
||||
|
||||
|
||||
--- Setup scale x, but can only be smaller, than start text scale
|
||||
local function update_text_area_size(self)
|
||||
reset_default_scale(self)
|
||||
|
||||
local max_width = self.text_area.x
|
||||
local max_height = self.text_area.y
|
||||
|
||||
local metrics = helper.get_text_metrics_from_node(self.node)
|
||||
|
||||
if metrics.width == 0 then
|
||||
@@ -125,15 +123,56 @@ local function update_text_area_size(self)
|
||||
return
|
||||
end
|
||||
|
||||
local scale_modifier = max_width / metrics.width
|
||||
scale_modifier = math.min(scale_modifier, self.start_scale.x)
|
||||
local text_area_width = self.text_area.x
|
||||
local text_area_height = self.text_area.y
|
||||
|
||||
-- Adjust by width
|
||||
local scale_modifier = text_area_width / metrics.width
|
||||
|
||||
-- Adjust by height
|
||||
if self:is_multiline() then
|
||||
local scale_modifier_by_height = math.sqrt(max_height / metrics.height)
|
||||
scale_modifier = math.min(self.start_scale.y, scale_modifier_by_height)
|
||||
-- Approximate scale by height to start adjust scale
|
||||
scale_modifier = math.sqrt(text_area_height / metrics.height)
|
||||
if metrics.width * scale_modifier > text_area_width then
|
||||
scale_modifier = text_area_width / metrics.width
|
||||
end
|
||||
|
||||
if metrics.width * scale_modifier > max_width then
|
||||
scale_modifier = math.min(max_width / metrics.width, self.start_scale.x)
|
||||
-- #RMME
|
||||
if self._minimal_scale then
|
||||
scale_modifier = math.max(scale_modifier, self._minimal_scale)
|
||||
end
|
||||
-- Limit max scale by initial scale
|
||||
scale_modifier = math.min(scale_modifier, self.start_scale.x)
|
||||
-- #RMME
|
||||
|
||||
local is_fit = is_fit_info_area(self, metrics)
|
||||
local step = is_fit and self.style.ADJUST_SCALE_DELTA or -self.style.ADJUST_SCALE_DELTA
|
||||
|
||||
for i = 1, self.style.ADJUST_STEPS do
|
||||
-- Grow down to check if we fit
|
||||
if step < 0 and is_fit then
|
||||
break
|
||||
end
|
||||
-- Grow up to check if we still fit
|
||||
if step > 0 and not is_fit then
|
||||
break
|
||||
end
|
||||
|
||||
scale_modifier = scale_modifier + step
|
||||
|
||||
if self._minimal_scale then
|
||||
scale_modifier = math.max(scale_modifier, self._minimal_scale)
|
||||
end
|
||||
-- Limit max scale by initial scale
|
||||
scale_modifier = math.min(scale_modifier, self.start_scale.x)
|
||||
|
||||
self.scale.x = scale_modifier
|
||||
self.scale.y = scale_modifier
|
||||
self.scale.z = self.start_scale.z
|
||||
gui.set_scale(self.node, self.scale)
|
||||
update_text_size(self)
|
||||
metrics = helper.get_text_metrics_from_node(self.node)
|
||||
is_fit = is_fit_info_area(self, metrics)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -141,12 +180,16 @@ local function update_text_area_size(self)
|
||||
scale_modifier = math.max(scale_modifier, self._minimal_scale)
|
||||
end
|
||||
|
||||
local new_scale = vmath.vector3(scale_modifier, scale_modifier, self.start_scale.z)
|
||||
gui.set_scale(self.node, new_scale)
|
||||
self.scale = new_scale
|
||||
-- Limit max scale by initial scale
|
||||
scale_modifier = math.min(scale_modifier, self.start_scale.x)
|
||||
|
||||
self.scale.x = scale_modifier
|
||||
self.scale.y = scale_modifier
|
||||
self.scale.z = self.start_scale.z
|
||||
gui.set_scale(self.node, self.scale)
|
||||
update_text_size(self)
|
||||
|
||||
self.on_update_text_scale:trigger(self:get_context(), new_scale, metrics)
|
||||
self.on_update_text_scale:trigger(self:get_context(), self.scale, metrics)
|
||||
end
|
||||
|
||||
|
||||
@@ -177,18 +220,6 @@ local function update_text_with_anchor_shift(self)
|
||||
end
|
||||
|
||||
|
||||
-- calculate space width with font
|
||||
local function get_space_width(self, font)
|
||||
if not self._space_width[font] then
|
||||
local no_space = resource.get_text_metrics(font, "1").width
|
||||
local with_space = resource.get_text_metrics(font, " 1").width
|
||||
self._space_width[font] = with_space - no_space
|
||||
end
|
||||
|
||||
return self._space_width[font]
|
||||
end
|
||||
|
||||
|
||||
local function update_adjust(self)
|
||||
if not self.adjust_type or self.adjust_type == const.TEXT_ADJUST.NO_ADJUST then
|
||||
reset_default_scale(self)
|
||||
@@ -224,18 +255,22 @@ end
|
||||
-- @table style
|
||||
-- @tfield string|nil TRIM_POSTFIX The postfix for TRIM adjust type. Default: ...
|
||||
-- @tfield string|nil DEFAULT_ADJUST The default adjust type for any text component. Default: DOWNSCALE
|
||||
-- @tfield string|nil ADJUST_STEPS Amount of iterations for text adjust by height. Default: 20
|
||||
-- @tfield string|nil ADJUST_SCALE_DELTA Scale step on each height adjust step. Default: 0.02
|
||||
function Text.on_style_change(self, style)
|
||||
self.style = {}
|
||||
self.style.TRIM_POSTFIX = style.TRIM_POSTFIX or "..."
|
||||
self.style.DEFAULT_ADJUST = style.DEFAULT_ADJUST or const.TEXT_ADJUST.DOWNSCALE
|
||||
self.style.ADJUST_STEPS = style.ADJUST_STEPS or 20
|
||||
self.style.ADJUST_SCALE_DELTA = style.ADJUST_SCALE_DELTA or 0.02
|
||||
end
|
||||
|
||||
|
||||
--- The @{Text} constructor
|
||||
-- @tparam Text self @{Text}
|
||||
-- @tparam string|node node Node name or GUI Text Node itself
|
||||
-- @tparam string|nil value Initial text. Default value is node text from GUI scene.
|
||||
-- @tparam string|nil adjust_type Adjust type for text. By default is DOWNSCALE. Look const.TEXT_ADJUST for reference. Default: downscale
|
||||
-- @tparam string|nil value Initial text. Default value is node text from GUI scene. Default: nil
|
||||
-- @tparam string|nil adjust_type Adjust type for text. By default is DOWNSCALE. Look const.TEXT_ADJUST for reference. Default: DOWNSCALE
|
||||
function Text.init(self, node, value, adjust_type)
|
||||
self.node = self:get_node(node)
|
||||
self.pos = gui.get_position(self.node)
|
||||
@@ -257,8 +292,6 @@ function Text.init(self, node, value, adjust_type)
|
||||
self.on_set_pivot = Event()
|
||||
self.on_update_text_scale = Event()
|
||||
|
||||
self._space_width = {}
|
||||
|
||||
self:set_to(value or gui.get_text(self.node))
|
||||
return self
|
||||
end
|
||||
@@ -282,38 +315,66 @@ end
|
||||
|
||||
--- Calculate text width with font with respect to trailing space
|
||||
-- @tparam Text self @{Text}
|
||||
-- @tparam string|nil text
|
||||
-- @tparam string text|nil
|
||||
-- @treturn number Width
|
||||
-- @treturn number Height
|
||||
function Text.get_text_size(self, text)
|
||||
text = text or self.last_value
|
||||
local font_name = gui.get_font(self.node)
|
||||
local font = gui.get_font_resource(font_name)
|
||||
local scale = gui.get_scale(self.node)
|
||||
local scale = self.last_scale or gui.get_scale(self.node)
|
||||
local linebreak = gui.get_line_break(self.node)
|
||||
local metrics = resource.get_text_metrics(font, text, {
|
||||
local dot_width = resource.get_text_metrics(font, ".").width
|
||||
|
||||
local metrics = resource.get_text_metrics(font, text .. ".", {
|
||||
line_break = linebreak,
|
||||
leading = 1,
|
||||
tracking = 0,
|
||||
width = self.start_size.x
|
||||
})
|
||||
local width = metrics.width
|
||||
for i = #text, 1, -1 do
|
||||
local c = string.sub(text, i, i)
|
||||
if c ~= ' ' then
|
||||
|
||||
local width = metrics.width - dot_width
|
||||
return width * scale.x, metrics.height * scale.y
|
||||
end
|
||||
|
||||
|
||||
--- Get chars count by width
|
||||
-- @tparam Text self @{Text}
|
||||
-- @tparam number width
|
||||
-- @treturn number Chars count
|
||||
function Text.get_text_index_by_width(self, width)
|
||||
local text = self.last_value
|
||||
local font_name = gui.get_font(self.node)
|
||||
local font = gui.get_font_resource(font_name)
|
||||
local scale = self.last_scale or gui.get_scale(self.node)
|
||||
|
||||
local text_index = 0
|
||||
local text_width = 0
|
||||
local text_length = utf8.len(text)
|
||||
local dot_width = resource.get_text_metrics(font, ".").width
|
||||
local previous_width = 0
|
||||
for i = 1, text_length do
|
||||
local subtext = utf8.sub(text, 1, i) .. "."
|
||||
local subtext_width = resource.get_text_metrics(font, subtext).width
|
||||
subtext_width = subtext_width - dot_width
|
||||
text_width = subtext_width * scale.x
|
||||
local width_delta = text_width - previous_width
|
||||
previous_width = text_width
|
||||
|
||||
if (text_width - width_delta/2) < width then
|
||||
text_index = i
|
||||
else
|
||||
break
|
||||
end
|
||||
|
||||
width = width + get_space_width(self, font)
|
||||
end
|
||||
|
||||
return width * scale.x, metrics.height * scale.y
|
||||
return text_index
|
||||
end
|
||||
|
||||
|
||||
--- Set text to text field
|
||||
-- @tparam Text self @{Text}
|
||||
-- @tparam string|number|boolean set_to Text for node
|
||||
-- @tparam string set_to Text for node
|
||||
-- @treturn Text Current text instance
|
||||
function Text.set_to(self, set_to)
|
||||
set_to = set_to or ""
|
||||
|
Reference in New Issue
Block a user