...

Source file src/code.rocketnine.space/tslocum/cview/window.go

Documentation: code.rocketnine.space/tslocum/cview

     1  package cview
     2  
     3  import (
     4  	"sync"
     5  
     6  	"github.com/gdamore/tcell/v2"
     7  )
     8  
     9  // Window is a draggable, resizable frame around a primitive. Windows must be
    10  // added to a WindowManager.
    11  type Window struct {
    12  	*Box
    13  
    14  	primitive Primitive
    15  
    16  	fullscreen bool
    17  
    18  	normalX, normalY int
    19  	normalW, normalH int
    20  
    21  	dragX, dragY   int
    22  	dragWX, dragWY int
    23  
    24  	sync.RWMutex
    25  }
    26  
    27  // NewWindow returns a new window around the given primitive.
    28  func NewWindow(primitive Primitive) *Window {
    29  	w := &Window{
    30  		Box:       NewBox(),
    31  		primitive: primitive,
    32  		dragWX:    -1,
    33  		dragWY:    -1,
    34  	}
    35  	w.Box.focus = w
    36  	return w
    37  }
    38  
    39  // SetFullscreen sets the flag indicating whether or not the the window should
    40  // be drawn fullscreen.
    41  func (w *Window) SetFullscreen(fullscreen bool) {
    42  	w.Lock()
    43  	defer w.Unlock()
    44  
    45  	if w.fullscreen == fullscreen {
    46  		return
    47  	}
    48  
    49  	w.fullscreen = fullscreen
    50  	if w.fullscreen {
    51  		w.normalX, w.normalY, w.normalW, w.normalH = w.GetRect()
    52  	} else {
    53  		w.SetRect(w.normalX, w.normalY, w.normalW, w.normalH)
    54  	}
    55  }
    56  
    57  // Focus is called when this primitive receives focus.
    58  func (w *Window) Focus(delegate func(p Primitive)) {
    59  	w.Lock()
    60  	defer w.Unlock()
    61  
    62  	w.Box.Focus(delegate)
    63  
    64  	w.primitive.Focus(delegate)
    65  }
    66  
    67  // Blur is called when this primitive loses focus.
    68  func (w *Window) Blur() {
    69  	w.Lock()
    70  	defer w.Unlock()
    71  
    72  	w.Box.Blur()
    73  
    74  	w.primitive.Blur()
    75  }
    76  
    77  // HasFocus returns whether or not this primitive has focus.
    78  func (w *Window) HasFocus() bool {
    79  	w.RLock()
    80  	defer w.RUnlock()
    81  
    82  	focusable := w.primitive.GetFocusable()
    83  	if focusable != nil {
    84  		return focusable.HasFocus()
    85  	}
    86  
    87  	return w.Box.HasFocus()
    88  }
    89  
    90  // Draw draws this primitive onto the screen.
    91  func (w *Window) Draw(screen tcell.Screen) {
    92  	if !w.GetVisible() {
    93  		return
    94  	}
    95  
    96  	w.RLock()
    97  	defer w.RUnlock()
    98  
    99  	w.Box.Draw(screen)
   100  
   101  	x, y, width, height := w.GetInnerRect()
   102  	w.primitive.SetRect(x, y, width, height)
   103  	w.primitive.Draw(screen)
   104  }
   105  
   106  // InputHandler returns the handler for this primitive.
   107  func (w *Window) InputHandler() func(event *tcell.EventKey, setFocus func(p Primitive)) {
   108  	return w.primitive.InputHandler()
   109  }
   110  
   111  // MouseHandler returns the mouse handler for this primitive.
   112  func (w *Window) MouseHandler() func(action MouseAction, event *tcell.EventMouse, setFocus func(p Primitive)) (consumed bool, capture Primitive) {
   113  	return w.WrapMouseHandler(func(action MouseAction, event *tcell.EventMouse, setFocus func(p Primitive)) (consumed bool, capture Primitive) {
   114  		if !w.InRect(event.Position()) {
   115  			return false, nil
   116  		}
   117  
   118  		if action == MouseLeftDown || action == MouseMiddleDown || action == MouseRightDown {
   119  			setFocus(w)
   120  		}
   121  
   122  		if action == MouseLeftDown {
   123  			x, y, width, height := w.GetRect()
   124  			mouseX, mouseY := event.Position()
   125  
   126  			leftEdge := mouseX == x
   127  			rightEdge := mouseX == x+width-1
   128  			bottomEdge := mouseY == y+height-1
   129  			topEdge := mouseY == y
   130  
   131  			if mouseY >= y && mouseY <= y+height-1 {
   132  				if leftEdge {
   133  					w.dragX = -1
   134  				} else if rightEdge {
   135  					w.dragX = 1
   136  				}
   137  			}
   138  
   139  			if mouseX >= x && mouseX <= x+width-1 {
   140  				if bottomEdge {
   141  					w.dragY = -1
   142  				} else if topEdge {
   143  					if leftEdge || rightEdge {
   144  						w.dragY = 1
   145  					} else {
   146  						w.dragWX = mouseX - x
   147  						w.dragWY = mouseY - y
   148  					}
   149  				}
   150  			}
   151  		}
   152  
   153  		_, capture = w.primitive.MouseHandler()(action, event, setFocus)
   154  		return true, capture
   155  	})
   156  }
   157  

View as plain text