Beispiel #1
0
func TestWebView_Title(t *testing.T) {
	webView := NewWebView()
	defer webView.Destroy()

	wantTitle := "foo"
	var gotTitle string
	webView.Connect("notify::title", func() {
		glib.IdleAdd(func() bool {
			gotTitle = webView.Title()
			if gotTitle != "" {
				gtk.MainQuit()
			}
			return false
		})
	})

	glib.IdleAdd(func() bool {
		webView.LoadHTML("<html><head><title>"+wantTitle+"</title></head><body></body></html>", "")
		return false
	})

	gtk.Main()

	if wantTitle != gotTitle {
		t.Errorf("want title %q, got %q", wantTitle, gotTitle)
	}
}
Beispiel #2
0
func TestWebView_URI(t *testing.T) {
	setup()
	defer teardown()

	mux.HandleFunc("/", func(w http.ResponseWriter, _ *http.Request) {})

	wantURI := server.URL + "/"
	var gotURI string
	webView.Connect("notify::uri", func() {
		glib.IdleAdd(func() bool {
			gotURI = webView.URI()
			if gotURI != "" {
				gtk.MainQuit()
			}
			return false
		})
	})

	glib.IdleAdd(func() bool {
		webView.LoadURI(server.URL)
		return false
	})

	gtk.Main()

	if wantURI != gotURI {
		t.Errorf("want URI %q, got %q", wantURI, gotURI)
	}
}
Beispiel #3
0
func (app *Applet) createGui(init, show bool) {
	if app.gui != nil {
		glib.IdleAdd(func() {
			app.Window().SetVisibility(show)
		})
		return
	}

	glib.IdleAdd(func() {
		app.gui, app.win = guigtk.NewGui(app.cp)
		if app.gui == nil {
			return
		}
		app.gui.Load()

		app.win.SetIconFromFile(app.FileLocation("icon")) // TODO: debug  path.Join(localDir, "data/icon.png")
		app.win.Connect("delete-event", func() bool { app.gui, app.win = nil, nil; return false })
		// app.win.Connect("delete-event", func() bool { window.Iconify(); return true })

		if init {
			app.cpInit()
		}
		if !show {
			app.win.Iconify()
		}
	})
}
Beispiel #4
0
// EvaluateJavaScript runs the JavaScript in script in the view's context and
// returns the script's result as a Go value.
func (v *View) EvaluateJavaScript(script string) (result interface{}, err error) {
	resultChan := make(chan interface{}, 1)
	errChan := make(chan error, 1)

	glib.IdleAdd(func() bool {
		v.WebView.RunJavaScript(script, func(result *gojs.Value, err error) {
			glib.IdleAdd(func() bool {
				if err == nil {
					goval, err := result.GoValue()
					if err != nil {
						errChan <- err
						return false
					}
					resultChan <- goval
				} else {
					errChan <- err
				}
				return false
			})
		})
		return false
	})

	select {
	case result = <-resultChan:
		return result, nil
	case err = <-errChan:
		return nil, err
	}
}
func main() {
	gtk.Init(nil)

	win, err := gtk.WindowNew(gtk.WINDOW_TOPLEVEL)
	if err != nil {
		log.Fatal("Unable to create window:", err)
	}
	win.Connect("destroy", func() {
		gtk.MainQuit()
	})

	win.Add(windowWidget())

	// Native GTK is not thread safe, and thus, gotk3's GTK bindings may not
	// be used from other goroutines.  Instead, glib.IdleAdd() must be used
	// to add a function to run in the GTK main loop when it is in an idle
	// state.
	//
	// Two examples of using glib.IdleAdd() are shown below.  The first runs
	// a user created function, LabelSetTextIdle, and passes it two
	// arguments for a label and the text to set it with.  The second calls
	// (*gtk.Label).SetText directly, passing in only the text as an
	// argument.
	//
	// If the function passed to glib.IdleAdd() returns one argument, and
	// that argument is a bool, this return value will be used in the same
	// manner as a native g_idle_add() call.  If this return value is false,
	// the function will be removed from executing in the GTK main loop's
	// idle state.  If the return value is true, the function will continue
	// to execute when the GTK main loop is in this state.
	go func() {
		for {
			time.Sleep(time.Second)
			s := fmt.Sprintf("Set a label %d time(s)!", nSets)
			_, err := glib.IdleAdd(LabelSetTextIdle, topLabel, s)
			if err != nil {
				log.Fatal("IdleAdd() failed:", err)
			}
			nSets++
			s = fmt.Sprintf("Set a label %d time(s)!", nSets)
			_, err = glib.IdleAdd(bottomLabel.SetText, s)
			if err != nil {
				log.Fatal("IdleAdd() failed:", err)
			}
			nSets++
		}
	}()

	win.ShowAll()
	gtk.Main()
}
Beispiel #6
0
func TestWebView_RunJavaScript(t *testing.T) {
	webView := NewWebView()
	defer webView.Destroy()

	wantResultString := "abc"
	webView.Connect("load-changed", func(_ *glib.Object, loadEvent LoadEvent) {
		switch loadEvent {
		case LoadFinished:
			webView.RunJavaScript(`document.getElementById("foo").innerHTML`, func(result *gojs.Value, err error) {
				if err != nil {
					t.Errorf("RunJavaScript error: %s", err)
				}
				resultString := webView.JavaScriptGlobalContext().ToStringOrDie(result)
				if wantResultString != resultString {
					t.Errorf("want result string %q, got %q", wantResultString, resultString)
				}
				gtk.MainQuit()
			})
		}
	})

	glib.IdleAdd(func() bool {
		webView.LoadHTML(`<p id=foo>abc</p>`, "")
		return false
	})

	gtk.Main()
}
Beispiel #7
0
func TestWebView_LoadHTML(t *testing.T) {
	webView := NewWebView()
	defer webView.Destroy()

	loadOk := false
	webView.Connect("load-failed", func() {
		t.Errorf("load failed")
	})
	webView.Connect("load-changed", func(_ *glib.Object, loadEvent LoadEvent) {
		switch loadEvent {
		case LoadFinished:
			loadOk = true
			gtk.MainQuit()
		}
	})

	glib.IdleAdd(func() bool {
		webView.LoadHTML("<p>hello</p>", "")
		return false
	})

	gtk.Main()

	if !loadOk {
		t.Error("!loadOk")
	}
}
Beispiel #8
0
func TestWebView_LoadURI_load_failed(t *testing.T) {
	webView := NewWebView()
	defer webView.Destroy()

	loadFailed := false
	loadFinished := false
	webView.Connect("load-failed", func() {
		loadFailed = true
	})
	webView.Connect("load-changed", func(_ *glib.Object, loadEvent LoadEvent) {
		switch loadEvent {
		case LoadFinished:
			loadFinished = true
			gtk.MainQuit()
		}
	})

	glib.IdleAdd(func() bool {
		// Load a bad URL to trigger load failure.
		webView.LoadURI("http://127.0.0.1:99999")
		return false
	})

	gtk.Main()

	if !loadFailed {
		t.Error("!loadFailed")
	}
	if !loadFinished {
		t.Error("!loadFinished")
	}
}
Beispiel #9
0
// NewView creates a new View in the context.
func (c *Context) NewView() *View {
	view := make(chan *View, 1)
	glib.IdleAdd(func() bool {
		webView := webkit2.NewWebView()
		settings := webView.Settings()
		settings.SetEnableWriteConsoleMessagesToStdout(true)
		settings.SetUserAgentWithApplicationDetails("WebLoop", "v1")
		v := &View{WebView: webView}
		loadChangedHandler, _ := webView.Connect("load-changed", func(_ *glib.Object, loadEvent webkit2.LoadEvent) {
			switch loadEvent {
			case webkit2.LoadFinished:
				// If we're here, then the load must not have failed, because
				// otherwise we would've disconnected this handler in the
				// load-failed signal handler.
				v.load <- struct{}{}
			}
		})
		webView.Connect("load-failed", func() {
			v.lastLoadErr = ErrLoadFailed
			webView.HandlerDisconnect(loadChangedHandler)
		})
		view <- v
		return false
	})
	return <-view
}
Beispiel #10
0
func TestWebView_GetSnapshot(t *testing.T) {
	webView := NewWebView()
	defer webView.Destroy()

	webView.Connect("load-changed", func(_ *glib.Object, loadEvent LoadEvent) {
		switch loadEvent {
		case LoadFinished:
			webView.GetSnapshot(func(img *image.RGBA, err error) {
				if err != nil {
					t.Errorf("GetSnapshot error: %q", err)
				}
				if img.Pix == nil {
					t.Error("!img.Pix")
				}
				if img.Stride == 0 || img.Rect.Max.X == 0 || img.Rect.Max.Y == 0 {
					t.Error("!img.Stride or !img.Rect.Max.X or !img.Rect.Max.Y")
				}
				gtk.MainQuit()
			})
		}
	})

	glib.IdleAdd(func() bool {
		webView.LoadHTML(`<p id=foo>abc</p>`, "")
		return false
	})

	gtk.Main()
}
Beispiel #11
0
func TestWebView_RunJavaScript_exception(t *testing.T) {
	webView := NewWebView()
	defer webView.Destroy()

	wantErr := errors.New("An exception was raised in JavaScript")
	webView.Connect("load-changed", func(_ *glib.Object, loadEvent LoadEvent) {
		switch loadEvent {
		case LoadFinished:
			webView.RunJavaScript(`throw new Error("foo")`, func(result *gojs.Value, err error) {
				if result != nil {
					ctx := webView.JavaScriptGlobalContext()
					t.Errorf("want result == nil, got %q", ctx.ToStringOrDie(result))
				}
				if !reflect.DeepEqual(wantErr, err) {
					t.Errorf("want error %q, got %q", wantErr, err)
				}
				gtk.MainQuit()
			})
		}
	})

	glib.IdleAdd(func() bool {
		webView.LoadHTML(`<p></p>`, "")
		return false
	})

	gtk.Main()
}
Beispiel #12
0
// Title returns the title of the current resource in the view.
func (v *View) Title() string {
	title := make(chan string, 1)
	glib.IdleAdd(func() bool {
		title <- v.WebView.Title()
		return false
	})
	return <-title
}
Beispiel #13
0
// URI returns the URI of the current resource in the view.
func (v *View) URI() string {
	uri := make(chan string, 1)
	glib.IdleAdd(func() bool {
		uri <- v.WebView.URI()
		return false
	})
	return <-uri
}
Beispiel #14
0
// addIdle adds a function to call on the next gtk idle cycle, to safely use
// the dock with our goroutines.
// It will also start the callIdle flush if it's not running.
//
func addIdle(call func()) {
	idleMu.Lock()
	idleDraw = append(idleDraw, call)
	if !idleRun {
		idleRun = true
		glib.IdleAdd(callIdle)
	}
	idleMu.Unlock()
}
Beispiel #15
0
func init() {
	Write = func(text string) error {
		clip, e := gtk.ClipboardGet(gdk.SELECTION_CLIPBOARD)
		if e != nil {
			return e
		}
		glib.IdleAdd(func() {
			clip.SetText(text)
		})
		return nil
	}

	Read = func() (string, error) {
		clip, e := gtk.ClipboardGet(gdk.SELECTION_CLIPBOARD)
		if e != nil {
			return "", e
		}
		cs := make(chan (string))
		ce := make(chan (error))

		defer func() {
			close(cs)
			close(ce)
		}()
		done := false
		glib.IdleAdd(func() { // Synced in the GTK loop to prevent thread crashs.
			str, e := clip.WaitForText()
			if !done {
				done = true
				cs <- str
				ce <- e
			}
		})
		go func() {
			<-time.After(time.Second * 3)
			if !done {
				done = true
				cs <- ""
				ce <- errors.New("clipboard read timeout")
			}
		}()
		return <-cs, <-ce
	}
}
Beispiel #16
0
// Open starts loading the resource at the specified URL.
func (v *View) Open(url string) {
	v.load = make(chan struct{}, 1)
	v.lastLoadErr = nil
	glib.IdleAdd(func() bool {
		if !v.destroyed {
			v.WebView.LoadURI(url)
		}
		return false
	})
}
Beispiel #17
0
// Load HTML from given string with given base URI.
func (v *View) LoadHTML(content, baseURI string) {
	v.load = make(chan struct{}, 1)
	v.lastLoadErr = nil
	glib.IdleAdd(func() bool {
		if !v.destroyed {
			v.WebView.LoadHTML(content, baseURI)
		}

		return false
	})
}
Beispiel #18
0
func runOnUIThreadAndWait(task uiTask) interface{} {
	resultChannel := make(chan interface{})
	defer close(resultChannel)

	glib.IdleAdd(func() bool {
		resultChannel <- task()
		return false
	})

	return <-resultChannel
}
Beispiel #19
0
// Load loads an applet or theme in the preview. Handbooker and Appleter can be used.
//
func (widget *Preview) Load(pack Previewer) {
	widget.title.SetMarkup(common.Big(common.Bold(pack.GetTitle())))
	author := pack.GetAuthor()
	if author != "" {
		author = fmt.Sprintf(tran.Slate("by %s"), author)
	}
	widget.author.SetMarkup(common.Small(common.Mono(author)))

	apl, ok := pack.(Appleter)
	if ok {
		widget.stateText.SetMarkup(apl.FormatState())
		widget.size.SetMarkup(common.Small(apl.FormatSize()))

		if icon := apl.IconState(); icon != "" {
			if pixbuf, e := common.PixbufAtSize(icon, 24, 24); !widget.log.Err(e, "Load image pixbuf") {
				widget.stateIcon.SetFromPixbuf(pixbuf)
				widget.stateIcon.Show()
			}
		}
	}

	// widget.RemoveTmpFile()

	widget.previewFrame.Hide() // Hide the preview frame until we have an image.

	// Async calls for description and image. They can have to be downloaded and be slow at it.

	chDesc := make(chan (string))
	go func() { // Go routines to get data.
		chDesc <- pack.GetDescription()
	}()
	go func() {
		imageLocation := pack.GetPreviewFilePath()
		// imageLocation, isTemp := pack.GetPreview(widget.TmpFile) // reuse the same tmp location if needed.

		desc := <-chDesc
		glib.IdleAdd(func() { // glib Idle to show the result.
			widget.description.SetMarkup(desc)
			widget.setImage(imageLocation)
		})
	}()

}
Beispiel #20
0
func Example() {
	runtime.LockOSThread()
	gtk.Init(nil)

	webView := webkit2.NewWebView()
	defer webView.Destroy()

	webView.Connect("load-failed", func() {
		fmt.Println("Load failed.")
	})
	webView.Connect("load-changed", func(_ *glib.Object, i int) {
		loadEvent := webkit2.LoadEvent(i)
		switch loadEvent {
		case webkit2.LoadFinished:
			fmt.Println("Load finished.")
			fmt.Printf("Title: %q\n", webView.Title())
			fmt.Printf("URI: %s\n", webView.URI())
			webView.RunJavaScript("window.location.hostname", func(val *gojs.Value, err error) {
				if err != nil {
					fmt.Println("JavaScript error.")
				} else {
					fmt.Printf("Hostname (from JavaScript): %q\n", val)
				}
				gtk.MainQuit()
			})
		}
	})

	glib.IdleAdd(func() bool {
		webView.LoadURI("https://www.google.com/")
		return false
	})

	gtk.Main()

	// output:
	// Load finished.
	// Title: "Google"
	// URI: https://www.google.com/
	// Hostname (from JavaScript): "www.google.com"
}
Beispiel #21
0
// TestConnectNotifySignal ensures that property notification signals (those
// whose name begins with "notify::") are queried by the name "notify" (with the
// "::" and the property name omitted). This is because the signal is "notify"
// and the characters after the "::" are not recognized by the signal system.
//
// See
// https://developer.gnome.org/gobject/stable/gobject-The-Base-Object-Type.html#GObject-notify
// for background, and
// https://developer.gnome.org/gobject/stable/gobject-Signals.html#g-signal-new
// for the specification of valid signal names.
func TestConnectNotifySignal(t *testing.T) {
	runtime.LockOSThread()

	// Create any GObject that has defined properties.
	spacing := 0
	box, _ := gtk.BoxNew(gtk.ORIENTATION_HORIZONTAL, spacing)

	// Connect to a "notify::" signal to listen on property changes.
	box.Connect("notify::spacing", func() {
		gtk.MainQuit()
	})

	glib.IdleAdd(func(s string) bool {
		t.Log(s)
		spacing++
		box.SetSpacing(spacing)
		return true
	}, "IdleAdd executed")

	gtk.Main()
}
Beispiel #22
0
func main() {
	gtk.Init(nil)
	win, e := gtk.WindowNew(gtk.WINDOW_TOPLEVEL)
	if e != nil {
		println(e.Error())
		return
	}

	path, isTest := vdata.TestPathDefault()
	var saveCall func(cftype.Builder)
	if isTest {
		saveCall = cfprint.Updated
	} else {
		saveCall = func(build cftype.Builder) { cfprint.Default(build, true) }
	}
	source := vdata.New(log.NewLog(log.Logs), win, saveCall)
	build := vdata.TestInit(source, path)
	source.SetGrouper(build)

	glib.IdleAdd(packWindow(win, source, build))
	gtk.Main()
}
Beispiel #23
0
func TestWebView_LoadURI(t *testing.T) {
	setup()
	defer teardown()

	responseOk := false
	mux.HandleFunc("/", func(w http.ResponseWriter, _ *http.Request) {
		w.Write([]byte("abc"))
		responseOk = true
	})

	loadFinished := false
	webView.Connect("load-failed", func() {
		t.Errorf("load failed")
	})
	webView.Connect("load-changed", func(_ *glib.Object, loadEvent LoadEvent) {
		switch loadEvent {
		case LoadFinished:
			loadFinished = true
			gtk.MainQuit()
		}
	})

	glib.IdleAdd(func() bool {
		webView.LoadURI(server.URL)
		return false
	})

	gtk.Main()

	if !responseOk {
		t.Error("!responseOk")
	}
	if !loadFinished {
		t.Error("!loadFinished")
	}
}
Beispiel #24
0
func (*RealGlib) IdleAdd(f interface{}, args ...interface{}) (glibi.SourceHandle, error) {
	res, err := glib.IdleAdd(f, args...)
	return glibi.SourceHandle(res), err
}
Beispiel #25
0
// NewApplet creates a new applet instance.
//
func NewApplet(base cdtype.AppBase, events *cdtype.Events) cdtype.AppInstance {
	app := &Applet{AppBase: base}
	app.SetConfig(&app.conf, app.actions()...)

	// Events.
	events.OnClick = func() { // Left click: open and manage the gui window.
		if app.Window().IsOpened() { // Window opened.
			app.Window().ToggleVisibility()
		} else {
			app.createGui(true, true)
		}
	}

	events.OnMiddleClick = func() { app.Action().Launch(app.Action().ID(app.conf.ActionClickMiddle)) }

	events.OnScroll = func(scrollUp bool) {
		var key int
		switch app.conf.ActionMouseWheel {
		case "Change volume":
			key = ternary.Int(scrollUp, int(upnptype.ActionVolumeUp), int(upnptype.ActionVolumeDown))

		case "Seek in track":
			key = ternary.Int(scrollUp, int(upnptype.ActionSeekForward), int(upnptype.ActionSeekBackward))
		}

		app.Action().Launch(key)
	}

	events.OnBuildMenu = app.Action().CallbackMenu(dockMenu)

	events.End = func() {
		if app.win != nil {
			glib.IdleAdd(app.win.Destroy)
		}
	}

	// Create the UPnP device manager.
	var e error
	app.cp, e = gupnp.New(&logger{app.Log()})
	app.Log().Err(e, "temp Dir")

	// Connect local tests.
	hook := app.cp.SubscribeHook("applet")
	hook.OnRendererFound = app.onMediaRendererFound
	hook.OnServerFound = app.onMediaServerFound
	hook.OnRendererLost = app.onMediaRendererLost
	hook.OnServerLost = app.onMediaServerLost

	// hook.OnRendererSelected = gui.SetRenderer
	// hook.OnServerSelected = gui.SetServer

	// hook.OnTransportState = func(r upnptype.Renderer, state upnptype.PlaybackState) { gui.SetPlaybackState(state) }
	// hook.OnCurrentTrackDuration = func(r upnptype.Renderer, dur int) { gui.SetDuration(mediacp.TimeToString(dur)) }
	// hook.OnCurrentTrackMetaData = func(r upnptype.Renderer, item upnptype.Item) { gui.SetTitle(item.Title) }
	// hook.OnMute = func(r upnptype.Renderer, muted bool) { gui.SetMuted(muted) }
	// hook.OnVolume = func(r upnptype.Renderer, vol uint) { gui.SetVolume(int(vol)) }
	// hook.OnCurrentTime = func(r upnptype.Renderer, secs int, f float64) { gui.SetCurrentTime(secs, f*100) }
	// hook.OnSetVolumeDelta = func(delta int) { gui.SetVolumeDelta(delta) }
	// }

	// Connect an UPnP backend to the manager.
	// mgr := backendsonos.NewManager(&logger{app.Log()})
	// mgr.SetEvents(app.cp.DefineEvents())
	// go mgr.Start(true)

	cp := backendgupnp.NewControlPoint()
	cp.SetEvents(app.cp.DefineEvents())

	return app
}
Beispiel #26
0
// ClickedQuit launches the OnQuit event defined.
// The OnQuit action is delayed to the next glib iteration to let GTK finish
// its current action (like closing a menu before the close window).
//
func (widget *GuiConfigure) ClickedQuit() {
	if widget.OnQuit != nil {
		glib.IdleAdd(widget.OnQuit)
	}
}
Beispiel #27
0
// Strings adds a string widget. Many options included.
// TODO: need password cypher, G_USER_DIRECTORY_PICTURES, play sound.
//
func Strings(key *cftype.Key) {
	value := key.Value().String()
	widget := newgtk.Entry()
	widget.SetText(value)

	if key.IsType(cftype.KeyPasswordEntry) { // Hide text and decrypt value.
		widget.SetVisibility(false)
		value = key.Source().DecryptString(value)
	}

	// Pack the widget before any other (in full size if needed).
	// So we do it now and fill the callbacks later
	key.PackKeyWidget(key, nil, nil, widget)
	var setValue func(interface{})

	// 	Add special buttons to fill the entry box.
	switch key.Type {
	case cftype.KeyFileSelector, cftype.KeyFolderSelector,
		cftype.KeySoundSelector, cftype.KeyImageSelector: // Add a file selector.

		fileChooser := newgtk.Button()
		img := newgtk.ImageFromIconName("document-open", gtk.ICON_SIZE_SMALL_TOOLBAR)
		fileChooser.SetImage(img)
		fileChooser.Connect("clicked", onFileChooserOpen, fileChooserData{widget, key})

		key.PackSubWidget(fileChooser)

		if key.IsType(cftype.KeySoundSelector) { //Sound Play Button
			play := newgtk.Button()
			imgPlay := newgtk.ImageFromIconName("media-playback-start", gtk.ICON_SIZE_SMALL_TOOLBAR)
			play.SetImage(imgPlay)

			// play.Connect("clicked", C._cairo_dock_play_a_sound, data)

			key.PackSubWidget(play)
		}

	case cftype.KeyShortkeySelector, cftype.KeyClassSelector: // Add a key/class grabber.
		grab := newgtk.ButtonWithLabel("Grab")
		key.PackSubWidget(grab)
		// 		gtk_widget_add_events(pMainWindow, GDK_KEY_PRESS_MASK);

		switch key.Type {
		case cftype.KeyClassSelector:
			grab.Connect("clicked", func() {
				widget.SetSensitive(false) // Block widgets.
				grab.SetSensitive(false)

				go func() {
					class, e := key.Source().GrabWindowClass() // Wait user selection in a routine.
					glib.IdleAdd(func() {                      // And resync with the GTK loop to display results.

						widget.SetSensitive(true) // Reactivate widgets.
						grab.SetSensitive(true)

						if !key.Log().Err(e, "ClassSelector", key.Group, key.Name) {

							setValue(class) // On success.
							key.Log().Debug("KeyClassSelector window selected", class)
						}
					})
				}()
			})

		case cftype.KeyShortkeySelector:
			grab.Connect("clicked", onKeyGrabClicked, &textGrabData{entry: widget, win: key.Source().GetWindow()})
		}

		// for _, sk := range key.Source().ListShortkeys() {
		// 	if sk.GetConfFilePath() == key.Storage().FilePath() {
		// 		println("found file shortkey")
		// 	}
		// }

	}

	// Display a default value when empty.
	if len(key.AuthorizedValues) > 0 && key.AuthorizedValues[0] != "" {
		defaultText := key.Translate(key.AuthorizedValues[0])
		cbChanged, _ := widget.Connect("changed", onTextDefaultChanged, key)
		data := textDefaultData{key: key, text: defaultText, cbID: cbChanged}
		widget.Connect("focus-in-event", onTextDefaultFocusIn, data)
		widget.Connect("focus-out-event", onTextDefaultFocusOut, data)

		// TODO: check other use of those fields.
		// 	 g_object_set_data (G_OBJECT (pEntry), "ignore-value", GINT_TO_POINTER (TRUE));
		// 	 g_object_set_data (G_OBJECT (pOneWidget), "default-text", cDefaultText);

		context, _ := widget.GetStyleContext()
		context.AddProvider(MainCSS(), gtk.STYLE_PROVIDER_PRIORITY_APPLICATION)

		setValue = func(uncast interface{}) {
			// if !key.IsDefault { // not sure why this was here.
			widget.SetText(uncast.(string))
			onTextDefaultFocusOut(widget, nil, data)
		}

		setValue(value) // will set IsDefault and button state.
	} else {
		setValue = func(uncast interface{}) { widget.SetText(uncast.(string)) }
	}
	getValue := func() (text interface{}) {
		if key.IsDefault {
			return ""
		}
		text, _ = widget.GetText()
		return text
	}

	key.PackKeyWidget(key, getValue, setValue)
}
Beispiel #28
0
// LaunchCommand adds a launch command widget.
// HELP ONLY
//
func LaunchCommand(key *cftype.Key) {
	if len(key.AuthorizedValues) == 0 || key.AuthorizedValues[0] == "" {
		key.Log().NewErrf("command missing", "widget LaunchCommand: %s", key.Name)
		return
	}
	// log.Info(key.Name, key.AuthorizedValues)

	if key.IsType(cftype.KeyLaunchCmdIf) {

		if len(key.AuthorizedValues) < 2 {
			key.Label().SetSensitive(false)
			return
		}

		key.Log().Info("KeyLaunchCmdIf : disabled for now")
		return

		// key.Log().Info("test", key.AuthorizedValues[1])

		// key.Log().Err(key.Log().ExecShow(key.AuthorizedValues[1]), "exec test")

		// gchar *cSecondCommand = pAuthorizedValuesList[1];
		// gchar *cResult = cairo_dock_launch_command_sync (cSecondCommand);
		// cd_debug ("%s: %s => %s", __func__, cSecondCommand, cResult);
		// if (cResult == NULL || *cResult == '0' || *cResult == '\0')  // result is 'fail'
		// {
		// 	gtk_widget_set_sensitive (pLabel, FALSE);
		// 	g_free (cResult);
		// 	break ;
		// }
		// g_free (cResult);
	}

	spinner := newgtk.Spinner()
	spinner.SetNoShowAll(true)
	key.PackSubWidget(spinner)

	btn := newgtk.ButtonFromIconName("go-jump", gtk.ICON_SIZE_BUTTON)
	key.PackSubWidget(btn)

	btn.Connect("clicked", func() {
		cmd, e := key.Log().ExecShlex(key.AuthorizedValues[0])
		if key.Log().Err(e, "widget LaunchCommand parse command", key.Name, ":", key.AuthorizedValues[0]) {
			return
		}

		e = cmd.Start()
		if key.Log().Err(e, "widget LaunchCommand exec", key.AuthorizedValues[0]) {
			return
		}

		btn.Hide()
		spinner.Show()
		spinner.Start()

		// Wait the external program in a go routine.
		// When finished, restore buttons state in the gtk idle loop.
		go func() {
			cmd.Wait()

			glib.IdleAdd(func() {
				btn.Show()
				spinner.Hide()
				spinner.Stop()
			})
		}()
	})

	// 	G_CALLBACK (_cairo_dock_widget_launch_command),
}