github.com/as/shiny@v0.8.2/screen/screen.go (about)

     1  // Copyright 2015 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package screen // import "github.com/as/shiny/screen"
     6  
     7  import (
     8  	"image"
     9  	"image/color"
    10  	"image/draw"
    11  	"unicode/utf8"
    12  
    13  	"github.com/as/shiny/event/key"
    14  	"github.com/as/shiny/event/lifecycle"
    15  	"github.com/as/shiny/event/mouse"
    16  	"github.com/as/shiny/event/paint"
    17  	"github.com/as/shiny/event/size"
    18  	"github.com/as/shiny/math/f64"
    19  )
    20  
    21  // Screen creates Buffers, Textures and Windows.
    22  type Screen interface {
    23  	NewBuffer(size image.Point) (Buffer, error)
    24  	NewTexture(size image.Point) (Texture, error)
    25  	NewWindow(opts *NewWindowOptions) (Window, error)
    26  }
    27  
    28  type Buffer interface {
    29  	Release()
    30  	Size() image.Point
    31  	Bounds() image.Rectangle
    32  	RGBA() *image.RGBA
    33  }
    34  
    35  type Texture interface {
    36  	Release()
    37  	Size() image.Point
    38  	Bounds() image.Rectangle
    39  	Uploader
    40  }
    41  
    42  // Window is a top-level, double-buffered GUI window.
    43  type Window interface {
    44  	Device() *Device
    45  	Release()
    46  	Uploader
    47  	Drawer
    48  	Publish() PublishResult
    49  }
    50  
    51  type (
    52  	Lifecycle = lifecycle.Event
    53  	Scroll    = mouse.Event
    54  	Mouse     = mouse.Event
    55  	Key       = key.Event
    56  	Size      = size.Event
    57  	Paint     = paint.Event
    58  )
    59  
    60  var Dev = &Device{
    61  	Scroll:    make(chan Scroll, 1),
    62  	Mouse:     make(chan Mouse, 1),
    63  	Key:       make(chan Key, 1),
    64  	Size:      make(chan Size, 1),
    65  	Paint:     make(chan Paint, 1),
    66  	Lifecycle: make(chan Lifecycle, 1),
    67  }
    68  
    69  type Device struct {
    70  	Lifecycle chan Lifecycle
    71  	Scroll    chan Scroll
    72  	Mouse     chan Mouse
    73  	Key       chan Key
    74  	Size      chan Size
    75  	Paint     chan Paint
    76  }
    77  
    78  func SendMouse(e Mouse) {
    79  	select {
    80  	case Dev.Mouse <- e:
    81  	default:
    82  		// TODO: Retry on failure, but only if it's a press or release
    83  		// note that this may hang the user, so a better fix should be
    84  		// in order
    85  		if e.Button != mouse.ButtonNone && e.Direction != mouse.DirNone {
    86  			Dev.Mouse <- e
    87  		}
    88  	}
    89  }
    90  
    91  func SendKey(e Key) {
    92  	select {
    93  	case Dev.Key <- e:
    94  	}
    95  }
    96  
    97  func SendSize(e Size) {
    98  	select {
    99  	case Dev.Size <- e:
   100  	default:
   101  	}
   102  }
   103  
   104  func SendPaint(e Paint) {
   105  	select {
   106  	case Dev.Paint <- e:
   107  	default:
   108  	}
   109  }
   110  
   111  func SendScroll(e Scroll) {
   112  	for {
   113  		select {
   114  		case Dev.Scroll <- e:
   115  			return
   116  		default:
   117  			select {
   118  			case <-Dev.Scroll:
   119  			default:
   120  			}
   121  		}
   122  	}
   123  }
   124  
   125  func SendLifecycle(e Lifecycle) {
   126  	select {
   127  	case Dev.Lifecycle <- e:
   128  	}
   129  
   130  }
   131  
   132  // PublishResult is the result of an Window.Publish call.
   133  type PublishResult struct {
   134  	BackBufferPreserved bool
   135  }
   136  
   137  // NewWindowOptions are optional arguments to NewWindow.
   138  // TODO(as): NewWindowOptions could be named better
   139  type NewWindowOptions struct {
   140  	Width, Height int
   141  	Title         string
   142  
   143  	// Overlay, if true, attempts to create a new window over top
   144  	// of the parent process's existing window (similar to running
   145  	// a graphical application in Plan9 over top an existing Rio
   146  	// window).
   147  	Overlay bool
   148  }
   149  
   150  func (o *NewWindowOptions) GetTitle() string {
   151  	if o == nil {
   152  		return ""
   153  	}
   154  	return sanitizeUTF8(o.Title, 4096)
   155  }
   156  
   157  func sanitizeUTF8(s string, n int) string {
   158  	if n < len(s) {
   159  		s = s[:n]
   160  	}
   161  	i := 0
   162  	for i < len(s) {
   163  		r, n := utf8.DecodeRuneInString(s[i:])
   164  		if r == 0 || (r == utf8.RuneError && n == 1) {
   165  			break
   166  		}
   167  		i += n
   168  	}
   169  	return s[:i]
   170  }
   171  
   172  // Uploader is something you can upload a Buffer to.
   173  type Uploader interface {
   174  	Upload(dp image.Point, src Buffer, sr image.Rectangle)
   175  	Fill(dr image.Rectangle, src color.Color, op draw.Op)
   176  }
   177  
   178  type Drawer interface {
   179  	Draw(src2dst f64.Aff3, src Texture, sr image.Rectangle, op draw.Op, opts *DrawOptions)
   180  	DrawUniform(src2dst f64.Aff3, src color.Color, sr image.Rectangle, op draw.Op, opts *DrawOptions)
   181  	Copy(dp image.Point, src Texture, sr image.Rectangle, op draw.Op, opts *DrawOptions)
   182  	Scale(dr image.Rectangle, src Texture, sr image.Rectangle, op draw.Op, opts *DrawOptions)
   183  }
   184  
   185  const (
   186  	Over = draw.Over
   187  	Src  = draw.Src
   188  )
   189  
   190  type DrawOptions struct {
   191  }