summaryrefslogtreecommitdiff
path: root/src/ui
diff options
context:
space:
mode:
Diffstat (limited to 'src/ui')
-rw-r--r--src/ui/banner.c55
-rw-r--r--src/ui/documentwidget.c19
2 files changed, 58 insertions, 16 deletions
diff --git a/src/ui/banner.c b/src/ui/banner.c
index e817f1bb..cb30d8c5 100644
--- a/src/ui/banner.c
+++ b/src/ui/banner.c
@@ -56,6 +56,8 @@ struct Impl_Banner {
56 iString icon; 56 iString icon;
57 int siteHeight; 57 int siteHeight;
58 iArray items; 58 iArray items;
59 iBool isHover;
60 size_t hoverIndex;
59 iBool isClick; 61 iBool isClick;
60}; 62};
61 63
@@ -91,6 +93,8 @@ void init_Banner(iBanner *d) {
91 init_String(&d->icon); 93 init_String(&d->icon);
92 init_Array(&d->items, sizeof(iBannerItem)); 94 init_Array(&d->items, sizeof(iBannerItem));
93 d->isClick = iFalse; 95 d->isClick = iFalse;
96 d->isHover = iFalse;
97 d->hoverIndex = iInvalidPos;
94} 98}
95 99
96void deinit_Banner(iBanner *d) { 100void deinit_Banner(iBanner *d) {
@@ -222,7 +226,12 @@ void draw_Banner(const iBanner *d) {
222 const iBannerItem *item = i.value; 226 const iBannerItem *item = i.value;
223 const iRect itemRect = { pos, init_I2(d->rect.size.x, item->height) }; 227 const iRect itemRect = { pos, init_I2(d->rect.size.x, item->height) };
224 fillRect_Paint(&p, itemRect, tmBannerItemBackground_ColorId); 228 fillRect_Paint(&p, itemRect, tmBannerItemBackground_ColorId);
225 drawRect_Paint(&p, itemRect, tmBannerItemFrame_ColorId); 229 drawRect_Paint(&p,
230 itemRect,
231 item->type == warning_BannerType && d->isHover &&
232 d->hoverIndex == index_ArrayConstIterator(&i)
233 ? tmBannerItemText_ColorId
234 : tmBannerItemFrame_ColorId);
226 setBaseAttributes_Text(uiContent_FontId, tmBannerItemText_ColorId); 235 setBaseAttributes_Text(uiContent_FontId, tmBannerItemText_ColorId);
227 iWrapText wt = { 236 iWrapText wt = {
228 .text = range_String(&item->text), 237 .text = range_String(&item->text),
@@ -251,11 +260,22 @@ static size_t itemAtCoord_Banner_(const iBanner *d, iInt2 coord) {
251iBool processEvent_Banner(iBanner *d, const SDL_Event *ev) { 260iBool processEvent_Banner(iBanner *d, const SDL_Event *ev) {
252 iWidget *w = as_Widget(d->doc); 261 iWidget *w = as_Widget(d->doc);
253 switch (ev->type) { 262 switch (ev->type) {
254 case SDL_MOUSEMOTION: 263 case SDL_MOUSEMOTION: {
255 if (contains_Rect(d->rect, init_I2(ev->motion.x, ev->motion.y))) { 264 const iInt2 coord = init_I2(ev->motion.x, ev->motion.y);
265 const iBool isInside = contains_Rect(d->rect, coord);
266 if (isInside) {
256 setCursor_Window(window_Widget(w), SDL_SYSTEM_CURSOR_HAND); 267 setCursor_Window(window_Widget(w), SDL_SYSTEM_CURSOR_HAND);
257 } 268 }
269 if (isInside ^ d->isHover) {
270 d->isHover = isInside;
271 }
272 const size_t at = d->isHover ? itemAtCoord_Banner_(d, coord) : iInvalidPos;
273 if (at != d->hoverIndex) {
274 d->hoverIndex = at;
275 refresh_Widget(w);
276 }
258 break; 277 break;
278 }
259 case SDL_MOUSEBUTTONDOWN: 279 case SDL_MOUSEBUTTONDOWN:
260 case SDL_MOUSEBUTTONUP: 280 case SDL_MOUSEBUTTONUP:
261 /* Clicking on the top/side banner navigates to site root. */ 281 /* Clicking on the top/side banner navigates to site root. */
@@ -276,6 +296,7 @@ iBool processEvent_Banner(iBanner *d, const SDL_Event *ev) {
276 } 296 }
277 else { 297 else {
278 const iBannerItem *item = constAt_Array(&d->items, index); 298 const iBannerItem *item = constAt_Array(&d->items, index);
299 d->isHover = iFalse;
279 if (item->type == error_BannerType) { 300 if (item->type == error_BannerType) {
280 postCommand_Widget(d->doc, "document.info"); 301 postCommand_Widget(d->doc, "document.info");
281 } 302 }
@@ -285,17 +306,23 @@ iBool processEvent_Banner(iBanner *d, const SDL_Event *ev) {
285 postCommandf_App("open newtab:1 url:about:fonts"); 306 postCommandf_App("open newtab:1 url:about:fonts");
286 break; 307 break;
287 case ansiEscapes_GmStatusCode: 308 case ansiEscapes_GmStatusCode:
288 makeQuestion_Widget(uiHeading_ColorEscape "${heading.dismiss.warning}", 309 makeQuestion_Widget(
289 format_Lang("${dlg.dismiss.ansi}", 310 uiHeading_ColorEscape "${heading.dismiss.warning}",
290 format_CStr(uiTextStrong_ColorEscape "%s" 311 format_Lang(
291 restore_ColorEscape, cstr_Rangecc(urlHost_String(url_DocumentWidget(d->doc))))), 312 "${dlg.dismiss.ansi}",
292 (iMenuItem[]){ { "${cancel}" }, 313 format_CStr(uiTextStrong_ColorEscape
293 { uiTextAction_ColorEscape "${dlg.dismiss.warning}", 314 "%s" restore_ColorEscape,
294 SDLK_RETURN, 0, 315 cstr_Rangecc(urlHost_String(
295 format_CStr("document.dismiss warning:%d", 316 url_DocumentWidget(d->doc))))),
296 ansiEscapes_GmDocumentWarning) 317 (iMenuItem[]){
297 } 318 { "${cancel}" },
298 }, 2); 319 { uiTextAction_ColorEscape "${dlg.dismiss.warning}",
320 SDLK_RETURN,
321 0,
322 format_CStr("!document.dismiss warning:%d ptr:%p",
323 ansiEscapes_GmDocumentWarning,
324 d->doc) } },
325 2);
299 break; 326 break;
300 default: 327 default:
301 postCommand_Widget(d->doc, "document.info"); 328 postCommand_Widget(d->doc, "document.info");
diff --git a/src/ui/documentwidget.c b/src/ui/documentwidget.c
index 755cec6a..7e7a2983 100644
--- a/src/ui/documentwidget.c
+++ b/src/ui/documentwidget.c
@@ -47,6 +47,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
47#include "root.h" 47#include "root.h"
48#include "mediaui.h" 48#include "mediaui.h"
49#include "scrollwidget.h" 49#include "scrollwidget.h"
50#include "sitespec.h"
50#include "touch.h" 51#include "touch.h"
51#include "translation.h" 52#include "translation.h"
52#include "uploadwidget.h" 53#include "uploadwidget.h"
@@ -1798,11 +1799,14 @@ static void cacheDocumentGlyphs_DocumentWidget_(const iDocumentWidget *d) {
1798} 1799}
1799 1800
1800static void addBannerWarnings_DocumentWidget_(iDocumentWidget *d) { 1801static void addBannerWarnings_DocumentWidget_(iDocumentWidget *d) {
1801 if (warnings_GmDocument(d->doc) & missingGlyphs_GmDocumentWarning) { 1802 const int dismissed = value_SiteSpec(collectNewRange_String(urlRoot_String(d->mod.url)),
1803 dismissWarnings_SiteSpecKey);
1804 const int warnings = warnings_GmDocument(d->doc) & ~dismissed;
1805 if (warnings & missingGlyphs_GmDocumentWarning) {
1802 add_Banner(d->banner, warning_BannerType, missingGlyphs_GmStatusCode, NULL); 1806 add_Banner(d->banner, warning_BannerType, missingGlyphs_GmStatusCode, NULL);
1803 /* TODO: List one or more of the missing characters and/or their Unicode blocks? */ 1807 /* TODO: List one or more of the missing characters and/or their Unicode blocks? */
1804 } 1808 }
1805 if (warnings_GmDocument(d->doc) & ansiEscapes_GmDocumentWarning) { 1809 if (warnings & ansiEscapes_GmDocumentWarning) {
1806 add_Banner(d->banner, warning_BannerType, ansiEscapes_GmStatusCode, NULL); 1810 add_Banner(d->banner, warning_BannerType, ansiEscapes_GmStatusCode, NULL);
1807 } 1811 }
1808} 1812}
@@ -3383,6 +3387,17 @@ static iBool handleCommand_DocumentWidget_(iDocumentWidget *d, const char *cmd)
3383 else if (equal_Command(cmd, "document.autoreload.set") && document_App() == d) { 3387 else if (equal_Command(cmd, "document.autoreload.set") && document_App() == d) {
3384 d->mod.reloadInterval = arg_Command(cmd); 3388 d->mod.reloadInterval = arg_Command(cmd);
3385 } 3389 }
3390 else if (equalWidget_Command(cmd, w, "document.dismiss")) {
3391 const iString *site = collectNewRange_String(urlRoot_String(d->mod.url));
3392 const int dismissed = value_SiteSpec(site, dismissWarnings_SiteSpecKey);
3393 const int arg = argLabel_Command(cmd, "warning");
3394 setValue_SiteSpec(site, dismissWarnings_SiteSpecKey, dismissed | arg);
3395 if (arg == ansiEscapes_GmDocumentWarning) {
3396 remove_Banner(d->banner, ansiEscapes_GmStatusCode);
3397 refresh_Widget(w);
3398 }
3399 return iTrue;
3400 }
3386 else if (startsWith_CStr(cmd, "pinch.") && document_Command(cmd) == d) { 3401 else if (startsWith_CStr(cmd, "pinch.") && document_Command(cmd) == d) {
3387 return handlePinch_DocumentWidget_(d, cmd); 3402 return handlePinch_DocumentWidget_(d, cmd);
3388 } 3403 }