=> 859fad2c6d5013ace7fcb749b591468dd0b65612
[1mdiff --git a/CMakeLists.txt b/CMakeLists.txt[m [1mindex b71be6ab..ed064730 100644[m [1m--- a/CMakeLists.txt[m [1m+++ b/CMakeLists.txt[m [36m@@ -129,6 +129,8 @@[m [mset (SOURCES[m src/ui/command.h[m src/ui/documentwidget.c[m src/ui/documentwidget.h[m [32m+[m[32m src/ui/indicatorwidget.c[m [32m+[m[32m src/ui/indicatorwidget.h[m src/ui/listwidget.c[m src/ui/listwidget.h[m src/ui/lookupwidget.c[m [1mdiff --git a/src/ui/documentwidget.c b/src/ui/documentwidget.c[m [1mindex 1f84aed6..bdf7d282 100644[m [1m--- a/src/ui/documentwidget.c[m [1m+++ b/src/ui/documentwidget.c[m [36m@@ -30,6 +30,7 @@[m [mSOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */[m #include "gmrequest.h"[m #include "gmutil.h"[m #include "history.h"[m [32m+[m[32m#include "indicatorwidget.h"[m #include "inputwidget.h"[m #include "keys.h"[m #include "labelwidget.h"[m [36m@@ -247,6 +248,9 @@[m [mvoid init_DocumentWidget(iDocumentWidget *d) {[m addChild_Widget(w, iClob(d->scroll = new_ScrollWidget()));[m d->menu = NULL; /* created when clicking */[m d->playerMenu = NULL;[m [32m+[m[32m addChildFlags_Widget(w,[m [32m+[m[32m iClob(new_IndicatorWidget()),[m [32m+[m[32m resizeToParentWidth_WidgetFlag | resizeToParentHeight_WidgetFlag);[m #if !defined (iPlatformApple) /* in system menu */[m addAction_Widget(w, reload_KeyShortcut, "navigate.reload");[m addAction_Widget(w, SDLK_w, KMOD_PRIMARY, "tabs.close");[m [1mdiff --git a/src/ui/indicatorwidget.c b/src/ui/indicatorwidget.c[m [1mnew file mode 100644[m [1mindex 00000000..d43e23d9[m [1m--- /dev/null[m [1m+++ b/src/ui/indicatorwidget.c[m [36m@@ -0,0 +1,158 @@[m [32m+[m[32m/* Copyright 2020 Jaakko Keränen[m [32m+[m [32m+[m[32mRedistribution and use in source and binary forms, with or without[m [32m+[m[32mmodification, are permitted provided that the following conditions are met:[m [32m+[m [32m+[m[32m1. Redistributions of source code must retain the above copyright notice, this[m [32m+[m[32m list of conditions and the following disclaimer.[m [32m+[m[32m2. Redistributions in binary form must reproduce the above copyright notice,[m [32m+[m[32m this list of conditions and the following disclaimer in the documentation[m [32m+[m[32m and/or other materials provided with the distribution.[m [32m+[m [32m+[m[32mTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND[m [32m+[m[32mANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED[m [32m+[m[32mWARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE[m [32m+[m[32mDISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR[m [32m+[m[32mANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES[m [32m+[m[32m(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;[m [32m+[m[32mLOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON[m [32m+[m[32mANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT[m [32m+[m[32m(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS[m [32m+[m[32mSOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */[m [32m+[m [32m+[m[32m#include "indicatorwidget.h"[m [32m+[m[32m#include "paint.h"[m [32m+[m[32m#include "util.h"[m [32m+[m[32m#include "app.h"[m [32m+[m[32m#include "command.h"[m [32m+[m [32m+[m[32m#include [m [32m+[m [32m+[m[32mstatic int timerId_; /* common timer for all indicators */[m [32m+[m[32mstatic int animCount_; /* number of animating indicators */[m [32m+[m [32m+[m[32mstatic uint32_t postRefresh_(uint32_t interval, void *context) {[m [32m+[m[32m iUnused(context);[m [32m+[m[32m postRefresh_App();[m [32m+[m[32m return interval;[m [32m+[m[32m}[m [32m+[m [32m+[m[32mstatic void startTimer_(void) {[m [32m+[m[32m animCount_++;[m [32m+[m[32m if (!timerId_) {[m [32m+[m[32m timerId_ = SDL_AddTimer(1000 / 60, postRefresh_, NULL);[m [32m+[m[32m }[m [32m+[m[32m}[m [32m+[m [32m+[m[32mstatic void stopTimer_(void) {[m [32m+[m[32m iAssert(animCount_ > 0);[m [32m+[m[32m if (--animCount_ == 0) {[m [32m+[m[32m iAssert(timerId_);[m [32m+[m[32m SDL_RemoveTimer(timerId_);[m [32m+[m[32m timerId_ = 0;[m [32m+[m[32m }[m [32m+[m[32m}[m [32m+[m [32m+[m[32mstruct Impl_IndicatorWidget{[m [32m+[m[32m iWidget widget;[m [32m+[m[32m iAnim pos;[m [32m+[m[32m};[m [32m+[m [32m+[m[32miDefineObjectConstruction(IndicatorWidget)[m [32m+[m [32m+[m[32miLocalDef iBool isActive_IndicatorWidget_(const iIndicatorWidget *d) {[m [32m+[m[32m return isSelected_Widget(d);[m [32m+[m[32m}[m [32m+[m [32m+[m[32mstatic void setActive_IndicatorWidget_(iIndicatorWidget *d, iBool set) {[m [32m+[m[32m setFlags_Widget(as_Widget(d), selected_WidgetFlag, set);[m [32m+[m[32m}[m [32m+[m [32m+[m[32mvoid init_IndicatorWidget(iIndicatorWidget *d) {[m [32m+[m[32m iWidget *w = &d->widget;[m [32m+[m[32m init_Widget(w);[m [32m+[m[32m init_Anim(&d->pos, 0);[m [32m+[m[32m}[m [32m+[m [32m+[m[32mstatic void startTimer_IndicatorWidget_(iIndicatorWidget *d) {[m [32m+[m[32m if (!isActive_IndicatorWidget_(d)) {[m [32m+[m[32m startTimer_();[m [32m+[m[32m setActive_IndicatorWidget_(d, iTrue);[m [32m+[m[32m }[m [32m+[m[32m}[m [32m+[m [32m+[m[32mstatic void stopTimer_IndicatorWidget_(iIndicatorWidget *d) {[m [32m+[m[32m if (isActive_IndicatorWidget_(d)) {[m [32m+[m[32m stopTimer_();[m [32m+[m[32m setActive_IndicatorWidget_(d, iFalse);[m [32m+[m[32m }[m [32m+[m[32m}[m [32m+[m [32m+[m[32mvoid deinit_IndicatorWidget(iIndicatorWidget *d) {[m [32m+[m[32m stopTimer_IndicatorWidget_(d);[m [32m+[m[32m}[m [32m+[m [32m+[m[32mstatic iBool isCompleted_IndicatorWidget_(const iIndicatorWidget *d) {[m [32m+[m[32m return targetValue_Anim(&d->pos) == 1.0f;[m [32m+[m[32m}[m [32m+[m [32m+[m[32mvoid draw_IndicatorWidget_(const iIndicatorWidget *d) {[m [32m+[m[32m const float pos = value_Anim(&d->pos);[m [32m+[m[32m if (pos > 0.0f && pos < 1.0f) {[m [32m+[m[32m const iWidget *w = &d->widget;[m [32m+[m[32m const iRect rect = innerBounds_Widget(w);[m [32m+[m[32m iPaint p;[m [32m+[m[32m init_Paint(&p);[m [32m+[m[32m drawHLine_Paint(&p,[m [32m+[m[32m topLeft_Rect(rect),[m [32m+[m[32m pos * width_Rect(rect),[m [32m+[m[32m isCompleted_IndicatorWidget_(d) ? uiTextAction_ColorId[m [32m+[m[32m : uiTextCaution_ColorId);[m [32m+[m[32m }[m [32m+[m[32m}[m [32m+[m [32m+[m[32miBool processEvent_IndicatorWidget_(iIndicatorWidget *d, const SDL_Event *ev) {[m [32m+[m[32m iWidget *w = &d->widget;[m [32m+[m[32m if (ev->type == SDL_USEREVENT && ev->user.code == refresh_UserEventCode) {[m [32m+[m[32m if (isFinished_Anim(&d->pos)) {[m [32m+[m[32m stopTimer_IndicatorWidget_(d);[m [32m+[m[32m }[m [32m+[m[32m }[m [32m+[m[32m else if (isCommand_SDLEvent(ev)) {[m [32m+[m[32m const char *cmd = command_UserEvent(ev);[m [32m+[m[32m if (startsWith_CStr(cmd, "document.request.")) {[m [32m+[m[32m if (pointerLabel_Command(cmd, "doc") == parent_Widget(w)) {[m [32m+[m[32m cmd += 17;[m [32m+[m[32m if (equal_Command(cmd, "started")) {[m [32m+[m[32m setValue_Anim(&d->pos, 0, 0);[m [32m+[m[32m setValue_Anim(&d->pos, 0.75f, 4000);[m [32m+[m[32m setFlags_Anim(&d->pos, easeOut_AnimFlag, iTrue);[m [32m+[m[32m startTimer_IndicatorWidget_(d);[m [32m+[m[32m }[m [32m+[m[32m else if (equal_Command(cmd, "finished")) {[m [32m+[m[32m if (value_Anim(&d->pos) > 0.01f) {[m [32m+[m[32m setValue_Anim(&d->pos, 1.0f, 250);[m [32m+[m[32m setFlags_Anim(&d->pos, easeOut_AnimFlag, iFalse);[m [32m+[m[32m startTimer_IndicatorWidget_(d);[m [32m+[m[32m }[m [32m+[m[32m else {[m [32m+[m[32m setValue_Anim(&d->pos, 0, 0);[m [32m+[m[32m stopTimer_IndicatorWidget_(d);[m [32m+[m[32m refresh_Widget(d);[m [32m+[m[32m }[m [32m+[m[32m }[m [32m+[m[32m else if (equal_Command(cmd, "cancelled")) {[m [32m+[m[32m setValue_Anim(&d->pos, 0, 0);[m [32m+[m[32m stopTimer_IndicatorWidget_(d);[m [32m+[m[32m refresh_Widget(d);[m [32m+[m[32m }[m [32m+[m[32m }[m [32m+[m[32m }[m [32m+[m[32m }[m [32m+[m[32m return iFalse;[m [32m+[m[32m}[m [32m+[m [32m+[m[32miBeginDefineSubclass(IndicatorWidget, Widget)[m [32m+[m[32m .draw = (iAny *) draw_IndicatorWidget_,[m [32m+[m[32m .processEvent = (iAny *) processEvent_IndicatorWidget_,[m [32m+[m[32miEndDefineSubclass(IndicatorWidget)[m [1mdiff --git a/src/ui/indicatorwidget.h b/src/ui/indicatorwidget.h[m [1mnew file mode 100644[m [1mindex 00000000..a3d9af39[m [1m--- /dev/null[m [1m+++ b/src/ui/indicatorwidget.h[m [36m@@ -0,0 +1,28 @@[m [32m+[m[32m/* Copyright 2020 Jaakko Keränen [m [32m+[m [32m+[m[32mRedistribution and use in source and binary forms, with or without[m [32m+[m[32mmodification, are permitted provided that the following conditions are met:[m [32m+[m [32m+[m[32m1. Redistributions of source code must retain the above copyright notice, this[m [32m+[m[32m list of conditions and the following disclaimer.[m [32m+[m[32m2. Redistributions in binary form must reproduce the above copyright notice,[m [32m+[m[32m this list of conditions and the following disclaimer in the documentation[m [32m+[m[32m and/or other materials provided with the distribution.[m [32m+[m [32m+[m[32mTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND[m [32m+[m[32mANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED[m [32m+[m[32mWARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE[m [32m+[m[32mDISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR[m [32m+[m[32mANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES[m [32m+[m[32m(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;[m [32m+[m[32mLOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON[m [32m+[m[32mANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT[m [32m+[m[32m(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS[m [32m+[m[32mSOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */[m [32m+[m [32m+[m[32m#pragma once[m [32m+[m [32m+[m[32m#include "widget.h"[m [32m+[m [32m+[m[32miDeclareWidgetClass(IndicatorWidget)[m [32m+[m[32miDeclareObjectConstruction(IndicatorWidget)[m [1mdiff --git a/src/ui/util.c b/src/ui/util.c[m [1mindex 38124b22..27950c5e 100644[m [1m--- a/src/ui/util.c[m [1m+++ b/src/ui/util.c[m [36m@@ -135,54 +135,15 @@[m [miBool isFinished_Anim(const iAnim *d) {[m }[m [m void init_Anim(iAnim *d, float value) {[m [31m- d->due = d->when = SDL_GetTicks(); // frameTime_Window(get_Window());[m [32m+[m[32m d->due = d->when = SDL_GetTicks();[m d->from = d->to = value;[m d->flags = 0;[m }[m [m [31m-void setValue_Anim(iAnim *d, float to, uint32_t span) {[m [31m- if (fabsf(to - d->to) > 0.00001f) {[m [31m- const uint32_t now = SDL_GetTicks();[m [31m- d->from = value_Anim(d);[m [31m- d->to = to;[m [31m- d->when = now;[m [31m- d->due = now + span;[m [31m- }[m [31m-}[m [31m-[m iLocalDef float pos_Anim_(const iAnim *d, uint32_t now) {[m return (float) (now - d->when) / (float) (d->due - d->when);[m }[m [m [31m-void setValueEased_Anim(iAnim *d, float to, uint32_t span) {[m [31m- if (fabsf(to - d->to) <= 0.00001f) {[m [31m- d->to = to; /* Pretty much unchanged. */[m [31m- return;[m [31m- }[m [31m- const uint32_t now = SDL_GetTicks();[m [31m- if (isFinished_Anim(d)) {[m [31m- d->from = d->to;[m [31m- d->when = now;[m [31m- d->flags = easeBoth_AnimFlag;[m [31m- }[m [31m- else {[m [31m- d->from = value_Anim(d);[m [31m- d->when = frameTime_Window(get_Window()); /* to match the timing of value_Anim */[m [31m- d->flags = easeOut_AnimFlag;[m [31m- }[m [31m- d->to = to;[m [31m- d->due = now + span;[m [31m-}[m [31m-[m [31m-void setFlags_Anim(iAnim *d, int flags, iBool set) {[m [31m- iChangeFlags(d->flags, flags, set);[m [31m-}[m [31m-[m [31m-void stop_Anim(iAnim *d) {[m [31m- d->from = d->to = value_Anim(d);[m [31m- d->when = d->due = SDL_GetTicks();[m [31m-}[m [31m-[m iLocalDef float easeIn_(float t) {[m return t * t;[m }[m [36m@@ -198,8 +159,7 @@[m [miLocalDef float easeBoth_(float t) {[m return 0.5f + easeOut_((t - 0.5f) * 2.0f) * 0.5f;[m }[m [m [31m-float value_Anim(const iAnim *d) {[m [31m- const uint32_t now = frameTime_Window(get_Window());[m [32m+[m[32mstatic float valueAt_Anim_(const iAnim *d, const uint32_t now) {[m if (now >= d->due) {[m return d->to;[m }[m [36m@@ -219,6 +179,52 @@[m [mfloat value_Anim(const iAnim *d) {[m return d->from * (1.0f - t) + d->to * t;[m }[m [m [32m+[m[32mvoid setValue_Anim(iAnim *d, float to, uint32_t span) {[m [32m+[m[32m if (span == 0) {[m [32m+[m[32m d->from = d->to = to;[m [32m+[m[32m d->when = d->due = SDL_GetTicks();[m [32m+[m[32m }[m [32m+[m[32m else if (fabsf(to - d->to) > 0.00001f) {[m [32m+[m[32m const uint32_t now = SDL_GetTicks();[m [32m+[m[32m d->from = valueAt_Anim_(d, now);[m [32m+[m[32m d->to = to;[m [32m+[m[32m d->when = now;[m [32m+[m[32m d->due = now + span;[m [32m+[m[32m }[m [32m+[m[32m}[m [32m+[m [32m+[m[32mvoid setValueEased_Anim(iAnim *d, float to, uint32_t span) {[m [32m+[m[32m if (fabsf(to - d->to) <= 0.00001f) {[m [32m+[m[32m d->to = to; /* Pretty much unchanged. */[m [32m+[m[32m return;[m [32m+[m[32m }[m [32m+[m[32m const uint32_t now = SDL_GetTicks();[m [32m+[m[32m if (isFinished_Anim(d)) {[m [32m+[m[32m d->from = d->to;[m [32m+[m[32m d->flags = easeBoth_AnimFlag;[m [32m+[m[32m }[m [32m+[m[32m else {[m [32m+[m[32m d->from = valueAt_Anim_(d, now);[m [32m+[m[32m d->flags = easeOut_AnimFlag;[m [32m+[m[32m }[m [32m+[m[32m d->to = to;[m [32m+[m[32m d->when = now;[m [32m+[m[32m d->due = now + span;[m [32m+[m[32m}[m [32m+[m [32m+[m[32mvoid setFlags_Anim(iAnim *d, int flags, iBool set) {[m [32m+[m[32m iChangeFlags(d->flags, flags, set);[m [32m+[m[32m}[m [32m+[m [32m+[m[32mvoid stop_Anim(iAnim *d) {[m [32m+[m[32m d->from = d->to = value_Anim(d);[m [32m+[m[32m d->when = d->due = SDL_GetTicks();[m [32m+[m[32m}[m [32m+[m [32m+[m[32mfloat value_Anim(const iAnim *d) {[m [32m+[m[32m return valueAt_Anim_(d, frameTime_Window(get_Window()));[m [32m+[m[32m}[m [32m+[m /*-----------------------------------------------------------------------------------------------*/[m [m void init_Click(iClick *d, iAnyObject *widget, int button) {[m [1mdiff --git a/src/ui/widget.h b/src/ui/widget.h[m [1mindex f39612ed..a1a38f28 100644[m [1m--- a/src/ui/widget.h[m [1m+++ b/src/ui/widget.h[m [36m@@ -160,6 +160,13 @@[m [miLocalDef iObjectList *children_Widget(iAnyObject *d) {[m iAssert(isInstance_Object(d, &Class_Widget));[m return ((iWidget *) d)->children;[m }[m [32m+[m[32miLocalDef iWidget *parent_Widget(const iAnyObject *d) {[m [32m+[m[32m if (d) {[m [32m+[m[32m iAssert(isInstance_Object(d, &Class_Widget));[m [32m+[m[32m return ((iWidget *) d)->parent;[m [32m+[m[32m }[m [32m+[m[32m return NULL;[m [32m+[m[32m}[m [m iBool isVisible_Widget (const iAnyObject *);[m iBool isDisabled_Widget (const iAnyObject *);[m
text/gemini; charset=utf-8
This content has been proxied by September (ba2dc).