clipregion.go 2.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283
  1. package winman
  2. import "github.com/gdamore/tcell/v2"
  3. // ClipRegion implements tcell.Screen and only allows setting content within
  4. // a defined region
  5. type ClipRegion struct {
  6. tcell.Screen
  7. x int
  8. y int
  9. width int
  10. height int
  11. style tcell.Style
  12. }
  13. // NewClipRegion Creates a new clipped screen with the given rectangular coordinates
  14. func NewClipRegion(screen tcell.Screen, x, y, width, height int) *ClipRegion {
  15. return &ClipRegion{
  16. Screen: screen,
  17. x: x,
  18. y: y,
  19. width: width,
  20. height: height,
  21. style: tcell.StyleDefault,
  22. }
  23. }
  24. // InRect returns true if the given coordinates are within this clipped region
  25. func (cr *ClipRegion) InRect(x, y int) bool {
  26. return !(x < cr.x || y < cr.y || x >= cr.x+cr.width || y >= cr.y+cr.height)
  27. }
  28. // Fill implements tcell.Screen.Fill
  29. func (cr *ClipRegion) Fill(ch rune, style tcell.Style) {
  30. for x := cr.x; x < cr.width; x++ {
  31. for y := cr.y; y < cr.height; y++ {
  32. cr.SetContent(x, y, ch, nil, style)
  33. }
  34. }
  35. }
  36. // SetCell is an older API, and will be removed. Please use
  37. // SetContent instead; SetCell is implemented in terms of SetContent.
  38. func (cr *ClipRegion) SetCell(x int, y int, style tcell.Style, ch ...rune) {
  39. if len(ch) > 0 {
  40. cr.SetContent(x, y, ch[0], ch[1:], style)
  41. } else {
  42. cr.SetContent(x, y, ' ', nil, style)
  43. }
  44. }
  45. // SetContent sets the contents of the given cell location. If
  46. // the coordinates are out of range, then the operation is ignored.
  47. //
  48. // The first rune is the primary non-zero width rune. The array
  49. // that follows is a possible list of combining characters to append,
  50. // and will usually be nil (no combining characters.)
  51. //
  52. // The results are not displayed until Show() or Sync() is called.
  53. //
  54. // Note that wide (East Asian full width) runes occupy two cells,
  55. // and attempts to place character at next cell to the right will have
  56. // undefined effects. Wide runes that are printed in the
  57. // last column will be replaced with a single width space on output.
  58. func (cr *ClipRegion) SetContent(x int, y int, mainc rune, combc []rune, style tcell.Style) {
  59. if cr.InRect(x, y) {
  60. cr.Screen.SetContent(x, y, mainc, combc, style)
  61. }
  62. }
  63. // ShowCursor is used to display the cursor at a given location.
  64. // If the coordinates -1, -1 are given or are otherwise outside the
  65. // dimensions of the screen, the cursor will be hidden.
  66. func (cr *ClipRegion) ShowCursor(x int, y int) {
  67. if cr.InRect(x, y) {
  68. cr.Screen.ShowCursor(x, y)
  69. }
  70. }
  71. // Clear clears the clipped region
  72. func (cr *ClipRegion) Clear() {
  73. cr.Fill(' ', cr.style)
  74. }