canvas.gui: Checkable buttons, layout for ScrollArea and images for Lables.
This commit is contained in:
parent
7e2c93825f
commit
48f33fe78f
6 changed files with 112 additions and 73 deletions
|
@ -35,7 +35,7 @@ var WindowButton = {
|
||||||
var window_focus = me._windowFocus();
|
var window_focus = me._windowFocus();
|
||||||
file ~= window_focus ? "_focused" : "_unfocused";
|
file ~= window_focus ? "_focused" : "_unfocused";
|
||||||
|
|
||||||
if( me._active )
|
if( me._down )
|
||||||
file ~= "_pressed";
|
file ~= "_pressed";
|
||||||
else if( me._hover )
|
else if( me._hover )
|
||||||
file ~= "_prelight";
|
file ~= "_prelight";
|
||||||
|
@ -405,7 +405,7 @@ var Window = {
|
||||||
|
|
||||||
var button_close = WindowButton.new(title_bar, "close")
|
var button_close = WindowButton.new(title_bar, "close")
|
||||||
.move(x, y);
|
.move(x, y);
|
||||||
button_close.onClick = func me.del();
|
button_close.listen("clicked", func me.del());
|
||||||
|
|
||||||
# title
|
# title
|
||||||
me._title = title_bar.createChild("text", "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
|
# Canvas GUI demo
|
||||||
#
|
#
|
||||||
# Shows an icon in the top-right corner which upon click opens a simple window
|
# 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)
|
my_canvas.addEventListener("click", func(e)
|
||||||
{
|
{
|
||||||
if( e.button == 1 )
|
|
||||||
return createLayoutTest();
|
|
||||||
|
|
||||||
var dlg = canvas.Window.new([400,300], "dialog")
|
var dlg = canvas.Window.new([400,300], "dialog")
|
||||||
.set("resize", 1);
|
.set("resize", 1);
|
||||||
var my_canvas = dlg.createCanvas()
|
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("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); });
|
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();
|
var root = my_canvas.createGroup();
|
||||||
root.addEventListener("test", func(e) { printf("test: %s", e.detail.test); });
|
root.createChild("image")
|
||||||
root.createChild("image")
|
.set("src", "http://wiki.flightgear.org/skins/common/images/icons-fg-135.png");
|
||||||
.set("src", "http://wiki.flightgear.org/skins/common/images/icons-fg-135.png");
|
|
||||||
var text =
|
var text =
|
||||||
root.createChild("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 :). β")
|
.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")
|
.set("fill", "#ff0000")
|
||||||
.hide();
|
.hide();
|
||||||
var visible_count = 0;
|
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("mouseover", func text_move.show());
|
||||||
text.addEventListener("mouseout", func text_move.hide());
|
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); });
|
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); });
|
||||||
|
|
|
@ -22,10 +22,16 @@ gui.Widget = {
|
||||||
m.setSizeHint([32, 32]);
|
m.setSizeHint([32, 32]);
|
||||||
m.setMaximumSize([m._MAX_SIZE, m._MAX_SIZE]);
|
m.setMaximumSize([m._MAX_SIZE, m._MAX_SIZE]);
|
||||||
|
|
||||||
m.setSetGeometryFunc(m.setGeometry);
|
m.setSetGeometryFunc(m._impl.setGeometry);
|
||||||
|
|
||||||
return m;
|
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 the widget to the given position (relative to its parent)
|
||||||
move: func(x, y)
|
move: func(x, y)
|
||||||
{
|
{
|
||||||
|
@ -48,11 +54,11 @@ gui.Widget = {
|
||||||
},
|
},
|
||||||
# Set geometry of widget (usually used by layouting system)
|
# 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)
|
setGeometry: func(geom)
|
||||||
{
|
{
|
||||||
me.move(geom[0], geom[1]);
|
me.move(geom[0], geom[1]);
|
||||||
me.setSize(geom[2] - geom[0], geom[3] - geom[1]);
|
me.setSize(geom[2], geom[3]);
|
||||||
me._onStateChange();
|
me._onStateChange();
|
||||||
return me;
|
return me;
|
||||||
},
|
},
|
||||||
|
@ -69,7 +75,7 @@ gui.Widget = {
|
||||||
me._focused = 1;
|
me._focused = 1;
|
||||||
canvas._focused_widget = me;
|
canvas._focused_widget = me;
|
||||||
|
|
||||||
me.onFocusIn();
|
me._trigger("focus-in");
|
||||||
me._onStateChange();
|
me._onStateChange();
|
||||||
|
|
||||||
return me;
|
return me;
|
||||||
|
@ -83,15 +89,16 @@ gui.Widget = {
|
||||||
me._focused = 0;
|
me._focused = 0;
|
||||||
me.getCanvas()._focused_widget = nil;
|
me.getCanvas()._focused_widget = nil;
|
||||||
|
|
||||||
me.onFocusOut();
|
me._trigger("focus-out");
|
||||||
me._onStateChange();
|
me._onStateChange();
|
||||||
|
|
||||||
return me;
|
return me;
|
||||||
},
|
},
|
||||||
onFocusIn: func {},
|
listen: func(type, cb)
|
||||||
onFocusOut: func {},
|
{
|
||||||
onMouseEnter: func {},
|
me._view._root.addEventListener("cb." ~ type, cb);
|
||||||
onMouseLeave: func {},
|
return me;
|
||||||
|
},
|
||||||
# protected:
|
# protected:
|
||||||
_MAX_SIZE: 32768, # size for "no size-limit"
|
_MAX_SIZE: 32768, # size for "no size-limit"
|
||||||
_onStateChange: func {},
|
_onStateChange: func {},
|
||||||
|
@ -112,7 +119,7 @@ gui.Widget = {
|
||||||
|
|
||||||
root.addEventListener("mouseenter", func {
|
root.addEventListener("mouseenter", func {
|
||||||
me._hover = 1;
|
me._hover = 1;
|
||||||
me.onMouseEnter();
|
me._trigger("mouse-enter");
|
||||||
me._onStateChange();
|
me._onStateChange();
|
||||||
});
|
});
|
||||||
root.addEventListener("mousedown", func {
|
root.addEventListener("mousedown", func {
|
||||||
|
@ -121,10 +128,17 @@ gui.Widget = {
|
||||||
});
|
});
|
||||||
root.addEventListener("mouseleave", func {
|
root.addEventListener("mouseleave", func {
|
||||||
me._hover = 0;
|
me._hover = 0;
|
||||||
me.onMouseLeave();
|
me._trigger("mouse-leave");
|
||||||
me._onStateChange();
|
me._onStateChange();
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
_trigger: func(type, data = nil)
|
||||||
|
{
|
||||||
|
me._view._root.dispatchEvent(
|
||||||
|
canvas.CustomEvent.new("cb." ~ type, {detail: data})
|
||||||
|
);
|
||||||
|
return me;
|
||||||
|
},
|
||||||
_windowFocus: func
|
_windowFocus: func
|
||||||
{
|
{
|
||||||
var canvas = me.getCanvas();
|
var canvas = me.getCanvas();
|
||||||
|
|
|
@ -70,7 +70,7 @@ DefaultStyle.widgets.button = {
|
||||||
me._label.set("fill", me._style.getColor("fg_color"));
|
me._label.set("fill", me._style.getColor("fg_color"));
|
||||||
file ~= "button";
|
file ~= "button";
|
||||||
|
|
||||||
if( model._active )
|
if( model._down )
|
||||||
{
|
{
|
||||||
file ~= "-active";
|
file ~= "-active";
|
||||||
me._label.setTranslation(w / 2 + 1, h / 2 + 6);
|
me._label.setTranslation(w / 2 + 1, h / 2 + 6);
|
||||||
|
@ -82,7 +82,7 @@ DefaultStyle.widgets.button = {
|
||||||
if( model._focused and !backdrop )
|
if( model._focused and !backdrop )
|
||||||
file ~= "-focused";
|
file ~= "-focused";
|
||||||
|
|
||||||
if( model._hover and !model._active )
|
if( model._hover and !model._down )
|
||||||
{
|
{
|
||||||
file ~= "-hover";
|
file ~= "-hover";
|
||||||
me._bg.set("fill", me._style.getColor("button_bg_color_hover"));
|
me._bg.set("fill", me._style.getColor("button_bg_color_hover"));
|
||||||
|
@ -104,6 +104,9 @@ DefaultStyle.widgets.label = {
|
||||||
{
|
{
|
||||||
if( me['_bg'] != nil )
|
if( me['_bg'] != nil )
|
||||||
me._bg.reset().rect(0, 0, w, h);
|
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 )
|
if( me['_text'] != nil )
|
||||||
# TODO different alignment
|
# TODO different alignment
|
||||||
me._text.setTranslation(2, h / 2);
|
me._text.setTranslation(2, h / 2);
|
||||||
|
@ -115,11 +118,23 @@ DefaultStyle.widgets.label = {
|
||||||
return me._deleteElement('text');
|
return me._deleteElement('text');
|
||||||
|
|
||||||
me._createElement("text", "text")
|
me._createElement("text", "text")
|
||||||
.set("text", text);
|
.set("text", text)
|
||||||
|
.set("fill", "black");
|
||||||
|
|
||||||
# TODO get real font metrics
|
# TODO get real font metrics
|
||||||
model.setMinimumSize([size(text) * 5 + 4, 14]);
|
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;
|
return me;
|
||||||
},
|
},
|
||||||
|
|
|
@ -4,7 +4,8 @@ gui.widgets.Button = {
|
||||||
var cfg = Config.new(cfg);
|
var cfg = Config.new(cfg);
|
||||||
var m = gui.Widget.new(gui.widgets.Button);
|
var m = gui.Widget.new(gui.widgets.Button);
|
||||||
m._focus_policy = m.StrongFocus;
|
m._focus_policy = m.StrongFocus;
|
||||||
m._active = 0;
|
m._down = 0;
|
||||||
|
m._checkable = 0;
|
||||||
m._flat = cfg.get("flat", 0);
|
m._flat = cfg.get("flat", 0);
|
||||||
|
|
||||||
if( style != nil and !m._flat )
|
if( style != nil and !m._flat )
|
||||||
|
@ -17,25 +18,41 @@ gui.widgets.Button = {
|
||||||
me._view.setText(me, text);
|
me._view.setText(me, text);
|
||||||
return me;
|
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;
|
return me;
|
||||||
|
|
||||||
me._active = 1;
|
me._trigger("clicked", {checked: checked});
|
||||||
|
me._trigger("toggled", {checked: checked});
|
||||||
|
|
||||||
|
me._down = checked;
|
||||||
me._onStateChange();
|
me._onStateChange();
|
||||||
return me;
|
return me;
|
||||||
},
|
},
|
||||||
clearActive: func
|
setDown: func(down = 1)
|
||||||
{
|
{
|
||||||
if( !me._active )
|
if( me._checkable or me._down == down )
|
||||||
return me;
|
return me;
|
||||||
|
|
||||||
me._active = 0;
|
me._down = down;
|
||||||
me._onStateChange();
|
me._onStateChange();
|
||||||
return me;
|
return me;
|
||||||
},
|
},
|
||||||
onClick: func {},
|
toggle: func
|
||||||
|
{
|
||||||
|
if( !me._checkable )
|
||||||
|
me._trigger("clicked", {checked: 0});
|
||||||
|
else
|
||||||
|
me.setChecked(!me._down);
|
||||||
|
|
||||||
|
return me;
|
||||||
|
},
|
||||||
# protected:
|
# protected:
|
||||||
_onStateChange: func
|
_onStateChange: func
|
||||||
{
|
{
|
||||||
|
@ -45,14 +62,11 @@ gui.widgets.Button = {
|
||||||
_setView: func(view)
|
_setView: func(view)
|
||||||
{
|
{
|
||||||
var el = view._root;
|
var el = view._root;
|
||||||
el.addEventListener("mousedown", func me.setActive());
|
el.addEventListener("mousedown", func me.setDown(1));
|
||||||
el.addEventListener("mouseup", func me.clearActive());
|
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
|
el.addEventListener("mouseleave",func me.setDown(0));
|
||||||
# custom callbacks. TODO pass 'me' as argument?
|
|
||||||
el.addEventListener("click", func call(me.onClick));
|
|
||||||
|
|
||||||
el.addEventListener("mouseleave",func me.clearActive());
|
|
||||||
el.addEventListener("drag", func(e) e.stopPropagation());
|
el.addEventListener("drag", func(e) e.stopPropagation());
|
||||||
|
|
||||||
call(gui.Widget._setView, [view], me);
|
call(gui.Widget._setView, [view], me);
|
||||||
|
|
|
@ -13,6 +13,11 @@ gui.widgets.Label = {
|
||||||
me._view.setText(me, text);
|
me._view.setText(me, text);
|
||||||
return me;
|
return me;
|
||||||
},
|
},
|
||||||
|
setImage: func(img)
|
||||||
|
{
|
||||||
|
me._view.setImage(me, img);
|
||||||
|
return me;
|
||||||
|
},
|
||||||
setBackground: func(bg)
|
setBackground: func(bg)
|
||||||
{
|
{
|
||||||
me._view.setBackground(me, bg);
|
me._view.setBackground(me, bg);
|
||||||
|
|
|
@ -7,6 +7,7 @@ gui.widgets.ScrollArea = {
|
||||||
m._scroll_pos = [0,0];
|
m._scroll_pos = [0,0];
|
||||||
m._max_scroll = [0, 0];
|
m._max_scroll = [0, 0];
|
||||||
m._content_size = [0, 0];
|
m._content_size = [0, 0];
|
||||||
|
m._layout = nil;
|
||||||
|
|
||||||
if( style != nil )
|
if( style != nil )
|
||||||
m._setView( style.createWidget(parent, "scroll-area", cfg) );
|
m._setView( style.createWidget(parent, "scroll-area", cfg) );
|
||||||
|
@ -15,6 +16,12 @@ gui.widgets.ScrollArea = {
|
||||||
|
|
||||||
return m;
|
return m;
|
||||||
},
|
},
|
||||||
|
setLayout: func(l)
|
||||||
|
{
|
||||||
|
me._layout = l;
|
||||||
|
l.setParent(me);
|
||||||
|
return me.update();
|
||||||
|
},
|
||||||
getContent: func()
|
getContent: func()
|
||||||
{
|
{
|
||||||
return me._view.content;
|
return me._view.content;
|
||||||
|
@ -143,12 +150,30 @@ gui.widgets.ScrollArea = {
|
||||||
_updateBB: func()
|
_updateBB: func()
|
||||||
{
|
{
|
||||||
# TODO only update on content resize
|
# 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] )
|
if( bb[2] < bb[0] or bb[3] < bb[1] )
|
||||||
return nil;
|
return nil;
|
||||||
var w = bb[2] - bb[0];
|
var w = bb[2] - bb[0];
|
||||||
var h = bb[3] - bb[1];
|
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] )
|
if( w > me._size[0] )
|
||||||
{
|
{
|
||||||
|
@ -168,8 +193,5 @@ gui.widgets.ScrollArea = {
|
||||||
|
|
||||||
me._content_size[0] = w;
|
me._content_size[0] = w;
|
||||||
me._content_size[1] = h;
|
me._content_size[1] = h;
|
||||||
|
|
||||||
var cur_offset = me.getContent().getTranslation();
|
|
||||||
me._content_offset = [cur_offset[0] - bb[0], cur_offset[1] - bb[1]];
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
Loading…
Add table
Reference in a new issue