975 lines
25 KiB
Text
975 lines
25 KiB
Text
var DefaultStyle = {
|
|
new: func(name, name_icon_theme)
|
|
{
|
|
return {
|
|
parents: [ gui.Style.new(name, name_icon_theme),
|
|
DefaultStyle ]
|
|
};
|
|
},
|
|
createWidget: func(parent, type, cfg)
|
|
{
|
|
var factory = me.widgets[type];
|
|
if( factory == nil )
|
|
{
|
|
debug.warn("DefaultStyle: unknown widget type (" ~ type ~ ")");
|
|
return nil;
|
|
}
|
|
|
|
var w = {
|
|
parents: [factory],
|
|
_style: me
|
|
};
|
|
call(factory.new, [parent, cfg], w);
|
|
return w;
|
|
},
|
|
widgets: {}
|
|
};
|
|
|
|
# A button
|
|
DefaultStyle.widgets.button = {
|
|
new: func(parent, cfg)
|
|
{
|
|
me._root = parent.createChild("group", "button");
|
|
me._bg =
|
|
me._root.createChild("path");
|
|
me._border =
|
|
me._root.createChild("image", "button")
|
|
.set("slice", "10 12"); #"7")
|
|
me._label =
|
|
me._root.createChild("text")
|
|
.set("font", "LiberationFonts/LiberationSans-Regular.ttf")
|
|
.set("character-size", 14)
|
|
.set("alignment", "center-baseline");
|
|
},
|
|
setSize: func(model, w, h)
|
|
{
|
|
me._bg.reset()
|
|
.rect(3, 3, w - 6, h - 6, {"border-radius": 5});
|
|
me._border.setSize(w, h);
|
|
},
|
|
setText: func(model, text)
|
|
{
|
|
me._label.setText(text);
|
|
|
|
var min_width = math.max(80, me._label.maxWidth() + 16);
|
|
model.setLayoutMinimumSize([min_width, 16]);
|
|
model.setLayoutSizeHint([min_width, 28]);
|
|
|
|
return me;
|
|
},
|
|
update: func(model)
|
|
{
|
|
var backdrop = !model._windowFocus();
|
|
var (w, h) = model._size;
|
|
var file = me._style._dir_widgets ~ "/";
|
|
|
|
# TODO unify color names with image names
|
|
var bg_color_name = "button_bg_color";
|
|
if( backdrop )
|
|
bg_color_name = "button_backdrop_bg_color";
|
|
else if( !model._enabled )
|
|
bg_color_name = "button_bg_color_insensitive";
|
|
else if( model._down )
|
|
bg_color_name = "button_bg_color_down";
|
|
else if( model._hover )
|
|
bg_color_name = "button_bg_color_hover";
|
|
me._bg.set("fill", me._style.getColor(bg_color_name));
|
|
|
|
if( backdrop )
|
|
{
|
|
file ~= "backdrop-";
|
|
me._label.set("fill", me._style.getColor("backdrop_fg_color"));
|
|
}
|
|
else
|
|
me._label.set("fill", me._style.getColor("fg_color"));
|
|
file ~= "button";
|
|
|
|
if( model._down )
|
|
{
|
|
file ~= "-active";
|
|
me._label.setTranslation(w / 2 + 1, h / 2 + 6);
|
|
}
|
|
else
|
|
me._label.setTranslation(w / 2, h / 2 + 5);
|
|
|
|
if( model._enabled )
|
|
{
|
|
if( model._focused and !backdrop )
|
|
file ~= "-focused";
|
|
|
|
if( model._hover and !model._down )
|
|
file ~= "-hover";
|
|
}
|
|
else
|
|
file ~= "-disabled";
|
|
|
|
me._border.set("src", file ~ ".png");
|
|
}
|
|
};
|
|
|
|
# A checkbox
|
|
DefaultStyle.widgets.checkbox = {
|
|
new: func(parent, cfg)
|
|
{
|
|
me._label_position = cfg.get("label-position", "right");
|
|
me._root = parent.createChild("group", "checkbox");
|
|
me._icon =
|
|
me._root.createChild("image", "checkbox-icon")
|
|
.setSize(18, 18);
|
|
me._label =
|
|
me._root.createChild("text")
|
|
.set("font", "LiberationFonts/LiberationSans-Regular.ttf")
|
|
.set("character-size", 14)
|
|
.set("alignment", "left-center");
|
|
},
|
|
setSize: func(model, w, h)
|
|
{
|
|
if (me._label_position == "left") {
|
|
me._label.setTranslation(3, int((h / 2) + 1));
|
|
me._icon.setTranslation(w - 24, int((h - 18) / 2));
|
|
} else {
|
|
me._icon.setTranslation(3, int((h - 18) / 2));
|
|
me._label.setTranslation(24, int(h / 2) + 1);
|
|
}
|
|
|
|
return me;
|
|
},
|
|
setText: func(model, text)
|
|
{
|
|
me._label.setText(text);
|
|
|
|
var min_width = me._label.maxWidth() + 3 + 24;
|
|
model.setLayoutMinimumSize([min_width, 18]);
|
|
model.setLayoutSizeHint([min_width, 24]);
|
|
|
|
return me;
|
|
},
|
|
update: func(model)
|
|
{
|
|
var backdrop = !model._windowFocus();
|
|
var (w, h) = model._size;
|
|
var file = me._style._dir_widgets ~ "/";
|
|
|
|
if( backdrop )
|
|
{
|
|
file ~= "backdrop-";
|
|
me._label.set("fill", me._style.getColor("backdrop_fg_color"));
|
|
}
|
|
else
|
|
me._label.set("fill", me._style.getColor("fg_color"));
|
|
file ~= "check";
|
|
|
|
if( model._down )
|
|
file ~= "-selected";
|
|
else
|
|
file ~= "-unselected";
|
|
|
|
if( model._enabled )
|
|
{
|
|
if( model._hover )
|
|
file ~= "-hover";
|
|
}
|
|
else
|
|
file ~= "-disabled";
|
|
|
|
me._icon.set("src", file ~ ".png");
|
|
}
|
|
};
|
|
|
|
# A label
|
|
DefaultStyle.widgets.label = {
|
|
new: func(parent, cfg)
|
|
{
|
|
me._root = parent.createChild("group", "label");
|
|
},
|
|
setSize: func(model, w, h)
|
|
{
|
|
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, 2 + h / 2);
|
|
me._text.set(
|
|
"max-width",
|
|
model._cfg.get("wordWrap", 0) ? (w - 4) : 0
|
|
);
|
|
}
|
|
return me;
|
|
},
|
|
setText: func(model, text)
|
|
{
|
|
if ( !isstr(text) or size(text) == 0 )
|
|
{
|
|
model.setHeightForWidthFunc(nil);
|
|
return me._deleteElement('text');
|
|
}
|
|
|
|
me._createElement("text", "text")
|
|
.setText(text);
|
|
|
|
var hfw_func = nil;
|
|
var min_width = me._text.maxWidth() + 4;
|
|
var width_hint = min_width;
|
|
|
|
if( model._cfg.get("wordWrap", 0) )
|
|
{
|
|
var m = me;
|
|
hfw_func = func(w) m.heightForWidth(w);
|
|
min_width = math.min(32, min_width);
|
|
|
|
# prefer approximately quadratic text blocks
|
|
if( width_hint > 24 )
|
|
width_hint = int(math.sqrt(width_hint * 24));
|
|
}
|
|
|
|
model.setHeightForWidthFunc(hfw_func);
|
|
model.setLayoutMinimumSize([min_width, 14]);
|
|
model.setLayoutSizeHint([width_hint, 24]);
|
|
|
|
return me.update(model);
|
|
},
|
|
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;
|
|
},
|
|
# @param bg CSS color or 'none'
|
|
setBackground: func(model, bg)
|
|
{
|
|
if( bg == nil or bg == "none" )
|
|
return me._deleteElement("bg");
|
|
|
|
me._createElement("bg", "path")
|
|
.set("fill", bg);
|
|
|
|
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));
|
|
},
|
|
update: func(model)
|
|
{
|
|
if( me['_text'] != nil )
|
|
{
|
|
var color_name = model._windowFocus() ? "fg_color" : "backdrop_fg_color";
|
|
me._text.set("fill", me._style.getColor(color_name));
|
|
}
|
|
},
|
|
# protected:
|
|
_createElement: func(name, type)
|
|
{
|
|
var mem = '_' ~ name;
|
|
if( me[ mem ] == nil )
|
|
{
|
|
me[ mem ] = me._root.createChild(type, "label-" ~ name);
|
|
|
|
if( type == "text" )
|
|
{
|
|
me[ mem ].set("font", "LiberationFonts/LiberationSans-Regular.ttf")
|
|
.set("character-size", 14)
|
|
.set("alignment", "left-center");
|
|
}
|
|
}
|
|
return me[ mem ];
|
|
},
|
|
_deleteElement: func(name)
|
|
{
|
|
name = '_' ~ name;
|
|
if( me[ name ] != nil )
|
|
{
|
|
me[ name ].del();
|
|
me[ name ] = nil;
|
|
}
|
|
return me;
|
|
}
|
|
};
|
|
|
|
# A one line text input field
|
|
DefaultStyle.widgets["line-edit"] = {
|
|
new: func(parent, cfg)
|
|
{
|
|
me._hpadding = cfg.get("hpadding", 8);
|
|
|
|
me._root = parent.createChild("group", "line-edit");
|
|
me._border =
|
|
me._root.createChild("image", "border")
|
|
.set("slice", "10 12"); #"7")
|
|
me._text =
|
|
me._root.createChild("text", "input")
|
|
.set("font", "LiberationFonts/LiberationSans-Regular.ttf")
|
|
.set("character-size", 14)
|
|
.set("alignment", "left-baseline")
|
|
.set("clip-frame", Element.PARENT);
|
|
me._cursor =
|
|
me._root.createChild("path", "cursor")
|
|
.set("stroke", "#333")
|
|
.set("stroke-width", 1)
|
|
.moveTo(me._hpadding, 5)
|
|
.vert(10);
|
|
me._hscroll = 0;
|
|
},
|
|
setSize: func(model, w, h)
|
|
{
|
|
me._border.setSize(w, h);
|
|
me._text.set(
|
|
"clip",
|
|
"rect(0, " ~ (w - me._hpadding) ~ ", " ~ h ~ ", " ~ me._hpadding ~ ")"
|
|
);
|
|
me._cursor.setDouble("coord[2]", h - 10);
|
|
|
|
return me.update(model);
|
|
},
|
|
setText: func(model, text)
|
|
{
|
|
me._text.setText(text);
|
|
model._onStateChange();
|
|
},
|
|
update: func(model)
|
|
{
|
|
var backdrop = !model._windowFocus();
|
|
var file = me._style._dir_widgets ~ "/";
|
|
|
|
if( backdrop )
|
|
file ~= "backdrop-";
|
|
|
|
file ~= "entry";
|
|
|
|
if( !model._enabled )
|
|
file ~= "-disabled";
|
|
else if( model._focused and !backdrop )
|
|
file ~= "-focused";
|
|
|
|
me._border.set("src", file ~ ".png");
|
|
|
|
var color_name = backdrop ? "backdrop_fg_color" : "fg_color";
|
|
me._text.set("fill", me._style.getColor(color_name));
|
|
|
|
me._cursor.setVisible(model._enabled and model._focused and !backdrop);
|
|
|
|
var width = model._size[0] - 2 * me._hpadding;
|
|
var cursor_pos = me._text.getCursorPos(0, model._cursor)[0];
|
|
var text_width = me._text.getCursorPos(0, me._text.lineLength(0))[0];
|
|
|
|
if( text_width <= width )
|
|
# fit -> align left (TODO handle different alignment)
|
|
me._hscroll = 0;
|
|
else if( me._hscroll + cursor_pos > width )
|
|
# does not fit, cursor to the right
|
|
me._hscroll = width - cursor_pos;
|
|
else if( me._hscroll + cursor_pos < 0 )
|
|
# does not fit, cursor to the left
|
|
me._hscroll = -cursor_pos;
|
|
else if( me._hscroll + text_width < width )
|
|
# does not fit, limit scroll to align with right side
|
|
me._hscroll = width - text_width;
|
|
|
|
var text_pos = me._hscroll + me._hpadding;
|
|
|
|
me._text
|
|
.setTranslation(text_pos, model._size[1] / 2 + 5)
|
|
.update();
|
|
me._cursor
|
|
.setDouble("coord[0]", text_pos + cursor_pos)
|
|
.update();
|
|
}
|
|
};
|
|
|
|
# ScrollArea
|
|
DefaultStyle.widgets["scroll-area"] = {
|
|
new: func(parent, cfg)
|
|
{
|
|
me._root = parent.createChild("group", "scroll-area");
|
|
|
|
me._bg = me._root.createChild("path", "background")
|
|
.set("fill", "#e0e0e0");
|
|
me.content = me._root.createChild("group", "scroll-content")
|
|
.set("clip-frame", Element.PARENT);
|
|
me.vert = me._newScroll(me._root, "vert");
|
|
me.horiz = me._newScroll(me._root, "horiz");
|
|
},
|
|
setColorBackground: func
|
|
{
|
|
if( size(arg) == 1 )
|
|
var arg = arg[0];
|
|
me._bg.setColorFill(arg);
|
|
},
|
|
update: func(model)
|
|
{
|
|
me.horiz.reset();
|
|
if( model._max_scroll[0] > 1 )
|
|
# only show scroll bar if horizontally scrollable
|
|
me.horiz.moveTo( model._scroller_offset[0] + model._scroller_pos[0],
|
|
model._size[1] - 2 )
|
|
.horiz(model._scroller_size[0]);
|
|
|
|
me.vert.reset();
|
|
if( model._max_scroll[1] > 1 )
|
|
# only show scroll bar if vertically scrollable
|
|
me.vert.moveTo( model._size[0] - 2,
|
|
model._scroller_offset[1] + model._scroller_pos[1] )
|
|
.vert(model._scroller_size[1]);
|
|
|
|
me._bg.reset()
|
|
.rect(0, 0, model._size[0], model._size[1]);
|
|
me.content.set(
|
|
"clip",
|
|
"rect(0, " ~ model._size[0] ~ ", " ~ model._size[1] ~ ", 0)"
|
|
);
|
|
},
|
|
# private:
|
|
_newScroll: func(el, orient)
|
|
{
|
|
return el.createChild("path", "scroll-" ~ orient)
|
|
.set("stroke", "#f07845")
|
|
.set("stroke-width", 4);
|
|
},
|
|
# Calculate size and limits of scroller
|
|
#
|
|
# @param model
|
|
# @param dir 0 for horizontal, 1 for vertical
|
|
# @return [scroller_size, min_pos, max_pos]
|
|
_updateScrollMetrics: func(model, dir)
|
|
{
|
|
if( model._content_size[dir] <= model._size[dir] )
|
|
return;
|
|
|
|
model._scroller_size[dir] =
|
|
math.max(
|
|
12,
|
|
model._size[dir] * (model._size[dir] / model._content_size[dir])
|
|
);
|
|
model._scroller_offset[dir] = 0;
|
|
model._scroller_delta[dir] = model._size[dir] - model._scroller_size[dir];
|
|
}
|
|
};
|
|
|
|
DefaultStyle.widgets["tab-widget"] = {
|
|
tabBarHeight: 30,
|
|
new: func(parent, cfg) {
|
|
me._root = parent.createChild("group", "tab-widget");
|
|
me.bg = me._root.createChild("path", "background")
|
|
.set("fill", "#e0e0e0");
|
|
me.tabBar = me._root.createChild("group", "tab-widget-tabbar");
|
|
me.content = me._root.createChild("group", "tab-widget-content");
|
|
},
|
|
|
|
update: func(model) {
|
|
me.bg.set("fill", me._style.getColor("bg_color"));
|
|
me.tabBar.update();
|
|
me.content.update();
|
|
},
|
|
|
|
setSize: func(model, w, h) {
|
|
me.bg.reset().rect(0, w, h, 0);
|
|
me.tabBar.set("clip", sprintf("rect(0, %d, %d, 0)", w, me.tabBarHeight));
|
|
me.content.setTranslation(0, me.tabBarHeight);
|
|
me.content.set("clip", sprintf("rect(0, %d, %d, 0)", w, h));
|
|
},
|
|
};
|
|
|
|
# Tab button for the tab widget
|
|
DefaultStyle.widgets["tab-widget-tab-button"] = {
|
|
new: func(parent, cfg) {
|
|
me._root = parent.createChild("group", "tab-widget-tab-button");
|
|
me._bg = me._root.createChild("path")
|
|
.set("fill", me._style.getColor("tab_widget_tab_button_bg_focused"))
|
|
.set("stroke", me._style.getColor("tab_widget_tab_button_border"))
|
|
.set("stroke-width", 1);
|
|
me._selected_indicator = me._root.createChild("path")
|
|
.set("stroke", me._style.getColor("tab_widget_tab_button_selected_indicator"))
|
|
.set("stroke-width", 3);
|
|
me._label = me._root.createChild("text")
|
|
.set("font", "LiberationFonts/LiberationSans-Regular.ttf")
|
|
.set("character-size", 14)
|
|
.set("alignment", "center-baseline");
|
|
},
|
|
|
|
setSize: func(model, w, h) {
|
|
me._bg.reset().rect(3, 0, w - 6, h);
|
|
me._selected_indicator.reset().moveTo(3, h).horiz(w - 6);
|
|
},
|
|
|
|
setText: func(model, text) {
|
|
me._label.setText(text);
|
|
|
|
var min_width = math.max(80, me._label.maxWidth() + 16);
|
|
model.setLayoutMinimumSize([min_width, 30]);
|
|
model.setLayoutSizeHint([min_width, 30]);
|
|
|
|
return me;
|
|
},
|
|
|
|
update: func(model) {
|
|
var backdrop = !model._windowFocus();
|
|
var (w, h) = model._size;
|
|
|
|
me._label.setTranslation(w / 2, h / 2 + 5);
|
|
|
|
var bg_color_name = "tab_widget_tab_button_bg_focused";
|
|
if (backdrop) {
|
|
bg_color_name = "tab_widget_tab_button_bg_unfocused";
|
|
} else if (model._selected) {
|
|
bg_color_name = "tab_widget_tab_button_bg_selected";
|
|
} else if (model._hover) {
|
|
bg_color_name = "tab_widget_tab_button_bg_hovered";
|
|
}
|
|
me._bg.set("fill", me._style.getColor(bg_color_name));
|
|
|
|
me._selected_indicator.setVisible(model._selected);
|
|
|
|
if (backdrop) {
|
|
me._label.set("fill", me._style.getColor("backdrop_fg_color"));
|
|
} else {
|
|
me._label.set("fill", me._style.getColor("fg_color"));
|
|
}
|
|
}
|
|
};
|
|
|
|
# A horizontal or vertical rule line
|
|
# possibly with a text label embedded
|
|
DefaultStyle.widgets.rule = {
|
|
new: func(parent, cfg)
|
|
{
|
|
me._root = parent.createChild("group", "rule");
|
|
var bgColor = me._style.getColor("fg_color");
|
|
var shadowColor = me._style.getColor("fg_color_shadow");
|
|
|
|
me._bg = me._root.createChild("path")
|
|
.set("fill", bgColor)
|
|
.set("stroke", bgColor)
|
|
.set("stroke-width", 1);
|
|
me._shadow = me._root.createChild("path")
|
|
.set("fill", shadowColor)
|
|
.set("stroke", shadowColor)
|
|
.set("stroke-width", 1);
|
|
|
|
me._isVertical = cfg.get("isVertical");
|
|
},
|
|
setSize: func(model, w, h)
|
|
{
|
|
var firstWidth = w;
|
|
var firstHeight = h;
|
|
var hh = h * 0.5;
|
|
|
|
if( me['_text'] != nil )
|
|
{
|
|
firstHeight = firstWidth = 20; # TODO make this settable in Style.xml
|
|
|
|
# TODO handle eliding for translations?
|
|
me._text.setTranslation(firstWidth + 3, hh);
|
|
var maxW = model._cfg.get("maxTextWidth", -1);
|
|
if (maxW > 0) {
|
|
me._text.set("max-width", maxW);
|
|
}
|
|
|
|
# assume horizontal for now, with a label
|
|
var bg2Left = maxW > 0 ? maxW : me._text.maxWidth() + 22;
|
|
var bg2Width = w - bg2Left;
|
|
me._bg2.reset().rect(bg2Left, hh - 1, bg2Width, 2);
|
|
me._shadow2.reset().moveTo(bg2Left + 1, hh).horiz(bg2Width - 1);
|
|
}
|
|
|
|
if (me._isVertical ) {
|
|
me._bg.reset().rect(0, 0, 2, firstHeight);
|
|
me._shadow.reset().moveTo(1, 1).vert(firstHeight - 1);
|
|
} else {
|
|
me._bg.reset().rect(0, hh - 1, firstWidth, 2);
|
|
me._shadow.reset().moveTo(1, hh).horiz(firstWidth - 1);
|
|
}
|
|
|
|
return me;
|
|
},
|
|
setText: func(model, text)
|
|
{
|
|
if( text == nil or size(text) == 0 )
|
|
{
|
|
# force a resize?
|
|
me._deleteElement('bg2');
|
|
me._deleteElement('shadow2');
|
|
return me._deleteElement('text');
|
|
}
|
|
|
|
if (me._isVertical) {
|
|
logprint(LOG_DEVALERT, "Text label not supported for vertical rules, yet");
|
|
return;
|
|
}
|
|
|
|
me._createElement("text", "text")
|
|
.setText(text);
|
|
|
|
var width_hint = me._text.maxWidth() + 40;
|
|
|
|
|
|
var bgColor = me._style.getColor("fg_color");
|
|
var shadowColor = me._style.getColor("fg_color_shadow");
|
|
|
|
me._bg2 = me._root.createChild("path")
|
|
.set("fill", bgColor)
|
|
.set("stroke", bgColor)
|
|
.set("stroke-width", 1);
|
|
me._shadow2 = me._root.createChild("path")
|
|
.set("fill", shadowColor)
|
|
.set("stroke", shadowColor)
|
|
.set("stroke-width", 1);
|
|
|
|
model.setLayoutMinimumSize([40, 14]);
|
|
# TODO mark as expanding?
|
|
model.setLayoutSizeHint([width_hint, 24]);
|
|
|
|
return me.update(model);
|
|
},
|
|
update: func(model)
|
|
{
|
|
|
|
# different color if disabled?
|
|
if( me['_text'] != nil )
|
|
{
|
|
var color_name = model._windowFocus() ? "fg_color" : "backdrop_fg_color";
|
|
me._text.set("fill", me._style.getColor(color_name));
|
|
}
|
|
},
|
|
# protected:
|
|
_createElement: func(name, type)
|
|
{
|
|
var mem = '_' ~ name;
|
|
if( me[ mem ] == nil )
|
|
{
|
|
me[ mem ] = me._root.createChild(type, "rule-" ~ name);
|
|
|
|
if( type == "text" )
|
|
{
|
|
me[ mem ].set("font", "LiberationFonts/LiberationSans-Regular.ttf")
|
|
.set("character-size", 14)
|
|
.set("alignment", "left-center");
|
|
}
|
|
}
|
|
return me[ mem ];
|
|
},
|
|
_deleteElement: func(name)
|
|
{
|
|
name = '_' ~ name;
|
|
if( me[ name ] != nil )
|
|
{
|
|
me[ name ].del();
|
|
me[ name ] = nil;
|
|
}
|
|
return me;
|
|
}
|
|
};
|
|
|
|
# a frame (sometimes called a group box), with optional label
|
|
# and enable/disable checkbox
|
|
DefaultStyle.widgets.frame = {
|
|
new: func(parent, cfg)
|
|
{
|
|
me._root = parent.createChild("group", "frame-box");
|
|
me._createElement("bg", "image")
|
|
.set("slice", "8 8");
|
|
me.content = me._root.createChild("group", "frame-content");
|
|
|
|
# handle label + checkable flag
|
|
},
|
|
|
|
update: func(model)
|
|
{
|
|
var file = me._style._dir_widgets ~ "/";
|
|
file ~= "frame";
|
|
|
|
# if( !model._enabled )
|
|
# file ~= "-disabled";
|
|
|
|
me._bg.set("src", file ~ ".png");
|
|
|
|
me._bg.setSize(model._size[0], model._size[1]);
|
|
},
|
|
# protected:
|
|
_createElement: func(name, type)
|
|
{
|
|
var mem = '_' ~ name;
|
|
if( me[ mem ] == nil )
|
|
{
|
|
me[ mem ] = me._root.createChild(type, "frame-" ~ name);
|
|
|
|
if( type == "text" )
|
|
{
|
|
me[ mem ].set("font", "LiberationFonts/LiberationSans-Regular.ttf")
|
|
.set("character-size", 14)
|
|
.set("alignment", "left-center");
|
|
}
|
|
}
|
|
return me[ mem ];
|
|
},
|
|
_deleteElement: func(name)
|
|
{
|
|
name = '_' ~ name;
|
|
if( me[ name ] != nil )
|
|
{
|
|
me[ name ].del();
|
|
me[ name ] = nil;
|
|
}
|
|
return me;
|
|
}
|
|
|
|
};
|
|
|
|
# a horizontal or vertical slider, for selecting /
|
|
# dragging over a numerical range
|
|
DefaultStyle.widgets.slider = {
|
|
new: func(parent, cfg)
|
|
{
|
|
me._root = parent.createChild("group", "slider");
|
|
me._createElement("bg", "image")
|
|
.set("slice", "2 6");
|
|
|
|
me._createElement("fill", "image")
|
|
.set("slice", "2 6");
|
|
|
|
me._fillHeight = me._fill.imageSize()[1];
|
|
me._createElement("thumb", "image");
|
|
me._thumbSize = me._thumb.imageSize();
|
|
|
|
me._ticks = 0;
|
|
me._ticksPath = nil;
|
|
},
|
|
|
|
setNormValue: func(model, normValue)
|
|
{
|
|
var (w, h) = model._size;
|
|
var halfThumbWidth = me._thumbSize[0] * 0.5;
|
|
var availWidthPos = w - me._thumbSize[0];
|
|
var thumbX = math.round(availWidthPos * normValue);
|
|
var thumbY = (h - me._thumbSize[1]) * 0.5;
|
|
me._thumb.setTranslation(thumbX - halfThumbWidth, thumbY);
|
|
me._fill.setSize(thumbX, me._fillHeight);
|
|
},
|
|
|
|
update: func(model)
|
|
{
|
|
var direction = "horizontal";
|
|
# set background state
|
|
var file = me._style._dir_widgets ~ "/";
|
|
file ~= "scale-" ~ direction ~ "-trough";
|
|
if( !model._enabled )
|
|
file ~= "-disabled";
|
|
|
|
me._bg.set("src", file ~ ".png");
|
|
|
|
# fill state
|
|
var file = me._style._dir_widgets ~ "/";
|
|
file ~= "scale-" ~ direction ~ "-fill";
|
|
if( !model._enabled ) {
|
|
file ~= "-disabled";
|
|
} else {
|
|
|
|
}
|
|
|
|
me._fill.set("src", file ~ ".png");
|
|
|
|
# set thumb state
|
|
file = me._style._dir_widgets ~ "/";
|
|
file ~= "slider-" ~ direction;
|
|
if( !model._enabled ) {
|
|
file ~= "-disabled";
|
|
} else {
|
|
if (model._down)
|
|
file ~= "-focused";
|
|
if (model._hover)
|
|
file ~= "-hover";
|
|
}
|
|
|
|
me._thumb.set("src", file ~ ".png");
|
|
|
|
# update the position as well, since other stuff
|
|
# may have changed
|
|
me.setNormValue(model, model._normValue());
|
|
},
|
|
|
|
setSize: func(model, w, h)
|
|
{
|
|
var fillTop = (h - me._fillHeight) * 0.5;
|
|
me._bg.setTranslation(0, fillTop);
|
|
me._fill.setTranslation(0, fillTop);
|
|
me._bg.setSize(w, me._fillHeight);
|
|
me.setNormValue(model, model._normValue());
|
|
},
|
|
|
|
updateRanges: func(minValue, maxValue, numTicks = 0)
|
|
{
|
|
if (me._ticks != numTicks) {
|
|
# update tick marks
|
|
if (numTicks == 0) {
|
|
me._ticks = 0;
|
|
me._deleteElement('ticksPath');
|
|
} else {
|
|
me._createElement('ticksPath', 'path');
|
|
me._ticks = numTicks;
|
|
|
|
# set style
|
|
# loop adding ticks
|
|
|
|
}
|
|
}
|
|
},
|
|
|
|
# protected:
|
|
_createElement: func(name, type)
|
|
{
|
|
var mem = '_' ~ name;
|
|
if( me[ mem ] == nil )
|
|
{
|
|
me[ mem ] = me._root.createChild(type, "slider-" ~ name);
|
|
|
|
if( type == "text" )
|
|
{
|
|
me[ mem ].set("font", "LiberationFonts/LiberationSans-Regular.ttf")
|
|
.set("character-size", 14)
|
|
.set("alignment", "left-center");
|
|
}
|
|
}
|
|
return me[ mem ];
|
|
},
|
|
_deleteElement: func(name)
|
|
{
|
|
name = '_' ~ name;
|
|
if( me[ name ] != nil )
|
|
{
|
|
me[ name ].del();
|
|
me[ name ] = nil;
|
|
}
|
|
return me;
|
|
}
|
|
};
|
|
|
|
DefaultStyle.widgets["menu-item"] = {
|
|
new: func(parent, cfg) {
|
|
me._root = parent.createChild("group", "menu-item");
|
|
me._bg = me._root.createChild("path");
|
|
|
|
me._icon = me._root.createChild("image")
|
|
.set("slice", "18 18");
|
|
|
|
me._label = me._root.createChild("text")
|
|
.set("font", "LiberationFonts/LiberationSans-Regular.ttf")
|
|
.set("character-size", 14)
|
|
.set("alignment", "left-baseline");
|
|
|
|
me._shortcut = me._root.createChild("text")
|
|
.set("font", "LiberationFonts/LiberationSans-Regular.ttf")
|
|
.set("character-size", 14)
|
|
.set("alignment", "right-baseline");
|
|
|
|
me._submenu_indicator = me._root.createChild("path")
|
|
.vert(12).line(6, -7).close();
|
|
},
|
|
|
|
setSize: func(model, w, h) {
|
|
me._bg.reset().rect(0, 0, w, h);
|
|
var offset = 0;
|
|
if (!model._is_menubar_item) {
|
|
offset += 5 + 18;
|
|
}
|
|
me._icon.setTranslation(5, int((h - 12) / 2));
|
|
me._label.setTranslation(offset + 5, int(h / 2) + 4);
|
|
me._shortcut.setTranslation(w - 5, int(h / 2) + 4);
|
|
me._submenu_indicator.setTranslation(w - 12, int((h - 12) / 2));
|
|
return me;
|
|
},
|
|
|
|
_updateLayoutSizes: func(model) {
|
|
var min_width = 5 + me._label.maxWidth() + 5;
|
|
if (!model._is_menubar_item) {
|
|
# add icon space
|
|
min_width += 5 + 18;
|
|
# add shortcut space
|
|
min_width += me._shortcut.maxWidth() + 10;
|
|
if (model._menu != nil) {
|
|
# add submenu indicator space
|
|
min_width += 12;
|
|
}
|
|
}
|
|
model.setLayoutMinimumSize([min_width, 24]);
|
|
model.setLayoutSizeHint([min_width, 24]);
|
|
|
|
return me;
|
|
},
|
|
|
|
setText: func(model, text) {
|
|
me._label.setText(text);
|
|
return me._updateLayoutSizes(model);
|
|
},
|
|
|
|
setShortcut: func(model, shortcut) {
|
|
me._shortcut.setText(shortcut.repr());
|
|
return me._updateLayoutSizes(model);
|
|
},
|
|
|
|
setIcon: func(icon) {
|
|
if (!icon) {
|
|
me._icon.hide();
|
|
} else {
|
|
me._icon.show();
|
|
var file = me._style._dir_widgets ~ "/" ~ icon;
|
|
me._icon.set("src", file);
|
|
}
|
|
return me;
|
|
},
|
|
|
|
update: func(model) {
|
|
me._bg.set("fill", me._style.getColor("menu_item_bg" ~ (model._hovered ? "_hovered" : "")));
|
|
var text_color_name = "menu_item_fg";
|
|
if (model._hovered) {
|
|
text_color_name ~= "_hovered";
|
|
} else if (!model._enabled) {
|
|
text_color_name ~= "_disabled";
|
|
}
|
|
me._label.set("fill", me._style.getColor(text_color_name));
|
|
me._shortcut.set("fill", me._style.getColor(text_color_name));
|
|
me._submenu_indicator.set("fill", me._style.getColor("menu_item_submenu_indicator" ~ (model._hovered ? "_hovered" : "")));
|
|
if (model._menu != nil) {
|
|
if (!model._is_menubar_item) {
|
|
me._submenu_indicator.show();
|
|
}
|
|
me._shortcut.hide();
|
|
} else {
|
|
me._submenu_indicator.hide();
|
|
me._shortcut.show();
|
|
}
|
|
|
|
return me;
|
|
}
|
|
};
|
|
|
|
DefaultStyle.widgets["menu-bar"] = {
|
|
new: func(parent, cfg) {
|
|
me._root = parent.createChild("group", "menu-bar");
|
|
me._bg = me._root.createChild("path");
|
|
me._items = me._root.createChild("group", "tab-widget-content");
|
|
},
|
|
|
|
setSize: func(model, w, h) {
|
|
me._bg.reset().rect(0, 0, w, h);
|
|
me._items.setTranslation(0, 0);
|
|
return me;
|
|
},
|
|
|
|
update: func(model) {
|
|
me._bg.set("fill", me._style.getColor("bg_color"));
|
|
|
|
return me;
|
|
}
|
|
}
|