Skip to content

Commit

Permalink
Add paste support to entry widget (#89)
Browse files Browse the repository at this point in the history
* Add initial paste support to entry

* Add Clipboard interface, implement for Gl driver

* Add Shortcut interface and default handler

* Allow adding of shortcuts to canvas
  • Loading branch information
lucor authored and andydotxyz committed Feb 28, 2019
1 parent 0570f9b commit 728a60a
Show file tree
Hide file tree
Showing 18 changed files with 686 additions and 28 deletions.
1 change: 1 addition & 0 deletions canvas.go
Expand Up @@ -17,4 +17,5 @@ type Canvas interface {
SetOnTypedRune(func(rune))
OnTypedKey() func(*KeyEvent)
SetOnTypedKey(func(*KeyEvent))
AddShortcut(shortcut Shortcut, handler func(shortcut Shortcut))
}
5 changes: 5 additions & 0 deletions canvasobject.go
Expand Up @@ -53,3 +53,8 @@ type Focusable interface {
TypedRune(rune)
TypedKey(*KeyEvent)
}

// Shortcutable describes any CanvasObject that can respond to shortcut commands (quit, cut, copy, and paste).
type Shortcutable interface {
TypedShortcut(shortcut Shortcut) bool
}
9 changes: 9 additions & 0 deletions clipboard.go
@@ -0,0 +1,9 @@
package fyne

// Clipboard represents the system clipboard interface
type Clipboard interface {
// Content returns the clipboard content
Content() string
// SetContent sets the clipboard content
SetContent(content string)
}
18 changes: 17 additions & 1 deletion driver/desktop/key.go
@@ -1,6 +1,8 @@
package desktop

import "fyne.io/fyne"
import (
"fyne.io/fyne"
)

const (
// KeyShift represents the left or right shift key
Expand All @@ -14,3 +16,17 @@ const (
// KeyMenu represents the left or right menu / application key
KeyMenu fyne.KeyName = "Menu"
)

// Modifier captures any key modifiers (shift etc) pressed during this key event
type Modifier int

const (
// ShiftModifier represents a shift key being held
ShiftModifier Modifier = 1 << iota
// ControlModifier represents the ctrl key being held
ControlModifier
// AltModifier represents either alt keys being held
AltModifier
// SuperModifier represents either super keys being held
SuperModifier
)
40 changes: 40 additions & 0 deletions driver/desktop/shortcut.go
@@ -0,0 +1,40 @@
package desktop

import (
"strings"

"fyne.io/fyne"
)

// CustomShortcut describes a shortcut desktop event.
type CustomShortcut struct {
fyne.KeyName
Modifier
}

// ShortcutName returns the shortcut name associated to the event
func (cs *CustomShortcut) ShortcutName() string {
id := &strings.Builder{}
id.WriteString("CustomDesktop:")
id.WriteString(modifierToString(cs.Modifier))
id.WriteString("+")
id.WriteString(string(cs.KeyName))
return id.String()
}

func modifierToString(mods Modifier) string {
s := []string{}
if (mods & ShiftModifier) != 0 {
s = append(s, string(KeyShift))
}
if (mods & ControlModifier) != 0 {
s = append(s, string(KeyControl))
}
if (mods & AltModifier) != 0 {
s = append(s, string(KeyAlt))
}
if (mods & SuperModifier) != 0 {
s = append(s, string(KeySuper))
}
return strings.Join(s, "+")
}
80 changes: 80 additions & 0 deletions driver/desktop/shortcut_test.go
@@ -0,0 +1,80 @@
package desktop

import (
"testing"

"fyne.io/fyne"
)

func TestCustomShortcut_Shortcut(t *testing.T) {
type fields struct {
KeyName fyne.KeyName
Modifier Modifier
}
tests := []struct {
name string
fields fields
want string
}{
{
name: "Ctrl+C",
fields: fields{
KeyName: fyne.KeyC,
Modifier: ControlModifier,
},
want: "CustomDesktop:Control+C",
},
{
name: "Ctrl+Alt+Esc",
fields: fields{
KeyName: fyne.KeyEscape,
Modifier: ControlModifier + AltModifier,
},
want: "CustomDesktop:Control+Alt+Escape",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
cs := &CustomShortcut{
KeyName: tt.fields.KeyName,
Modifier: tt.fields.Modifier,
}
if got := cs.ShortcutName(); got != tt.want {
t.Errorf("CustomShortcut.ShortcutName() = %v, want %v", got, tt.want)
}
})
}
}

func Test_modifierToString(t *testing.T) {
type args struct {
}
tests := []struct {
name string
mods Modifier
want string
}{
{
name: "None",
mods: 0,
want: "",
},
{
name: "Ctrl",
mods: ControlModifier,
want: "Control",
},
{
name: "Shift+Ctrl",
mods: ShiftModifier + ControlModifier,
want: "Shift+Control",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := modifierToString(tt.mods); got != tt.want {
t.Errorf("modifierToString() = %v, want %v", got, tt.want)
}
})
}
}
5 changes: 5 additions & 0 deletions driver/gl/canvas.go
Expand Up @@ -17,6 +17,7 @@ type glCanvas struct {

onTypedRune func(rune)
onTypedKey func(*fyne.KeyEvent)
shortcut fyne.ShortcutHandler

program uint32
scale float32
Expand Down Expand Up @@ -130,6 +131,10 @@ func (c *glCanvas) SetOnTypedKey(typed func(*fyne.KeyEvent)) {
c.onTypedKey = typed
}

func (c *glCanvas) AddShortcut(shortcut fyne.Shortcut, handler func(shortcut fyne.Shortcut)) {
c.shortcut.AddShortcut(shortcut, handler)
}

func (c *glCanvas) paint(size fyne.Size) {
if c.Content() == nil {
return
Expand Down
27 changes: 27 additions & 0 deletions driver/gl/clipboard.go
@@ -0,0 +1,27 @@
package gl

import (
"log"

"github.com/go-gl/glfw/v3.2/glfw"
)

// clipboard represents the system clipboard
type clipboard struct {
window *glfw.Window
}

// Content returns the clipboard content
func (c *clipboard) Content() string {
content, err := c.window.GetClipboardString()
if err != nil {
log.Printf("unable to get clipboard string: %v", err)
return ""
}
return content
}

// SetContent sets the clipboard content
func (c *clipboard) SetContent(content string) {
c.window.SetClipboardString(content)
}

0 comments on commit 728a60a

Please sign in to comment.