// Copyright 2017-2025 WIT.COM Inc. All rights reserved. // Use of this source code is governed by the GPL 3.0 package main import ( "fmt" "strings" "github.com/awesome-gocui/gocui" log "go.wit.com/log" "go.wit.com/toolkits/tree" "go.wit.com/widget" ) // dropdowns don't exist so this is an attempt to pretend they exist // by having a fake window view in gocui that appears with the dropdown // items. by detecting where the user clicks, we should be // able to set the text of the button to that value (and // rezise it. // the thing is this is so damned complicated because it // is very hard to debug this. thanks to the floating on // screen debugging output I might be able to figure it // it out now. maybe. notsure. func makeDropdownView(ddItems string) *guiWidget { newNode := addDropdown() tk := newNode.TK.(*guiWidget) tk.labelN = ddItems tk.SetText(ddItems) tk.gocuiSize.w0 = 100 tk.gocuiSize.w1 = 120 tk.gocuiSize.h0 = 15 tk.gocuiSize.h1 = 18 tk.v, _ = me.baseGui.SetView("ddview", tk.gocuiSize.w0, tk.gocuiSize.h0, tk.gocuiSize.w1, tk.gocuiSize.h1, 0) if tk.v == nil { return tk } tk.v.Wrap = true tk.v.Frame = true tk.v.Clear() fmt.Fprint(tk.v, ddItems) tk.Show() return tk } func addDropdown() *tree.Node { n := new(tree.Node) n.WidgetType = widget.Flag n.WidgetId = -222 n.ParentId = 0 // store the internal toolkit information tk := new(guiWidget) tk.frame = true tk.labelN = "DropBox text" tk.node = n // copy the data from the action message tk.node.State.Label = "DropBox" // set the name used by gocui to the id tk.cuiName = "-1 DR" tk.color = &colorFlag // add this new widget on the binary tree tk.parent = me.treeRoot.TK.(*guiWidget) if tk.parent == nil { panic("addDropdown() didn't get treeRoot guiWidget") } else { tk.parent.children = append(tk.parent.children, tk) } n.TK = tk return n } func (tk *guiWidget) showDropdown() { var ddItems string // todo: fix this after switching to protobuf // var items []string // items = tk.node.State.Strings //for i, s := range items { /* for i, s := range tk.node.Strings() { // log.Log(GOCUI, "showDropdown()", tk.String(), i, s) ddItems += s + "\n" } */ // log.Log(GOCUI, "new dropdown items should be set to:", ddItems) // sizeW, sizeH := tk.Size() // log.Log(GOCUI, "showDropdown() size W,H=", sizeW, sizeH) startW, startH := tk.Position() // log.Log(GOCUI, "showDropdown() location W,H=", startW, startH) me.dropdownV.MoveToOffset(startW+3, startH+2) me.dropdownV.labelN = ddItems me.dropdownV.Show() } func hideDDview() error { w, h := me.baseGui.MousePosition() log.Log(GOCUI, "hide dropdown menu() view msgMouseDown (w,h) =", w, h) if me.dropdownV == nil { return gocui.ErrUnknownView } if me.dropdownV.v == nil { return gocui.ErrUnknownView } me.dropdownV.SetVisible(false) return nil } func showDDview() error { w, h := me.baseGui.MousePosition() log.Log(GOCUI, "show dropdown menu() view msgMouseDown (w,h) =", w, h) if me.dropdownV == nil { return gocui.ErrUnknownView } if me.dropdownV.v == nil { return gocui.ErrUnknownView } me.dropdownV.SetVisible(true) return nil } // if there is a drop down view active, treat it like a dialog box and close it func (w *guiWidget) dropdownClicked(mouseW, mouseH int) string { w.Hide() // only need height to figure out what line in the dropdown menu the user clicked _, startH := w.Position() // startW, startH := w.Position() // log.Log(GOCUI, "dropdownClicked() start (w,h) =", startW, startH) // log.Log(GOCUI, "dropdownClicked() at (w,h) =", mouseW, mouseH) itemNumber := mouseH - startH items := strings.Split(w.labelN, "\n") // log.Log(GOCUI, "dropdownClicked() look for item", itemNumber, "len(items) =", len(items)) if itemNumber < 1 { return "" } if len(items) >= itemNumber { // log.Log(GOCUI, "dropdownClicked() found", items[itemNumber-1]) if items[itemNumber-1] != "" { if me.dropdownW != nil { // log.Log(GOCUI, "dropdownClicked() send event for", me.dropdownW.cuiName, me.dropdownW.node.WidgetType) me.dropdownW.SetText(items[itemNumber-1]) me.dropdownW.node.SetCurrentS(items[itemNumber-1]) me.myTree.SendUserEvent(me.dropdownW.node) } } return items[itemNumber-1] } return "" } var dtoggle bool = false // temporarily tracking show & hide var doffset int = 5 // how many spaces over the dropdown menu should be from the mouse func dropdownUnclicked(w, h int) { var d *guiWidget if me.dropdownV == nil { log.Log(GOCUI, "mouseUp() dropdownV = nil") return } // examine everything under X & Y on the screen) for _, tk := range findByXY(w, h) { // tk.dumpWidget("dropdownUnclicked()") if tk.node.WidgetType == widget.Dropdown { d = tk } } if d == nil { // log.Log(GOCUI, fmt.Sprintf("dropdownUnclicked() there was no dropdown widget at (w=%d h=%d)", mouseW, mouseH)) return } // log.Log(GOCUI, "dropdownUnclicked()", d.node.Strings(), "end. now try to enable me.dropdownV") dtext := strings.Join(d.node.Strings(), "\n") tk := me.dropdownV if dtoggle { // log.Log(GOCUI, "dropdownUnclicked() set visible=false") tk.Hide() dtoggle = false tk.SetText("goodbye") } else { // log.Log(GOCUI, "dropdownUnclicked() set visible=true") tk.MoveToOffset(w+doffset, h) tk.SetText(dtext) tk.Show() dtoggle = true } }