// PackReset adds a reset value button. // func PackReset(key *cftype.Key, value interface{}) *gtk.Button { fileDefault := key.Storage().FileDefault() if fileDefault == "" { return nil } back := newgtk.ButtonFromIconName("edit-clear", gtk.ICON_SIZE_MENU) back.Connect("clicked", func() { key.ValueSet(value) }) key.PackSubWidget(back) return back }
// 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), }
// CheckButton adds a check button widget. // func CheckButton(key *cftype.Key) { if key.NbElements > 1 { // TODO: remove temp test key.Log().Info("CheckButton multi", key.NbElements, key.Type.String()) } values := key.Value().ListBool() var activers []widgetActiver for k := 0; k < key.NbElements; k++ { var value bool if k < len(values) { value = values[k] } w := newgtk.Switch() w.SetActive(value) key.PackSubWidget(w) activers = append(activers, w) if key.IsType(cftype.KeyBoolCtrl) { // _allocate_new_buffer; // data[0] = pKeyBox; // data[1] = (pFrameVBox != NULL ? pFrameVBox : pGroupBox); // if (pAuthorizedValuesList != NULL && pAuthorizedValuesList[0] != NULL) // NbControlled = g_ascii_strtod (pAuthorizedValuesList[0], NULL); // else // NbControlled = 1; // data[2] = GINT_TO_POINTER (NbControlled); // if (NbControlled < 0) // a negative value means that the behavior is inverted. // { // bValue = !bValue; // NbControlled = -NbControlled; // } // g_signal_connect (G_OBJECT (pOneWidget), "toggled", G_CALLBACK(_cairo_dock_toggle_control_button), data); // g_object_set_data (G_OBJECT (pKeyBox), "nb-ctrl-widgets", GINT_TO_POINTER (NbControlled)); // g_object_set_data (G_OBJECT (pKeyBox), "one-widget", pOneWidget); // if (! bValue) // les widgets suivants seront inactifs. // { // CDControlWidget *cw = g_new0 (CDControlWidget, 1); // pControlWidgets = g_list_prepend (pControlWidgets, cw); // cw->iNbSensitiveWidgets = 0; // cw->NbControlled = NbControlled; // cw->iFirstSensitiveWidget = 1; // cw->pControlContainer = (pFrameVBox != NULL ? pFrameVBox : pGroupBox); // } // sinon le widget suivant est sensitif, donc rien a faire. } } if key.NbElements == 1 { key.PackKeyWidget(key, func() interface{} { return activers[0].GetActive() }, func(uncast interface{}) { activers[0].SetActive(uncast.(bool)) }, ) } else { key.PackKeyWidget(key, func() interface{} { return listActiverGet(activers) }, func(uncast interface{}) { listActiverSet(activers, uncast.([]bool)) }, ) } }
// Float adds a float selector widget. SpinButton or Horizontal Scale // func Float(key *cftype.Key) { if key.NbElements > 1 { // TODO: remove temp test key.Log().Info("Float multi", key.NbElements, key.Type.String()) } values := key.Value().ListFloat() minValue, maxValue := minMaxValues(key) var valuers []WidgetValuer for k := 0; k < key.NbElements; k++ { var value float64 if k < len(values) { value = values[k] } switch key.Type { case cftype.KeyFloatScale: adjustment := newgtk.Adjustment( value, minValue, maxValue, (maxValue-minValue)/20, (maxValue-minValue)/10, 0, ) w := newgtk.Scale(gtk.ORIENTATION_HORIZONTAL, adjustment) w.Set("digits", 3) key.PackSubWidget(WrapKeyScale(key, w)) valuers = append(valuers, w) case cftype.KeyFloatSpin: w := newgtk.SpinButtonWithRange(minValue, maxValue, 1) w.Set("digits", 3) w.SetValue(value) key.PackSubWidget(w) valuers = append(valuers, w) } } switch { case key.NbElements == 1: key.PackKeyWidget(key, func() interface{} { return valuers[0].GetValue() }, func(uncast interface{}) { valuers[0].SetValue(uncast.(float64)) }, ) oldval, e := key.Storage().Default(key.Group, key.Name) if e == nil { PackReset(key, oldval.Float()) } default: key.PackKeyWidget(key, func() interface{} { return listValuerGet(valuers) }, func(uncast interface{}) { listValuerSet(valuers, uncast.([]float64)) }, ) oldval, e := key.Storage().Default(key.Group, key.Name) if e == nil { PackReset(key, oldval.ListFloat()) } } }
// IntegerSize adds an integer selector widget. // func IntegerSize(key *cftype.Key) { if key.NbElements > 1 { // TODO: remove temp test key.Log().Info("IntegerSize multi", key.NbElements, key.Type.String()) } toggle := newgtk.ToggleButton() img := newgtk.ImageFromIconName("media-playback-pause", gtk.ICON_SIZE_MENU) // get better image. toggle.SetImage(img) values := key.Value().ListInt() minValue, maxValue := minMaxValues(key) var valuers []WidgetValuer key.NbElements *= 2 // Two widgets to add. // Value pair data. var firstValue int var firstWidget *gtk.SpinButton var cbBlock func() func() for k := 0; k < key.NbElements; k++ { var value int if k < len(values) { value = values[k] } w := newgtk.SpinButtonWithRange(minValue, maxValue, 1) w.SetValue(float64(value)) key.PackSubWidget(w) valuers = append(valuers, w) if k&1 == 0 { // first value, separator label := newgtk.Label("x") key.PackSubWidget(label) firstWidget = w firstValue = value } else { // second value. connect both spin values. if firstValue == value { toggle.SetActive(true) } cb0, e := firstWidget.Connect("value-changed", onValuePairChanged, &valuePair{ linked: w, toggle: toggle}) key.Log().Err(e, "IntegerSize connect value-changed 1") cb1, e := w.Connect("value-changed", onValuePairChanged, &valuePair{ linked: firstWidget, toggle: toggle}) key.Log().Err(e, "IntegerSize connect value-changed 2") cbBlock = func() func() { firstWidget.HandlerBlock(cb0) w.HandlerBlock(cb1) return func() { firstWidget.HandlerUnblock(cb0) w.HandlerUnblock(cb1) } } } } setValue := func(uncast interface{}) { if cbBlock == nil { key.Log().NewErr("no valuePair callbacks", "IntegerSize", key.Name) } else { defer cbBlock()() // This disables now and reenables during defer. } values := uncast.([]int) if len(values) < 2 { key.Log().NewErr("not enough values provided", "IntegerSize set value", key.Name, values) values = []int{0, 0} } listValuerSet(valuers, cast.IntsToFloats(values)) toggle.SetActive(values[0] == values[1]) } key.PackKeyWidget(key, func() interface{} { return cast.FloatsToInts(listValuerGet(valuers)) }, setValue, toggle, ) oldval, e := key.Storage().Default(key.Group, key.Name) key.Log().Err(e, "IntegerSize original value") if e == nil { PackReset(key, oldval.ListInt()) } }
// 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) }