nicer window resize limits

This commit is contained in:
nakst 2021-09-08 12:23:30 +01:00
parent 81cc802542
commit 424d65d8c4
5 changed files with 90 additions and 32 deletions

View File

@ -104,23 +104,34 @@ bool InstanceLoadFolder(Instance *instance, String path /* takes ownership */, i
EsCommandSetEnabled(&instance->commandRefresh, true);
// Load the view settings for the folder.
// If the folder does not have any settings, inherit from closest ancestor with settings.
bool foundViewSettings = false;
size_t lastMatchBytes = 0;
ptrdiff_t updateLRU = -1;
if (folder->path.bytes < sizeof(folderViewSettings[0].path)) {
for (uintptr_t i = 0; i < folderViewSettings.Length(); i++) {
if (folderViewSettings[i].pathBytes == folder->path.bytes
&& 0 == EsMemoryCompare(folderViewSettings[i].path, STRING(folder->path))) {
String path = StringFromLiteralWithSize(folderViewSettings[i].path, folderViewSettings[i].pathBytes);
bool matchFull = StringEquals(path, folder->path);
bool matchPartial = matchFull || PathHasPrefix(folder->path, path);
if (matchFull || (matchPartial && lastMatchBytes < path.bytes)) {
foundViewSettings = true;
FolderViewSettingsEntry entry = folderViewSettings[i];
instance->viewSettings = entry.settings;
folderViewSettings.Delete(i);
folderViewSettings.Add(entry); // Update the LRU order.
break;
instance->viewSettings = folderViewSettings[i].settings;
updateLRU = i;
if (matchFull) break;
else lastMatchBytes = path.bytes; // Keep looking for a closer ancestor.
}
}
}
if (updateLRU != -1) {
FolderViewSettingsEntry entry = folderViewSettings[updateLRU];
folderViewSettings.Delete(updateLRU);
folderViewSettings.Add(entry);
}
if (!foundViewSettings) {
if (folder->itemHandler->getDefaultViewSettings) {
folder->itemHandler->getDefaultViewSettings(folder, &instance->viewSettings);

View File

@ -420,6 +420,7 @@ void HeapDuplicate(void **pointer, size_t *outBytes, const void *data, size_t by
struct EsWindow : EsElement {
EsHandle handle;
EsWindowStyle windowStyle;
uint32_t windowWidth, windowHeight;
bool willUpdate, toolbarFillMode, destroyInstanceAfterClose, hasDialog, doNotPaint;
@ -427,10 +428,11 @@ struct EsWindow : EsElement {
bool hovering, activated;
bool visualizeRepaints, visualizeLayoutBounds, visualizePaintSteps; // Inspector properties.
EsPoint mousePosition;
EsElement *mainPanel, *toolbar;
EsPanel *toolbarSwitcher;
EsElement *dialogOverlay, *dialogPanel;
EsPoint mousePosition;
EsElement *hovered,
*pressed,
@ -449,9 +451,9 @@ struct EsWindow : EsElement {
Array<EsElement *> checkVisible;
bool processCheckVisible;
EsElement *dialogOverlay, *dialogPanel;
EsWindowStyle windowStyle;
EsRectangle beforeMaximiseBounds;
EsRectangle beforeMaximiseBounds, targetBounds, animateFromBounds;
bool animateToTargetBoundsAfterResize;
double animateToTargetBoundsTimeMs;
EsRectangle updateRegion;
EsRectangle updateRegionInProgress; // For visualizePaintSteps.
@ -561,20 +563,14 @@ void WindowChangeBounds(int direction, int newX, int newY, int *originalX, int *
EsRectangle screen;
EsSyscall(ES_SYSCALL_SCREEN_WORK_AREA_GET, 0, (uintptr_t) &screen, 0, 0);
int newWidth = bounds.r - bounds.l;
int newHeight = bounds.b - bounds.t;
int windowSnapRange = GetConstantNumber("windowSnapRange");
int windowMinimumWidth = GetConstantNumber("windowMinimumWidth");
int windowMinimumHeight = GetConstantNumber("windowMinimumHeight");
int windowRestoreDragYPosition = GetConstantNumber("windowRestoreDragYPosition");
window->isMaximised = false;
if (newWidth < windowMinimumWidth && direction & RESIZE_LEFT) bounds.l = bounds.r - windowMinimumWidth;
if (newWidth < windowMinimumWidth && direction & RESIZE_RIGHT) bounds.r = bounds.l + windowMinimumWidth;
if (newHeight < windowMinimumHeight && direction & RESIZE_TOP) bounds.t = bounds.b - windowMinimumHeight;
if (newHeight < windowMinimumHeight && direction & RESIZE_BOTTOM) bounds.b = bounds.t + windowMinimumHeight;
window->animateToTargetBoundsAfterResize = false;
window->animateToTargetBoundsTimeMs = -1;
if (direction == RESIZE_MOVE) {
if (newY < screen.t + windowSnapRange && canSnap) {
@ -605,6 +601,17 @@ void WindowChangeBounds(int direction, int newX, int newY, int *originalX, int *
bounds.b = bounds.t + oldHeight;
}
} else {
EsRectangle targetBounds = bounds;
#define WINDOW_CLAMP_SIZE(_size, _direction, _side, _target) \
if (_size(bounds) < windowMinimum ## _size && (direction & _direction)) targetBounds._side = _target, bounds._side = RubberBand(bounds._side, _target)
WINDOW_CLAMP_SIZE(Width, RESIZE_LEFT, l, bounds.r - windowMinimumWidth);
WINDOW_CLAMP_SIZE(Width, RESIZE_RIGHT, r, bounds.l + windowMinimumWidth);
WINDOW_CLAMP_SIZE(Height, RESIZE_TOP, t, bounds.b - windowMinimumHeight);
WINDOW_CLAMP_SIZE(Height, RESIZE_BOTTOM, b, bounds.t + windowMinimumHeight);
window->animateToTargetBoundsAfterResize = !EsRectangleEquals(targetBounds, bounds);
window->animateFromBounds = bounds;
window->targetBounds = targetBounds;
window->resetPositionOnNextMove = window->restoreOnNextMove = false;
}
@ -658,7 +665,25 @@ int ProcessWindowBorderMessage(EsWindow *window, EsMessage *message, EsRectangle
window->resetPositionOnNextMove = true;
}
if (window->animateToTargetBoundsAfterResize) {
window->animateToTargetBoundsTimeMs = 0;
window->StartAnimating();
}
gui.resizing = false;
} else if (message->type == ES_MSG_ANIMATE && window->animateToTargetBoundsAfterResize) {
double progress = window->animateToTargetBoundsTimeMs / 100.0;
window->animateToTargetBoundsTimeMs += message->animate.deltaMs;
if (progress > 1 || progress < 0) {
message->animate.complete = true;
window->animateToTargetBoundsAfterResize = false;
} else {
progress = SmoothAnimationTimeSharp(progress);
EsRectangle bounds = EsRectangleLinearInterpolate(window->animateFromBounds, window->targetBounds, progress);
EsSyscall(ES_SYSCALL_WINDOW_MOVE, window->handle, (uintptr_t) &bounds, 0, ES_WINDOW_MOVE_DYNAMIC);
message->animate.complete = false;
}
} else {
return 0;
}

View File

@ -2041,6 +2041,7 @@ function EsRectangle EsRectangleCenter(EsRectangle parent, EsRectangle child);
function EsRectangle EsRectangleCut(EsRectangle a, int32_t amount, char side);
function EsRectangle EsRectangleFit(EsRectangle parent, EsRectangle child, bool allowScalingUp); // Preserves aspect ratio.
function EsRectangle EsRectangleIntersection(EsRectangle a, EsRectangle b);
function EsRectangle EsRectangleLinearInterpolate(EsRectangle a, EsRectangle b, float progress);
function EsRectangle EsRectangleSplit(EsRectangle *a, int32_t amount, char side, int32_t gap = 0); // Same as EsRectangleCut, but the source rectangle is modified.
function EsRectangle EsRectangleSubtract(EsRectangle a, EsRectangle b);
function EsRectangle EsRectangleTranslate(EsRectangle a, EsRectangle b);
@ -2199,6 +2200,8 @@ function bool EsCRTisnanf(float f);
function int EsCRTisspace(int c);
function int EsCRTisupper(int c);
function int EsCRTisxdigit(int c);
function double EsCRTlog2(double x);
function float EsCRTlog2f(float x);
function void *EsCRTmalloc(size_t size);
function void *EsCRTmemchr(const void *_s, int _c, size_t n);
function int EsCRTmemcmp(const void *s1, const void *s2, size_t n);

View File

@ -64,6 +64,22 @@ inline int MinimumInteger(int a, int b) {
return a < b ? a : b;
}
inline float AbsoluteFloat(float f) {
return f > 0 ? f : -f;
}
inline float SignFloat(float f) {
return f < 0 ? -1 : f > 0 ? 1 : 0;
}
inline int AbsoluteInteger(int a) {
return a > 0 ? a : -a;
}
inline int64_t AbsoluteInteger64(int64_t a) {
return a > 0 ? a : -a;
}
/////////////////////////////////
// Interpolation.
/////////////////////////////////
@ -79,6 +95,18 @@ float LinearInterpolate(float from, float to, float progress) {
return from + progress * (to - from);
}
EsRectangle EsRectangleLinearInterpolate(EsRectangle from, EsRectangle to, float progress) {
return ES_RECT_4(LinearInterpolate(from.l, to.l, progress), LinearInterpolate(from.r, to.r, progress),
LinearInterpolate(from.t, to.t, progress), LinearInterpolate(from.b, to.b, progress));
}
float RubberBand(float original, float target) {
float sign = SignFloat(original - target);
float distance = AbsoluteFloat(original - target);
float amount = EsCRTlog2f(distance);
return target + sign * amount * 2.0f;
}
#ifndef KERNEL
float GammaInterpolate(float from, float to, float progress) {
from = from * from;
@ -184,18 +212,6 @@ float EsCRTfloorf(float x) {
return convert.f;
}
inline float AbsoluteFloat(float f) {
return f > 0 ? f : -f;
}
inline int AbsoluteInteger(int a) {
return a > 0 ? a : -a;
}
inline int64_t AbsoluteInteger64(int64_t a) {
return a > 0 ? a : -a;
}
double EsCRTfloor(double x) {
if (x == 0) return x;

View File

@ -155,6 +155,7 @@ EsStringAllocateAndFormat=153
EsStringAllocateAndFormatV=154
EsStringCompare=155
EsStringCompareRaw=156
EsCRTlog2=157
EsStringFormat=158
EsStringFormatTemporary=159
EsStringFormatV=160
@ -198,6 +199,7 @@ EsCRTqsort=197
EsCRTrealloc=198
EsCRTsinf=199
EsElementGetScaleFactor=200
EsCRTlog2f=201
EsCRTsqrt=202
EsCRTsqrtf=203
EsSplitterCreate=204
@ -436,3 +438,4 @@ EsUserTaskSetProgress=436
EsUserTaskIsRunning=437
EsTextboxSetFont=438
EsTextboxSetTextSize=439
EsRectangleLinearInterpolate=440