namespace Upp; namespace Upp; enum_property Frame { "NullFrame()", "FieldFrame()", "InsetFrame()", "OutsetFrame()", "ButtonFrame()", "ThinInsetFrame()", "ThinOutsetFrame()", "BlackFrame()", "TopSeparatorFrame()", "BottomSeparatorFrame()", "LeftSeparatorFrame()", "RightSeparatorFrame()", "default" }; enum_property Align { "ALIGN_LEFT", "ALIGN_CENTER", "ALIGN_RIGHT" }; fn IsUHD() { return GetTextSize("X", StdFont()).cy > 24; } fn DPI(n) { return IsUHD() ? 2 * n : n; } fn DeflateRect(&r) { r.top++; r.left++; r.right--; r.bottom--; } fn DrawFrame(w, &r, c1, c2) { w.DrawRect(r.left, r.top, r.right - r.left, 1, c1); w.DrawRect(r.left, r.top, 1, r.bottom - r.top, c1); w.DrawRect(r.right - 1, r.top, 1, r.bottom - r.top, c2); w.DrawRect(r.left, r.bottom - 1, r.right - r.left, 1, c2); DeflateRect(r); } fn DrawBorder(w, &r, ...) { for(i = 0; i < count(argv); i += 2) DrawFrame(w, r, argv[i], argv[i + 1]); } fn DrawButtonFrame(w, &r) { if(IsUHD()) DrawBorder(w, r, :Gray, :Gray, :Gray, :Gray); else DrawBorder(w, r, :Gray, :Gray); } fn DrawEdgeButtonFrame(w, &r) { DrawBorder(w, r, :SWhite, :SWhite, :Gray, :Gray); } fn DrawButton(w, r) { w.DrawRect(r, :SWhiteGray); DrawButtonFrame(w, r); } fn DrawEdgeButton(w, &r) { DrawEdgeButtonFrame(w, r); w.DrawRect(r, :SLtGray); } fn DrawInsetFrame(w, &r) { DrawButtonFrame(w, r); } fn DrawCtrlFrame(w, &r, frame) { width = r.right - r.left; height = r.bottom - r.top; switch(frame) { case "FieldFrame()": case "default": IsUHD() ? DrawBorder(w, r, :SGray, :SGray, :SGray, :SGray) : DrawBorder(w, r, :SGray, :SGray); break; case "InsetFrame()": DrawBorder(w, r, :Gray, :White, :Black, :LtGray); break; case "OutsetFrame()": DrawBorder(w, r, :LtGray, :Black, :White, :Gray); break; case "ButtonFrame()": DrawButtonFrame(w, r); break; case "ThinInsetFrame()": DrawBorder(w, r, :Gray, :White); break; case "ThinOutsetFrame()": DrawBorder(w, r, :White, :Gray); break; case "BlackFrame()": DrawBorder(w, r, :SBlack, :SBlack); break; case "TopSeparatorFrame()": w.DrawRect(r.left, r.top, width, 1, :Gray); w.DrawRect(r.left, r.top + 1, width, 1, :White); r.top += 2; break; case "BottomSeparatorFrame()": w.DrawRect(r.left, r.bottom - 2, width, 1, :Gray); w.DrawRect(r.left, r.bottom - 1, width, 1, :White); r.bottom -= 2; break; case "LeftSeparatorFrame()": w.DrawRect(r.left, r.top, 1, height, :Gray); w.DrawRect(r.left + 1, r.top, 1, height, :White); r.left += 2; break; case "RightSeparatorFrame()": w.DrawRect(r.right - 2, r.top, 1, height, :Gray); w.DrawRect(r.right - 1, r.top, 1, height, :White); r.right -= 2; break; } } fn GradientColor(fc, tc, i, n) { return Color( fc.r + i * (tc.r - fc.r) / n, fc.g + i * (tc.g - fc.g) / n, fc.b + i * (tc.b - fc.b) / n ); } fn max(a, b) { return a > b ? a : b; } fn min(a, b) { return a < b ? a : b; } fn abs(a) { return a < 0 ? -a : a; } fn atoi(a) { n = 0; for(i = 0; i < count(a); i++) n = 10 * n + a[i] - '0'; return n; } fn DrawVertArrowFromTip(w, tipx, tipy, dir, l, color) { for(i = 0; i < l; i++) { w.DrawRect(tipx - i, tipy, 2 * i + 1, 1, color); tipy += dir; } } fn DrawVertArrow(ww, r, size, dir) { w = r.right - r.left; h = r.bottom - r.top; y = r.top + (h - size) / 2; DrawVertArrowFromTip(ww, r.left + w / 2, dir > 0 ? y : y + size, dir, size, :SBlack); } fn DrawSpinButtons(w, r) { h = r.bottom - r.top; h2 = int(h / 2); h7 = int(7 * h / 10); x = r.right - h7; ah = int(h / 6); ax = x + h7 / 2; rr = RectC(x, r.top, h7, h2); DrawEdgeButton(w, rr); DrawVertArrow(w, rr, h / 6, 1); rr = RectC(x, r.top + h2, h7, h - h2); DrawEdgeButton(w, rr); DrawVertArrow(w, rr, h / 6, -1); } fn XMinSize() { return Size(8, 13); } subctrl NormalSize { GetMinSize() { sz = XMinSize(); sz.cy += 2; return sz; } GetStdSize() { sz = GetMinSize(); sz.cx *= 7; return sz; } }; subctrl Base { >NormalSize; ViewRect(w) { r = GetRect(); DrawCtrlFrame(w, r, .SetFrame); return r; } ViewSize(w) { r = ViewRect(w); return Size(r.right - r.left, r.bottom - r.top); } }; subctrl Unknown { >NormalSize; ViewRect(w) { r = GetRect(); DrawCtrlFrame(w, r, .SetFrame); return r; } ViewSize(w) { r = ViewRect(w); return Size(r.right - r.left, r.bottom - r.top); } }; subctrl TextCtrl { GetMinSize() { sz = XMinSize(); sz.cy += 2; return sz; } GetStdSize() { sz = GetMinSize(); sz.cx *= 8; return sz; } Text SetLabel @1 ? "Label of control" ; ViewRect(w) { r = GetRect(); DrawCtrlFrame(w, r, .SetFrame); return r; } ViewSize(w) { r = ViewRect(w); return Size(r.right - r.left, r.bottom - r.top); } Paint(w) { sz = ViewSize(w); textsize = GetSmartTextSize(.SetLabel, .SetFont); px = 0; if(.SetAlign == "ALIGN_CENTER") px = (sz.cx - textsize.cx) / 2; if(.SetAlign == "ALIGN_RIGHT") px = sz.cx - textsize.cx; w.DrawSmartText(px, (sz.cy - textsize.cy) / 2, .SetLabel, .SetFont, .SetInk, sz.cx); } }; ctrl Label { group "Static"; GetMinSize() { return XMinSize(); } GetStdSize() { sz = GetMinSize(); sz.cy += 6; sz.cx *= 5; return sz; } >TextCtrl; Doc SetLabel @0 ? "Label of control"; Align SetAlign = ALIGN_LEFT @2; Font SetFont = StdFont() @2; Color SetInk = :SBlack @2; Frame SetFrame @3; // Qtf SetInfo @1 ? "Info of control" ; Paint(w) { sz = ViewSize(w); textsize = GetSmartTextSize(.SetLabel, .SetFont); px = 0; if(.SetAlign == "ALIGN_CENTER") px = (sz.cx - textsize.cx) / 2; if(.SetAlign == "ALIGN_RIGHT") px = sz.cx - textsize.cx; w.DrawSmartText(px, (sz.cy - textsize.cy) / 2, .SetLabel, .SetFont, .SetInk, sz.cx); } Sample() { .SetLabel = "Label"; .SetFont = Arial(10).Bold().Italic(); } }; ctrl StaticText { group "Static"; GetMinSize() { return XMinSize(); } GetStdSize() { sz = XMinSize(); sz.cy += 6; sz.cx *= 5; return sz; } Doc SetText ? "Label of control" ; Align SetAlign = ALIGN_LEFT; Font SetFont = StdFont(); Color SetInk = :SBlack; Frame SetFrame @1; // Qtf SetInfo @1 ? "Info of control" ; ViewRect(w) { r = GetRect(); DrawCtrlFrame(w, r, .SetFrame); return r; } ViewSize(w) { r = ViewRect(w); return Size(r.right - r.left, r.bottom - r.top); } Paint(w) { sz = ViewSize(w); textsize = GetSmartTextSize(.SetText, .SetFont); px = 0; if(.SetAlign == "ALIGN_CENTER") px = (sz.cx - textsize.cx) / 2; if(.SetAlign == "ALIGN_RIGHT") px = sz.cx - textsize.cx; w.DrawSmartText(px, (sz.cy - textsize.cy) / 2, .SetText, .SetFont, .SetInk); } Sample() { .SetText = "Text"; .SetFont = Arial(10).Bold().Italic(); } }; ctrl LabelBox { group "Static"; GetMinSize() { return Size(0, 0); } GetStdSize() { return Size(64, 24); } >Base; Text SetLabel ? "Box label"; Font SetFont = StdFont(); Color SetInk = :SBlack; Align SetAlign = ALIGN_LEFT; Paint(w) { sz = GetSize(); ts = GetSmartTextSize(.SetLabel, .SetFont); d = ts.cy / 2; if(.SetAlign == "ALIGN_RIGHT") d = sz.cx - d; if(.SetAlign == "ALIGN_CENTER") d = sz.cx / 2 - d; if(2 * GetSmartTextSize("X").cy > sz.cy) { d = sz.cy / 2; w.DrawSmartText(d, (sz.cy - ts.cy) / 2, .SetLabel, .SetFont, .SetInk, sz.cx); w.DrawRect(1, d, d - 1, 1, :Gray); w.DrawRect(1, d + 1, d - 1, 1, :Gray); w.DrawRect(d + ts.cx, d, sz.cx - ts.cx - d - 2, 1, :Gray); w.DrawRect(d + ts.cx, d + 1, sz.cx - ts.cx - d - 2, 1, :Gray); } else { d = ts.cy / 2; DrawButtonFrame(w, RectC(0, d, sz.cx, sz.cy - d)); w.DrawRect(8, 0, ts.cx + 4, ts.cy, :SLtGray); w.DrawSmartText(10, 0, .SetLabel, .SetFont, .SetInk); } } } fn DrawClassName(w, r, text) { font = Arial(10); sz = GetTextSize(text, font); w.DrawRect(r.right - sz.cx - sz.cy, r.bottom - sz.cy, sz.cx + 2 * sz.cy, sz.cy, :SGray); w.DrawText(r.right - sz.cx - sz.cy / 2, r.bottom - sz.cy, text, font, :SYellow); } ctrl ParentCtrl { group "Special"; GetMinSize() { return Size(0, 0); } GetStdSize() { return Size(64, 24); } Frame SetFrame @3; Paint(w) { r = GetRect(); DrawCtrlFrame(w, r, .SetFrame); DrawBorder(w, r, :SGray, :SGray); DrawClassName(w, r, "ParentCtrl"); } Sample() {} }; ctrl ImageCtrl { group "Static"; GetMinSize() { return Size(0, 0); } GetStdSize() { return Size(64, 24); } Frame SetFrame @3; Paint(w) { r = GetRect(); DrawCtrlFrame(w, r, .SetFrame); DrawBorder(w, r, :SGray, :SGray); DrawClassName(w, r, "ImageCtrl"); } Sample() {} }; ctrl DrawingCtrl { group "Static"; GetMinSize() { return Size(0, 0); } GetStdSize() { return Size(64, 24); } Frame SetFrame @3; Paint(w) { r = GetRect(); DrawCtrlFrame(w, r, .SetFrame); DrawBorder(w, r, :SGray, :SGray); DrawClassName(w, r, "DrawingCtrl"); } Sample() {} }; ctrl StaticRect { group "Static"; GetMinSize() { return Size(0, 0); } GetStdSize() { return Size(64, 24); } Color SetPaper = :SLtBlue @2; Frame SetFrame @3; Paint(w) { r = GetRect(); DrawCtrlFrame(w, r, .SetFrame); w.DrawRect(r, .SetPaper); DrawBorder(w, r, :SGray, :SGray); DrawClassName(w, r, "StaticRect"); } Sample() {} }; ctrl DataPusher { group "Push"; GetStdSize() { return Size(64, 24); } >Base; Frame SetFrame = default; bool SetEditable = true @1; Text Tip @1; Paint(w) { r = GetRect(); DrawCtrlFrame(w, r, .SetFrame); w.DrawRect(r, :SWhite); } }; ctrl ColorPusher { group "Push"; GetStdSize() { return Size(64, 24); } >Base; Frame SetFrame = default; bool SetEditable = true @1; Text Tip @1; bool NotNull = false; bool WithVoid = false; bool SColors = false; bool WithText = false; bool WithHex = false; bool Track = false; bool NoRampWheel = false; Text NullText; Text VoidText; Paint(w) { r = GetRect(); DrawCtrlFrame(w, r, .SetFrame); w.DrawRect(r, :SWhite); DeflateRect(r); w.DrawRect(r, :LtBlue); DrawFrame(w, r, :SBlack, :SBlack); if(.WithText || .WithHex) { text = .WithText ? "LtBlue" : "#0000FF"; w.DrawText(r.left + 6, (r.top + r.bottom - GetSmartTextSize(text, StdFont()).cy) / 2, text, StdFont(), :White); } } }; ctrl Button { group "Push"; GetMinSize() { sz = XMinSize(); sz.cy += 2; return sz; } GetStdSize() { sz = GetMinSize(); sz.cx *= 7; return sz; } Text SetLabel ? "Button label"; Font SetFont = StdFont(); Frame SetFrame @1; Text Tip @1; Paint(w) { r = GetRect(); DrawCtrlFrame(w, r, .SetFrame); DrawButtonFrame(w, r); sz = Size(r.right - r.left, r.bottom - r.top); n = int(sz.cy / 8); w.DrawRect(r.left, r.top, sz.cx, sz.cy, :SWhiteGray); textsize = GetSmartTextSize(.SetLabel, .SetFont); py = (sz.cy - textsize.cy) / 2; if(count(.SetLabel) && (.SetLabel)[0] == 1) w.DrawSmartText(r.left, r.top + py, .SetLabel, .SetFont, :SBlack, sz.cx); else { px = (sz.cx - textsize.cx) / 2; w.DrawSmartText(px + r.left, py + r.top, .SetLabel, .SetFont, :SBlack, sz.cx); } } } fn DrawCircle(w, xx, yy, c, color) { if(c > 15) { w.DrawRect(xx + 5, yy, c - 10, c, color); w.DrawRect(xx, yy + 5, c, c - 10, color); w.DrawRect(xx + 3, yy + 1, c - 6, c - 2, color); w.DrawRect(xx + 1, yy + 3, c - 2, c - 6, color); w.DrawRect(xx + 2, yy + 2, c - 4, c - 4, color); } else { w.DrawRect(xx + 2, yy, c - 4, c, color); w.DrawRect(xx, yy + 2, c, c - 4, color); w.DrawRect(xx + 1, yy + 1, c - 2, c - 2, color); } } fn OptionSize() { return IsUHD() ? 24 : 11; } fn DrawOption(w, x, y, kind) { osz = OptionSize(); if(kind == 2) { DrawCircle(w, x, y, osz, :Gray); if(osz > 15) DrawCircle(w, x + 2, y + 2, osz - 4, :SWhite); else DrawCircle(w, x + 1, y + 1, osz - 2, :SWhite); } else { r = RectC(x, y, osz, osz); w.DrawRect(r, :SWhite); if(osz > 15) { DrawButtonFrame(w, r); if(kind == 1) w.DrawRect(x + 4, y + osz / 2 - 1, osz - 8, 2, :SBlack); } else { DrawBorder(w, r, :Gray, :Gray); if(kind == 1) w.DrawRect(x + 3, y + osz / 2 - 1, osz - 6, 2, :SBlack); } } } ctrl Option { group "Push"; Text SetLabel @1 ? "Option text"; Font SetFont = StdFont() @1; Frame SetFrame @2; bool Box; bool AutoBox; bool BlackEdge; bool SwitchImage; bool SetEditable = true @1 ? "Editable"; bool ThreeState; bool NotNull; Text Tip @2; GetMinSize() { sz = XMinSize(); sz.cy += 2; return sz; } GetStdSize() { sz = GetMinSize(); sz.cx *= 7; sz.cy = max(16, sz.cy); return sz; } ViewRect(w) { r = GetRect(); DrawCtrlFrame(w, r, .SetFrame); return r; } ViewSize(w) { r = ViewRect(w); return Size(r.right - r.left, r.bottom - r.top); } Paint(w) { sz = ViewSize(w); kind = .SwitchImage ? 2 : .ThreeState ? 1 : 0; osz = OptionSize(); textsize = GetSmartTextSize(.SetLabel, .SetFont); if(.Box || .AutoBox) { d = textsize.cy / 2; DrawButtonFrame(w, RectC(0, d, sz.cx, sz.cy - d)); d = (textsize.cy - osz) / 2; w.DrawRect(8, 0, osz + textsize.cx + 8, textsize.cy, :SLtGray); DrawOption(w, 10, d, kind); w.DrawSmartText(osz + 10 + DPI(4), 0, .SetLabel, .SetFont); } else { DrawOption(w, 0, (sz.cy - osz) / 2, kind); w.DrawSmartText(osz + DPI(4), (sz.cy - textsize.cy) / 2, .SetLabel, .SetFont); } } } ctrl OptionBox { > Option; bool Box = true; } ctrl Switch { group "Push"; GetMinSize() { sz = XMinSize(); sz.cy += 2; return sz; } GetStdSize() { sz = GetMinSize(); sz.cx *= 7; sz.cy = max(16, sz.cy); return sz; } Doc SetLabel; Font SetFont = StdFont(); bool SetEditable = true @1 ? "Editable"; // Qtf SetInfo @1 ? "Info of control" ; Paint(w) { sz = GetSize(); ln = []; cs = []; gap = []; sep = []; g = 0; sp = 0; n = count(.SetLabel); for(i = 0; i < n; i++) { ch = .SetLabel[i]; if(ch == '^') { if(i + 1 < n && .SetLabel[i + 1] == '^') { ln[] = '^'; ln[] = '^'; i++; } else { g = atoi(ln); ln = ""; } } else if(ch == '|') { if(i + 1 < n && .SetLabel[i + 1] == '|') { ln[] = '|'; ln[] = '|'; i++; } else { g = atoi(ln); ln = ""; sp = 1; } } else if(ch >= 32 && ch < 65536) { ln[] = ch; } else if(ch == '\n') { cs[] = ln; gap[] = g; sep[] = sp; ln = ""; g = 0; } } cs[] = ln; gap[] = g; sep[] = sp; tcy = GetTextSize("W", .SetFont).cy; linecy = max(16, tcy + 2); osz = OptionSize(); setlabel = .SetLabel; horz = 0; for(pass = 0; pass < 2; pass++) { y = 0; x = 0; for(i = 0; i < count(cs); i++) { textsize = GetSmartTextSize(cs[i], .SetFont); if(gap[i]) { gsz = gap[i] * tcy / 4; if(sep[i] && pass) { if(horz) w.DrawRect(x + y + gsz / 2, y, 1 + IsUHD(), linecy, :SGray); else w.DrawRect(x, y + gsz / 2, sz.cx, 1 + IsUHD(), :SGray); } if(horz) x += gsz; else y += gsz; } if(horz) { if(pass) { DrawOption(w, x, (sz.cy - osz) / 2, 2); w.DrawSmartText(x + osz + DPI(4), (sz.cy - tcy) / 2, cs[i], .SetFont); } x += osz + DPI(4) + textsize.cx + tcy / 2; } else { if(pass) { DrawOption(w, x, y, 2); w.DrawSmartText(x + osz + DPI(4), y + (osz - tcy) / 2, cs[i], .SetFont); } y += linecy; } } if(y > sz.cy) horz = 1; } } }; ctrl EditField { group "Input fields"; GetMinSize() { sz = XMinSize(); sz.cy += 6; return sz; } GetStdSize() { sz = GetMinSize(); sz.cx *= 8; return sz; } Font SetFont = StdFont() @3; int MaxChars @2; bool AlignRight @1; bool SetEditable = true @4 ? "Editable"; Frame SetFrame = default @5; Text Tip @5; bool WantFocus = true @7; Paint(w) { r = GetRect(); DrawCtrlFrame(w, r, .SetFrame); w.DrawRect(r, :SWhite); PaintData(w); } PaintText(w, text) { w.DrawText(3, (GetSize().cy - GetTextSize(text, Arial(10)).cy) / 2, (.SetEditable ? "" : "R/O ") + text, Arial(10), :SMagenta); } PaintData(w) { PaintText(w, "EditField"); } } ctrl DocEdit { group "Editors"; GetMinSize() { sz = XMinSize(); sz.cy += 6; return sz; } GetStdSize() { sz = GetMinSize(); sz.cx *= 8; return sz; } Font SetFont = StdFont(); Frame SetFrame = default @1; bool SetEditable = true @1 ? "Editable"; bool WantFocus = true; Text Tip @1; // Qtf SetInfo @1 ? "Info of control" ; Paint(w) { r = GetRect(); DrawCtrlFrame(w, r, .SetFrame); w.DrawRect(r, :SWhite); PaintData(w); } PaintText(w, text) { w.DrawText(3, (GetSize().cy - GetTextSize(text, Arial(10)).cy) / 2, (.SetEditable ? "" : "R/O ") + text, Arial(10), :SMagenta); } PaintData(w) { PaintText(w, "DocEdit"); } } ctrl LineEdit { group "Editors"; GetMinSize() { sz = XMinSize(); sz.cy += 6; return sz; } GetStdSize() { sz = GetMinSize(); sz.cx *= 8; return sz; } Font SetFont = StdFont() @3; // int MaxChars @2; // bool AlignRight @1; bool SetEditable = true @4 ? "Editable"; Frame SetFrame = default @5; Text Tip @5; bool WantFocus = true @7; Paint(w) { r = GetRect(); DrawCtrlFrame(w, r, .SetFrame); w.DrawRect(r, :SWhite); PaintData(w); } PaintText(w, text) { w.DrawText(3, (GetSize().cy - GetTextSize(text, Arial(10)).cy) / 2, (.SetEditable ? "" : "R/O ") + text, Arial(10), :SMagenta); } PaintData(w) { PaintText(w, "LineEdit"); } } subctrl EditNotNull { >EditField; bool NotNull = false; PaintMinMax(w, type, minval, maxval) { PaintMinMaxText(w, type, minval, maxval, addtext); } PaintMinMaxText(w, type, minval, maxval, addtext) { text = (.NotNull ? "!" : "") + type; if(minval != "" && maxval != "") text << " " << minval << "..." << maxval; else if(minval != "") text << " >= " << minval; else if(maxval != "") text << " <= " << maxval; text << addtext; PaintText(w, text); } } ctrl EditString { >EditNotNull; raw MaxLen; bool TrimLeft = false; bool TrimRight = false; PaintData(w) { text = (.NotNull ? "!" : "") + "Str"; if(.MaxLen != "") text << "(" << .MaxLen << ")"; PaintText(w, text); } } ctrl SuggestCtrl { >EditString; PaintData(w) { text = (.NotNull ? "!" : "") + "SuggestCtrl"; if(.MaxLen != "") text << "(" << .MaxLen << ")"; PaintText(w, text); } } fn IntStr(x) { return x == :IntNull || x < :DblNullLim ? "" : to_string(x); } fn DblStr(x) { return x < :DblNullLim ? "" : to_string(x); } ctrl EditInt { >EditNotNull; int Min; int Max; PaintData(w) { PaintMinMax(w, "int", IntStr(.Min), IntStr(.Max)); } } ctrl EditInt64 { >EditNotNull; int Min; int Max; PaintData(w) { PaintMinMax(w, "int64", IntStr(.Min), IntStr(.Max)); } } ctrl EditIntNotNull { >EditInt; bool NotNull = true; }; ctrl EditDouble { >EditNotNull; double Min; double Max; PaintData(w) { PaintMinMax(w, "dbl", DblStr(.Min), DblStr(.Max)); } } ctrl EditDoubleNotNull { >EditDouble; bool NotNull = true; } ctrl EditFloat { >EditNotNull; double Min; double Max; PaintData(w) { PaintMinMax(w, "flt", DblStr(.Min), DblStr(.Max)); } } ctrl EditFloatNotNull { >EditFloat; bool NotNull = true; } ctrl EditDate { >EditNotNull; PaintData(w) { PaintMinMax(w, "Date", "", ""); } } ctrl EditDateNotNull { >EditDate; bool NotNull = true; } ctrl EditTime { >EditNotNull; PaintData(w) { PaintMinMax(w, "Time", "", ""); } } ctrl EditTimeNotNull { >EditTime; bool NotNull = true; } ctrl EditIntSpin { >EditInt; Paint(w) { r = GetRect(); DrawCtrlFrame(w, r, .SetFrame); w.DrawRect(r, :SWhite); DrawSpinButtons(w, r); PaintMinMax(w, "int", IntStr(.Min), IntStr(.Max)); } } ctrl EditInt64Spin { >EditInt64; Paint(w) { r = GetRect(); DrawCtrlFrame(w, r, .SetFrame); w.DrawRect(r, :SWhite); DrawSpinButtons(w, r); PaintMinMax(w, "int64", IntStr(.Min), IntStr(.Max)); } } ctrl EditDoubleSpin { >EditDouble; double SetInc = 0.1; Paint(w) { r = GetRect(); DrawCtrlFrame(w, r, .SetFrame); w.DrawRect(r, :SWhite); DrawSpinButtons(w, r); PaintMinMaxText(w, "dbl", DblStr(.Min), DblStr(.Max), "+-" + DblStr(.SetInc)); } } ctrl EditFloatSpin { >EditDoubleSpin; Paint(w) { r = GetRect(); DrawCtrlFrame(w, r, .SetFrame); w.DrawRect(r, :SWhite); DrawSpinButtons(w, r); PaintMinMaxText(w, "flt", DblStr(.Min), DblStr(.Max), "+-" + DblStr(.SetInc)); } } ctrl EditDateSpin { >EditDate; double SetInc = 1; Paint(w) { r = GetRect(); DrawCtrlFrame(w, r, .SetFrame); w.DrawRect(r, :SWhite); DrawSpinButtons(w, r); PaintMinMaxText(w, "date", DblStr(.Min), DblStr(.Max), "+-" + DblStr(.SetInc)); } } ctrl EditTimeSpin { >EditTime; double SetInc = 1; Paint(w) { r = GetRect(); DrawCtrlFrame(w, r, .SetFrame); w.DrawRect(r, :SWhite); DrawSpinButtons(w, r); PaintMinMaxText(w, "time", DblStr(.Min), DblStr(.Max), "+-" + DblStr(.SetInc)); } } fn DrawArrowButton(w, rr, dir) { DrawEdgeButton(w, rr); DrawVertArrow(w, rr, OptionSize() / 3, dir); } fn DrawHArrowButton(w, rr, dir) { DrawEdgeButton(w, rr); DrawHorzArrow(w, rr, dir); } fn DrawDropButton(w, rr) { DrawArrowButton(w, rr, -1); } fn PaintVScrollBar(w, r) { wd = r.right - r.left; up = r; r.top = (up.bottom = up.top + wd); down = r; r.bottom = (down.top = down.bottom - wd); DrawArrowButton(w, up, 1); DrawArrowButton(w, down, -1); w.DrawRect(r, :SWhiteGray); } fn PaintHScrollBar(w, r) { hg = r.bottom - r.top; left = r; r.left = (left.right = left.left + hg); right = r; r.right = (right.left = right.right - hg); DrawHArrowButton(w, left, 1); DrawHArrowButton(w, right, -1); w.DrawRect(r, :SWhiteGray); } ctrl DropList { group "Input fields"; GetMinSize() { sz = XMinSize(); sz.cy += 6; return sz; } GetStdSize() { sz = GetMinSize(); sz.cx *= 8; return sz; } Frame SetFrame = default; bool SetEditable = true @2 ? "Editable"; bool WantFocus = true; bool DisplayAll = false; bool AlwaysDrop = false @1; bool NotNull = false; Text Tip @2; // Qtf SetInfo @1 ? "Info of control" ; Paint(w) { r = GetRect(); DrawCtrlFrame(w, r, .SetFrame); w.DrawRect(r, :SWhite); n = r.bottom - r.top; DrawDropButton(w, RectC(r.right - n, r.top, n, n)); w.DrawText(3, (GetSize().cy - GetTextSize("", Arial(10)).cy) / 2, (.SetEditable ? "" : "R/O ") + "DropList", Arial(10), :SMagenta); } } ctrl DropTree { group "Input fields"; GetMinSize() { sz = XMinSize(); sz.cy += 6; return sz; } GetStdSize() { sz = GetMinSize(); sz.cx *= 8; return sz; } Frame SetFrame = default; bool SetEditable = true @2 ? "Editable"; bool WantFocus = true; bool DisplayAll = false; bool AutoResize = false; bool DropFocus = false; bool AlwaysDrop = false @1; Text Tip @2; // Qtf SetInfo @1 ? "Info of control" ; Paint(w) { r = GetRect(); DrawCtrlFrame(w, r, .SetFrame); w.DrawRect(r, :SWhite); n = r.bottom - r.top; DrawDropButton(w, RectC(r.right - n, r.top, n, n)); w.DrawText(3, (GetSize().cy - GetTextSize("", Arial(10)).cy) / 2, (.SetEditable ? "" : "R/O ") + "DropTree", Arial(10), :SMagenta); } } template WithDropChoice { bool Dropping = true; String Appending = ", "; raw SetDropLines = 16; Text Tip @1; Paint(w) { CtrlPaint(w); r = GetRect(); DrawCtrlFrame(w, r, .SetFrame); n = r.bottom - r.top; DrawDropButton(w, RectC(r.right - n, r.top, n, n)); } }; fn PaintTab(w, x, y, text, color) { tsz = GetSmartTextSize(text, StdFont()); h = 4 * tsz.cy / 3; sz = Size(tsz.cx + tsz.cy, h); r = RectC(x, y, sz.cx, sz.cy); w.DrawRect(r, color); DrawButtonFrame(w, r); w.DrawSmartText(x + tsz.cy / 2, y + 4, text, StdFont(), :SBlack, sz.cx); sz.cx -= 4; return sz; } ctrl TabCtrl { group "Complex"; GetStdSize() { return Size(150, 100); } // Font SetFont = StdFont(); bool AcceptCurrent = false; // Qtf SetInfo @1 ? "Info of control" ; Paint(w) { r = GetRect(); x0 = x = r.left; y = r.top; tsz = PaintTab(w, x, y, "Tab 1", :SWhiteGray); x += tsz.cx; x += PaintTab(w, x, y + 3, "Tab 2", :SLtGray).cx; x += PaintTab(w, x, y + 3, "Tab 3", :SLtGray).cx; r.top += tsz.cy; DrawButton(w, r); PaintTab(w, x0, y, "Tab 1", :SWhiteGray); if(IsUHD()) w.DrawRect(2, r.top - 2, tsz.cx, 4, :SWhiteGray); else w.DrawRect(1, r.top - 1, tsz.cx + 2, 2, :SWhiteGray); } }; fn PaintHeaderTab(w, r, text) { DrawEdgeButtonFrame(w, r); w.DrawText(r.left + 2, (r.top + r.bottom - GetTextSize(text).cy) >> 1, text, StdFont()); } fn PaintHeaderTabs(w, ...) { for(i = 0; i < count(argv); i += 2) PaintHeaderTab(w, argv[i], argv[i + 1]); } fn PaintCenterText(w, x, y, text, fnt, color) { sz = GetTextSize(text, fnt); w.DrawText(x - sz.cx / 2, y - sz.cy / 2, text, fnt, color); } ctrl ArrayCtrl { group "Complex"; GetStdSize() { return Size(150, 100); } Frame SetFrame = default @1; bool AutoHideSb = false; bool Header = true; bool Inserting = false; bool Appending = false; bool AppendLine = false; bool Removing = false; bool AskRemove = true; bool Duplicating = false; bool Moving = false; bool Track = false; bool VertGrid = true; bool HorzGrid = true; bool NoCursor = false; bool MouseMoveCursor = false; bool MultiSelect = false; int SetLineCy; // Qtf SetInfo @1 ? "Info of control" ; Paint(w) { PaintArray(w, GetRect()); } PaintArray(w, r) { col1 = "A"; col2 = "B"; col3 = "C"; fontcy = GetTextSize(col1).cy; DrawCtrlFrame(w, r, .SetFrame); if(!.AutoHideSb) { rsb = r; r.right = rsb.left = rsb.right - fontcy - 4; PaintVScrollBar(w, rsb); } wd = r.right - r.left; hdrcy = .Header ? fontcy + 4 : 0; third = wd / 3; r1 = r; r1.bottom = r1.top + hdrcy; r1.right = r.left + third; r2 = r1; r2.right = (r2.left = r1.right) + third; r3 = r2; r3.left = r2.right; r3.right = r.right; if(hdrcy) PaintHeaderTabs(w, r1, col1, r2, col2, r3, col3); linecy = .SetLineCy; if(is_void(linecy) || linecy <= 0) linecy = fontcy + 1; celltop = r1.bottom; cellht = 3 * linecy; cellbot = celltop + cellht + 1; w.DrawRect(r.left, celltop, wd, cellht, :SWhite); if(.NoCursor == "false") w.DrawRect(r.left, celltop + linecy, wd, linecy, :SBlue); for(i = 1; i <= 3; i++) { if(.HorzGrid) w.DrawRect(r.left, celltop + linecy * i, wd, 1, :SLtGray); if(.VertGrid) w.DrawRect(r.left + i * third - 1, celltop, 1, cellht, :SLtGray); } w.DrawRect(r.left, cellbot, wd, r.bottom - cellbot, :SWhite.r < 50 ? Color(90, 90, 90) : Color(160, 160, 160)); w.DrawText(3, r.bottom - fontcy, "ArrayCtrl", Arial(10), :SMagenta); } }; fn DrawTreeItem(w, x, y, text, kind) { osz = OptionSize(); textsize = GetTextSize(text); if(kind) DrawOption(w, x, y + (textsize.cy - osz) / 2, 1); w.DrawText(x + osz + 2, y, text, StdFont(), :SBlack); } ctrl TreeCtrl { group "Complex"; GetStdSize() { return Size(150, 100); } Frame SetFrame = default @1; // Qtf SetInfo @1 ? "Info of control" ; Paint(w) { r = GetRect(); w.DrawRect(r, :SWhite); fontcy = GetTextSize("X").cy; DrawCtrlFrame(w, r, .SetFrame); rsb = r; r.right = rsb.left = rsb.right - fontcy - 4; PaintVScrollBar(w, rsb); w.DrawText(3, r.bottom - fontcy, "TreeCtrl", Arial(10), :SMagenta); DeflateRect(r); DeflateRect(r); DrawTreeItem(w, r.left + 2 + 0 * fontcy, r.top + 2 + 0 * fontcy, "Root", 1); DrawTreeItem(w, r.left + 2 + 1 * fontcy, r.top + 2 + 1 * fontcy, "Node 1", 0); DrawTreeItem(w, r.left + 2 + 1 * fontcy, r.top + 2 + 2 * fontcy, "Node 2", 1); DrawTreeItem(w, r.left + 2 + 2 * fontcy, r.top + 2 + 3 * fontcy, "Node 3", 0); } }; ctrl ColumnList { group "Complex"; GetStdSize() { return Size(150, 100); } Frame SetFrame = default @1; // Qtf SetInfo @1 ? "Info of control" ; Paint(w) { r = GetRect(); w.DrawRect(r, :SWhite); fontcy = GetTextSize("X").cy; DrawCtrlFrame(w, r, .SetFrame); rsb = r; r.right = rsb.left = rsb.right - fontcy - 4; PaintVScrollBar(w, rsb); w.DrawText(3, 3, "ColumnList", Arial(10), :SMagenta); } }; ctrl RichTextView { group "Complex"; GetMinSize() { sz = XMinSize(); sz.cy += 6; return sz; } GetStdSize() { sz = GetMinSize(); sz.cx *= 8; return sz; } Frame SetFrame = default @1; Color Background = :SWhite; bool VCenter = false; bool NoSb = false @0; bool AutoHideSb = false; int HMargins = 0; int VMargins = 0; Paint(w) { r = GetRect(); DrawCtrlFrame(w, r, .SetFrame); w.DrawRect(r, .Background); w.DrawText(3, 3, "RichTextView", Arial(10), :SMagenta); } } ctrl RichTextCtrl { group "Static"; >RichTextView; GetMinSize() { sz = XMinSize(); sz.cy += 6; return sz; } GetStdSize() { sz = GetMinSize(); sz.cx *= 8; return sz; } Frame SetFrame = NullFrame() @1; Color Background = Null @0; bool NoSb = false @0; bool AutoHideSb = true @0; Paint(w) { r = GetRect(); DrawCtrlFrame(w, r, .SetFrame); if(!is_void(.Background)) w.DrawRect(r, .Background); w.DrawText(3, 3, "RichTextCtrl", Arial(10), :SMagenta); } } ctrl DropDate { group "Input fields"; GetMinSize() { sz = XMinSize(); sz.cy += 6; return sz; } GetStdSize() { sz = GetMinSize(); sz.cx *= 13; return sz; } bool SelectAll = true; bool SwapMonthYear = false; bool OneButton = false; bool NotNull = false; Frame SetFrame = default; bool SetEditable = true @2 ? "Editable"; bool WantFocus = true; Text Tip @2; Paint(w) { r = GetRect(); DrawCtrlFrame(w, r, .SetFrame); w.DrawRect(r, :SWhite); n = r.bottom - r.top; DrawDropButton(w, RectC(r.right - n, r.top, n, n)); w.DrawText(3, (GetSize().cy - GetTextSize("", Arial(10)).cy) / 2, (.SetEditable ? "" : "R/O ") + (.NotNull ? "!" : "") + "25/07/2022", Arial(10), :SMagenta); } } ctrl DropTime { group "Input fields"; GetMinSize() { sz = XMinSize(); sz.cy += 6; return sz; } GetStdSize() { sz = GetMinSize(); sz.cx *= 15; return sz; } bool SelectAll = true; bool SwapMonthYear = false; bool Seconds = true; bool DayEnd = false; bool TimeAlways = false; bool NotNull = false; Frame SetFrame = default; bool SetEditable = true @2 ? "Editable"; bool WantFocus = true @2; Text Tip @2; Paint(w) { r = GetRect(); DrawCtrlFrame(w, r, .SetFrame); w.DrawRect(r, :SWhite); n = r.bottom - r.top; DrawDropButton(w, RectC(r.right - n, r.top, n, n)); w.DrawText(3, (GetSize().cy - GetTextSize("", Arial(10)).cy) / 2, (.SetEditable ? "" : "R/O ") + (.NotNull ? "!" : "") + "25/07/2022 10:34:58", Arial(10), :SMagenta); } } fn DrawHorzArrowFromTip(w, tipx, tipy, dir, l, color) { for(i = 0; i < l; i++) { w.DrawRect(tipx, tipy - i, 1, 2 * i + 1, color); tipx += dir; } } fn DrawHorzArrow(ww, r, dir) { size = OptionSize() / 3; w = r.right - r.left; h = r.bottom - r.top; x = r.left + (h - size) / 2; DrawHorzArrowFromTip(ww, dir > 0 ? x : x + size, r.top + h / 2, dir, size, :SBlack); } ctrl Clock { group "Input fields"; GetMinSize() { return Size(150, 156); } GetStdSize() { return Size(150, 156); } Frame SetFrame = BlackFrame() @2; bool SetEditable = true @2 ? "Editable"; bool WantFocus = true @2; bool Seconds = true; Text Tip @2; PaintPtr(w, cmx, cmy, pos, m, d, color, cf) { dx = m * sin(pos * 2 * 3.1415); dy = m * cos(pos * 2 * 3.1415); sx = cmx - dx * 35 / 2.0; sy = cmy + dy * 35 / 2.0; ex = cmx + dx * cf; ey = cmy - dy * cf; w.DrawLine(sx, sy, ex, ey, d, color); } Paint(w) { ts = GetTextSize("X"); r = GetRect(); ro = GetRect(); b = r.bottom; hs = 20; r.bottom = hs; w.DrawRect(r, :SLtBlue); r.top = r.bottom; r.bottom = b; w.DrawRect(r, :SWhite); width = r.right - r.left; height = r.bottom - r.top; w.DrawRect(0, hs, 5, ro.bottom - hs, Color(200, 200, 200)); w.DrawRect(ro.right - 5, hs, 5, ro.bottom - hs, Color(200, 200, 200)); cmx = width / 2; cmy = height / 2 + hs; cf = min(cmy - 15, cmx) - 5; for(i = 1; i <= 60; i++) { x = cmx + (0.95 * sin(i * 3.1415 / 30.0) * cf); y = cmy - (0.95 * cos(i * 3.1415 / 30.0) * cf); if(i % 5 == 0) w.DrawRect(x, y, 2, 2, :SBlack); else w.DrawRect(x, y, 1, 1, :SBlack); } fnt = Arial(10); for(i = 1; i <= 12; i++) { x = cmx + (0.8 * sin(i * 3.1415 / 6.0) * cf); y = cmy - (0.8 * cos(i * 3.1415 / 6.0) * cf); PaintCenterText(w, x, y, to_string(i), .fnt, :SBlack); } hour = 10; minute = 34; second = 15; tm = hour * 3600 + minute * 60 + second; PaintPtr(w, cmx, cmy, tm / 3600 / 12, 0.5, 5, :SRed, cf); PaintPtr(w, cmx, cmy, tm / 3600, 0.6, 3, :SBlue, cf); PaintPtr(w, cmx, cmy, tm / 60, 0.75, 2, :SBlack, cf); r = Rect(ro.left + 3, ro.top + 2, ro.left + 3 + 16, ro.top + 18); left = r.left; r.left += 15 + 25; r.right += 15 + 25; PaintCenterText(w, (r.right + left) / 2, (r.top + r.bottom) / 2, to_string(hour), .fnt, :SWhite); r = Rect(ro.right - 3 - 16, ro.top + 2, ro.right - 3, ro.top + 18); right = r.right; r.left -= 15 + 25; r.right -= 15 + 25; PaintCenterText(w, (right + r.left) / 2, (r.top + r.bottom) / 2, to_string(minute), .fnt, :SWhite); DrawCtrlFrame(w, ro, .SetFrame); } } ctrl Calendar { group "Input fields"; GetMinSize() { return Size(180, 120); } GetStdSize() { return Size(236, 156); } Frame SetFrame = BlackFrame(); bool SetEditable = true @2 ? "Editable"; bool WantFocus = true @2; bool SelectAll = true; bool SwapMonthYear = false; bool OneButton = false; Text Tip @2; Paint(w) { ts = GetTextSize("X"); r = GetRect(); ro = GetRect(); f = StdFont(); b = r.bottom; hs = 20; r.bottom = hs; w.DrawRect(r, :SLtBlue); r.top = r.bottom; r.bottom = b; w.DrawRect(r, :SWhite); width = r.right - r.left; height = r.bottom - r.top - 15; sw = width / 8; sh = height / 7; w.DrawRect(r.left + 4, r.top + sh, width - 8, 1, :SBlack); w.DrawRect(r.left + sw, r.top + 4, 1, height - 8, :SBlack); ts = GetTextSize("Wk"); ty = r.top + (sh - ts.cy) / 2; w.DrawText(r.left + (sw - ts.cx) / 2 , ty, "Wk", f, :SBlack); days = ["Mo", "Tu", "We", "Th", "Fr", "Sa", "Su"]; for(i = 0; i < 7; i++) w.DrawText(r.left + sw + i * sw + (sw - ts.cx) / 2, ty, days[i], f, :SBlack); d = 1; tn = GetTextSize("0"); gray = 0; fnt = f; for(j = 0; j < 6; j++) { ty = r.top + sh + j * sh + (sh - ts.cy) / 2; w.DrawText(r.left + (sw - tn.cx) / 2, ty, to_string(j + 1), f, :SBlack); for(i = 0; i < 7; i++) { if(d == 19) { w.DrawRect(r.left + sw + i * sw + 0, r.top + sh + j * sh + 0, sw, sh, :SBlack); w.DrawRect(r.left + sw + i * sw + 1, r.top + sh + j * sh + 1, sw - 2, sh - 2, :SYellow); fnt = f.Bold(1); } day = to_string(d); ts = GetTextSize(day, fnt); w.DrawText(r.left + sw + i * sw + (sw - ts.cx) / 2, ty, day, fnt, gray ? :SGray : (i == 6 ? :SRed : :SBlack)); fnt = f.Bold(false); if(++d > 31) { d = 1; gray = 1; } } } today = "Today: 25/07/2022"; ts = GetTextSize(today, StdFont().Bold()); w.DrawText((r.right - ts.cx) / 2, r.bottom - 3 - ts.cy, today, f.Bold(), :SBlue); r = Rect(ro.left + 3, ro.top + 2, ro.left + 3 + 16, ro.top + 18); left = r.left; r.left += 15 + 65; r.right += 15 + 65; PaintCenterText(w, (left + r.right) / 2, (r.top + r.bottom) / 2, "January", f.Bold(), :SWhite); r = Rect(ro.right - 3 - 16, ro.top + 2, ro.right - 3, ro.top + 18); right = r.right; r.left -= 15 + 40; r.right -= 15 + 40; PaintCenterText(w, (r.left + right) / 2, (r.top + r.bottom) / 2, "2022", f.Bold(), :SWhite); DrawCtrlFrame(w, ro, .SetFrame); } } ctrl SliderCtrl { group "Progress"; GetMinSize() { return Size(0, 0); } GetStdSize() { return Size(64, 24); } Frame SetFrame @1; bool Jump = false; Paint(w) { r = GetRect(); DrawCtrlFrame(w, r, .SetFrame); sz = Size(r.right - r.left, r.bottom - r.top); halfX = int(r.left + r.right) >> 1; halfY = int(r.top + r.bottom) >> 1; osz = 3 * OptionSize() / 2; osz2 = int(osz / 2); osz4 = int(osz / 4); if (sz.cx < sz.cy) { DrawInsetFrame(w, Rect(halfX - 2, r.top + 2, halfX + 2, r.bottom - 2)); DrawButton(w, RectC(halfX - osz2, halfY - osz4, osz, osz2)); } else { DrawInsetFrame(w, Rect(r.left + 2, halfY - 2, r.right - 2, halfY + 2)); DrawButton(w, RectC(halfX - osz4, halfY - osz2, osz2, osz)); } } } ctrl ProgressIndicator { group "Progress"; GetMinSize() { return Size(0, 0); } GetStdSize() { return Size(64, 24); } Frame SetFrame @1; Paint(w) { r = GetRect(); DrawCtrlFrame(w, r, .SetFrame); DrawInsetFrame(w, r); sz = Size(r.right - r.left, r.bottom - r.top); w.DrawRect(r.left, r.top, sz.cx, sz.cy, :SBlack); DeflateRect(r); sz = Size(r.right - r.left, r.bottom - r.top); w.DrawRect(r.left, r.top, sz.cx, sz.cy, :SWhite); if(sz.cx > sz.cy) { w.DrawRect(r.left, r.top, sz.cx >> 2, sz.cy, :SLtGreen); } else { w.DrawRect(r.left, r.bottom - (sz.cy >> 2), sz.cx, sz.cy >> 2, :SLtGreen); } } }