summaryrefslogtreecommitdiff
path: root/src/ui
diff options
context:
space:
mode:
Diffstat (limited to 'src/ui')
-rw-r--r--src/ui/documentwidget.c172
-rw-r--r--src/ui/listwidget.c51
2 files changed, 56 insertions, 167 deletions
diff --git a/src/ui/documentwidget.c b/src/ui/documentwidget.c
index 2dd50e5b..9b6ad509 100644
--- a/src/ui/documentwidget.c
+++ b/src/ui/documentwidget.c
@@ -128,42 +128,6 @@ void deserialize_Model(iModel *d, iStream *ins) {
128 128
129iDefineTypeConstruction(Model) 129iDefineTypeConstruction(Model)
130 130
131#if 0
132/*----------------------------------------------------------------------------------------------*/
133
134iDeclareType(VisBuffer)
135iDeclareTypeConstruction(VisBuffer)
136
137struct Impl_VisBuffer {
138 SDL_Texture * texture[2];
139 int index;
140 iInt2 size;
141 iRangei validRange;
142};
143
144void init_VisBuffer(iVisBuffer *d) {
145 iZap(*d);
146}
147
148void deinit_VisBuffer(iVisBuffer *d) {
149 iForIndices(i, d->texture) {
150 if (d->texture[i]) {
151 SDL_DestroyTexture(d->texture[i]);
152 }
153 }
154}
155
156void dealloc_VisBuffer(iVisBuffer *d) {
157 d->size = zero_I2();
158 iZap(d->validRange);
159 iForIndices(i, d->texture) {
160 SDL_DestroyTexture(d->texture[i]);
161 d->texture[i] = NULL;
162 }
163}
164
165iDefineTypeConstruction(VisBuffer)
166#endif
167/*----------------------------------------------------------------------------------------------*/ 131/*----------------------------------------------------------------------------------------------*/
168 132
169static const int smoothSpeed_DocumentWidget_ = 120; /* unit: gap_Text per second */ 133static const int smoothSpeed_DocumentWidget_ = 120; /* unit: gap_Text per second */
@@ -313,16 +277,6 @@ static int forceBreakWidth_DocumentWidget_(const iDocumentWidget *d) {
313 return 0; 277 return 0;
314} 278}
315 279
316iLocalDef int documentToWindowY_DocumentWidget_(const iDocumentWidget *d, int docY) {
317 return docY - d->scrollY + documentBounds_DocumentWidget_(d).pos.y;
318}
319
320#if 0
321iLocalDef int windowToDocumentY_DocumentWidget_(const iDocumentWidget *d, int localY) {
322 return localY + d->scrollY - documentBounds_DocumentWidget_(d).pos.y;
323}
324#endif
325
326static iInt2 documentPos_DocumentWidget_(const iDocumentWidget *d, iInt2 pos) { 280static iInt2 documentPos_DocumentWidget_(const iDocumentWidget *d, iInt2 pos) {
327 return addY_I2(sub_I2(pos, topLeft_Rect(documentBounds_DocumentWidget_(d))), d->scrollY); 281 return addY_I2(sub_I2(pos, topLeft_Rect(documentBounds_DocumentWidget_(d))), d->scrollY);
328} 282}
@@ -1585,15 +1539,7 @@ static iBool processEvent_DocumentWidget_(iDocumentWidget *d, const SDL_Event *e
1585 1539
1586iDeclareType(DrawContext) 1540iDeclareType(DrawContext)
1587 1541
1588#if 0
1589enum iDrawRunPass {
1590 static_DrawRunPass,
1591 dynamic_DrawRunPass,
1592};
1593#endif
1594
1595struct Impl_DrawContext { 1542struct Impl_DrawContext {
1596// enum iDrawRunPass pass;
1597 const iDocumentWidget *widget; 1543 const iDocumentWidget *widget;
1598 iRect widgetBounds; 1544 iRect widgetBounds;
1599 iInt2 viewPos; /* document area origin */ 1545 iInt2 viewPos; /* document area origin */
@@ -1644,35 +1590,21 @@ static void drawRun_DrawContext_(void *context, const iGmRun *run) {
1644 iDrawContext *d = context; 1590 iDrawContext *d = context;
1645 const iInt2 origin = d->viewPos; 1591 const iInt2 origin = d->viewPos;
1646 if (run->imageId) { 1592 if (run->imageId) {
1647 /*if (d->pass == static_DrawRunPass)*/ { 1593 SDL_Texture *tex = imageTexture_GmDocument(d->widget->doc, run->imageId);
1648 SDL_Texture *tex = imageTexture_GmDocument(d->widget->doc, run->imageId); 1594 if (tex) {
1649 if (tex) { 1595 const iRect dst = moved_Rect(run->visBounds, origin);
1650 const iRect dst = moved_Rect(run->visBounds, origin); 1596 SDL_RenderCopy(d->paint.dst->render, tex, NULL,
1651 SDL_RenderCopy(d->paint.dst->render, tex, NULL, 1597 &(SDL_Rect){ dst.pos.x, dst.pos.y, dst.size.x, dst.size.y });
1652 &(SDL_Rect){ dst.pos.x, dst.pos.y, dst.size.x, dst.size.y });
1653 }
1654 } 1598 }
1655 return; 1599 return;
1656 } 1600 }
1657 enum iColorId fg = run->color; 1601 enum iColorId fg = run->color;
1658 const iGmDocument *doc = d->widget->doc; 1602 const iGmDocument *doc = d->widget->doc;
1659 /* Matches the current drawing pass? */ 1603 const iBool isHover =
1660// const iBool isDynamic = (run->linkId && ~run->flags & decoration_GmRunFlag);
1661// if (isDynamic ^ (d->pass == dynamic_DrawRunPass)) {
1662// return;
1663// }
1664 const iBool isHover =
1665 (run->linkId && d->widget->hoverLink && run->linkId == d->widget->hoverLink->linkId && 1604 (run->linkId && d->widget->hoverLink && run->linkId == d->widget->hoverLink->linkId &&
1666 ~run->flags & decoration_GmRunFlag); 1605 ~run->flags & decoration_GmRunFlag);
1667 const iInt2 visPos = add_I2(run->visBounds.pos, origin); 1606 const iInt2 visPos = add_I2(run->visBounds.pos, origin);
1668 fillRect_Paint(&d->paint, 1607 fillRect_Paint(&d->paint, (iRect){ visPos, run->visBounds.size }, tmBackground_ColorId);
1669 (iRect){ visPos,
1670 /* Links have additional hover info on the right side. */
1671// init_I2(run->linkId && ~run->flags & decoration_GmRunFlag
1672// ? d->widgetBounds.size.x - visPos.x :
1673 init_I2(run->visBounds.size.x,
1674 run->visBounds.size.y) },
1675 tmBackground_ColorId);
1676 if (run->linkId && ~run->flags & decoration_GmRunFlag) { 1608 if (run->linkId && ~run->flags & decoration_GmRunFlag) {
1677 fg = linkColor_GmDocument(doc, run->linkId, isHover ? textHover_GmLinkPart : text_GmLinkPart); 1609 fg = linkColor_GmDocument(doc, run->linkId, isHover ? textHover_GmLinkPart : text_GmLinkPart);
1678 if (linkFlags_GmDocument(doc, run->linkId) & content_GmLinkFlag) { 1610 if (linkFlags_GmDocument(doc, run->linkId) & content_GmLinkFlag) {
@@ -1680,42 +1612,40 @@ static void drawRun_DrawContext_(void *context, const iGmRun *run) {
1680 } 1612 }
1681 } 1613 }
1682 if (run->flags & siteBanner_GmRunFlag) { 1614 if (run->flags & siteBanner_GmRunFlag) {
1683 /*if (d->pass == static_DrawRunPass)*/ { 1615 /* Draw the site banner. */
1684 /* Draw the site banner. */ 1616 fillRect_Paint(
1685 fillRect_Paint( 1617 &d->paint,
1686 &d->paint, 1618 initCorners_Rect(topLeft_Rect(d->widgetBounds),
1687 initCorners_Rect(topLeft_Rect(d->widgetBounds), 1619 init_I2(right_Rect(bounds_Widget(constAs_Widget(d->widget))),
1688 init_I2(right_Rect(bounds_Widget(constAs_Widget(d->widget))), 1620 visPos.y + height_Rect(run->visBounds))),
1689 visPos.y + height_Rect(run->visBounds))), 1621 tmBannerBackground_ColorId);
1690 tmBannerBackground_ColorId); 1622 const iChar icon = siteIcon_GmDocument(doc);
1691 const iChar icon = siteIcon_GmDocument(doc); 1623 iString bannerText;
1692 iString bannerText; 1624 init_String(&bannerText);
1693 init_String(&bannerText); 1625 iInt2 bpos = add_I2(visPos, init_I2(0, lineHeight_Text(banner_FontId) / 2));
1694 iInt2 bpos = add_I2(visPos, init_I2(0, lineHeight_Text(banner_FontId) / 2)); 1626 if (icon) {
1695 if (icon) { 1627// appendChar_String(&bannerText, 0x2b24); // icon);
1696// appendChar_String(&bannerText, 0x2b24); // icon); 1628// const iRect iconRect = visualBounds_Text(hugeBold_FontId, range_String(&bannerText));
1697// const iRect iconRect = visualBounds_Text(hugeBold_FontId, range_String(&bannerText)); 1629// drawRange_Text(hugeBold_FontId, /*run->font,*/
1698// drawRange_Text(hugeBold_FontId, /*run->font,*/ 1630// addY_I2(bpos, -mid_Rect(iconRect).y + lineHeight_Text(run->font) / 2),
1699// addY_I2(bpos, -mid_Rect(iconRect).y + lineHeight_Text(run->font) / 2), 1631// tmBannerIcon_ColorId,
1700// tmBannerIcon_ColorId, 1632// range_String(&bannerText));
1701// range_String(&bannerText)); 1633// clear_String(&bannerText);
1702// clear_String(&bannerText); 1634 appendChar_String(&bannerText, icon);
1703 appendChar_String(&bannerText, icon); 1635 const iRect iconRect = visualBounds_Text(run->font, range_String(&bannerText));
1704 const iRect iconRect = visualBounds_Text(run->font, range_String(&bannerText)); 1636 drawRange_Text(
1705 drawRange_Text( 1637 run->font,
1706 run->font, 1638 addY_I2(bpos, -mid_Rect(iconRect).y + lineHeight_Text(run->font) / 2),
1707 addY_I2(bpos, -mid_Rect(iconRect).y + lineHeight_Text(run->font) / 2), 1639 tmBannerIcon_ColorId,
1708 tmBannerIcon_ColorId, 1640 range_String(&bannerText));
1709 range_String(&bannerText)); 1641 bpos.x += right_Rect(iconRect) + 3 * gap_Text;
1710 bpos.x += right_Rect(iconRect) + 3 * gap_Text; 1642 }
1711 } 1643 drawRange_Text(run->font,
1712 drawRange_Text(run->font, 1644 bpos,
1713 bpos, 1645 tmBannerTitle_ColorId,
1714 tmBannerTitle_ColorId, 1646 isEmpty_String(d->widget->titleUser) ? run->text
1715 isEmpty_String(d->widget->titleUser) ? run->text 1647 : range_String(d->widget->titleUser));
1716 : range_String(d->widget->titleUser)); 1648 deinit_String(&bannerText);
1717 deinit_String(&bannerText);
1718 }
1719 } 1649 }
1720 else { 1650 else {
1721 if (d->showLinkNumbers && run->linkId && run->flags & decoration_GmRunFlag) { 1651 if (d->showLinkNumbers && run->linkId && run->flags & decoration_GmRunFlag) {
@@ -1734,7 +1664,7 @@ static void drawRun_DrawContext_(void *context, const iGmRun *run) {
1734 runDrawn:; 1664 runDrawn:;
1735 } 1665 }
1736 /* Presentation of links. */ 1666 /* Presentation of links. */
1737 if (run->linkId && ~run->flags & decoration_GmRunFlag/* && d->pass == dynamic_DrawRunPass*/) { 1667 if (run->linkId && ~run->flags & decoration_GmRunFlag) {
1738 const int metaFont = paragraph_FontId; 1668 const int metaFont = paragraph_FontId;
1739 /* TODO: Show status of an ongoing media request. */ 1669 /* TODO: Show status of an ongoing media request. */
1740 const int flags = linkFlags_GmDocument(doc, run->linkId); 1670 const int flags = linkFlags_GmDocument(doc, run->linkId);
@@ -1908,6 +1838,15 @@ static void draw_DocumentWidget_(const iDocumentWidget *d) {
1908 setClip_Paint(&ctx.paint, bounds); 1838 setClip_Paint(&ctx.paint, bounds);
1909 const int yTop = docBounds.pos.y - d->scrollY; 1839 const int yTop = docBounds.pos.y - d->scrollY;
1910 draw_VisBuf(visBuf, init_I2(bounds.pos.x, yTop)); 1840 draw_VisBuf(visBuf, init_I2(bounds.pos.x, yTop));
1841 /* Text markers. */
1842 if (!isEmpty_Range(&d->foundMark) || !isEmpty_Range(&d->selectMark)) {
1843 SDL_SetRenderDrawBlendMode(renderer_Window(get_Window()),
1844 isDark_ColorTheme(colorTheme_App()) ? SDL_BLENDMODE_ADD
1845 : SDL_BLENDMODE_BLEND);
1846 ctx.viewPos = topLeft_Rect(docBounds);
1847 render_GmDocument(d->doc, vis, drawMark_DrawContext_, &ctx);
1848 SDL_SetRenderDrawBlendMode(renderer_Window(get_Window()), SDL_BLENDMODE_NONE);
1849 }
1911 unsetClip_Paint(&ctx.paint); 1850 unsetClip_Paint(&ctx.paint);
1912 /* Fill the top and bottom, in case the document is short. */ 1851 /* Fill the top and bottom, in case the document is short. */
1913 if (yTop > top_Rect(bounds)) { 1852 if (yTop > top_Rect(bounds)) {
@@ -1922,15 +1861,6 @@ static void draw_DocumentWidget_(const iDocumentWidget *d) {
1922 init_Rect(bounds.pos.x, yBottom, bounds.size.x, bottom_Rect(bounds) - yBottom), 1861 init_Rect(bounds.pos.x, yBottom, bounds.size.x, bottom_Rect(bounds) - yBottom),
1923 tmBackground_ColorId); 1862 tmBackground_ColorId);
1924 } 1863 }
1925 /* Text markers. */
1926 if (!isEmpty_Range(&d->foundMark) || !isEmpty_Range(&d->selectMark)) {
1927 SDL_SetRenderDrawBlendMode(renderer_Window(get_Window()),
1928 isDark_ColorTheme(colorTheme_App()) ? SDL_BLENDMODE_ADD
1929 : SDL_BLENDMODE_BLEND);
1930 ctx.viewPos = topLeft_Rect(docBounds);
1931 render_GmDocument(d->doc, vis, drawMark_DrawContext_, &ctx);
1932 SDL_SetRenderDrawBlendMode(renderer_Window(get_Window()), SDL_BLENDMODE_NONE);
1933 }
1934 draw_Widget(w); 1864 draw_Widget(w);
1935} 1865}
1936 1866
diff --git a/src/ui/listwidget.c b/src/ui/listwidget.c
index b10bf8c3..fb328c2f 100644
--- a/src/ui/listwidget.c
+++ b/src/ui/listwidget.c
@@ -302,31 +302,6 @@ static iBool processEvent_ListWidget_(iListWidget *d, const SDL_Event *ev) {
302 return processEvent_Widget(w, ev); 302 return processEvent_Widget(w, ev);
303} 303}
304 304
305#if 0
306static void allocVisBuffer_ListWidget_(iListWidget *d) {
307 /* Make sure two buffers cover the entire visible area. */
308// const iRect inner = innerBounds_Widget(as_Widget(d));
309 const iInt2 size = init_I2(inner.size.x, (inner.size.y / 2 / d->itemHeight + 1) * d->itemHeight);
310 if (!d->visBuffers[0].texture || !isEqual_I2(size, d->visBufSize)) {
311 d->visBufSize = size;
312 iForIndices(i, d->visBuffers) {
313 if (d->visBuffers[i].texture) {
314 SDL_DestroyTexture(d->visBuffers[i].texture);
315 }
316 d->visBuffers[i].texture =
317 SDL_CreateTexture(renderer_Window(get_Window()),
318 SDL_PIXELFORMAT_RGBA8888,
319 SDL_TEXTUREACCESS_STATIC | SDL_TEXTUREACCESS_TARGET,
320 size.x,
321 size.y);
322 SDL_SetTextureBlendMode(d->visBuffers[i].texture, SDL_BLENDMODE_NONE);
323 d->visBuffers[i].origin = i * size.y;
324 iZap(d->visBuffers[i].validRange);
325 }
326 }
327}
328#endif
329
330static void drawItem_ListWidget_(const iListWidget *d, iPaint *p, size_t index, iInt2 pos) { 305static void drawItem_ListWidget_(const iListWidget *d, iPaint *p, size_t index, iInt2 pos) {
331 const iWidget * w = constAs_Widget(d); 306 const iWidget * w = constAs_Widget(d);
332 const iRect bounds = innerBounds_Widget(w); 307 const iRect bounds = innerBounds_Widget(w);
@@ -340,15 +315,14 @@ static const iListItem *item_ListWidget_(const iListWidget *d, size_t pos) {
340} 315}
341 316
342static void draw_ListWidget_(const iListWidget *d) { 317static void draw_ListWidget_(const iListWidget *d) {
343 const iWidget *w = constAs_Widget(d); 318 const iWidget *w = constAs_Widget(d);
344 const iRect bounds = innerBounds_Widget(w); 319 const iRect bounds = innerBounds_Widget(w);
345 if (!bounds.size.y || !bounds.size.x || !d->itemHeight) { 320 if (!bounds.size.y || !bounds.size.x || !d->itemHeight) {
346 return; 321 return;
347 } 322 }
348 iPaint p; 323 iPaint p;
349 init_Paint(&p); 324 init_Paint(&p);
350 drawBackground_Widget(w); 325 drawBackground_Widget(w);
351// iListWidget *m = iConstCast(iListWidget *, d);
352 alloc_VisBuf(d->visBuf, bounds.size, d->itemHeight); 326 alloc_VisBuf(d->visBuf, bounds.size, d->itemHeight);
353 /* Update invalid regions/items. */ { 327 /* Update invalid regions/items. */ {
354 /* TODO: This seems to draw two items per each shift of the visible region, even though 328 /* TODO: This seems to draw two items per each shift of the visible region, even though
@@ -362,19 +336,15 @@ static void draw_ListWidget_(const iListWidget *d) {
362 const int bottom = numItems_ListWidget(d) * d->itemHeight; 336 const int bottom = numItems_ListWidget(d) * d->itemHeight;
363 const iRangei vis = { d->scrollY / d->itemHeight * d->itemHeight, 337 const iRangei vis = { d->scrollY / d->itemHeight * d->itemHeight,
364 ((d->scrollY + bounds.size.y) / d->itemHeight + 1) * d->itemHeight }; 338 ((d->scrollY + bounds.size.y) / d->itemHeight + 1) * d->itemHeight };
365// printf("visBufSize.y = %d\n", d->visBufSize.y);
366 reposition_VisBuf(d->visBuf, vis); 339 reposition_VisBuf(d->visBuf, vis);
367 /* Check which parts are invalid. */ 340 /* Check which parts are invalid. */
368 iRangei invalidRange[3]; 341 iRangei invalidRange[3];
369 invalidRanges_VisBuf(d->visBuf, (iRangei){ 0, bottom }, invalidRange); 342 invalidRanges_VisBuf(d->visBuf, (iRangei){ 0, bottom }, invalidRange);
370 iForIndices(i, d->visBuf->buffers) { 343 iForIndices(i, d->visBuf->buffers) {
371 iVisBufTexture *buf = &d->visBuf->buffers[i]; 344 iVisBufTexture *buf = &d->visBuf->buffers[i];
372// printf("%zu: orig %d, invalid %d ... %d\n", i, buf->origin, invalidRange[i].start, invalidRange[i].end);
373 iRanges drawItems = { iMax(0, buf->origin) / d->itemHeight, 345 iRanges drawItems = { iMax(0, buf->origin) / d->itemHeight,
374 iMax(0, buf->origin + d->visBuf->texSize.y) / d->itemHeight }; 346 iMax(0, buf->origin + d->visBuf->texSize.y) / d->itemHeight };
375 iBool isTargetSet = iFalse;
376 if (isEmpty_Rangei(buf->validRange)) { 347 if (isEmpty_Rangei(buf->validRange)) {
377 isTargetSet = iTrue;
378 beginTarget_Paint(&p, buf->texture); 348 beginTarget_Paint(&p, buf->texture);
379 fillRect_Paint(&p, (iRect){ zero_I2(), d->visBuf->texSize }, bg[i]); 349 fillRect_Paint(&p, (iRect){ zero_I2(), d->visBuf->texSize }, bg[i]);
380 } 350 }
@@ -384,21 +354,14 @@ static void draw_ListWidget_(const iListWidget *d) {
384 const iListItem *item = constAt_PtrArray(&d->items, index); 354 const iListItem *item = constAt_PtrArray(&d->items, index);
385 const iRect itemRect = { init_I2(0, index * d->itemHeight - buf->origin), 355 const iRect itemRect = { init_I2(0, index * d->itemHeight - buf->origin),
386 init_I2(d->visBuf->texSize.x, d->itemHeight) }; 356 init_I2(d->visBuf->texSize.x, d->itemHeight) };
387 if (!isTargetSet) { 357 beginTarget_Paint(&p, buf->texture);
388 beginTarget_Paint(&p, buf->texture);
389 isTargetSet = iTrue;
390 }
391 fillRect_Paint(&p, itemRect, bg[i]); 358 fillRect_Paint(&p, itemRect, bg[i]);
392 class_ListItem(item)->draw(item, &p, itemRect, d); 359 class_ListItem(item)->draw(item, &p, itemRect, d);
393// printf("- drawing invalid item %zu\n", index);
394 } 360 }
395 } 361 }
396 /* Visible range is not fully covered. Fill in the new items. */ 362 /* Visible range is not fully covered. Fill in the new items. */
397 if (!isEmpty_Rangei(invalidRange[i])) { 363 if (!isEmpty_Rangei(invalidRange[i])) {
398 if (!isTargetSet) { 364 beginTarget_Paint(&p, buf->texture);
399 beginTarget_Paint(&p, buf->texture);
400 isTargetSet = iTrue;
401 }
402 drawItems.start = invalidRange[i].start / d->itemHeight; 365 drawItems.start = invalidRange[i].start / d->itemHeight;
403 drawItems.end = invalidRange[i].end / d->itemHeight + 1; 366 drawItems.end = invalidRange[i].end / d->itemHeight + 1;
404 for (size_t j = drawItems.start; j < drawItems.end && j < size_PtrArray(&d->items); j++) { 367 for (size_t j = drawItems.start; j < drawItems.end && j < size_PtrArray(&d->items); j++) {
@@ -407,13 +370,9 @@ static void draw_ListWidget_(const iListWidget *d) {
407 init_I2(d->visBuf->texSize.x, d->itemHeight) }; 370 init_I2(d->visBuf->texSize.x, d->itemHeight) };
408 fillRect_Paint(&p, itemRect, bg[i]); 371 fillRect_Paint(&p, itemRect, bg[i]);
409 class_ListItem(item)->draw(item, &p, itemRect, d); 372 class_ListItem(item)->draw(item, &p, itemRect, d);
410// printf("- drawing item %zu\n", j);
411 } 373 }
412 } 374 }
413 if (isTargetSet) { 375 endTarget_Paint(&p);
414 endTarget_Paint(&p);
415 }
416// fflush(stdout);
417 } 376 }
418 validate_VisBuf(d->visBuf); 377 validate_VisBuf(d->visBuf);
419 clear_IntSet(&iConstCast(iListWidget *, d)->invalidItems); 378 clear_IntSet(&iConstCast(iListWidget *, d)->invalidItems);