golayoutiup

How do I update the layout in IUP?


I can't fathom out how to get my layout to update once the window is displayed. I must be missing something!

Here is a simplified version of code I have tried. Selecting the second tab, and clicking the toggle should result in a line being added (and then subsequently removed) to the first tab. selectedMarkets is being changed, but the rebuilt layout does not appear.

package main

import (
    "slices"

    "github.com/gen2brain/iup-go/iup"
)

type marketControls struct {
    mCVal string
}

var (
    selectedMarkets    = make(map[string]marketControls)
    dlg                iup.Ihandle
    marketValuesHandle iup.Ihandle
)

func main() {

    // Test value to show it is added to layout

    mC := new(marketControls)
    mC.mCVal = "woo"

    selectedMarkets["01"] = *mC

    iup.Open()
    defer iup.Close()

    marketValuesHandle = buildMarketPanel()

    dlg = iup.Dialog(
        iup.Hbox(
            iup.Tabs(
                marketValuesHandle,
                buildSelectionPanel(),
            ).SetAttributes("TABTITLE0=\"Market Values\",TABTITLE1=\"Market Selections\",MINSIZE=338x, MAXSIZE=340x"),
        ),
    ).SetAttributes("MARGIN=10x10")

    setSelectionsCallbacks()

    iup.Show(dlg)

    iup.MainLoop()

}

func buildMarketPanel() iup.Ihandle {

    gb := iup.GridBox().SetAttributes(map[string]string{
        "NUMDIV":        "2",
        "NORMALIZESIZE": "BOTH",
        "ORIENTATION":   "HORIZONTAL",
        "ALIGNMENTCOL":  "ACENTER",
        "MARGIN":        "10x10",
        "GAPLIN":        "20",
        "GAPCOL":        "10",
    })

    gb = fillMarketPanel(gb)

    return gb
}

func fillMarketPanel(gb iup.Ihandle) iup.Ihandle {

    gb = iup.Append(gb, iup.Label("Market").SetAttributes("FONTSTYLE=Bold"))
    gb = iup.Append(gb, iup.Label("Value").SetAttributes("FONTSTYLE=Bold"))

    var mCKeys []string

    for key := range selectedMarkets {
        mCKeys = append(mCKeys, key)
    }

    slices.Sort(mCKeys)

    for _, key := range mCKeys {
        gb = iup.Append(gb, iup.Label(key))

        marketVal := selectedMarkets[key].mCVal
        gb = iup.Append(gb, iup.Label(marketVal))
    }

    return gb
}

func buildSelectionPanel() iup.Ihandle {

    gb := iup.GridBox(

        iup.Label("Selections").SetAttributes("FONTSTYLE=Bold"),
        iup.Toggle("  Sel 00").SetHandle("sp00"),
    ).SetAttributes(map[string]string{
        "NUMDIV":         "1",
        "HOMOGENEOUSCOL": "Yes",
        "NORMALIZESIZE":  "BOTH",
        "ORIENTATION":    "HORIZONTAL",
        "ALIGNMENTLIN":   "ACENTER",
        "ALIGNMENTCOL":   "ACENTER",
        "MARGIN":         "10x10",
        "GAPLIN":         "10",
        "GAPCOL":         "10",
    })

    return gb
}

func setSelectionsCallbacks() {

    iup.SetCallback(iup.GetHandle("sp00"), "VALUECHANGED_CB", iup.ValueChangedFunc(changedSelection))
}

func changedSelection(ih iup.Ihandle) int {

    offOn := ih.GetAttribute("VALUE")

    if offOn == "ON" {

        mC := new(marketControls)
        mC.mCVal = ""

        selectedMarkets["00"] = *mC

    } else {

        delete(selectedMarkets, "00")

    }

    marketValuesHandle = buildMarketPanel()

    // Tried each of these

    iup.Redraw(marketValuesHandle, 1)
    iup.Update(marketValuesHandle)
    iup.Redraw(dlg, 1)
    iup.Update(dlg)

    return iup.DEFAULT
}

A little more complicated than I expected, but here's my fix after Antonio's suggestion:

package main

import (
    "slices"

    "github.com/gen2brain/iup-go/iup"
)

type marketControls struct {
    mCVal string
}

var (
    selectedMarkets = make(map[string]marketControls)

    tabsHandle             iup.Ihandle
    marketValuesHandle     iup.Ihandle
    marketSelectionsHandle iup.Ihandle
)

func main() {

    // Test value to show it is added to layout

    mC := new(marketControls)
    mC.mCVal = "woo"

    selectedMarkets["01"] = *mC

    iup.Open()
    defer iup.Close()

    tabsHandle = iup.Tabs().SetAttributes("TABTITLE0=\"Market Values\",TABTITLE1=\"Market Selections\",MINSIZE=338x, MAXSIZE=340x")

    marketValuesHandle = buildMarketPanel()
    marketSelectionsHandle = buildSelectionPanel()

    tabsHandle = iup.Append(tabsHandle, marketValuesHandle)
    tabsHandle = iup.Append(tabsHandle, marketSelectionsHandle)

    dlg := iup.Dialog(
        iup.Hbox(
            tabsHandle,
        ),
    ).SetAttributes("MARGIN=10x10")

    setSelectionsCallbacks()

    iup.Show(dlg)

    iup.MainLoop()

}

func buildMarketPanel() iup.Ihandle {

    gb := iup.GridBox().SetAttributes(map[string]string{
        "NUMDIV":        "2",
        "NORMALIZESIZE": "BOTH",
        "ORIENTATION":   "HORIZONTAL",
        "ALIGNMENTCOL":  "ACENTER",
        "MARGIN":        "10x10",
        "GAPLIN":        "20",
        "GAPCOL":        "10",
    })

    gb = fillMarketPanel(gb)

    return gb
}

func fillMarketPanel(gb iup.Ihandle) iup.Ihandle {

    gb = iup.Append(gb, iup.Label("Market").SetAttributes("FONTSTYLE=Bold"))
    gb = iup.Append(gb, iup.Label("Value").SetAttributes("FONTSTYLE=Bold"))

    var mCKeys []string

    for key := range selectedMarkets {
        mCKeys = append(mCKeys, key)
    }

    slices.Sort(mCKeys)

    for _, key := range mCKeys {
        gb = iup.Append(gb, iup.Label(key))

        marketVal := selectedMarkets[key].mCVal
        gb = iup.Append(gb, iup.Label(marketVal))
    }

    return gb
}

func buildSelectionPanel() iup.Ihandle {

    gb := iup.GridBox(

        iup.Label("Selections").SetAttributes("FONTSTYLE=Bold"),
        iup.Toggle("  Sel 00").SetHandle("sp00"),
    ).SetAttributes(map[string]string{
        "NUMDIV":         "1",
        "HOMOGENEOUSCOL": "Yes",
        "NORMALIZESIZE":  "BOTH",
        "ORIENTATION":    "HORIZONTAL",
        "ALIGNMENTLIN":   "ACENTER",
        "ALIGNMENTCOL":   "ACENTER",
        "MARGIN":         "10x10",
        "GAPLIN":         "10",
        "GAPCOL":         "10",
    })

    return gb
}

func setSelectionsCallbacks() {

    iup.SetCallback(iup.GetHandle("sp00"), "VALUECHANGED_CB", iup.ValueChangedFunc(changedSelection))
}

func changedSelection(ih iup.Ihandle) int {

    offOn := ih.GetAttribute("VALUE")

    if offOn == "ON" {

        mC := new(marketControls)
        mC.mCVal = ""

        selectedMarkets["00"] = *mC

    } else {

        delete(selectedMarkets, "00")

    }

    iup.Unmap(marketValuesHandle)
    iup.Detach(marketValuesHandle)
    marketValuesHandle = buildMarketPanel()
    tabsHandle = iup.Insert(tabsHandle, marketSelectionsHandle, marketValuesHandle).SetAttributes("TABTITLE0=\"Market Values\",MINSIZE=338x, MAXSIZE=340x")
    iup.Map(marketValuesHandle)
    iup.Refresh(tabsHandle)

    return iup.DEFAULT
}

Solution

  • When you dynamically add controls to a dialog, the new controls are not automatically mapped into the native system. You can call iup.Map(gb) after fillMarketPanel for instance. Notice that you don't need to call iup.Map for each new control if they all share the same new hierarchy, i.e. iup.Map is a recursive call.