update styles for buttons and checkboxes; refactoring - extract color related definitions to colors.d

This commit is contained in:
Vadim Lopatin 2015-01-14 13:21:58 +03:00
parent 9a8eb66e6b
commit 37d5f1efcd
10 changed files with 231 additions and 209 deletions

View File

@ -355,6 +355,7 @@
<File path="src\dlangui\dialogs\msgbox.d" />
</Folder>
<Folder name="graphics">
<File path="src\dlangui\graphics\colors.d" />
<File path="src\dlangui\graphics\drawbuf.d" />
<File path="src\dlangui\graphics\fonts.d" />
<File path="src\dlangui\graphics\ftfonts.d" />

View File

@ -424,15 +424,30 @@ extern (C) int UIAppMain(string[] args) {
}
{
LinearLayout layout3 = new LinearLayout("tab3");
LinearLayout layout3 = new VerticalLayout("tab3");
// 3 types of buttons: Button, ImageButton, ImageTextButton
layout3.addChild(new TextWidget(null, "Buttons in HorizontalLayout"d));
WidgetGroup buttons1 = new HorizontalLayout();
buttons1.addChild(new Button("btn1", "Button 1"d));
buttons1.addChild(new Button("btn2", "Button 2"d));
buttons1.addChild(new Button("btn3", "Button 3"d));
buttons1.addChild(new ResizerWidget());
buttons1.addChild(new Button("btn4", "Button 4"d));
buttons1.addChild(new TextWidget(null, "Button widgets: "d));
buttons1.addChild(new Button("btn1", "Button"d));
buttons1.addChild((new Button("btn2", "Disabled Button"d)).enabled(false));
buttons1.addChild(new TextWidget(null, "ImageButton widgets: "d));
buttons1.addChild(new ImageButton("btn3", "text-plain"));
buttons1.addChild(new TextWidget(null, "disabled: "d));
buttons1.addChild((new ImageButton("btn4", "folder")).enabled(false));
buttons1.addChild(new TextWidget(null, "ImageTextButton widgets: "d));
buttons1.addChild(new ImageTextButton("btn5", "text-plain", "Enabled"d));
buttons1.addChild((new ImageTextButton("btn6", "folder", "Disabled"d)).enabled(false));
layout3.addChild(buttons1);
WidgetGroup buttons11 = new HorizontalLayout();
buttons11.addChild(new TextWidget(null, "Construct buttons by action: "d));
Action FILE_OPEN_ACTION = new Action(ACTION_FILE_OPEN, "MENU_FILE_OPEN"c, "document-open", KeyCode.KEY_O, KeyFlag.Control);
buttons11.addChild(new Button(FILE_OPEN_ACTION));
buttons11.addChild(new ImageButton(FILE_OPEN_ACTION));
buttons11.addChild(new ImageTextButton(FILE_OPEN_ACTION));
layout3.addChild(buttons11);
layout3.addChild(new VSpacer());
layout3.addChild(new TextWidget(null, "CheckBoxes in HorizontalLayout"d));
WidgetGroup buttons2 = new HorizontalLayout();

View File

@ -5,6 +5,7 @@
align="Center"
margins="5,5,5,5"
focusRectColors="#000"
textFlags="UnderlineHotKeys"
/>
<style id="BUTTON_TRANSPARENT"
backgroundImageId="btn_background_transparent"
@ -12,7 +13,9 @@
/>
<style id="BUTTON_LABEL"
layoutWidth="FILL_PARENT"
margins="2,2,2,2"
align="Left|VCenter"
textFlags="UnderlineHotKeys"
/>
<style id="BUTTON_ICON"
align="Center"
@ -20,7 +23,10 @@
<style id="TEXT"
margins="2,2,2,2"
padding="1,1,1,1"
/>
align="Left|VCenter"
>
<state state_enabled="false" textColor="#A0000000"/>
</style>
<style id="HSPACER"
layoutWidth="FILL_PARENT"
layoutWeight="100"

View File

@ -64,6 +64,7 @@ public import dlangui.widgets.grid;
public import dlangui.widgets.tree;
public import dlangui.widgets.combobox;
public import dlangui.widgets.popup;
public import dlangui.graphics.colors;
public import dlangui.graphics.fonts;
public import dlangui.graphics.drawbuf;
public import dlangui.platforms.common.platform;

View File

@ -0,0 +1,166 @@
module dlangui.graphics.colors;
private import std.string : strip;
/// special color constant to identify value as not a color (to use default/parent value instead)
immutable uint COLOR_UNSPECIFIED = 0xFFDEADFF;
/// transparent color constant
immutable uint COLOR_TRANSPARENT = 0xFFFFFFFF;
immutable uint COLOR_TRANSFORM_OFFSET_NONE = 0x80808080;
immutable uint COLOR_TRANSFORM_MULTIPLY_NONE = 0x40404040;
uint makeRGBA(T)(T r, T g, T b, T a) {
return (cast(uint)a << 24)|(cast(uint)r << 16)|(cast(uint)g << 8)|(cast(uint)b);
}
/// blend two RGB pixels using alpha
uint blendARGB(uint dst, uint src, uint alpha) {
uint dstalpha = dst >> 24;
if (dstalpha > 0x80)
return src;
uint srcr = (src >> 16) & 0xFF;
uint srcg = (src >> 8) & 0xFF;
uint srcb = (src >> 0) & 0xFF;
uint dstr = (dst >> 16) & 0xFF;
uint dstg = (dst >> 8) & 0xFF;
uint dstb = (dst >> 0) & 0xFF;
uint ialpha = 256 - alpha;
uint r = ((srcr * ialpha + dstr * alpha) >> 8) & 0xFF;
uint g = ((srcg * ialpha + dstg * alpha) >> 8) & 0xFF;
uint b = ((srcb * ialpha + dstb * alpha) >> 8) & 0xFF;
return (r << 16) | (g << 8) | b;
}
/// blend two alpha values 0..255 (255 is fully transparent, 0 is opaque)
uint blendAlpha(uint a1, uint a2) {
if (!a1)
return a2;
if (!a2)
return a1;
return (((a1 ^ 0xFF) * (a2 ^ 0xFF)) >> 8) ^ 0xFF;
}
/// applies additional alpha to color
uint addAlpha(uint color, uint alpha) {
alpha = blendAlpha(color >> 24, alpha);
return (color & 0xFFFFFF) | (alpha << 24);
}
ubyte rgbToGray(uint color) {
uint srcr = (color >> 16) & 0xFF;
uint srcg = (color >> 8) & 0xFF;
uint srcb = (color >> 0) & 0xFF;
return cast(uint)(((srcr + srcg + srcg + srcb) >> 2) & 0xFF);
}
// todo
struct ColorTransformHandler {
void init(ref ColorTransform transform) {
}
uint transform(uint color) {
return color;
}
}
uint transformComponent(int src, int addBefore, int multiply, int addAfter) {
int add1 = (cast(int)(addBefore << 1)) - 0x100;
int add2 = (cast(int)(addAfter << 1)) - 0x100;
int mul = cast(int)(multiply << 2);
int res = (((src + add1) * mul) >> 8) + add2;
if (res < 0)
res = 0;
else if (res > 255)
res = 255;
return cast(uint)res;
}
uint transformRGBA(uint src, uint addBefore, uint multiply, uint addAfter) {
uint a = transformComponent(src >> 24, addBefore >> 24, multiply >> 24, addAfter >> 24);
uint r = transformComponent((src >> 16) & 0xFF, (addBefore >> 16) & 0xFF, (multiply >> 16) & 0xFF, (addAfter >> 16) & 0xFF);
uint g = transformComponent((src >> 8) & 0xFF, (addBefore >> 8) & 0xFF, (multiply >> 8) & 0xFF, (addAfter >> 8) & 0xFF);
uint b = transformComponent(src & 0xFF, addBefore & 0xFF, multiply & 0xFF, addAfter & 0xFF);
return (a << 24) | (r << 16) | (g << 8) | b;
}
struct ColorTransform {
uint addBefore = COLOR_TRANSFORM_OFFSET_NONE;
uint multiply = COLOR_TRANSFORM_MULTIPLY_NONE;
uint addAfter = COLOR_TRANSFORM_OFFSET_NONE;
@property bool empty() const {
return addBefore == COLOR_TRANSFORM_OFFSET_NONE
&& multiply == COLOR_TRANSFORM_MULTIPLY_NONE
&& addAfter == COLOR_TRANSFORM_OFFSET_NONE;
}
uint transform(uint color) {
return transformRGBA(color, addBefore, multiply, addAfter);
}
}
/// blend two RGB pixels using alpha
ubyte blendGray(ubyte dst, ubyte src, uint alpha) {
uint ialpha = 256 - alpha;
return cast(ubyte)(((src * ialpha + dst * alpha) >> 8) & 0xFF);
}
/// returns true if color is #FFxxxxxx (color alpha is 255)
bool isFullyTransparentColor(uint color) pure nothrow {
return (color >> 24) == 0xFF;
}
/// decodes hex digit (0..9, a..f, A..F), returns uint.max if invalid
uint decodeHexDigit(char ch) {
if (ch >= '0' && ch <= '9')
return ch - '0';
else if (ch >= 'a' && ch <= 'f')
return ch - 'a' + 10;
else if (ch >= 'A' && ch <= 'F')
return ch - 'A' + 10;
return uint.max;
}
/// decode color string supported formats: #RGB #ARGB #RRGGBB #AARRGGBB
uint decodeHexColor(string s, uint defValue = 0) {
s = strip(s);
switch (s) {
case "@null":
case "transparent":
return COLOR_TRANSPARENT;
case "black":
return 0x000000;
case "white":
return 0xFFFFFF;
case "red":
return 0xFF0000;
case "green":
return 0x00FF00;
case "blue":
return 0x0000FF;
case "gray":
return 0x808080;
case "lightgray":
case "silver":
return 0xC0C0C0;
default:
break;
}
if (s.length != 4 && s.length != 5 && s.length != 7 && s.length != 9)
return defValue;
if (s[0] != '#')
return defValue;
uint value = 0;
for (int i = 1; i < s.length; i++) {
uint digit = decodeHexDigit(s[i]);
if (digit == uint.max)
return defValue;
value = (value << 4) | digit;
if (s.length < 7) // double the same digit for short forms
value = (value << 4) | digit;
}
return value;
}

View File

@ -19,109 +19,8 @@ module dlangui.graphics.drawbuf;
public import dlangui.core.types;
import dlangui.core.logger;
import dlangui.graphics.colors;
immutable uint COLOR_TRANSFORM_OFFSET_NONE = 0x80808080;
immutable uint COLOR_TRANSFORM_MULTIPLY_NONE = 0x40404040;
uint makeRGBA(T)(T r, T g, T b, T a) {
return (cast(uint)a << 24)|(cast(uint)r << 16)|(cast(uint)g << 8)|(cast(uint)b);
}
/// blend two RGB pixels using alpha
uint blendARGB(uint dst, uint src, uint alpha) {
uint dstalpha = dst >> 24;
if (dstalpha > 0x80)
return src;
uint srcr = (src >> 16) & 0xFF;
uint srcg = (src >> 8) & 0xFF;
uint srcb = (src >> 0) & 0xFF;
uint dstr = (dst >> 16) & 0xFF;
uint dstg = (dst >> 8) & 0xFF;
uint dstb = (dst >> 0) & 0xFF;
uint ialpha = 256 - alpha;
uint r = ((srcr * ialpha + dstr * alpha) >> 8) & 0xFF;
uint g = ((srcg * ialpha + dstg * alpha) >> 8) & 0xFF;
uint b = ((srcb * ialpha + dstb * alpha) >> 8) & 0xFF;
return (r << 16) | (g << 8) | b;
}
/// blend two alpha values 0..255 (255 is fully transparent, 0 is opaque)
uint blendAlpha(uint a1, uint a2) {
if (!a1)
return a2;
if (!a2)
return a1;
return (((a1 ^ 0xFF) * (a2 ^ 0xFF)) >> 8) ^ 0xFF;
}
/// applies additional alpha to color
uint addAlpha(uint color, uint alpha) {
alpha = blendAlpha(color >> 24, alpha);
return (color & 0xFFFFFF) | (alpha << 24);
}
ubyte rgbToGray(uint color) {
uint srcr = (color >> 16) & 0xFF;
uint srcg = (color >> 8) & 0xFF;
uint srcb = (color >> 0) & 0xFF;
return cast(uint)(((srcr + srcg + srcg + srcb) >> 2) & 0xFF);
}
// todo
struct ColorTransformHandler {
void init(ref ColorTransform transform) {
}
uint transform(uint color) {
return color;
}
}
uint transformComponent(int src, int addBefore, int multiply, int addAfter) {
int add1 = (cast(int)(addBefore << 1)) - 0x100;
int add2 = (cast(int)(addAfter << 1)) - 0x100;
int mul = cast(int)(multiply << 2);
int res = (((src + add1) * mul) >> 8) + add2;
if (res < 0)
res = 0;
else if (res > 255)
res = 255;
return cast(uint)res;
}
uint transformRGBA(uint src, uint addBefore, uint multiply, uint addAfter) {
uint a = transformComponent(src >> 24, addBefore >> 24, multiply >> 24, addAfter >> 24);
uint r = transformComponent((src >> 16) & 0xFF, (addBefore >> 16) & 0xFF, (multiply >> 16) & 0xFF, (addAfter >> 16) & 0xFF);
uint g = transformComponent((src >> 8) & 0xFF, (addBefore >> 8) & 0xFF, (multiply >> 8) & 0xFF, (addAfter >> 8) & 0xFF);
uint b = transformComponent(src & 0xFF, addBefore & 0xFF, multiply & 0xFF, addAfter & 0xFF);
return (a << 24) | (r << 16) | (g << 8) | b;
}
struct ColorTransform {
uint addBefore = COLOR_TRANSFORM_OFFSET_NONE;
uint multiply = COLOR_TRANSFORM_MULTIPLY_NONE;
uint addAfter = COLOR_TRANSFORM_OFFSET_NONE;
@property bool empty() const {
return addBefore == COLOR_TRANSFORM_OFFSET_NONE
&& multiply == COLOR_TRANSFORM_MULTIPLY_NONE
&& addAfter == COLOR_TRANSFORM_OFFSET_NONE;
}
uint transform(uint color) {
return transformRGBA(color, addBefore, multiply, addAfter);
}
}
/// blend two RGB pixels using alpha
ubyte blendGray(ubyte dst, ubyte src, uint alpha) {
uint ialpha = 256 - alpha;
return cast(ubyte)(((src * ialpha + dst * alpha) >> 8) & 0xFF);
}
/// returns true if color is #FFxxxxxx (color alpha is 255)
bool isFullyTransparentColor(uint color) pure nothrow {
return (color >> 24) == 0xFF;
}
/**
* 9-patch image scaling information (see Android documentation).

View File

@ -39,6 +39,7 @@ version (USE_DLIBIMAGE) {
import dlangui.core.logger;
import dlangui.core.types;
import dlangui.graphics.colors;
import dlangui.graphics.drawbuf;
import std.stream;
import std.conv : to;

View File

@ -28,6 +28,7 @@ module dlangui.graphics.resources;
import dlangui.graphics.images;
import dlangui.graphics.drawbuf;
import dlangui.graphics.colors;
import dlangui.core.logger;
import std.file;
import std.algorithm;
@ -93,22 +94,7 @@ class FrameDrawable : Drawable {
@property override Rect padding() { return _frameWidths; }
}
/// decode color string #AARRGGBB, e.g. #5599AA
static uint decodeHexColor(string s) {
uint value = 0;
foreach(c; s) {
int digit = -1;
if (c >='0' && c <= '9')
digit = c - '0';
else if (c >='a' && c <= 'f')
digit = c - 'a' + 10;
else if (c >='A' && c <= 'F')
digit = c - 'A' + 10;
if (digit >= 0)
value = (value << 4) | digit;
}
return value;
}
/// decode size string, e.g. 1px or 2 or 3pt
static uint decodeDimension(string s) {
uint value = 0;

View File

@ -397,7 +397,7 @@ class Button : Widget {
FontRef font = font();
Point sz = font.textSize(text);
applyAlign(rc, sz);
font.drawText(buf, rc.left, rc.top, text, textColor);
font.drawText(buf, rc.left, rc.top, text, textColor, 4, 0, textFlags);
}
}

View File

@ -25,14 +25,12 @@ private import std.string;
private import std.algorithm;
import dlangui.core.types;
import dlangui.graphics.colors;
import dlangui.graphics.fonts;
import dlangui.graphics.drawbuf;
import dlangui.graphics.resources;
immutable ubyte ALIGN_UNSPECIFIED = 0;
immutable uint COLOR_UNSPECIFIED = 0xFFDEADFF;
/// transparent color constant
immutable uint COLOR_TRANSPARENT = 0xFFFFFFFF;
/// unspecified font size constant - to take parent style property value
immutable ushort FONT_SIZE_UNSPECIFIED = 0xFFFF;
/// unspecified font weight constant - to take parent style property value
@ -95,32 +93,6 @@ enum TextFlag : uint {
Underline = 8
}
/// custom drawable attribute container for styles
class DrawableAttribute {
protected string _id;
protected string _drawableId;
protected DrawableRef _drawable;
protected bool _initialized;
this(string id, string drawableId) {
_id = id;
_drawableId = drawableId;
}
@property string id() const { return _id; }
@property string drawableId() const { return _drawableId; }
@property void drawableId(string newDrawable) { _drawableId = newDrawable; clear(); }
@property ref DrawableRef drawable() const {
if (!_drawable.isNull)
return (cast(DrawableAttribute)this)._drawable;
(cast(DrawableAttribute)this)._drawable = drawableCache.get(_id);
(cast(DrawableAttribute)this)._initialized = true;
return (cast(DrawableAttribute)this)._drawable;
}
void clear() {
_drawable.clear();
_initialized = false;
}
}
/// style properties
class Style {
protected string _id;
@ -905,58 +877,6 @@ Rect decodeRect(string s) {
return Rect(0,0,0,0);
}
/// decodes hex digit (0..9, a..f, A..F), returns uint.max if invalid
uint decodeHexDigit(char ch) {
if (ch >= '0' && ch <= '9')
return ch - '0';
else if (ch >= 'a' && ch <= 'f')
return ch - 'a' + 10;
else if (ch >= 'A' && ch <= 'F')
return ch - 'A' + 10;
return uint.max;
}
/// supported formats: #RGB #ARGB #RRGGBB #AARRGGBB
uint decodeColor(string s, uint defValue) {
s = strip(s);
switch (s) {
case "@null":
case "transparent":
return COLOR_TRANSPARENT;
case "black":
return 0x000000;
case "white":
return 0xFFFFFF;
case "red":
return 0xFF0000;
case "green":
return 0x00FF00;
case "blue":
return 0x0000FF;
case "gray":
return 0x808080;
case "lightgray":
case "silver":
return 0xC0C0C0;
default:
break;
}
if (s.length != 4 && s.length != 5 && s.length != 7 && s.length != 9)
return defValue;
if (s[0] != '#')
return defValue;
uint value = 0;
for (int i = 1; i < s.length; i++) {
uint digit = decodeHexDigit(s[i]);
if (digit == uint.max)
return defValue;
value = (value << 4) | digit;
if (s.length < 7) // double the same digit for short forms
value = (value << 4) | digit;
}
return value;
}
private import std.array : split;
/// Decode color list attribute, e.g.: "#84A, #99FFFF" -> [0x8844aa, 0x99ffff]
@ -966,7 +886,7 @@ uint[] decodeFocusRectColors(string s) {
return null;
uint[] res = new uint[colors.length];
for (int i = 0; i < colors.length; i++) {
uint cl = decodeColor(colors[i], COLOR_UNSPECIFIED);
uint cl = decodeHexColor(colors[i], COLOR_UNSPECIFIED);
if (cl == COLOR_UNSPECIFIED)
return null;
res[i] = cl;
@ -1120,7 +1040,7 @@ bool loadStyleAttributes(Style style, Element elem, bool allowStates) {
// <color id="buttons_panel_color" value="#303080"/>
string colorid = attrValue(item, "id");
string colorvalue = attrValue(item, "value");
uint color = decodeColor(colorvalue, COLOR_TRANSPARENT);
uint color = decodeHexColor(colorvalue, COLOR_TRANSPARENT);
if (colorid)
style.setCustomColor(colorid, color);
}
@ -1217,6 +1137,33 @@ Theme loadTheme(string resourceId) {
return null;
}
/// custom drawable attribute container for styles
class DrawableAttribute {
protected string _id;
protected string _drawableId;
protected DrawableRef _drawable;
protected bool _initialized;
this(string id, string drawableId) {
_id = id;
_drawableId = drawableId;
}
@property string id() const { return _id; }
@property string drawableId() const { return _drawableId; }
@property void drawableId(string newDrawable) { _drawableId = newDrawable; clear(); }
@property ref DrawableRef drawable() const {
if (!_drawable.isNull)
return (cast(DrawableAttribute)this)._drawable;
(cast(DrawableAttribute)this)._drawable = drawableCache.get(_id);
(cast(DrawableAttribute)this)._initialized = true;
return (cast(DrawableAttribute)this)._drawable;
}
void clear() {
_drawable.clear();
_initialized = false;
}
}
shared static ~this() {
currentTheme = null;
}