ListClipper.go 3.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182
  1. package imgui
  2. // #include "ListClipper.h"
  3. // #include "imguiWrapper.h"
  4. import "C"
  5. // ListClipper is a helper to manually clip large list of items.
  6. // If you are submitting lots of evenly spaced items and you have a random access to the list,
  7. // you can perform coarse clipping based on visibility to save yourself from processing those items at all.
  8. // The clipper calculates the range of visible items and advance the cursor to compensate for
  9. // the non-visible items we have skipped.
  10. // ImGui already clips items based on their bounds but it needs to measure text size to do so.
  11. // Coarse clipping before submission makes this cost and your own data fetching/submission cost null.
  12. //
  13. // Usage
  14. // var clipper imgui.ListClipper
  15. // clipper.Begin(1000) // we have 1000 elements, evenly spaced.
  16. // for clipper.Step()
  17. // for i := clipper.DisplayStart; i < clipper.DisplayEnd; i++
  18. // imgui.Text(fmt.Sprintf("line number %d", i))
  19. //
  20. // Step 0: the clipper let you process the first element, regardless of it being visible or not,
  21. // so it can measure the element height (step skipped if user passed a known height at begin).
  22. //
  23. // Step 1: the clipper infers height from first element, calculates the actual range of elements to display,
  24. // and positions the cursor before the first element.
  25. //
  26. // Step 2: dummy step only required if an explicit itemsHeight was passed to Begin() and user call Step().
  27. // Does nothing and switch to Step 3.
  28. //
  29. // Step 3: the clipper validates that we have reached the expected Y position (corresponding to element DisplayEnd),
  30. // advance the cursor to the end of the list and then returns 'false' to end the loop.
  31. type ListClipper uintptr
  32. func NewListClipper() ListClipper {
  33. listClipper := C.iggNewListClipper()
  34. return ListClipper(listClipper)
  35. }
  36. func (c ListClipper) handle() C.IggListClipper {
  37. return C.IggListClipper(c)
  38. }
  39. func (c ListClipper) DisplayStart() int {
  40. return int(C.iggListClipperDisplayStart(c.handle()))
  41. }
  42. func (c ListClipper) DisplayEnd() int {
  43. return int(C.iggListClipperDisplayEnd(c.handle()))
  44. }
  45. // Step must be called in a loop until it returns false.
  46. // The DisplayStart/DisplayEnd fields will be set and you can process/draw those items.
  47. func (c *ListClipper) Step() bool {
  48. return C.iggListClipperStep(c.handle()) != 0
  49. }
  50. // Begin calls BeginV(itemsCount, -1.0) .
  51. func (c *ListClipper) Begin(itemsCount int) {
  52. c.BeginV(itemsCount, -1)
  53. }
  54. // BeginV must be called before stepping.
  55. // Use an itemCount of math.MaxInt if you don't know how many items you have.
  56. // In this case the cursor won't be advanced in the final step.
  57. //
  58. // For itemsHeight, use -1.0 to be calculated automatically on first step.
  59. // Otherwise pass in the distance between your items, typically
  60. // GetTextLineHeightWithSpacing() or GetFrameHeightWithSpacing().
  61. func (c *ListClipper) BeginV(itemsCount int, itemsHeight float32) {
  62. C.iggListClipperBegin(c.handle(), C.int(itemsCount), C.float(itemsHeight))
  63. }
  64. // End resets the clipper. This function is automatically called on the last call of Step() that returns false.
  65. func (c *ListClipper) End() {
  66. C.iggListClipperEnd(c.handle())
  67. }
  68. // Delete removes the list clipper from memory.
  69. func (c *ListClipper) Delete() {
  70. C.iggListClipperDelete(c.handle())
  71. }