// Creates and initializes the frontend. func createFrontend() *tbfe { var t tbfe t.dorender = make(chan bool, render_chan_len) t.shutdown = make(chan bool, 2) t.layout = make(map[*backend.View]layout) t.editor = t.setupEditor() t.console = t.editor.Console() t.currentWindow = t.editor.NewWindow() // Assuming that all extra arguments are files if files := flag.Args(); len(files) > 0 { for _, file := range files { t.currentView = createNewView(file, t.currentWindow) } } else { t.currentView = t.currentWindow.NewFile() } t.console.Buffer().AddCallback(t.scroll) t.setupCallbacks(t.currentView) path := path.Join("..", "..", "3rdparty", "bundles", "TextMate-Themes", "Monokai.tmTheme") if sc, err := textmate.LoadTheme(path); err != nil { log.Error(err) } else { scheme = sc } setColorMode() setSchemeSettings() w, h := termbox.Size() t.handleResize(h, w, true) // These might take a while t.editor.Init() go sublime.Init() return &t }
func (t *tbfe) loop() { backend.OnNew.Add(func(v *backend.View) { v.Settings().AddOnChange("lime.frontend.html.render", func(name string) { t.dirty = true }) }) backend.OnModified.Add(func(v *backend.View) { t.dirty = true }) backend.OnSelectionModified.Add(func(v *backend.View) { t.dirty = true }) ed := backend.GetEditor() ed.SetFrontend(t) ed.LogInput(false) ed.LogCommands(false) c := ed.Console() if sc, err := textmate.LoadTheme("../../3rdparty/bundles/TextMate-Themes/GlitterBomb.tmTheme"); err != nil { log4go.Error(err) } else { scheme = sc } defer func() { fmt.Println(util.Prof) }() w := ed.NewWindow() v := w.OpenFile("main.go", 0) v.Settings().Set("trace", true) v.Settings().Set("syntax", "../../3rdparty/bundles/go.tmbundle/Syntaxes/Go.tmLanguage") c.Buffer().AddCallback(t.scroll) sel := v.Sel() sel.Clear() // end := v.Buffer().Size() - 2 sel.Add(Region{0, 0}) // sel.Add(Region{end - 22, end - 22}) // sel.Add(Region{end - 16, end - 20}) // sel.Add(Region{end - 13, end - 10}) { w, h := 800, 600 t.lock.Lock() t.layout[v] = layout{0, 0, w, h - console_height - 1, Region{}, 0} t.layout[c] = layout{0, h - console_height + 1, w, console_height - 5, Region{}, 0} t.lock.Unlock() t.Show(v, Region{1, 1}) } t.Show(v, Region{100, 100}) t.Show(v, Region{1, 1}) go func() { ed.Init() sublime.Init() }() log4go.Debug("serving") http.HandleFunc("/key", t.key) http.HandleFunc("/", t.ServeHTTP) http.HandleFunc("/view", t.view) if err := http.ListenAndServe("localhost:8080", nil); err != nil { log4go.Error("Error serving: %s", err) } log4go.Debug("Done") }
func (t *qmlfrontend) loop() (err error) { backend.OnNew.Add(func(v *backend.View) { fv := &frontendView{bv: v} v.Buffer().AddCallback(fv.bufferChanged) v.Settings().AddOnChange("blah", func(name string) { if name == "lime.syntax.updated" { // force redraw, as the syntax regions might have changed... for i := range fv.FormattedLine { fv.formatLine(i) } } }) fv.Title.Text = v.Buffer().FileName() if len(fv.Title.Text) == 0 { fv.Title.Text = "untitled" } w2 := t.windows[v.Window()] w2.views = append(w2.views, fv) w2.Len = len(w2.views) t.qmlChanged(w2, &w2.Len) }) backend.OnClose.Add(func(v *backend.View) { w2 := t.windows[v.Window()] for i := range w2.views { if w2.views[i].bv == v { copy(w2.views[i:], w2.views[i+1:]) w2.views = w2.views[:len(w2.views)-1] w2.Len = len(w2.views) t.qmlChanged(w2, &w2.Len) return } } log4go.Error("Couldn't find closed view...") }) backend.OnLoad.Add(func(v *backend.View) { w2 := t.windows[v.Window()] i := 0 for i, _ = range w2.views { if w2.views[i].bv == v { break } } v2 := w2.views[i] v2.Title.Text = v.Buffer().FileName() t.qmlChanged(v2, &v2.Title) }) ed := backend.GetEditor() ed.SetFrontend(t) ed.LogInput(false) ed.LogCommands(false) c := ed.Console() t.Console = &frontendView{bv: c} c.Buffer().AddCallback(t.Console.bufferChanged) c.Buffer().AddCallback(t.scroll) const qmlMainFile = "main.qml" 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 { log4go.Debug("calling destroy") // TODO(.): calling this appears to make the editor *very* crash-prone, just let it leak for now // engine.Destroy() engine = nil } log4go.Debug("calling newEngine") engine = qml.NewEngine() log4go.Debug("setvar frontend") engine.Context().SetVar("frontend", t) log4go.Debug("setvar editor") engine.Context().SetVar("editor", backend.GetEditor()) log4go.Debug("loadfile") component, err = engine.LoadFile(qmlMainFile) return } if err := newEngine(); err != nil { log4go.Error(err) } backend.OnNewWindow.Add(func(w *backend.Window) { fw := &frontendWindow{bw: w} t.windows[w] = fw if component != nil { fw.launch(&wg, component) } }) // TODO: should be done backend side if sc, err := textmate.LoadTheme("../../3rdparty/bundles/TextMate-Themes/Monokai.tmTheme"); err != nil { log4go.Error(err) } else { scheme = sc } defer func() { fmt.Println(util.Prof) }() w := ed.NewWindow() v := w.OpenFile("main.go", 0) // TODO: should be done backend side v.Settings().Set("syntax", "../../3rdparty/bundles/go.tmbundle/Syntaxes/Go.tmLanguage") v.Sel().Clear() v.Sel().Add(Region{0, 0}) v = w.OpenFile("../../backend/editor.go", 0) // TODO: should be done backend side v.Settings().Set("syntax", "../../3rdparty/bundles/go.tmbundle/Syntaxes/Go.tmLanguage") v.Sel().Clear() v.Sel().Add(Region{0, 0}) ed.Init() sublime.Init() watch, err := fsnotify.NewWatcher() if err != nil { log4go.Error("Unable to create file watcher: %s", err) return } defer watch.Close() watch.Watch(".") defer watch.RemoveWatch(".") reloadRequested := false go func() { for { select { case ev := <-watch.Event: if ev != nil && strings.HasSuffix(ev.Name, ".qml") && ev.IsModify() && !ev.IsAttrib() { reloadRequested = true // Close all open windows to de-reference all // qml objects for _, v := range t.windows { if v.window != nil { v.window.Hide() v.window.Destroy() v.window = nil } } } } } }() for { // Reset reload status reloadRequested = false log4go.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. wg.Wait() log4go.Debug("All windows closed. reloadRequest: %v", reloadRequested) // then we check if there's a reload request in the pipe if !reloadRequested || len(t.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 { log4go.Debug("Calling newEngine") if err := newEngine(); err != nil { // Reset reload status reloadRequested = false log4go.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) } continue } log4go.Debug("break") break } log4go.Debug("re-launching all windows") // Succeeded loading the file, re-launch all windows for _, v := range t.windows { v.launch(&wg, component) } } return }
func (t *tbfe) loop() { var ( ed = t.setupEditor() c = ed.Console() w = ed.NewWindow() v *backend.View ) // Assuming that all extra arguments are files if files := flag.Args(); len(files) > 0 { for _, file := range files { v = createNewView(file, w) } } else { v = w.NewFile() } c.Buffer().AddCallback(t.scroll) t.setupCallbacks(v) path := "../../3rdparty/bundles/TextMate-Themes/Monokai.tmTheme" if sc, err := textmate.LoadTheme(path); err != nil { log4go.Error(err) return } else { scheme = sc } setColorMode() setSchemeSettings() // We start the renderThread here, after we have done our setup of termbox. // That way, we do not clash with our output. go t.renderthread() evchan := make(chan termbox.Event, 32) defer func() { close(evchan) }() go func() { for { evchan <- termbox.PollEvent() } }() { w, h := termbox.Size() t.lock.Lock() if *showConsole { t.layout[v] = layout{0, 0, w, h - *consoleHeight - 4, Region{}, 0} t.layout[c] = layout{0, h - *consoleHeight - 2, w, *consoleHeight - 1, Region{}, 0} } else { t.layout[v] = layout{0, 0, w, h - 3, Region{}, 0} } t.lock.Unlock() t.Show(v, Region{1, 1}) } t.Show(v, Region{100, 100}) t.Show(v, Region{1, 1}) go func() { ed.Init() sublime.Init() }() for { p := util.Prof.Enter("mainloop") blink_phase := time.Second if p, ok := ed.Settings().Get("caret_blink_phase", 1.0).(float64); ok { blink_phase = time.Duration(float64(time.Second) * p) } // Divided by two since we're only doing a simple toggle blink timer := time.NewTimer(blink_phase / 2) select { case ev := <-evchan: mp := util.Prof.Enter("evchan") limit := 3 loop: switch ev.Type { case termbox.EventError: log4go.Debug("error occured") return case termbox.EventResize: // We have to resize our layouts... // There is currently duplicate code for calculating the layout: // during initialization (above), and here. Not nice if *showConsole { view_layout := t.layout[v] view_layout.height = ev.Height - *consoleHeight - 4 view_layout.width = ev.Width console_layout := t.layout[c] console_layout.y = ev.Height - *consoleHeight - 2 console_layout.width = ev.Width t.layout[v] = view_layout t.layout[c] = console_layout } else { view_layout := t.layout[v] view_layout.height = ev.Height - 3 view_layout.width = ev.Width t.layout[v] = view_layout } // Ensure that the new visible region is recalculated t.Show(v, t.VisibleRegion(v)) case termbox.EventKey: var kp backend.KeyPress if ev.Ch != 0 { kp.Key = backend.Key(ev.Ch) } else if v2, ok := lut[ev.Key]; ok { kp = v2 } else { break } if ev.Key == termbox.KeyCtrlQ { return } ed.HandleInput(kp) blink = false } if len(evchan) > 0 { limit-- ev = <-evchan goto loop } mp.Exit() case <-timer.C: // TODO(q): Shouldn't redraw if blink is disabled... blink = !blink t.render() } timer.Stop() p.Exit() } }
func (t *tbfe) loop() { qml.Init(nil) engine := qml.NewEngine() engine.Context().SetVar("lines", t) engine.Context().SetVar("frontend", t) engine.Context().SetVar("editor", backend.GetEditor()) backend.OnNew.Add(func(v *backend.View) { fv := &frontendView{bv: v} v.Buffer().AddCallback(fv.bufferChanged) v.Settings().AddOnChange("blah", func(name string) { if name == "lime.syntax.updated" { // force redraw, as the syntax regions might have changed... for i := range fv.FormattedLine { fv.formatLine(i) } } }) t.views[v] = fv t.Len = len(t.views) qml.Changed(t, &t.Len) }) ed := backend.GetEditor() ed.SetFrontend(t) ed.LogInput(false) ed.LogCommands(false) c := ed.Console() t.Console = &frontendView{bv: c} c.Buffer().AddCallback(t.Console.bufferChanged) if sc, err := textmate.LoadTheme("../../3rdparty/bundles/TextMate-Themes/GlitterBomb.tmTheme"); err != nil { log4go.Error(err) } else { scheme = sc } defer func() { fmt.Println(util.Prof) }() w := ed.NewWindow() v := w.OpenFile("main.go", 0) v.Settings().Set("trace", true) v.Settings().Set("syntax", "../../3rdparty/bundles/go.tmbundle/Syntaxes/Go.tmLanguage") c.Buffer().AddCallback(t.scroll) sel := v.Sel() sel.Clear() sel.Add(Region{0, 0}) { w, h := 800, 600 t.lock.Lock() t.layout[v] = layout{0, 0, w, h - console_height - 1, Region{}, 0} t.layout[c] = layout{0, h - console_height + 1, w, console_height - 5, Region{}, 0} t.lock.Unlock() t.Show(v, Region{1, 1}) } t.Show(v, Region{100, 100}) t.Show(v, Region{1, 1}) // t.Len, _ = v.Buffer().RowCol(v.Buffer().Size()) ed.Init() sublime.Init() component, err := engine.LoadFile("main.qml") if err != nil { log4go.Exit(err) } window := component.CreateWindow(nil) window.Show() log4go.Debug("Done") window.Wait() }
func (t *qmlfrontend) loop() (err error) { backend.OnNew.Add(t.onNew) backend.OnClose.Add(t.onClose) backend.OnLoad.Add(t.onLoad) ed := backend.GetEditor() ed.Init() go sublime.Init() ed.SetFrontend(t) ed.LogInput(false) ed.LogCommands(false) c := ed.Console() t.Console = &frontendView{bv: c} c.Buffer().AddObserver(t.Console) c.Buffer().AddObserver(t) 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() log.Debug("setvar frontend") engine.Context().SetVar("frontend", t) log.Debug("setvar editor") engine.Context().SetVar("editor", backend.GetEditor()) log.Debug("loadfile") component, err = engine.LoadFile(qmlMainFile) if err != nil { return err } limeViewComponent, err = engine.LoadFile(qmlViewFile) return } if err := newEngine(); err != nil { log.Error(err) } backend.OnNewWindow.Add(func(w *backend.Window) { fw := &frontendWindow{bw: w} t.windows[w] = fw if component != nil { fw.launch(&wg, component) } }) // TODO: should be done backend side if sc, err := textmate.LoadTheme("../../packages/themes/TextMate-Themes/Monokai.tmTheme"); err != nil { log.Error(err) } else { scheme = sc } defer func() { fmt.Println(util.Prof) }() w := ed.NewWindow() v := w.OpenFile("main.go", 0) // TODO: should be done backend side v.Settings().Set("syntax", "../../packages/go.tmbundle/Syntaxes/Go.tmLanguage") v = w.OpenFile("../../backend/editor.go", 0) // TODO: should be done backend side v.Settings().Set("syntax", "../../packages/go.tmbundle/Syntaxes/Go.tmLanguage") watch, err := fsnotify.NewWatcher() if err != nil { log.Errorf("Unable to create file watcher: %s", err) return } defer watch.Close() watch.Watch(".") defer watch.RemoveWatch(".") reloadRequested := false go func() { for { select { case ev := <-watch.Event: if ev != nil && strings.HasSuffix(ev.Name, ".qml") && ev.IsModify() && !ev.IsAttrib() { reloadRequested = true // Close all open windows to de-reference all // qml objects for _, v := range t.windows { if v.window != nil { v.window.Hide() v.window.Destroy() v.window = nil } } } } } }() 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. wg.Wait() log.Debug("All windows closed. reloadRequest: %v", reloadRequested) // then we check if there's a reload request in the pipe if !reloadRequested || len(t.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 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) } continue } log.Debug("break") break } log.Debug("re-launching all windows") // Succeeded loading the file, re-launch all windows for _, v := range t.windows { v.launch(&wg, component) } } return }
func (t *tbfe) loop() { var ( ed = t.setupEditor() c = ed.Console() w = ed.NewWindow() v = createNewView("main.go", w) sel = v.Sel() ) t.settings = getSettings(v) c.Buffer().AddCallback(t.scroll) t.setupCallbacks(v) loadTextMateScheme() setColorMode() setSchemeSettings() sel.Clear() sel.Add(Region{0, 0}) evchan := make(chan termbox.Event, 32) defer func() { close(evchan) fmt.Println(util.Prof) }() go func() { for { evchan <- termbox.PollEvent() } }() { w, h := termbox.Size() t.lock.Lock() t.layout[v] = layout{0, 0, w, h - console_height - 1, Region{}, 0} t.layout[c] = layout{0, h - console_height + 1, w, console_height - 5, Region{}, 0} t.lock.Unlock() t.Show(v, Region{1, 1}) } t.Show(v, Region{100, 100}) t.Show(v, Region{1, 1}) go func() { ed.Init() sublime.Init() }() for { p := util.Prof.Enter("mainloop") blink_phase := time.Second if p, ok := ed.Settings().Get("caret_blink_phase", 1.0).(float64); ok { blink_phase = time.Duration(float64(time.Second) * p) } // Divided by two since we're only doing a simple toggle blink timer := time.NewTimer(blink_phase / 2) select { case ev := <-evchan: mp := util.Prof.Enter("evchan") limit := 3 loop: switch ev.Type { case termbox.EventError: log4go.Debug("error occured") return case termbox.EventKey: var kp backend.KeyPress if ev.Ch != 0 { kp.Key = backend.Key(ev.Ch) } else if v2, ok := lut[ev.Key]; ok { kp = v2 } else { break } if ev.Key == termbox.KeyCtrlQ { return } ed.HandleInput(kp) blink = false } if len(evchan) > 0 { limit-- ev = <-evchan goto loop } mp.Exit() case <-timer.C: // TODO(q): Shouldn't redraw if blink is disabled... blink = !blink t.render() } timer.Stop() p.Exit() } }
func (t *tbfe) loop() { backend.OnNew.Add(func(v *backend.View) { v.Settings().AddOnChange("lime.frontend.html.render", func(name string) { if name != "lime.syntax.updated" { return } t.SetDirty() }) }) // TODO: maybe not useful? /*backend.OnModified.Add(func(v *backend.View) { t.SetDirty() })*/ backend.OnSelectionModified.Add(func(v *backend.View) { t.BroadcastData(t.GetSelectionMessage(v)) }) ed := backend.GetEditor() ed.SetFrontend(t) ed.LogInput(false) ed.LogCommands(false) c := ed.Console() if sc, err := textmate.LoadTheme("../../packages/themes/TextMate-Themes/Monokai.tmTheme"); err != nil { log.Error(err) } else { scheme = sc } defer func() { fmt.Println(util.Prof) }() w := ed.NewWindow() v := w.OpenFile("main.go", 0) //v.Settings().Set("trace", true) v.Settings().Set("syntax", "../../packages/go.tmbundle/Syntaxes/Go.tmLanguage") c.Buffer().AddObserver(t) sel := v.Sel() sel.Clear() // end := v.Buffer().Size() - 2 sel.Add(Region{0, 0}) // sel.Add(Region{end - 22, end - 22}) // sel.Add(Region{end - 16, end - 20}) // sel.Add(Region{end - 13, end - 10}) { w, h := 800, 600 t.lock.Lock() t.layout[v] = layout{0, 0, w, h - console_height - 1, Region{}, 0} t.layout[c] = layout{0, h - console_height + 1, w, console_height - 5, Region{}, 0} t.lock.Unlock() t.Show(v, Region{1, 1}) } t.Show(v, Region{100, 100}) t.Show(v, Region{1, 1}) go func() { ed.Init() sublime.Init() }() log.Debug("Serving on port %d", *port) http.HandleFunc("/", t.ServeHTTP) http.HandleFunc("/view", t.view) http.HandleFunc("/key", t.key) http.HandleFunc("/themes/", t.theme) http.Handle("/ws", websocket.Handler(t.WebsocketServer)) if err := http.ListenAndServe(fmt.Sprintf("localhost:%d", *port), nil); err != nil { log.Errorf("Error serving: %s", err) } log.Debug("Done") }
func (t *tbfe) loop() { qml.Init(nil) engine := qml.NewEngine() engine.Context().SetVar("lines", t) engine.Context().SetVar("frontend", t) engine.Context().SetVar("editor", backend.GetEditor()) backend.OnNew.Add(func(v *backend.View) { fv := &frontendView{bv: v} v.Buffer().AddCallback(fv.bufferChanged) v.Settings().AddOnChange("blah", func(name string) { if name == "lime.syntax.updated" { // force redraw, as the syntax regions might have changed... for i := range fv.FormattedLine { fv.formatLine(i) } } }) fv.Title.Text = v.Buffer().FileName() if len(fv.Title.Text) == 0 { fv.Title.Text = "untitled" } w2 := t.windows[v.Window()] w2.views = append(w2.views, fv) w2.Len = len(w2.views) t.qmlChanged(w2, &w2.Len) }) backend.OnLoad.Add(func(v *backend.View) { w2 := t.windows[v.Window()] i := 0 for i, _ = range w2.views { if w2.views[i].bv == v { break } } v2 := w2.views[i] v2.Title.Text = v.Buffer().FileName() t.qmlChanged(v2, &v2.Title) }) ed := backend.GetEditor() ed.SetFrontend(t) ed.LogInput(false) ed.LogCommands(false) c := ed.Console() t.Console = &frontendView{bv: c} c.Buffer().AddCallback(t.Console.bufferChanged) c.Buffer().AddCallback(t.scroll) component, err := engine.LoadFile("main.qml") if err != nil { log4go.Exit(err) } wg := sync.WaitGroup{} backend.OnNewWindow.Add(func(w *backend.Window) { wg.Add(1) fw := &frontendWindow{bw: w, window: component.CreateWindow(nil)} t.windows[w] = fw fw.window.Show() fw.window.Set("myWindow", fw) go func() { fw.window.Wait() wg.Done() }() }) // TODO: should be done backend side if sc, err := textmate.LoadTheme("../../3rdparty/bundles/TextMate-Themes/GlitterBomb.tmTheme"); err != nil { log4go.Error(err) } else { scheme = sc } defer func() { fmt.Println(util.Prof) }() w := ed.NewWindow() v := w.OpenFile("main.go", 0) // TODO: should be done backend side v.Settings().Set("syntax", "../../3rdparty/bundles/go.tmbundle/Syntaxes/Go.tmLanguage") v = w.OpenFile("../../backend/editor.go", 0) // TODO: should be done backend side v.Settings().Set("syntax", "../../3rdparty/bundles/go.tmbundle/Syntaxes/Go.tmLanguage") ed.Init() sublime.Init() wg.Wait() }
func (t *tbfe) loop() { var ( ed = t.setupEditor() c = ed.Console() w = ed.NewWindow() v *backend.View ) // Assuming that all extra arguments are files if files := flag.Args(); len(files) > 0 { for _, file := range files { v = createNewView(file, w) } } else { v = w.NewFile() } t.settings = getSettings(v) c.Buffer().AddCallback(t.scroll) t.setupCallbacks(v) path := "../../3rdparty/bundles/TextMate-Themes/GlitterBomb.tmTheme" if sc, err := textmate.LoadTheme(path); err != nil { log4go.Error(err) return } else { scheme = sc } setColorMode() setSchemeSettings() evchan := make(chan termbox.Event, 32) defer func() { close(evchan) fmt.Println(util.Prof) }() go func() { for { evchan <- termbox.PollEvent() } }() { w, h := termbox.Size() t.lock.Lock() if *showConsole { t.layout[v] = layout{0, 0, w, h - *consoleHeight - 4, Region{}, 0} t.layout[c] = layout{0, h - *consoleHeight - 2, w, *consoleHeight - 1, Region{}, 0} } else { t.layout[v] = layout{0, 0, w, h - 3, Region{}, 0} } t.lock.Unlock() t.Show(v, Region{1, 1}) } t.Show(v, Region{100, 100}) t.Show(v, Region{1, 1}) go func() { ed.Init() sublime.Init() }() for { p := util.Prof.Enter("mainloop") blink_phase := time.Second if p, ok := ed.Settings().Get("caret_blink_phase", 1.0).(float64); ok { blink_phase = time.Duration(float64(time.Second) * p) } // Divided by two since we're only doing a simple toggle blink timer := time.NewTimer(blink_phase / 2) select { case ev := <-evchan: mp := util.Prof.Enter("evchan") limit := 3 loop: switch ev.Type { case termbox.EventError: log4go.Debug("error occured") return case termbox.EventKey: var kp backend.KeyPress if ev.Ch != 0 { kp.Key = backend.Key(ev.Ch) } else if v2, ok := lut[ev.Key]; ok { kp = v2 } else { break } if ev.Key == termbox.KeyCtrlQ { return } ed.HandleInput(kp) blink = false } if len(evchan) > 0 { limit-- ev = <-evchan goto loop } mp.Exit() case <-timer.C: // TODO(q): Shouldn't redraw if blink is disabled... blink = !blink t.render() } timer.Stop() p.Exit() } }
func (t *tbfe) loop() { qml.Init(nil) engine := qml.NewEngine() engine.Context().SetVar("lines", t) engine.Context().SetVar("frontend", t) engine.Context().SetVar("editor", backend.GetEditor()) backend.OnNew.Add(func(v *backend.View) { v.Settings().AddOnChange("lime.frontend.html.render", func(name string) { t.dirty = true }) }) backend.OnModified.Add(func(v *backend.View) { t.dirty = true }) backend.OnSelectionModified.Add(func(v *backend.View) { t.dirty = true }) ed := backend.GetEditor() ed.SetFrontend(t) ed.LogInput(false) ed.LogCommands(false) c := ed.Console() if sc, err := textmate.LoadTheme("../../3rdparty/bundles/TextMate-Themes/GlitterBomb.tmTheme"); err != nil { log4go.Error(err) } else { scheme = sc } defer func() { fmt.Println(util.Prof) }() w := ed.NewWindow() v := w.OpenFile("main.go", 0) v.Settings().Set("trace", true) v.Settings().Set("syntax", "../../3rdparty/bundles/go.tmbundle/Syntaxes/Go.tmLanguage") c.Buffer().AddCallback(t.scroll) sel := v.Sel() sel.Clear() sel.Add(Region{0, 0}) { w, h := 800, 600 t.lock.Lock() t.layout[v] = layout{0, 0, w, h - console_height - 1, Region{}, 0} t.layout[c] = layout{0, h - console_height + 1, w, console_height - 5, Region{}, 0} t.lock.Unlock() t.Show(v, Region{1, 1}) } t.Show(v, Region{100, 100}) t.Show(v, Region{1, 1}) t.Len, _ = v.Buffer().RowCol(v.Buffer().Size()) ed.Init() sublime.Init() component, err := engine.LoadFile("main.qml") if err != nil { log4go.Exit(err) } window := component.CreateWindow(nil) window.Show() qml.Changed(t, &t.Len) log4go.Debug("Done") window.Wait() }