mirror of https://github.com/buggins/dlangui.git
Merge pull request #498 from dayllenger/optimizations
Measure & layout optimizations
This commit is contained in:
commit
513a98a332
|
@ -513,6 +513,55 @@ struct Ref(T) { // if (T is RefCountedObject)
|
|||
}
|
||||
|
||||
|
||||
/**
|
||||
This struct allows to not execute some code if some variables was not changed since the last check.
|
||||
Used for optimizations.
|
||||
|
||||
Reference types, arrays and pointers are compared by reference.
|
||||
*/
|
||||
struct CalcSaver(Params...) {
|
||||
import std.typecons : Tuple;
|
||||
Tuple!Params values;
|
||||
|
||||
bool check(Params args) {
|
||||
bool changed;
|
||||
foreach (i, arg; args) {
|
||||
if (values[i] !is arg) {
|
||||
values[i] = arg;
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
return changed;
|
||||
}
|
||||
}
|
||||
|
||||
///
|
||||
unittest {
|
||||
|
||||
class A { }
|
||||
|
||||
CalcSaver!(uint, double[], A) saver;
|
||||
|
||||
uint x = 5;
|
||||
double[] arr = [1, 2, 3];
|
||||
A a = new A();
|
||||
|
||||
assert(saver.check(x, arr, a));
|
||||
// values are not changing
|
||||
assert(!saver.check(x, arr, a));
|
||||
assert(!saver.check(x, arr, a));
|
||||
assert(!saver.check(x, arr, a));
|
||||
assert(!saver.check(x, arr, a));
|
||||
|
||||
x = 8;
|
||||
arr ~= 25;
|
||||
a = new A();
|
||||
// values are changed
|
||||
assert(saver.check(x, arr, a));
|
||||
assert(!saver.check(x, arr, a));
|
||||
}
|
||||
|
||||
|
||||
//================================================================================
|
||||
// some utility functions
|
||||
|
||||
|
|
|
@ -115,20 +115,26 @@ class TextWidget : Widget {
|
|||
return this;
|
||||
}
|
||||
|
||||
private CalcSaver!(Font, dstring, uint, uint) _measureSaver;
|
||||
|
||||
override void measure(int parentWidth, int parentHeight) {
|
||||
FontRef font = font();
|
||||
//auto measureStart = std.datetime.Clock.currAppTick;
|
||||
Point sz;
|
||||
if (maxLines == 1) {
|
||||
sz = font.textSize(text, MAX_WIDTH_UNSPECIFIED, 4, 0, textFlags);
|
||||
} else {
|
||||
sz = font.measureMultilineText(text,maxLines,parentWidth-margins.left-margins.right-padding.left-padding.right, 4, 0, textFlags);
|
||||
uint w = (maxLines == 1) ? MAX_WIDTH_UNSPECIFIED :
|
||||
parentWidth - margins.left - margins.right - padding.left - padding.right;
|
||||
uint flags = textFlags;
|
||||
|
||||
// optimization: do not measure if nothing changed
|
||||
if (_measureSaver.check(font.get, text, w, flags) || _needLayout) {
|
||||
Point sz;
|
||||
if (maxLines == 1) {
|
||||
sz = font.textSize(text, w, 4, 0, flags);
|
||||
} else {
|
||||
sz = font.measureMultilineText(text, maxLines, w, 4, 0, flags);
|
||||
}
|
||||
// it's not very correct, but in such simple widget it doesn't make issues
|
||||
measuredContent(SIZE_UNSPECIFIED, SIZE_UNSPECIFIED, sz.x, sz.y);
|
||||
_needLayout = false;
|
||||
}
|
||||
//auto measureEnd = std.datetime.Clock.currAppTick;
|
||||
//auto duration = measureEnd - measureStart;
|
||||
//if (duration.length > 10)
|
||||
// Log.d("TextWidget measureText took ", duration.length, " ticks");
|
||||
measuredContent(parentWidth, parentHeight, sz.x, sz.y);
|
||||
}
|
||||
|
||||
override void onDraw(DrawBuf buf) {
|
||||
|
|
|
@ -643,7 +643,7 @@ class FrameLayout : WidgetGroupDefaultDrawing {
|
|||
applyPadding(rc);
|
||||
for (int i = 0; i < _children.count; i++) {
|
||||
Widget item = _children.get(i);
|
||||
if (item.visibility != Visibility.Gone) {
|
||||
if (item.visibility == Visibility.Visible) {
|
||||
item.layout(rc);
|
||||
}
|
||||
}
|
||||
|
@ -657,6 +657,7 @@ class FrameLayout : WidgetGroupDefaultDrawing {
|
|||
Widget item = _children.get(i);
|
||||
if (item.compareId(ID)) {
|
||||
item.visibility = Visibility.Visible;
|
||||
item.requestLayout();
|
||||
foundWidget = item;
|
||||
found = true;
|
||||
} else {
|
||||
|
|
Loading…
Reference in New Issue