1
0
Fork 0

canvas.gui: Checkable buttons, layout for ScrollArea and images for Lables.

This commit is contained in:
Thomas Geymayer 2014-06-10 18:46:52 +02:00
parent 7e2c93825f
commit 48f33fe78f
6 changed files with 112 additions and 73 deletions

View file

@ -35,7 +35,7 @@ var WindowButton = {
var window_focus = me._windowFocus();
file ~= window_focus ? "_focused" : "_unfocused";
if( me._active )
if( me._down )
file ~= "_pressed";
else if( me._hover )
file ~= "_prelight";
@ -405,7 +405,7 @@ var Window = {
var button_close = WindowButton.new(title_bar, "close")
.move(x, y);
button_close.onClick = func me.del();
button_close.listen("clicked", func me.del());
# title
me._title = title_bar.createChild("text", "title")
@ -452,32 +452,6 @@ var Dialog = {
}
};
var createLayoutTest = func
{
var dlg = canvas.Window.new([350,250], "dialog")
.set("resize", 1);
dlg.getCanvas(1)
.set("background", style.getColor("bg_color"));
var root = dlg.getCanvas().createGroup();
var vbox = VBoxLayout.new();
dlg.setLayout(vbox);
var b = gui.widgets.Button.new(root, style, {}).setText("Stretch");
b.setMaximumSize([9999, 9999]);
vbox.addItem(b, 1);
var button_box = HBoxLayout.new();
vbox.addItem(button_box);
var b1 = gui.widgets.Button.new(root, style, {}).setText("Ok");
button_box.addItem(b1);
b1.setFocus();
var b2 = gui.widgets.Button.new(root, style, {}).setText("Abort");
button_box.addItem(b2);
}
# Canvas GUI demo
#
# Shows an icon in the top-right corner which upon click opens a simple window
@ -498,9 +472,6 @@ var initDemo = func
});
my_canvas.addEventListener("click", func(e)
{
if( e.button == 1 )
return createLayoutTest();
var dlg = canvas.Window.new([400,300], "dialog")
.set("resize", 1);
var my_canvas = dlg.createCanvas()
@ -511,9 +482,8 @@ var initDemo = func
my_canvas.addEventListener("drag", func(e) { printf("drag: screen(%.1f|%.1f) client(%.1f|%.1f) local(%.1f|%.1f) delta(%.1f|%.1f)", e.screenX, e.screenY, e.clientX, e.clientY, e.localX, e.localY, e.deltaX, e.deltaY); });
my_canvas.addEventListener("wheel", func(e) { printf("wheel: screen(%.1f|%.1f) client(%.1f|%.1f) %.1f", e.screenX, e.screenY, e.clientX, e.clientY, e.deltaY); });
var root = my_canvas.createGroup();
root.addEventListener("test", func(e) { printf("test: %s", e.detail.test); });
root.createChild("image")
.set("src", "http://wiki.flightgear.org/skins/common/images/icons-fg-135.png");
root.createChild("image")
.set("src", "http://wiki.flightgear.org/skins/common/images/icons-fg-135.png");
var text =
root.createChild("text")
.setText("This could be used for building an 'Aircraft Help' dialog.\nYou can also #use it to play around with the new Canvas system :). β")
@ -533,7 +503,6 @@ root.createChild("image")
.set("fill", "#ff0000")
.hide();
var visible_count = 0;
text.addEventListener("click", func root.dispatchEvent(canvas.CustomEvent.new("test", {detail: {"test": "some important data.."}})));
text.addEventListener("mouseover", func text_move.show());
text.addEventListener("mouseout", func text_move.hide());
text.addEventListener("mousemove", func(e) { printf("move: screen(%.1f|%.1f) client(%.1f|%.1f) local(%.1f|%.1f) delta(%.1f|%.1f)", e.screenX, e.screenY, e.clientX, e.clientY, e.localX, e.localY, e.deltaX, e.deltaY); });

View file

@ -22,10 +22,16 @@ gui.Widget = {
m.setSizeHint([32, 32]);
m.setMaximumSize([m._MAX_SIZE, m._MAX_SIZE]);
m.setSetGeometryFunc(m.setGeometry);
m.setSetGeometryFunc(m._impl.setGeometry);
return m;
},
setFixedSize: func(x, y)
{
me.setMinimumSize([x, y]);
me.setSizeHint([x, y]);
me.setMaximumSize([x, y]);
},
# Move the widget to the given position (relative to its parent)
move: func(x, y)
{
@ -48,11 +54,11 @@ gui.Widget = {
},
# Set geometry of widget (usually used by layouting system)
#
# @param geom [<min-x>, <min-y>, <max-x>, <max-y>]
# @param geom [<x>, <y>, <width>, <height>]
setGeometry: func(geom)
{
me.move(geom[0], geom[1]);
me.setSize(geom[2] - geom[0], geom[3] - geom[1]);
me.setSize(geom[2], geom[3]);
me._onStateChange();
return me;
},
@ -69,7 +75,7 @@ gui.Widget = {
me._focused = 1;
canvas._focused_widget = me;
me.onFocusIn();
me._trigger("focus-in");
me._onStateChange();
return me;
@ -83,15 +89,16 @@ gui.Widget = {
me._focused = 0;
me.getCanvas()._focused_widget = nil;
me.onFocusOut();
me._trigger("focus-out");
me._onStateChange();
return me;
},
onFocusIn: func {},
onFocusOut: func {},
onMouseEnter: func {},
onMouseLeave: func {},
listen: func(type, cb)
{
me._view._root.addEventListener("cb." ~ type, cb);
return me;
},
# protected:
_MAX_SIZE: 32768, # size for "no size-limit"
_onStateChange: func {},
@ -112,7 +119,7 @@ gui.Widget = {
root.addEventListener("mouseenter", func {
me._hover = 1;
me.onMouseEnter();
me._trigger("mouse-enter");
me._onStateChange();
});
root.addEventListener("mousedown", func {
@ -121,10 +128,17 @@ gui.Widget = {
});
root.addEventListener("mouseleave", func {
me._hover = 0;
me.onMouseLeave();
me._trigger("mouse-leave");
me._onStateChange();
});
},
_trigger: func(type, data = nil)
{
me._view._root.dispatchEvent(
canvas.CustomEvent.new("cb." ~ type, {detail: data})
);
return me;
},
_windowFocus: func
{
var canvas = me.getCanvas();

View file

@ -70,7 +70,7 @@ DefaultStyle.widgets.button = {
me._label.set("fill", me._style.getColor("fg_color"));
file ~= "button";
if( model._active )
if( model._down )
{
file ~= "-active";
me._label.setTranslation(w / 2 + 1, h / 2 + 6);
@ -82,7 +82,7 @@ DefaultStyle.widgets.button = {
if( model._focused and !backdrop )
file ~= "-focused";
if( model._hover and !model._active )
if( model._hover and !model._down )
{
file ~= "-hover";
me._bg.set("fill", me._style.getColor("button_bg_color_hover"));
@ -104,6 +104,9 @@ DefaultStyle.widgets.label = {
{
if( me['_bg'] != nil )
me._bg.reset().rect(0, 0, w, h);
if( me['_img'] != nil )
me._img.set("size[0]", w)
.set("size[1]", h);
if( me['_text'] != nil )
# TODO different alignment
me._text.setTranslation(2, h / 2);
@ -115,11 +118,23 @@ DefaultStyle.widgets.label = {
return me._deleteElement('text');
me._createElement("text", "text")
.set("text", text);
.set("text", text)
.set("fill", "black");
# TODO get real font metrics
model.setMinimumSize([size(text) * 5 + 4, 14]);
model.setSizeHint([size(text) * 8 + 8, 24]);
model.setSizeHint([size(text) * 5 + 14, 24]);
return me;
},
setImage: func(model, img)
{
if( img == nil or size(img) == 0 )
return me._deleteElement('img');
me._createElement("img", "image")
.set("src", img)
.set("preserveAspectRatio", "xMidYMid slice");
return me;
},

View file

@ -4,7 +4,8 @@ gui.widgets.Button = {
var cfg = Config.new(cfg);
var m = gui.Widget.new(gui.widgets.Button);
m._focus_policy = m.StrongFocus;
m._active = 0;
m._down = 0;
m._checkable = 0;
m._flat = cfg.get("flat", 0);
if( style != nil and !m._flat )
@ -17,25 +18,41 @@ gui.widgets.Button = {
me._view.setText(me, text);
return me;
},
setActive: func
setCheckable: func(checkable)
{
if( me._active )
me._checkable = checkable;
return me;
},
setChecked: func(checked = 1)
{
if( !me._checkable or me._down == checked )
return me;
me._active = 1;
me._trigger("clicked", {checked: checked});
me._trigger("toggled", {checked: checked});
me._down = checked;
me._onStateChange();
return me;
},
clearActive: func
setDown: func(down = 1)
{
if( !me._active )
if( me._checkable or me._down == down )
return me;
me._active = 0;
me._down = down;
me._onStateChange();
return me;
},
onClick: func {},
toggle: func
{
if( !me._checkable )
me._trigger("clicked", {checked: 0});
else
me.setChecked(!me._down);
return me;
},
# protected:
_onStateChange: func
{
@ -45,14 +62,11 @@ gui.widgets.Button = {
_setView: func(view)
{
var el = view._root;
el.addEventListener("mousedown", func me.setActive());
el.addEventListener("mouseup", func me.clearActive());
el.addEventListener("mousedown", func me.setDown(1));
el.addEventListener("mouseup", func me.setDown(0));
el.addEventListener("click", func me.toggle());
# Use 'call' to ensure 'me' is not set and can be used in the closure of
# custom callbacks. TODO pass 'me' as argument?
el.addEventListener("click", func call(me.onClick));
el.addEventListener("mouseleave",func me.clearActive());
el.addEventListener("mouseleave",func me.setDown(0));
el.addEventListener("drag", func(e) e.stopPropagation());
call(gui.Widget._setView, [view], me);

View file

@ -13,6 +13,11 @@ gui.widgets.Label = {
me._view.setText(me, text);
return me;
},
setImage: func(img)
{
me._view.setImage(me, img);
return me;
},
setBackground: func(bg)
{
me._view.setBackground(me, bg);

View file

@ -7,6 +7,7 @@ gui.widgets.ScrollArea = {
m._scroll_pos = [0,0];
m._max_scroll = [0, 0];
m._content_size = [0, 0];
m._layout = nil;
if( style != nil )
m._setView( style.createWidget(parent, "scroll-area", cfg) );
@ -15,6 +16,12 @@ gui.widgets.ScrollArea = {
return m;
},
setLayout: func(l)
{
me._layout = l;
l.setParent(me);
return me.update();
},
getContent: func()
{
return me._view.content;
@ -143,12 +150,30 @@ gui.widgets.ScrollArea = {
_updateBB: func()
{
# TODO only update on content resize
var bb = me.getContent().getTightBoundingBox();
if( me._layout == nil )
{
var bb = me.getContent().getTightBoundingBox();
if( bb[2] < bb[0] or bb[3] < bb[1] )
return nil;
var w = bb[2] - bb[0];
var h = bb[3] - bb[1];
if( bb[2] < bb[0] or bb[3] < bb[1] )
return nil;
var w = bb[2] - bb[0];
var h = bb[3] - bb[1];
var cur_offset = me.getContent().getTranslation();
me._content_offset = [cur_offset[0] - bb[0], cur_offset[1] - bb[1]];
}
else
{
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]));
me._layout.setGeometry([0, 0, w, h]);
# Layout always has the origin at (0, 0)
me._content_offset = [0, 0];
}
if( w > me._size[0] )
{
@ -168,8 +193,5 @@ gui.widgets.ScrollArea = {
me._content_size[0] = w;
me._content_size[1] = h;
var cur_offset = me.getContent().getTranslation();
me._content_offset = [cur_offset[0] - bb[0], cur_offset[1] - bb[1]];
}
};