summaryrefslogtreecommitdiff
path: root/src/ui/listwidget.c
diff options
context:
space:
mode:
authorJaakko Keränen <jaakko.keranen@iki.fi>2020-09-12 08:27:20 +0300
committerJaakko Keränen <jaakko.keranen@iki.fi>2020-09-12 08:27:20 +0300
commitbc869008f0cfba661e92b3975db3ca6a65be4bf7 (patch)
tree23915c4e696bd4a8e7b9e4d90f63e2ffa44274ab /src/ui/listwidget.c
parent949947908e70217af7545f0edc43bcdfd3dea92e (diff)
ListWidget: Cleanup
Diffstat (limited to 'src/ui/listwidget.c')
-rw-r--r--src/ui/listwidget.c96
1 files changed, 18 insertions, 78 deletions
diff --git a/src/ui/listwidget.c b/src/ui/listwidget.c
index 985ba2e7..dd11b008 100644
--- a/src/ui/listwidget.c
+++ b/src/ui/listwidget.c
@@ -332,7 +332,8 @@ static iBool processEvent_ListWidget_(iListWidget *d, const SDL_Event *ev) {
332 332
333static void allocVisBuffer_ListWidget_(iListWidget *d) { 333static void allocVisBuffer_ListWidget_(iListWidget *d) {
334 /* Make sure two buffers cover the entire visible area. */ 334 /* Make sure two buffers cover the entire visible area. */
335 const iInt2 size = div_I2(addY_I2(innerBounds_Widget(as_Widget(d)).size, 1), init_I2(1, 2)); 335 const iRect inner = innerBounds_Widget(as_Widget(d));
336 const iInt2 size = init_I2(inner.size.x, (inner.size.y / 2 / d->itemHeight + 1) * d->itemHeight);
336 if (!d->visBuffers[0].texture || !isEqual_I2(size, d->visBufSize)) { 337 if (!d->visBuffers[0].texture || !isEqual_I2(size, d->visBufSize)) {
337 d->visBufSize = size; 338 d->visBufSize = size;
338 iForIndices(i, d->visBuffers) { 339 iForIndices(i, d->visBuffers) {
@@ -400,17 +401,20 @@ static void draw_ListWidget_(const iListWidget *d) {
400 iListWidget *m = iConstCast(iListWidget *, d); 401 iListWidget *m = iConstCast(iListWidget *, d);
401 allocVisBuffer_ListWidget_(m); 402 allocVisBuffer_ListWidget_(m);
402 /* Update invalid regions/items. */ 403 /* Update invalid regions/items. */
404 /* TODO: This seems to draw two items per each shift of the visible region, even though
405 one should be enough. Probably an off-by-one error in the calculation of the
406 invalid range. */
403 if (d->visBufSize.y > 0) { 407 if (d->visBufSize.y > 0) {
404 /*if (d->visBufferValid != full_BufferValidity || !isEmpty_IntSet(&d->invalidItems)) */
405 iAssert(d->visBuffers[0].texture); 408 iAssert(d->visBuffers[0].texture);
406 iAssert(d->visBuffers[1].texture); 409 iAssert(d->visBuffers[1].texture);
407 iAssert(d->visBuffers[2].texture); 410 iAssert(d->visBuffers[2].texture);
408// const int vbSrc = d->visBufferIndex; 411 const int bg[3] = { w->bgColor, w->bgColor, w->bgColor };
409// const int vbDst = d->visBufferIndex ^ 1; 412// const int bg[3] = { red_ColorId, magenta_ColorId, blue_ColorId };
410 const int bottom = numItems_ListWidget(d) * d->itemHeight; 413 const int bottom = numItems_ListWidget(d) * d->itemHeight;
411 const iRangei vis = { d->scrollY, d->scrollY + bounds.size.y }; 414 const iRangei vis = { d->scrollY / d->itemHeight * d->itemHeight,
415 ((d->scrollY + bounds.size.y) / d->itemHeight + 1) * d->itemHeight };
412 iRangei good = { 0, 0 }; 416 iRangei good = { 0, 0 };
413 printf("visBufSize.y = %d\n", d->visBufSize.y); 417// printf("visBufSize.y = %d\n", d->visBufSize.y);
414 size_t avail[3], numAvail = 0; 418 size_t avail[3], numAvail = 0;
415 /* Check which buffers are available for reuse. */ { 419 /* Check which buffers are available for reuse. */ {
416 iForIndices(i, d->visBuffers) { 420 iForIndices(i, d->visBuffers) {
@@ -457,14 +461,14 @@ static void draw_ListWidget_(const iListWidget *d) {
457 } 461 }
458 iForIndices(i, d->visBuffers) { 462 iForIndices(i, d->visBuffers) {
459 iListVisBuffer *buf = m->visBuffers + i; 463 iListVisBuffer *buf = m->visBuffers + i;
460 printf("%zu: orig %d, invalid %d ... %d\n", i, buf->origin, invalidRange[i].start, invalidRange[i].end); 464// printf("%zu: orig %d, invalid %d ... %d\n", i, buf->origin, invalidRange[i].start, invalidRange[i].end);
461 iRanges drawItems = { iMax(0, buf->origin) / d->itemHeight, 465 iRanges drawItems = { iMax(0, buf->origin) / d->itemHeight,
462 iMax(0, buf->origin + d->visBufSize.y) / d->itemHeight + 1 }; 466 iMax(0, buf->origin + d->visBufSize.y) / d->itemHeight + 1 };
463 iBool isTargetSet = iFalse; 467 iBool isTargetSet = iFalse;
464 if (isEmpty_Rangei(buf->validRange)) { 468 if (isEmpty_Rangei(buf->validRange)) {
465 isTargetSet = iTrue; 469 isTargetSet = iTrue;
466 beginTarget_Paint(&p, buf->texture); 470 beginTarget_Paint(&p, buf->texture);
467 fillRect_Paint(&p, (iRect){ zero_I2(), d->visBufSize }, w->bgColor); 471 fillRect_Paint(&p, (iRect){ zero_I2(), d->visBufSize }, bg[i]);
468 } 472 }
469 iConstForEach(IntSet, v, &d->invalidItems) { 473 iConstForEach(IntSet, v, &d->invalidItems) {
470 const size_t index = *v.value; 474 const size_t index = *v.value;
@@ -476,101 +480,37 @@ static void draw_ListWidget_(const iListWidget *d) {
476 beginTarget_Paint(&p, buf->texture); 480 beginTarget_Paint(&p, buf->texture);
477 isTargetSet = iTrue; 481 isTargetSet = iTrue;
478 } 482 }
479 fillRect_Paint(&p, itemRect, w->bgColor); 483 fillRect_Paint(&p, itemRect, bg[i]);
480 class_ListItem(item)->draw(item, &p, itemRect, d); 484 class_ListItem(item)->draw(item, &p, itemRect, d);
481 printf("- drawing invalid item %zu\n", index); 485// printf("- drawing invalid item %zu\n", index);
482 } 486 }
483 } 487 }
488 /* Visible range is not fully covered. Fill in the new items. */
484 if (!isEmpty_Rangei(invalidRange[i])) { 489 if (!isEmpty_Rangei(invalidRange[i])) {
485 if (!isTargetSet) { 490 if (!isTargetSet) {
486 beginTarget_Paint(&p, buf->texture); 491 beginTarget_Paint(&p, buf->texture);
487 isTargetSet = iTrue; 492 isTargetSet = iTrue;
488 } 493 }
489 /* Visible range is not fully covered. Fill in the new items. */
490// fillRect_Paint(&p, (iRect){ init_I2(0, invalidRange[i].start - buf->origin),
491// init_I2(d->visBufSize.x, invalidRange[i].end - buf->origin) },
492// w->bgColor);
493 drawItems.start = invalidRange[i].start / d->itemHeight; 494 drawItems.start = invalidRange[i].start / d->itemHeight;
494 drawItems.end = invalidRange[i].end / d->itemHeight + 1; 495 drawItems.end = invalidRange[i].end / d->itemHeight + 1;
495 for (size_t j = drawItems.start; j < drawItems.end && j < size_PtrArray(&d->items); j++) { 496 for (size_t j = drawItems.start; j < drawItems.end && j < size_PtrArray(&d->items); j++) {
496 const iListItem *item = constAt_PtrArray(&d->items, j); 497 const iListItem *item = constAt_PtrArray(&d->items, j);
497 const iRect itemRect = { init_I2(0, j * d->itemHeight - buf->origin), 498 const iRect itemRect = { init_I2(0, j * d->itemHeight - buf->origin),
498 init_I2(d->visBufSize.x, d->itemHeight) }; 499 init_I2(d->visBufSize.x, d->itemHeight) };
499 fillRect_Paint(&p, itemRect, w->bgColor); 500 fillRect_Paint(&p, itemRect, bg[i]);
500 class_ListItem(item)->draw(item, &p, itemRect, d); 501 class_ListItem(item)->draw(item, &p, itemRect, d);
501 printf("- drawing item %zu\n", j); 502// printf("- drawing item %zu\n", j);
502 } 503 }
503 } 504 }
504 /* TODO: Redraw invalidated items. */
505 if (isTargetSet) { 505 if (isTargetSet) {
506 endTarget_Paint(&p); 506 endTarget_Paint(&p);
507 } 507 }
508 buf->validRange = 508 buf->validRange =
509 intersect_Rangei(vis, (iRangei){ buf->origin, buf->origin + d->visBufSize.y }); 509 intersect_Rangei(vis, (iRangei){ buf->origin, buf->origin + d->visBufSize.y });
510 fflush(stdout); 510// fflush(stdout);
511 } 511 }
512#if 0
513 beginTarget_Paint(&p, d->visBuffer[vbDst]);
514 const iRect bufBounds = (iRect){ zero_I2(), bounds.size };
515 iRanges invalidRange = { 0, 0 };
516 if (!d->visBufferValid) {
517 fillRect_Paint(&p, bufBounds, w->bgColor);
518 }
519 else if (d->visBufferValid == partial_BufferValidity) {
520 /* Copy previous contents. */
521 const int delta = d->scrollY - d->visBufferScrollY;
522 SDL_RenderCopy(
523 render,
524 d->visBuffer[vbSrc],
525 NULL,
526 &(SDL_Rect){ 0, -delta, bounds.size.x, bounds.size.y });
527 if (delta > 0) {
528 /* Scrolling down. */
529 invalidRange.start = (d->visBufferScrollY + bounds.size.y) / d->itemHeight;
530 invalidRange.end = (d->scrollY + bounds.size.y) / d->itemHeight + 1;
531 }
532 else if (delta < 0) {
533 /* Scrolling up. */
534 invalidRange.start = d->scrollY / d->itemHeight;
535 invalidRange.end = d->visBufferScrollY / d->itemHeight + 1;
536 }
537 }
538 /* Draw items. */ {
539 const iRanges visRange = visRange_ListWidget_(d);
540 iInt2 pos = init_I2(0, -(d->scrollY % d->itemHeight));
541 for (size_t i = visRange.start; i < visRange.end; i++) {
542 /* TODO: Refactor to loop through invalidItems only. */
543 if (!d->visBufferValid || contains_Range(&invalidRange, i) ||
544 contains_IntSet(&d->invalidItems, i)) {
545 const iListItem *item = constAt_PtrArray(&d->items, i);
546 const iRect itemRect = { pos, init_I2(width_Rect(bounds), d->itemHeight) };
547 setClip_Paint(&p, intersect_Rect(itemRect, bufBounds));
548 if (d->visBufferValid) {
549 fillRect_Paint(&p, itemRect, w->bgColor);
550 }
551 class_ListItem(item)->draw(item, &p, itemRect, d);
552 /* Clear under the scrollbar. */
553 if (isVisible_Widget(d->scroll)) {
554 fillRect_Paint(
555 &p,
556 (iRect){ addX_I2(topRight_Rect(itemRect), -width_Widget(d->scroll)),
557 bottomRight_Rect(itemRect) },
558 w->bgColor);
559 }
560 unsetClip_Paint(&p);
561 }
562 pos.y += d->itemHeight;
563 }
564 }
565 endTarget_Paint(&p);
566 /* Update state. */
567// m->visBufferValid = iTrue;
568// m->visBufferScrollY = m->scrollY;
569// m->visBufferIndex = vbDst;
570#endif
571 clear_IntSet(&m->invalidItems); 512 clear_IntSet(&m->invalidItems);
572 } 513 }
573 //SDL_RenderCopy(render, d->visBuffer[d->visBufferIndex], NULL, (const SDL_Rect *) &bounds);
574 setClip_Paint(&p, bounds_Widget(w)); 514 setClip_Paint(&p, bounds_Widget(w));
575 iForIndices(i, d->visBuffers) { 515 iForIndices(i, d->visBuffers) {
576 const iListVisBuffer *buf = d->visBuffers + i; 516 const iListVisBuffer *buf = d->visBuffers + i;