function MakeRow {
  parameter p.
  return p:AddHLayout().
}

function MakeButton {
  parameter p.
  parameter l.
  parameter f is {}.
  local b is p:AddButton(l).
  set b:onClick to f.
  return b.
}

function MakeToggle {
  parameter p.
  parameter l.
  parameter f.

  local btn is p:AddButton(l).
  set btn:TOGGLE to true.
  set btn:onToggle to f.
  return btn.
}

function MakeMenu {
  parameter stack. // the stack where menu stuff goes
  parameter btn. // the button that should show this menu
  parameter options.
  parameter execLabel.
  parameter callback.
  parameter preback is { parameter nil. }.

  local top is stack:AddVLayout().
  local sbox is top:AddScrollBox().

  local optionList is Lex().
  for option in options {
    local row is MakeRow(sbox).
    local name is option[0].
    local type is option[1].
    local field is 0.
    if type = "SCALAR" {
      row:AddLabel(name).
      set field to row:AddTextField(option[2]).
    } else if type = "BOOL" {
      set field to row:AddCheckBox(name, option[2]).
    } else if type = "RO" {
      row:AddLabel(name).
      set field to row:AddLabel(option[2]).
    } else {
      print "WARNING: Unsupported type passed to MakeMenu".
    }
    optionList:Add(name, field).
  }

  set btn:onClick to {
    preback(optionList).
    stack:ShowOnly(top).
  }.

  if execLabel <> "" {
    set top:AddButton(execLabel):onClick to callback:Bind(optionList).
  }
}

function AddStockButtons {
  parameter row.
  parameter bootname.

  MakeToggle(row, "Term", {
    parameter d.

    if d {
      CORE:PART:GETMODULE("kOSProcessor"):DOEVENT("Open Terminal").
    } else {
      CORE:PART:GETMODULE("kOSProcessor"):DOEVENT("Close Terminal").
    }
  }).
  
  MakeButton(row, "Update", {
    switch to 0.
    run reinstall(bootname).
  }).
}