Пример #1
0
func (t *TextBox) DoubleClick(ev gxui.MouseEvent) (consume bool) {
	if p, ok := t.RuneIndexAt(ev.Point); ok {
		s, e := t.controller.WordAt(p)
		if ev.Modifier&gxui.ModControl != 0 {
			t.controller.AddSelection(gxui.CreateTextSelection(s, e, false))
		} else {
			t.controller.SetSelection(gxui.CreateTextSelection(s, e, false))
		}
	}
	t.InputEventHandler.DoubleClick(ev)
	return true
}
Пример #2
0
func (u *Undo) Exec(target interface{}) (executed, consume bool) {
	finder, ok := target.(EditorFinder)
	if !ok {
		return false, false
	}
	editor := finder.CurrentEditor()
	if editor == nil {
		u.err = "undo: no file open"
		return true, true
	}
	history := editor.History()
	edit, ok := history.Undo()
	if !ok {
		u.warn = "undo: nothing to undo"
		return true, true
	}
	text, _ := editor.Controller().ReplaceAt(editor.Runes(), edit.At, edit.At+len(edit.New), edit.Old)
	editor.Controller().SetTextRunes(text)
	absDelta := edit.Delta
	if absDelta < 0 {
		absDelta = -absDelta
	}
	editor.Controller().SetSelection(gxui.CreateTextSelection(edit.At, edit.At+absDelta, true))
	editor.ScrollToRune(edit.At)
	return true, true
}
Пример #3
0
func (l *CodeEditorLine) PaintEditorSelections(c gxui.Canvas, info CodeEditorLinePaintInfo) {
	controller := l.textbox.controller

	ls, le := uint64(controller.LineStart(l.lineIndex)), uint64(controller.LineEnd(l.lineIndex))

	selections := controller.Selections()
	if l.textbox.selectionDragging {
		interval.Replace(&selections, l.textbox.selectionDrag)
	}
	interval.Visit(&selections, gxui.CreateTextSelection(int(ls), int(le), false), func(s, e uint64, _ int) {
		if s < e {
			var startOffset math.Point
			if s > ls {
				startOffset = l.endOfChar(info.GlyphOffsets[s-ls-1])
			}
			var endOffset math.Point
			if e > ls {
				endOffset = l.endOfChar(info.GlyphOffsets[e-ls-1])
			}

			width := endOffset.X - startOffset.X
			m := l.outer.MeasureRunes(int(s), int(e))
			m.W = width
			top := math.Point{X: l.caretWidth + startOffset.X, Y: 0}
			bottom := top.Add(m.Point())
			l.outer.PaintSelection(c, top, bottom)
		}
	})
}
Пример #4
0
func (f *Find) Start(control gxui.Control) gxui.Control {
	f.editor = findEditor(control)
	if f.editor == nil {
		return nil
	}
	f.display = f.theme.CreateLabel()
	f.display.SetText("Start typing to search")
	f.pattern = newFindBox(f.driver, f.theme, f.editor)
	f.next = f.pattern
	f.pattern.OnTextChanged(func([]gxui.TextBoxEdit) {
		f.editor.Controller().ClearSelections()
		needle := f.pattern.Text()
		if len(needle) == 0 {
			f.display.SetText("Start typing to search")
			return
		}
		haystack := f.editor.Text()
		start := 0
		var selections gxui.TextSelectionList
		for next := strings.Index(haystack, needle); next != -1; next = strings.Index(haystack[start:], needle) {
			start += next
			selection := gxui.CreateTextSelection(start, start+len(needle), false)
			selections = append(selections, selection)
			start++
		}
		f.editor.Select(selections)
		f.display.SetText(fmt.Sprintf("%s: %d results found", needle, len(selections)))
	})
	return f.display
}
Пример #5
0
func (e *CodeEditor) KeyPress(ev gxui.KeyboardEvent) (consume bool) {
	switch ev.Key {
	case gxui.KeyTab:
		replace := true
		for _, sel := range e.controller.Selections() {
			start, end := sel.Range()
			if e.controller.LineIndex(start) != e.controller.LineIndex(end) {
				replace = false
				break
			}
		}
		switch {
		case replace:
			e.controller.ReplaceAll(strings.Repeat(" ", e.tabWidth))
			e.controller.Deselect(false)
		case ev.Modifier.Shift():
			e.controller.UnindentSelection()
		default:
			e.controller.IndentSelection()
		}
		return true
	case gxui.KeySpace:
		if ev.Modifier.Control() {
			e.ShowSuggestionList()
			return
		}
	case gxui.KeyUp:
		fallthrough
	case gxui.KeyDown:
		if e.IsSuggestionListShowing() {
			return e.suggestionList.KeyPress(ev)
		}
	case gxui.KeyLeft:
		e.HideSuggestionList()
	case gxui.KeyRight:
		e.HideSuggestionList()
	case gxui.KeyEnter:
		controller := e.controller
		if e.IsSuggestionListShowing() {
			text := e.suggestionAdapter.Suggestion(e.suggestionList.Selected()).Code()
			start, end := controller.WordAt(e.controller.LastCaret())
			controller.SetSelection(gxui.CreateTextSelection(start, end, false))
			controller.ReplaceAll(text)
			controller.Deselect(false)
			e.HideSuggestionList()
		} else {
			e.controller.ReplaceWithNewlineKeepIndent()
		}
		return true
	case gxui.KeyEscape:
		if e.IsSuggestionListShowing() {
			e.HideSuggestionList()
			return true
		}
	}
	return e.TextBox.KeyPress(ev)
}
Пример #6
0
func (t *TextBox) MouseMove(ev gxui.MouseEvent) {
	t.List.MouseMove(ev)
	if t.selectionDragging {
		if p, ok := t.RuneIndexAt(ev.Point); ok {
			t.selectionDrag = gxui.CreateTextSelection(t.selectionDrag.From(), p, false)
			t.selectionDragging = true
			t.onRedrawLines.Fire()
		}
	}
}
Пример #7
0
func (t *TextBox) lineMouseDown(line TextBoxLine, ev gxui.MouseEvent) {
	if ev.Button == gxui.MouseButtonLeft {
		p := line.RuneIndexAt(ev.Point)
		t.selectionDragging = true
		t.selectionDrag = gxui.CreateTextSelection(p, p, false)
		if !ev.Modifier.Control() {
			t.controller.SetCaret(p)
		}
	}
}
Пример #8
0
func (t *DefaultTextBoxLine) PaintSelections(c gxui.Canvas) {
	controller := t.textbox.controller

	ls, le := controller.LineStart(t.lineIndex), controller.LineEnd(t.lineIndex)

	selections := controller.Selections()
	if t.textbox.selectionDragging {
		interval.Replace(&selections, t.textbox.selectionDrag)
	}
	interval.Visit(&selections, gxui.CreateTextSelection(ls, le, false), func(s, e uint64, _ int) {
		if s < e {
			x := t.outer.MeasureRunes(ls, int(s)).W
			m := t.outer.MeasureRunes(int(s), int(e))
			top := math.Point{X: t.caretWidth + x, Y: 0}
			bottom := top.Add(m.Point())
			t.outer.PaintSelection(c, top, bottom)
		}
	})
}
Пример #9
0
func (r *Redo) Exec(interface{}) (executed, consume bool) {
	if r.editor == nil {
		r.err = "redo: no file open"
		return true, true
	}
	history := r.editor.History()
	edit, ok := history.RedoCurrent()
	if !ok {
		r.warn = "redo: nothing to redo"
		return true, true
	}
	text, _ := r.editor.Controller().ReplaceAt(r.editor.Runes(), edit.At, edit.At+len(edit.Old), edit.New)
	r.editor.Controller().SetTextRunes(text)
	absDelta := edit.Delta
	if absDelta < 0 {
		absDelta = -absDelta
	}
	r.editor.Controller().SetSelection(gxui.CreateTextSelection(edit.At, edit.At+absDelta, true))
	r.editor.ScrollToRune(edit.At)
	return true, true
}
Пример #10
0
func (e *editor) KeyPress(event gxui.KeyboardEvent) bool {
	if event.Modifier.Control() || event.Modifier.Super() {
		switch event.Key {
		case gxui.KeySpace:
			e.ShowSuggestionList()
			return true
		case gxui.KeyS:
			if !e.lastModified.IsZero() {
				finfo, err := os.Stat(e.filepath)
				if err != nil {
					panic(err)
				}
				if finfo.ModTime().After(e.lastModified) {
					panic("Cannot save file: written since last open")
				}
			}
			f, err := os.Create(e.filepath)
			if err != nil {
				panic(err)
			}
			if !strings.HasSuffix(e.Text(), "\n") {
				e.SetText(e.Text() + "\n")
			}
			if _, err := f.WriteString(e.Text()); err != nil {
				panic(err)
			}
			finfo, err := f.Stat()
			if err != nil {
				panic(err)
			}
			e.lastModified = finfo.ModTime()
			f.Close()
			e.hasChanges = false
			return true
		case gxui.KeyTab:
			return false
		}
	}
	switch event.Key {
	case gxui.KeyTab:
		// TODO: Gain knowledge about scope, so we know how much to indent.
		switch {
		case event.Modifier.Shift():
			e.Controller().UnindentSelection(e.TabWidth())
		default:
			e.Controller().IndentSelection(e.TabWidth())
		}
		return true
	case gxui.KeyUp:
		fallthrough
	case gxui.KeyDown:
		if e.IsSuggestionListShowing() {
			return e.suggestions.KeyPress(event)
		}
	case gxui.KeyLeft:
		e.HideSuggestionList()
	case gxui.KeyRight:
		e.HideSuggestionList()
	case gxui.KeyEnter:
		controller := e.Controller()
		if e.IsSuggestionListShowing() {
			text := e.adapter.Suggestion(e.suggestions.Selected()).Code()
			start, end := controller.WordAt(controller.LastCaret())
			controller.SetSelection(gxui.CreateTextSelection(start, end, false))
			controller.ReplaceAll(text)
			controller.Deselect(false)
			e.HideSuggestionList()
		} else {
			// TODO: implement electric braces.  See
			// http://www.emacswiki.org/emacs/AutoPairs under
			// "Electric-RET".
			e.Controller().ReplaceWithNewlineKeepIndent()
		}
		return true
	case gxui.KeyEscape:
		if e.IsSuggestionListShowing() {
			e.HideSuggestionList()
			return true
		}
	}
	return e.CodeEditor.KeyPress(event)
}
Пример #11
0
func (e *CodeEditor) KeyPress(event gxui.KeyboardEvent) bool {
	defer e.storePositions()
	if event.Modifier != 0 && event.Modifier != gxui.ModShift {
		// ctrl-, alt-, and cmd-/super- keybindings should be dealt
		// with by the commands mapped to key bindings.
		return false
	}
	switch event.Key {
	case gxui.KeyPeriod:
		e.ShowSuggestionList()
		return true
	case gxui.KeyBackspace:
		result := e.TextBox.KeyPress(event)
		if e.IsSuggestionListShowing() {
			e.SortSuggestionList()
		}
		return result
	case gxui.KeyPageUp, gxui.KeyPageDown, gxui.KeyDelete:
		// These are all bindings that the TextBox handles fine.
		return e.TextBox.KeyPress(event)
	case gxui.KeyTab:
		// TODO: Gain knowledge about scope, so we know how much to indent.
		switch {
		case event.Modifier.Shift():
			e.Controller().UnindentSelection()
		default:
			e.Controller().IndentSelection()
		}
		return true
	case gxui.KeyUp, gxui.KeyDown:
		if e.IsSuggestionListShowing() {
			return e.suggestions.KeyPress(event)
		}
		return false
	case gxui.KeyLeft, gxui.KeyRight:
		if e.IsSuggestionListShowing() {
			e.HideSuggestionList()
		}
		return false
	case gxui.KeyEnter:
		controller := e.Controller()
		if e.IsSuggestionListShowing() {
			text := e.adapter.Suggestion(e.suggestions.Selected()).Code()
			start, end := controller.WordAt(controller.LastCaret())
			controller.SetSelection(gxui.CreateTextSelection(start, end, false))
			controller.ReplaceAll(text)
			controller.Deselect(false)
			e.HideSuggestionList()
			return true
		}
		// TODO: implement electric braces.  See
		// http://www.emacswiki.org/emacs/AutoPairs under
		// "Electric-RET".
		e.Controller().ReplaceWithNewlineKeepIndent()
		e.ScrollToRune(e.Controller().FirstCaret())
		return true
	case gxui.KeyEscape:
		if e.IsSuggestionListShowing() {
			e.HideSuggestionList()
			return true
		}
		// TODO: Keep track of some sort of concept of a "focused" caret and
		// focus that.
		e.Controller().SetCaret(e.Controller().FirstCaret())
	}
	return false
}