ui calculator
This commit is contained in:
@@ -0,0 +1,629 @@
|
||||
package calculator
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"galaxy/calc"
|
||||
"galaxy/client/widget/numeric"
|
||||
"galaxy/util"
|
||||
"slices"
|
||||
"strconv"
|
||||
"sync"
|
||||
|
||||
"fyne.io/fyne/v2"
|
||||
"fyne.io/fyne/v2/container"
|
||||
"fyne.io/fyne/v2/lang"
|
||||
"fyne.io/fyne/v2/widget"
|
||||
)
|
||||
|
||||
type CalculatorOpt func(*Calculator)
|
||||
type ShipClass struct {
|
||||
Name string
|
||||
Drive float64
|
||||
Armament uint
|
||||
Weapons float64
|
||||
Shields float64
|
||||
Cargo float64
|
||||
}
|
||||
type ShipClassFn func(string, float64, uint, float64, float64, float64)
|
||||
|
||||
type Calculator struct {
|
||||
CanvasObject fyne.CanvasObject
|
||||
|
||||
playerDrivesTech float64
|
||||
playerWeaponsTech float64
|
||||
playerShieldsTech float64
|
||||
playerCargoTech float64
|
||||
|
||||
shipDriveEntry *numeric.FloatEntry
|
||||
shipWeaponsEntry *numeric.FloatEntry
|
||||
shipArmamentEntry *numeric.IntEntry
|
||||
shipShieldsEntry *numeric.FloatEntry
|
||||
shipCargoEntry *numeric.FloatEntry
|
||||
|
||||
playerDrivesTechEntry *numeric.FloatEntry
|
||||
playerWeaponsTechEntry *numeric.FloatEntry
|
||||
playerShieldsTechEntry *numeric.FloatEntry
|
||||
playerCargoTechEntry *numeric.FloatEntry
|
||||
|
||||
drivesTechOverride *widget.Check
|
||||
weaponsTechOverride *widget.Check
|
||||
shieldsTechOverride *widget.Check
|
||||
cargoTechOverride *widget.Check
|
||||
|
||||
massEntry *numeric.FloatEntry
|
||||
speedEntry *numeric.FloatEntry
|
||||
attackEntry *numeric.FloatEntry
|
||||
defenseEntry *numeric.FloatEntry
|
||||
cargoLoadEntry *numeric.FloatEntry
|
||||
planetMatEntry *numeric.FloatEntry
|
||||
|
||||
massOverride *widget.Check
|
||||
speedOverride *widget.Check
|
||||
attackOverride *widget.Check
|
||||
defenseOverride *widget.Check
|
||||
cargoLoadMaximize *widget.Check
|
||||
planetMatOverride *widget.Check
|
||||
|
||||
planetLabel *widget.Label
|
||||
planetMassProdLabel *widget.Label
|
||||
planetShipsProdLabel *widget.Label
|
||||
planetContainer fyne.CanvasObject
|
||||
planetProdContainer fyne.CanvasObject
|
||||
|
||||
shipSelector *widget.SelectEntry
|
||||
shipCreateButton *widget.Button
|
||||
|
||||
onCreateHandler ShipClassFn
|
||||
loader ShipClassFn
|
||||
knownClasses []ShipClass
|
||||
|
||||
validateMu sync.RWMutex
|
||||
|
||||
l, mat, res float64
|
||||
|
||||
Valid bool
|
||||
}
|
||||
|
||||
func WithPlayerDrives(v float64) CalculatorOpt {
|
||||
return func(c *Calculator) { c.playerDrivesTech = v }
|
||||
}
|
||||
|
||||
func WithPlayerWeapons(v float64) CalculatorOpt {
|
||||
return func(c *Calculator) { c.playerWeaponsTech = v }
|
||||
}
|
||||
|
||||
func WithPlayerShields(v float64) CalculatorOpt {
|
||||
return func(c *Calculator) { c.playerShieldsTech = v }
|
||||
}
|
||||
|
||||
func WithPlayerCargo(v float64) CalculatorOpt {
|
||||
return func(c *Calculator) { c.playerCargoTech = v }
|
||||
}
|
||||
|
||||
func WithCreateHandler(f ShipClassFn) CalculatorOpt {
|
||||
return func(c *Calculator) { c.onCreateHandler = f }
|
||||
}
|
||||
|
||||
func NewCaclulator(opts ...CalculatorOpt) *Calculator {
|
||||
c := &Calculator{}
|
||||
|
||||
c.shipCreateButton = widget.NewButton(lang.L("ship.action.create"), c.onCreateShipClassButton)
|
||||
c.shipCreateButton.Disable()
|
||||
c.loader = c.LoadShipClass
|
||||
|
||||
c.planetMatEntry = numeric.NewFloatEntry(10, c.onPlanetMatChange)
|
||||
c.planetMatOverride = widget.NewCheck("", c.overridePlanetMat)
|
||||
c.planetMatOverride.Disable()
|
||||
c.planetLabel = widget.NewLabel("")
|
||||
c.planetMassProdLabel = bareLabel("")
|
||||
c.planetShipsProdLabel = bareLabel("")
|
||||
c.planetProdContainer = container.NewHBox(
|
||||
label(lang.L("planet.prod.mass")+":"),
|
||||
fixedLabel(c.planetMassProdLabel, 80),
|
||||
label(lang.L("planet.prod.ships")+":"),
|
||||
fixedLabel(c.planetShipsProdLabel, 80),
|
||||
)
|
||||
c.planetProdContainer.Hide()
|
||||
|
||||
c.planetContainer = container.NewVBox(
|
||||
widget.NewSeparator(),
|
||||
container.NewHBox(c.planetLabel),
|
||||
rowForItem(lang.L("planet.mat")+":", floatEntry(c.planetMatEntry, 100), c.planetMatOverride),
|
||||
c.planetProdContainer,
|
||||
)
|
||||
c.planetContainer.Hide()
|
||||
|
||||
c.shipSelector = widget.NewSelectEntry(nil)
|
||||
c.shipSelector.OnChanged = c.onShipSelectorChange
|
||||
|
||||
c.shipDriveEntry = numeric.NewFloatEntry(7, c.onShipDriveChange)
|
||||
c.shipWeaponsEntry = numeric.NewFloatEntry(7, c.onShipWeaponsChange)
|
||||
c.shipArmamentEntry = numeric.NewIntEntry(7, c.onShipArmamentChange)
|
||||
c.shipShieldsEntry = numeric.NewFloatEntry(7, c.onShipShieldsChange)
|
||||
c.shipCargoEntry = numeric.NewFloatEntry(7, c.onShipCargoChange)
|
||||
|
||||
c.playerDrivesTechEntry = numeric.NewFloatEntry(7, c.onDrivesTechChange)
|
||||
c.playerWeaponsTechEntry = numeric.NewFloatEntry(7, c.onWeaponsTechChange)
|
||||
c.playerShieldsTechEntry = numeric.NewFloatEntry(7, c.onShieldsTechChange)
|
||||
c.playerCargoTechEntry = numeric.NewFloatEntry(7, c.onCargoTechChange)
|
||||
|
||||
c.massEntry = numeric.NewFloatEntry(7, c.onMassChange)
|
||||
c.speedEntry = numeric.NewFloatEntry(7, c.onSpeedChange)
|
||||
c.attackEntry = numeric.NewFloatEntry(7, c.onAttackChange)
|
||||
c.defenseEntry = numeric.NewFloatEntry(7, c.onDefenseChange)
|
||||
c.cargoLoadEntry = numeric.NewFloatEntry(7, c.onCargoLoadChange)
|
||||
|
||||
c.drivesTechOverride = widget.NewCheck("", c.overrideDrivesTech)
|
||||
c.drivesTechOverride.Disable()
|
||||
c.weaponsTechOverride = widget.NewCheck("", c.overrideWeaponsTech)
|
||||
c.weaponsTechOverride.Disable()
|
||||
c.shieldsTechOverride = widget.NewCheck("", c.overrideShieldsTech)
|
||||
c.shieldsTechOverride.Disable()
|
||||
c.cargoTechOverride = widget.NewCheck("", c.overrideCargoTech)
|
||||
c.cargoTechOverride.Disable()
|
||||
|
||||
c.massOverride = widget.NewCheck("", c.overrideMass)
|
||||
c.massOverride.Disable()
|
||||
c.speedOverride = widget.NewCheck("", c.overrideSpeed)
|
||||
c.speedOverride.Disable()
|
||||
c.attackOverride = widget.NewCheck("", c.overrideAttack)
|
||||
c.attackOverride.Disable()
|
||||
c.defenseOverride = widget.NewCheck("", c.overrideDefense)
|
||||
c.defenseOverride.Disable()
|
||||
c.cargoLoadMaximize = widget.NewCheck(lang.L("label.max"), c.maximizeCargoLoad)
|
||||
c.cargoLoadMaximize.SetChecked(true)
|
||||
|
||||
createShip := container.NewBorder(
|
||||
nil, // top
|
||||
nil, // bottom
|
||||
nil, // left
|
||||
c.shipCreateButton, // right
|
||||
c.shipSelector, // center
|
||||
)
|
||||
|
||||
c.CanvasObject = container.NewVBox(
|
||||
container.NewPadded(createShip),
|
||||
widget.NewSeparator(),
|
||||
rowForTech(lang.L("tech.d")+":",
|
||||
c.shipDriveEntry, floatEntry(c.playerDrivesTechEntry, 80), c.drivesTechOverride),
|
||||
rowForWeapons(lang.L("tech.w")+":",
|
||||
c.shipArmamentEntry, c.shipWeaponsEntry, floatEntry(c.playerWeaponsTechEntry, 80), c.weaponsTechOverride),
|
||||
rowForTech(lang.L("tech.s")+":",
|
||||
c.shipShieldsEntry, floatEntry(c.playerShieldsTechEntry, 80), c.shieldsTechOverride),
|
||||
rowForTech(lang.L("tech.c")+":",
|
||||
c.shipCargoEntry, floatEntry(c.playerCargoTechEntry, 80), c.cargoTechOverride),
|
||||
widget.NewSeparator(),
|
||||
rowForItem(lang.L("ship.load")+":",
|
||||
floatEntry(c.cargoLoadEntry, 80), c.cargoLoadMaximize),
|
||||
rowForItem(lang.L("ship.mass")+":",
|
||||
floatEntry(c.massEntry, 80), c.massOverride),
|
||||
rowForItem(lang.L("ship.speed")+":",
|
||||
floatEntry(c.speedEntry, 80), c.speedOverride),
|
||||
rowForItem(lang.L("ship.attack")+":",
|
||||
floatEntry(c.attackEntry, 80), c.attackOverride),
|
||||
rowForItem(lang.L("ship.defense")+":",
|
||||
floatEntry(c.defenseEntry, 80), c.defenseOverride),
|
||||
c.planetContainer,
|
||||
)
|
||||
|
||||
c.Init(opts...)
|
||||
|
||||
return c
|
||||
}
|
||||
|
||||
func (c *Calculator) Init(opts ...CalculatorOpt) {
|
||||
for i := range opts {
|
||||
opts[i](c)
|
||||
}
|
||||
|
||||
c.playerDrivesTechEntry.SetOrigin(c.playerDrivesTech)
|
||||
c.playerWeaponsTechEntry.SetOrigin(c.playerWeaponsTech)
|
||||
c.playerShieldsTechEntry.SetOrigin(c.playerShieldsTech)
|
||||
c.playerCargoTechEntry.SetOrigin(c.playerCargoTech)
|
||||
|
||||
c.CanvasObject.Show()
|
||||
}
|
||||
|
||||
func (c *Calculator) Refresh() {
|
||||
c.validate()
|
||||
c.CanvasObject.Refresh()
|
||||
}
|
||||
|
||||
func (c *Calculator) RegisterClasses(shipClass ...ShipClass) {
|
||||
c.knownClasses = shipClass
|
||||
names := make([]string, len(c.knownClasses))
|
||||
for i := range c.knownClasses {
|
||||
names[i] = c.knownClasses[i].Name
|
||||
}
|
||||
slices.Sort(names)
|
||||
c.shipSelector = widget.NewSelectEntry(names)
|
||||
c.shipSelector.OnChanged = c.onShipSelectorChange
|
||||
}
|
||||
|
||||
func (c *Calculator) onCreateShipClassButton() {
|
||||
if c.onCreateHandler == nil || !c.Valid {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Calculator) validate() {
|
||||
fyne.Do(func() {
|
||||
c.validateMu.Lock()
|
||||
err := c.validateEntries()
|
||||
c.Valid = err == nil
|
||||
if err != nil {
|
||||
} else {
|
||||
}
|
||||
c.shipClassNameValidate()
|
||||
c.validateMu.Unlock()
|
||||
})
|
||||
}
|
||||
|
||||
func (c *Calculator) validateEntries() (err error) {
|
||||
defer func() {
|
||||
if err != nil {
|
||||
c.cargoLoadEntry.Clear()
|
||||
if !c.massOverride.Checked {
|
||||
c.massEntry.Clear()
|
||||
}
|
||||
if !c.speedOverride.Checked {
|
||||
c.speedEntry.Clear()
|
||||
}
|
||||
if !c.attackOverride.Checked {
|
||||
c.attackEntry.Clear()
|
||||
}
|
||||
if !c.defenseOverride.Checked {
|
||||
c.defenseEntry.Clear()
|
||||
}
|
||||
// c.planetProdContainer.Hide()
|
||||
}
|
||||
}()
|
||||
drive, ok := c.shipDriveEntry.Value()
|
||||
if !ok {
|
||||
err = errors.New("Parameter Drive is not valid")
|
||||
return
|
||||
}
|
||||
driveTech, ok := c.playerDrivesTechEntry.Value()
|
||||
if !ok {
|
||||
err = errors.New("Drive tech level is not valid")
|
||||
return
|
||||
}
|
||||
armament, ok := c.shipArmamentEntry.Value()
|
||||
if !ok {
|
||||
err = errors.New("Parameter Armament is not valid")
|
||||
return
|
||||
}
|
||||
weapons, ok := c.shipWeaponsEntry.Value()
|
||||
if !ok {
|
||||
err = errors.New("Parameter Weapons is not valid")
|
||||
return
|
||||
}
|
||||
weaponsTech, ok := c.playerWeaponsTechEntry.Value()
|
||||
if !ok {
|
||||
err = errors.New("Weapons tech level is not valid")
|
||||
return
|
||||
}
|
||||
shields, ok := c.shipShieldsEntry.Value()
|
||||
if !ok {
|
||||
err = errors.New("Parameter Shields is not valid")
|
||||
return
|
||||
}
|
||||
shieldsTech, ok := c.playerShieldsTechEntry.Value()
|
||||
if !ok {
|
||||
err = errors.New("Shields tech level is not valid")
|
||||
return
|
||||
}
|
||||
cargo, ok := c.shipCargoEntry.Value()
|
||||
if !ok {
|
||||
err = errors.New("Parameter Cargo is not valid")
|
||||
return
|
||||
}
|
||||
cargoTech, ok := c.playerCargoTechEntry.Value()
|
||||
if !ok {
|
||||
err = errors.New("Cargo tech level is not valid")
|
||||
return
|
||||
}
|
||||
|
||||
err = calc.ValidateShipTypeValues(drive, armament, weapons, shields, cargo)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
var cargoLoad float64
|
||||
if c.cargoLoadMaximize.Checked {
|
||||
cargoLoad = calc.CargoCapacity(cargo, cargoTech)
|
||||
c.cargoLoadEntry.SetOrigin(cargoLoad)
|
||||
} else if cargoLoad, ok = c.cargoLoadEntry.Value(); !ok {
|
||||
err = errors.New("Cargo load value is not valid")
|
||||
return
|
||||
}
|
||||
|
||||
emptyMass, ok := calc.EmptyMass(drive, weapons, uint(armament), shields, cargo)
|
||||
if !ok {
|
||||
err = errors.New("Unable to calculate empty mass (check armament and weapons)")
|
||||
return
|
||||
}
|
||||
fullMass := calc.FullMass(emptyMass, cargoLoad)
|
||||
speed := calc.Speed(calc.DriveEffective(drive, driveTech), fullMass)
|
||||
effectiveAttack := calc.EffectiveAttack(weapons, weaponsTech)
|
||||
effectiveDefense := calc.EffectiveDefence(shields, shieldsTech, fullMass)
|
||||
|
||||
c.massEntry.SetOrigin(emptyMass)
|
||||
c.speedEntry.SetOrigin(speed)
|
||||
c.attackEntry.SetOrigin(effectiveAttack)
|
||||
c.defenseEntry.SetOrigin(effectiveDefense)
|
||||
|
||||
planetMat, ok := c.planetMatEntry.Value()
|
||||
if !ok {
|
||||
// c.planetProdContainer.Hide()
|
||||
} else {
|
||||
massProd := calc.PlanetProduceShipMass(c.l, planetMat, c.res)
|
||||
c.planetMassProdLabel.SetText(strconv.FormatFloat(util.Fixed3(massProd), 'f', -1, 64))
|
||||
ships := 0.
|
||||
if emptyMass > 0 {
|
||||
ships = massProd / emptyMass
|
||||
}
|
||||
c.planetShipsProdLabel.SetText(strconv.FormatFloat(util.Fixed3(ships), 'f', -1, 64))
|
||||
c.planetProdContainer.Show()
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (c *Calculator) onOriginInputChange(cb *widget.Check, e *numeric.FloatEntry) {
|
||||
if e == nil {
|
||||
return
|
||||
}
|
||||
if cb != nil {
|
||||
cb.Checked = e.Overriden()
|
||||
if !cb.Checked {
|
||||
cb.Disable()
|
||||
} else {
|
||||
cb.Enable()
|
||||
}
|
||||
}
|
||||
c.onFloatEntryChange(e)
|
||||
}
|
||||
|
||||
func (c *Calculator) onFloatEntryChange(e *numeric.FloatEntry) {
|
||||
if e == nil {
|
||||
return
|
||||
}
|
||||
e.Validate()
|
||||
c.validate()
|
||||
}
|
||||
|
||||
func (c *Calculator) onIntEntryChange(e *numeric.IntEntry) {
|
||||
if e == nil {
|
||||
return
|
||||
}
|
||||
e.Validate()
|
||||
c.validate()
|
||||
}
|
||||
|
||||
func (c *Calculator) overrideChecked(cb *widget.Check, e *numeric.FloatEntry) {
|
||||
if cb == nil || e == nil {
|
||||
return
|
||||
}
|
||||
if !cb.Checked {
|
||||
e.Reset()
|
||||
cb.Disable()
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Calculator) onShipDriveChange(string) {
|
||||
c.onFloatEntryChange(c.shipDriveEntry)
|
||||
}
|
||||
|
||||
func (c *Calculator) onShipArmamentChange(string) {
|
||||
defer c.onIntEntryChange(c.shipArmamentEntry)
|
||||
if weapons, ok := c.shipWeaponsEntry.Value(); !ok || !c.shipWeaponsEntry.Valid {
|
||||
return
|
||||
} else if armament, ok := c.shipArmamentEntry.Value(); !ok || !c.shipArmamentEntry.Valid {
|
||||
return
|
||||
} else if armament > 0 && weapons == 0 {
|
||||
c.shipWeaponsEntry.SetOrigin(1.0)
|
||||
} else if armament == 0 && weapons > 0 {
|
||||
c.shipWeaponsEntry.SetOrigin(0.0)
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Calculator) onShipWeaponsChange(string) {
|
||||
defer c.onFloatEntryChange(c.shipWeaponsEntry)
|
||||
if weapons, ok := c.shipWeaponsEntry.Value(); !ok || !c.shipWeaponsEntry.Valid {
|
||||
return
|
||||
} else if armament, ok := c.shipArmamentEntry.Value(); !ok || !c.shipArmamentEntry.Valid {
|
||||
return
|
||||
} else if weapons > 0 && armament == 0 {
|
||||
c.shipArmamentEntry.SetOrigin(1)
|
||||
} else if weapons == 0 && armament > 0 {
|
||||
c.shipArmamentEntry.SetOrigin(0)
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Calculator) onShipShieldsChange(string) {
|
||||
c.onFloatEntryChange(c.shipShieldsEntry)
|
||||
}
|
||||
|
||||
func (c *Calculator) onShipCargoChange(string) {
|
||||
c.onFloatEntryChange(c.shipCargoEntry)
|
||||
}
|
||||
|
||||
func (c *Calculator) onDrivesTechChange(string) {
|
||||
c.onOriginInputChange(c.drivesTechOverride, c.playerDrivesTechEntry)
|
||||
}
|
||||
|
||||
func (c *Calculator) overrideDrivesTech(bool) {
|
||||
c.overrideChecked(c.drivesTechOverride, c.playerDrivesTechEntry)
|
||||
}
|
||||
|
||||
func (c *Calculator) onWeaponsTechChange(string) {
|
||||
c.onOriginInputChange(c.weaponsTechOverride, c.playerWeaponsTechEntry)
|
||||
}
|
||||
|
||||
func (c *Calculator) overrideWeaponsTech(bool) {
|
||||
c.overrideChecked(c.weaponsTechOverride, c.playerWeaponsTechEntry)
|
||||
}
|
||||
|
||||
func (c *Calculator) onShieldsTechChange(string) {
|
||||
c.onOriginInputChange(c.shieldsTechOverride, c.playerShieldsTechEntry)
|
||||
}
|
||||
|
||||
func (c *Calculator) overrideShieldsTech(bool) {
|
||||
c.overrideChecked(c.shieldsTechOverride, c.playerShieldsTechEntry)
|
||||
}
|
||||
|
||||
func (c *Calculator) onCargoTechChange(string) {
|
||||
c.onOriginInputChange(c.cargoTechOverride, c.playerCargoTechEntry)
|
||||
}
|
||||
|
||||
func (c *Calculator) overrideCargoTech(bool) {
|
||||
c.overrideChecked(c.cargoTechOverride, c.playerCargoTechEntry)
|
||||
}
|
||||
|
||||
func (c *Calculator) onCargoLoadChange(string) {
|
||||
c.onFloatEntryChange(c.cargoLoadEntry)
|
||||
}
|
||||
|
||||
func (c *Calculator) onMassChange(string) {
|
||||
c.onOriginInputChange(c.massOverride, c.massEntry)
|
||||
}
|
||||
|
||||
func (c *Calculator) overrideMass(bool) {
|
||||
c.overrideChecked(c.massOverride, c.massEntry)
|
||||
}
|
||||
|
||||
func (c *Calculator) onSpeedChange(string) {
|
||||
c.onOriginInputChange(c.speedOverride, c.speedEntry)
|
||||
}
|
||||
|
||||
func (c *Calculator) overrideSpeed(bool) {
|
||||
c.overrideChecked(c.speedOverride, c.speedEntry)
|
||||
}
|
||||
|
||||
func (c *Calculator) onAttackChange(string) {
|
||||
c.onOriginInputChange(c.attackOverride, c.attackEntry)
|
||||
}
|
||||
|
||||
func (c *Calculator) overrideAttack(bool) {
|
||||
c.overrideChecked(c.attackOverride, c.attackEntry)
|
||||
}
|
||||
|
||||
func (c *Calculator) onDefenseChange(string) {
|
||||
c.onOriginInputChange(c.defenseOverride, c.defenseEntry)
|
||||
}
|
||||
|
||||
func (c *Calculator) overrideDefense(bool) {
|
||||
c.overrideChecked(c.defenseOverride, c.defenseEntry)
|
||||
}
|
||||
|
||||
func (c *Calculator) maximizeCargoLoad(bool) {
|
||||
c.validate()
|
||||
}
|
||||
|
||||
func (c *Calculator) onPlanetMatChange(string) {
|
||||
c.onOriginInputChange(c.planetMatOverride, c.planetMatEntry)
|
||||
}
|
||||
|
||||
func (c *Calculator) overridePlanetMat(bool) {
|
||||
c.overrideChecked(c.planetMatOverride, c.planetMatEntry)
|
||||
}
|
||||
|
||||
func (c *Calculator) onShipSelectorChange(v string) {
|
||||
i, ok := c.shipClassNameValidate()
|
||||
if i < 0 || !ok || c.loader == nil {
|
||||
return
|
||||
}
|
||||
c.loader(
|
||||
c.knownClasses[i].Name,
|
||||
c.knownClasses[i].Drive,
|
||||
c.knownClasses[i].Armament,
|
||||
c.knownClasses[i].Weapons,
|
||||
c.knownClasses[i].Shields,
|
||||
c.knownClasses[i].Cargo,
|
||||
)
|
||||
}
|
||||
|
||||
func (c *Calculator) shipClassNameValidate() (int, bool) {
|
||||
var canCreateShip bool
|
||||
defer func() {
|
||||
if canCreateShip && c.Valid {
|
||||
c.shipCreateButton.Enable()
|
||||
} else {
|
||||
c.shipCreateButton.Disable()
|
||||
}
|
||||
}()
|
||||
name, canCreateShip := util.ValidateTypeName(c.shipSelector.Text)
|
||||
if canCreateShip {
|
||||
c.shipSelector.Text = name
|
||||
}
|
||||
i := slices.IndexFunc(c.knownClasses, func(v ShipClass) bool { return v.Name == name })
|
||||
canCreateShip = canCreateShip && i < 0
|
||||
return i, canCreateShip
|
||||
}
|
||||
|
||||
func (c *Calculator) LoadShipClass(n string, D float64, A uint, W float64, S float64, C float64) {
|
||||
c.shipDriveEntry.SetOrigin(D)
|
||||
c.shipArmamentEntry.SetOrigin(int(A))
|
||||
c.shipWeaponsEntry.SetOrigin(W)
|
||||
c.shipShieldsEntry.SetOrigin(S)
|
||||
c.shipCargoEntry.SetOrigin(C)
|
||||
}
|
||||
|
||||
func rowForItem(l string, entry, override fyne.CanvasObject) fyne.CanvasObject {
|
||||
i := []fyne.CanvasObject{label(l), entry}
|
||||
if override != nil {
|
||||
i = append(i, override)
|
||||
}
|
||||
return container.NewHBox(i...)
|
||||
}
|
||||
|
||||
func rowForTech(l string, shipEntry, techEntry, btn fyne.CanvasObject) fyne.CanvasObject {
|
||||
return container.NewHBox(
|
||||
label(l),
|
||||
floatEntry(shipEntry, 115),
|
||||
widget.NewLabel("@"),
|
||||
techEntry,
|
||||
btn,
|
||||
)
|
||||
}
|
||||
|
||||
func rowForWeapons(l string, armamentEntry, weaponsEntry, techEntry, btn fyne.CanvasObject) fyne.CanvasObject {
|
||||
return container.NewHBox(
|
||||
label(l),
|
||||
intEntry(armamentEntry, 35),
|
||||
floatEntry(weaponsEntry, 75),
|
||||
widget.NewLabel("@"),
|
||||
techEntry,
|
||||
btn,
|
||||
)
|
||||
}
|
||||
|
||||
func label(l string) fyne.CanvasObject {
|
||||
return fixedLabel(bareLabel(l), 110)
|
||||
}
|
||||
|
||||
func fixedLabel(w *widget.Label, width float32) fyne.CanvasObject {
|
||||
s := container.NewHScroll(w)
|
||||
s.SetMinSize(fyne.NewSize(width, 1))
|
||||
return s
|
||||
}
|
||||
|
||||
func bareLabel(l string) *widget.Label {
|
||||
w := widget.NewLabelWithStyle(l, fyne.TextAlignTrailing, fyne.TextStyle{Monospace: true, Symbol: false})
|
||||
w.Selectable = false
|
||||
w.Truncation = fyne.TextTruncateOff
|
||||
return w
|
||||
}
|
||||
|
||||
func intEntry(content fyne.CanvasObject, width float32) fyne.CanvasObject {
|
||||
s := container.NewHScroll(content)
|
||||
s.SetMinSize(fyne.NewSize(width, 1))
|
||||
return s
|
||||
}
|
||||
|
||||
func floatEntry(content fyne.CanvasObject, width float32) fyne.CanvasObject {
|
||||
s := container.NewHScroll(content)
|
||||
s.SetMinSize(fyne.NewSize(width, 1))
|
||||
return s
|
||||
}
|
||||
Reference in New Issue
Block a user