Пример #1
0
func (f *frontend) Prompt(title, folder string, flags int) []string {
	w := f.windows[backend.GetEditor().ActiveWindow()]
	obj := w.qw.ObjectByName("fileDialog")
	obj.Set("title", title)
	obj.Set("folder", "file://"+folder)
	obj.Set("selectExisting", flags&backend.PROMPT_SAVE_AS == 0)
	obj.Set("selectFolder", flags&backend.PROMPT_ONLY_FOLDER == 1)
	obj.Set("selectMultiple", flags&backend.PROMPT_SELECT_MULTIPLE == 1)

	f.promptWaitGroup.Add(1)
	obj.Call("open")
	f.promptWaitGroup.Wait()

	if f.promptResult != "accepted" {
		return nil
	}

	res := obj.List("fileUrls")
	files := make([]string, res.Len())
	res.Convert(&files)
	for i, file := range files {
		if file[:7] == "file://" {
			files[i] = file[7:]
		}
	}
	log.Fine("Selected %s files", files)
	return files
}
Пример #2
0
func newView(bv *backend.View) *view {
	v := &view{
		id:    int(bv.Id()),
		bv:    bv,
		Title: bv.FileName(),
	}
	if len(v.Title) == 0 {
		v.Title = "untitled"
	}
	bv.AddObserver(v)
	bv.Settings().AddOnChange("qml.view.syntax", v.onChange)
	bv.Settings().AddOnChange("qml.view.syntaxfile", func(name string) {
		if name != "syntax" {
			return
		}
		syn := bv.Settings().String("syntax", "Plain Text")
		syntax := backend.GetEditor().GetSyntax(syn)
		w := fe.windows[bv.Window()]
		w.qw.Call("setSyntaxStatus", syntax.Name())
	})
	bv.Settings().AddOnChange("qml.view.tabSize", func(name string) {
		if name != "tab_size" {
			return
		}
		ts := bv.Settings().Int("tab_size", 4)
		w := fe.windows[bv.Window()]
		w.qw.Call("setIndentStatus", strconv.Itoa(ts))
	})
	return v
}
Пример #3
0
func (f *frontend) StatusMessage(msg string) {
	w := f.windows[backend.GetEditor().ActiveWindow()]
	w.qw.Call("setFrontendStatus", msg)
	go func() {
		time.Sleep(5 * time.Second)
		w.qw.Call("setFrontendStatus", "")
	}()
}
Пример #4
0
func (t *tbfe) setupEditor() *backend.Editor {
	ed := backend.GetEditor()
	ed.SetFrontend(t)
	ed.LogInput(false)
	ed.LogCommands(false)

	return ed
}
Пример #5
0
func TestUpdateVisibleRegion(t *testing.T) {
	var (
		fe tbfe
		e  = backend.GetEditor()
		w  = e.NewWindow()
		v  = w.NewFile()
	)

	fe.layout = make(map[*backend.View]layout)
	fe.layout[v] = layout{0, 0, 100, 100 - *consoleHeight - 1, Region{}, 0}
	fe.setupCallbacks(v)

	edit := v.BeginEdit()
	v.Insert(edit, 0, "foo")
	v.EndEdit(edit)

	if end := fe.layout[v].visible.End(); end != 3 {
		t.Fatalf("Expected 3, got %d", end)
	}
}
Пример #6
0
func (f *frontend) message(text string, icon, btns int) string {
	cbs := make(map[string]int)
	if btns&okButton != 0 {
		cbs["accepted"] = 1
	}
	if btns&cancelButton != 0 {
		cbs["rejected"] = 0
	}

	w := f.windows[backend.GetEditor().ActiveWindow()]
	obj := w.qw.ObjectByName("messageDialog")
	obj.Set("text", text)
	obj.Set("icon", icon)
	obj.Set("standardButtons", btns)

	f.promptWaitGroup.Add(1)
	obj.Call("open")
	f.promptWaitGroup.Wait()

	log.Fine("returning %d from dialog", f.promptResult)
	return f.promptResult
}
Пример #7
0
func (f *frontend) HandleInput(text string, keycode int, modifiers int) bool {
	log.Debug("frontend.HandleInput: text=%v, key=%x, modifiers=%x", text, keycode, modifiers)
	shift := false
	alt := false
	ctrl := false
	super := false

	if key, ok := lut[keycode]; ok {
		ed := backend.GetEditor()

		if modifiers&shift_mod != 0 {
			shift = true
		}
		if modifiers&alt_mod != 0 {
			alt = true
		}
		if modifiers&ctrl_mod != 0 {
			if runtime.GOOS == "darwin" {
				super = true
			} else {
				ctrl = true
			}
		}
		if modifiers&meta_mod != 0 {
			if runtime.GOOS == "darwin" {
				ctrl = true
			} else {
				super = true
			}
		}

		ed.HandleInput(keys.KeyPress{Text: text, Key: key, Shift: shift, Alt: alt, Ctrl: ctrl, Super: super})
		return true
	}
	return false
}
Пример #8
0
func (f *frontend) loop() (err error) {
	ed := backend.GetEditor()
	// TODO: As InitCallback doc says initiation code to be deferred until
	// after the UI is up and running. but because we dont have any
	// scheme we are initing editor before the UI comes up.
	ed.Init()
	ed.SetDefaultPath("../packages/Default")
	ed.SetUserPath("../packages/User")
	ed.SetClipboardFuncs(clipboard.WriteAll, clipboard.ReadAll)

	// Some packages(e.g Vintageos) need available window and view at start
	// so we need at least one window and view before loading packages.
	// Sublime text also has available window view on startup
	w := ed.NewWindow()
	w.NewFile()
	ed.AddPackagesPath("../packages")

	ed.SetFrontend(f)
	ed.LogInput(false)
	ed.LogCommands(false)

	c := ed.Console()
	f.Console = newView(c)
	c.AddObserver(f.Console)
	c.AddObserver(f)

	var (
		engine    *qml.Engine
		component qml.Object
		// WaitGroup keeping track of open windows
		wg sync.WaitGroup
	)

	// create and setup a new engine, destroying
	// the old one if one exists.
	//
	// This is needed to re-load qml files to get
	// the new file contents from disc as otherwise
	// the old file would still be what is referenced.
	newEngine := func() (err error) {
		if engine != nil {
			log.Debug("calling destroy")
			// TODO(.): calling this appears to make the editor *very* crash-prone, just let it leak for now
			// engine.Destroy()
			engine = nil
		}
		log.Debug("calling newEngine")
		engine = qml.NewEngine()
		engine.On("quit", f.Quit)
		log.Fine("setvar frontend")
		engine.Context().SetVar("frontend", f)

		log.Fine("loading %s", qmlWindowFile)
		component, err = engine.LoadFile(qmlWindowFile)
		return
	}
	if err := newEngine(); err != nil {
		log.Error("Error on creating new engine: %s", err)
		panic(err)
	}

	addWindow := func(bw *backend.Window) {
		w := newWindow(bw)
		f.windows[bw] = w
		w.launch(&wg, component)
	}

	backend.OnNew.Add(f.onNew)
	backend.OnClose.Add(f.onClose)
	backend.OnLoad.Add(f.onLoad)
	backend.OnSelectionModified.Add(f.onSelectionModified)
	backend.OnNewWindow.Add(addWindow)
	backend.OnStatusChanged.Add(f.onStatusChanged)

	// we need to add windows and views that are added before we registered
	// actions for OnNewWindow and OnNew events
	for _, w := range ed.Windows() {
		addWindow(w)
		for _, v := range w.Views() {
			f.onNew(v)
			f.onLoad(v)
		}
	}

	defer func() {
		fmt.Println(util.Prof)
	}()

	// The rest of code is related to livereloading qml files
	// TODO: this doesnt work currently
	watch, err := fsnotify.NewWatcher()
	if err != nil {
		log.Error("Unable to create file watcher: %s", err)
		return
	}
	defer watch.Close()
	watch.Add("qml")
	defer watch.Remove("qml")

	reloadRequested := false
	waiting := false

	go func() {
		// reloadRequested = true
		// f.Quit()

		lastTime := time.Now()

		for {

			select {
			case ev := <-watch.Events:
				if time.Now().Sub(lastTime) < 1*time.Second {
					// quitting too frequently causes crashes
					lastTime = time.Now()
					continue
				}
				if strings.HasSuffix(ev.Name, ".qml") && ev.Op == fsnotify.Write && ev.Op != fsnotify.Chmod && !reloadRequested && waiting {
					reloadRequested = true
					f.Quit()
					lastTime = time.Now()
				}
			}
		}
	}()

	for {
		// Reset reload status
		reloadRequested = false

		log.Debug("Waiting for all windows to close")
		// wg would be the WaitGroup all windows belong to, so first we wait for
		// all windows to close.
		waiting = true
		wg.Wait()
		waiting = false
		log.Debug("All windows closed. reloadRequest: %v", reloadRequested)
		// then we check if there's a reload request in the pipe
		if !reloadRequested || len(f.windows) == 0 {
			// This would be a genuine exit; all windows closed by the user
			break
		}

		// *We* closed all windows because we want to reload freshly changed qml
		// files.
		for {
			log.Debug("Calling newEngine")
			if err := newEngine(); err != nil {
				// Reset reload status
				reloadRequested = false
				waiting = true
				log.Error(err)
				for !reloadRequested {
					// This loop allows us to re-try reloading
					// if there was an error in the file this time,
					// we just loop around again when we receive the next
					// reload request (ie on the next save of the file).
					time.Sleep(time.Second)
				}
				waiting = false
				continue
			}
			log.Debug("break")
			break
		}
		log.Debug("re-launching all windows")
		// Succeeded loading the file, re-launch all windows
		for _, w := range f.windows {
			w.launch(&wg, component)

			for _, bv := range w.Back().Views() {
				f.onNew(bv)
				f.onLoad(bv)

			}
		}
	}

	return
}
Пример #9
0
func (f *frontend) colorScheme() backend.ColorScheme {
	ed := backend.GetEditor()
	return ed.GetColorScheme(ed.Settings().String("color_scheme", ""))
}
Пример #10
0
func (f *frontend) RunCommandWithArgs(command string, args backend.Args) {
	ed := backend.GetEditor()
	go ed.RunCommand(command, args)
}
Пример #11
0
func (f *frontend) scroll(b Buffer) {
	f.Show(backend.GetEditor().Console(), Region{b.Size(), b.Size()})
}
Пример #12
0
func (t *tbfe) scroll(b Buffer) {
	t.Show(backend.GetEditor().Console(), Region{b.Size(), b.Size()})
}