From 3505d3c8bfca76401b4d3cb37de943bc72153e4b Mon Sep 17 00:00:00 2001 From: Thomas Geymayer <tomgey@gmail.com> Date: Fri, 13 Jun 2014 00:15:30 +0200 Subject: [PATCH] canvas.gui: support height-for-width layouting. Setting wordWrap on canvas.gui.Label enables height-for-width where the height of the label depends on the layouted texts width. --- Nasal/canvas/gui/Config.nas | 5 ++++ Nasal/canvas/gui/Widget.nas | 2 +- Nasal/canvas/gui/styles/DefaultStyle.nas | 38 +++++++++++++++++++----- Nasal/canvas/gui/widgets/Label.nas | 4 +-- Nasal/canvas/gui/widgets/ScrollArea.nas | 8 +++-- 5 files changed, 45 insertions(+), 12 deletions(-) diff --git a/Nasal/canvas/gui/Config.nas b/Nasal/canvas/gui/Config.nas index b8bdfe183..24f516a00 100644 --- a/Nasal/canvas/gui/Config.nas +++ b/Nasal/canvas/gui/Config.nas @@ -17,5 +17,10 @@ var Config = { return val; return default; + }, + set: func(key, value) + { + me._cfg[key] = value; + return me; } }; diff --git a/Nasal/canvas/gui/Widget.nas b/Nasal/canvas/gui/Widget.nas index e3a19b824..44f8c8b8a 100644 --- a/Nasal/canvas/gui/Widget.nas +++ b/Nasal/canvas/gui/Widget.nas @@ -61,7 +61,7 @@ gui.Widget = { me._size[1] = h; if( me._view != nil ) - me._view.setSize(w, h); + me._view.setSize(me, w, h); return me; }, # Set geometry of widget (usually used by layouting system) diff --git a/Nasal/canvas/gui/styles/DefaultStyle.nas b/Nasal/canvas/gui/styles/DefaultStyle.nas index 887997428..ec177e4a0 100644 --- a/Nasal/canvas/gui/styles/DefaultStyle.nas +++ b/Nasal/canvas/gui/styles/DefaultStyle.nas @@ -39,7 +39,7 @@ DefaultStyle.widgets.button = { .set("character-size", 14) .set("alignment", "center-baseline"); }, - setSize: func(w, h) + setSize: func(model, w, h) { me._bg.reset() .rect(3, 3, w - 6, h - 6, {"border-radius": 5}); @@ -108,7 +108,7 @@ DefaultStyle.widgets.label = { { me._root = parent.createChild("group", "label"); }, - setSize: func(w, h) + setSize: func(model, w, h) { if( me['_bg'] != nil ) me._bg.reset().rect(0, 0, w, h); @@ -116,22 +116,39 @@ DefaultStyle.widgets.label = { me._img.set("size[0]", w) .set("size[1]", h); if( me['_text'] != nil ) + { # TODO different alignment - me._text.setTranslation(2, h / 2); + me._text.setTranslation(2, 2 + h / 2); + me._text.set( + "max-width", + model._cfg.get("wordWrap", 0) ? (w - 4) : 0 + ); + } return me; }, setText: func(model, text) { if( text == nil or size(text) == 0 ) + { + model.setHeightForWidthFunc(nil); return me._deleteElement('text'); + } me._createElement("text", "text") .set("text", text) .set("fill", "black"); - # TODO get real font metrics - model.setMinimumSize([size(text) * 5 + 4, 14]); - model.setSizeHint([size(text) * 5 + 14, 24]); + if( model._cfg.get("wordWrap", 0) ) + { + var m = me; + model.setHeightForWidthFunc(func(w) m.heightForWidth(w)); + } + else + { + # TODO get real font metrics + model.setMinimumSize([size(text) * 5 + 4, 14]); + model.setSizeHint([size(text) * 5 + 14, 24]); + } return me; }, @@ -155,9 +172,16 @@ DefaultStyle.widgets.label = { me._createElement("bg", "path") .set("fill", bg); - me.setSize(model._size[0], model._size[1]); + me.setSize(model, model._size[0], model._size[1]); return me; }, + heightForWidth: func(w) + { + if( me['_text'] == nil ) + return -1; + + return math.max(14, me._text.heightForWidth(w - 4)); + }, # protected: _createElement: func(name, type) { diff --git a/Nasal/canvas/gui/widgets/Label.nas b/Nasal/canvas/gui/widgets/Label.nas index 47654d158..a648e1bec 100644 --- a/Nasal/canvas/gui/widgets/Label.nas +++ b/Nasal/canvas/gui/widgets/Label.nas @@ -1,10 +1,10 @@ gui.widgets.Label = { new: func(parent, style, cfg) { - var cfg = Config.new(cfg); var m = gui.Widget.new(gui.widgets.Label); + m._cfg = Config.new(cfg); m._focus_policy = m.NoFocus; - m._setView( style.createWidget(parent, "label", cfg) ); + m._setView( style.createWidget(parent, "label", m._cfg) ); return m; }, diff --git a/Nasal/canvas/gui/widgets/ScrollArea.nas b/Nasal/canvas/gui/widgets/ScrollArea.nas index 64528525c..99eea1457 100644 --- a/Nasal/canvas/gui/widgets/ScrollArea.nas +++ b/Nasal/canvas/gui/widgets/ScrollArea.nas @@ -179,8 +179,12 @@ gui.widgets.ScrollArea = { var min_size = me._layout.minimumSize(); var max_size = me._layout.maximumSize(); var size_hint = me._layout.sizeHint(); - var w = math.min(max_size[0], math.max(math.max(min_size[0], size_hint[0]), me._size[0])); - var h = math.min(max_size[1], math.max(math.max(min_size[1], size_hint[1]), me._size[1])); + var w = math.min(max_size[0], math.max(size_hint[0], me._size[0])); + var h = math.max( + math.min(max_size[1], math.max(size_hint[1], me._size[1])), + me._layout.heightForWidth(w) + ); + me._layout.setGeometry([0, 0, w, h]); # Layout always has the origin at (0, 0)